Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用scrapy按字段排序json_Python_Json_Web Scraping_Scrapy_Scrapy Spider - Fatal编程技术网

Python 使用scrapy按字段排序json

Python 使用scrapy按字段排序json,python,json,web-scraping,scrapy,scrapy-spider,Python,Json,Web Scraping,Scrapy,Scrapy Spider,我已经创建了一个spider来从projecteuler.net中解决问题。我已结束对一个相关问题的回答 我使用命令scrapy crawl euler-o euler.json启动它,它输出一组无序的json对象,每个人都会回答一个问题:这对我来说很好,因为我将使用javascript处理它,即使我认为通过scrapy解决排序问题非常简单 但不幸的是,按scrapy(我需要按id字段升序)排序要在json中写入的项似乎并没有这么简单。我已经研究了每一个组件(中间件、管道、出口商、信号等),但似

我已经创建了一个spider来从projecteuler.net中解决问题。我已结束对一个相关问题的回答

我使用命令scrapy crawl euler-o euler.json启动它,它输出一组无序的json对象,每个人都会回答一个问题:这对我来说很好,因为我将使用javascript处理它,即使我认为通过scrapy解决排序问题非常简单

但不幸的是,按scrapy(我需要按id字段升序)排序要在json中写入的项似乎并没有这么简单。我已经研究了每一个组件(中间件、管道、出口商、信号等),但似乎没有人对此有用。我得出的结论是,在scrapy中根本不存在解决这个问题的解决方案(除了,可能是一个非常复杂的技巧),您必须在第二阶段订购。你同意吗,或者你有什么想法?我在这里复制我的刮板的代码

蜘蛛网:

# -*- coding: utf-8 -*-
import scrapy
from eulerscraper.items import Problem
from scrapy.loader import ItemLoader


class EulerSpider(scrapy.Spider):
    name = 'euler'
    allowed_domains = ['projecteuler.net']
    start_urls = ["https://projecteuler.net/archives"]

    def parse(self, response):
        numpag = response.css("div.pagination a[href]::text").extract()
        maxpag = int(numpag[len(numpag) - 1])

        for href in response.css("table#problems_table a::attr(href)").extract():
            next_page = "https://projecteuler.net/" + href
            yield response.follow(next_page, self.parse_problems)

        for i in range(2, maxpag + 1):
            next_page = "https://projecteuler.net/archives;page=" + str(i)
            yield response.follow(next_page, self.parse_next)

        return [scrapy.Request("https://projecteuler.net/archives", self.parse)]

    def parse_next(self, response):
        for href in response.css("table#problems_table a::attr(href)").extract():
            next_page = "https://projecteuler.net/" + href
            yield response.follow(next_page, self.parse_problems)

    def parse_problems(self, response):
        l = ItemLoader(item=Problem(), response=response)
        l.add_css("title", "h2")
        l.add_css("id", "#problem_info")
        l.add_css("content", ".problem_content")

        yield l.load_item()
项目:


如果我需要对输出文件进行排序(我会假设您有一个合理的理由希望这样做),我可能会编写一个自定义文件

是Scrapy内置的
jsonimexporter
的实现方式。
通过一些简单的更改,您可以对其进行修改,将项目添加到
export\u item()
中的列表中,然后在
finish\u export()
中对项目进行排序并写出文件


由于您只需要抓取几百个项目,因此存储它们的列表以及在抓取完成之前不写入文件的缺点对您来说应该不是问题。

现在,我已经找到了一个使用管道的有效解决方案:

import json

class JsonWriterPipeline(object):

    def open_spider(self, spider):
        self.list_items = []
        self.file = open('euler.json', 'w')

    def close_spider(self, spider):
        ordered_list = [None for i in range(len(self.list_items))]

        self.file.write("[\n")

        for i in self.list_items:
            ordered_list[int(i['id']-1)] = json.dumps(dict(i))

        for i in ordered_list:
            self.file.write(str(i)+",\n")

        self.file.write("]\n")
        self.file.close()

    def process_item(self, item, spider):
        self.list_items.append(item)
        return item
尽管这可能不是最优的,因为指南在另一个例子中建议:

JsonWriterPipeline的目的只是介绍如何编写项目管道。如果您真的想将所有刮取的项目存储到JSON文件中,那么应该使用提要导出


如何将无序的json导出到python中的并对其进行排序?您不能对json进行排序,它们的RFC清楚地表明它们是无序对象的集合。在python中,您也不能对dict对象的表示进行排序,除非您对键列表进行排序并按照列表的顺序对它们进行解析。在python的json对象中读取它们时,可以按照相同的顺序获取它们的键,但这对按键值排序没有任何帮助。我的结论是,您需要将结果导入到不同的有序数据类型(OrderedDict)中并在那里进行排序,然后对排序后的数据执行任何需要执行的操作。熊猫数据帧还处理许多常见的数据排序操作,可能也值得研究这些操作。我没有明确的答案,您必须尝试不同的实现,看看哪种数据结构最适合您的问题。@BoboDarph:是的,JSON数组中元素的顺序是保留的。来自RFC 7159——JavaScript对象表示法(JSON)数据交换格式(emphasis mine):对象是零个或多个名称/值对的无序集合,其中名称是字符串,值是字符串、数字、布尔值、null、对象或数组。数组是零个或多个值的有序序列。术语“对象”和“数组”来自JavaScript的约定。我将创建自己的导出器,而不是覆盖它。当然,编辑第三方库的源文件很少是个好主意。对不起,如果我用词混乱。
import json

class JsonWriterPipeline(object):

    def open_spider(self, spider):
        self.list_items = []
        self.file = open('euler.json', 'w')

    def close_spider(self, spider):
        ordered_list = [None for i in range(len(self.list_items))]

        self.file.write("[\n")

        for i in self.list_items:
            ordered_list[int(i['id']-1)] = json.dumps(dict(i))

        for i in ordered_list:
            self.file.write(str(i)+",\n")

        self.file.write("]\n")
        self.file.close()

    def process_item(self, item, spider):
        self.list_items.append(item)
        return item