Python 分布式爬虫框架 Scrapy 4-10 保存item到json

上一节我们已经知道,pipeline可以拦截我们的Item,故而数据的保存通过pipeline实现。

我们先实现数据的json格式保存,在pipelines.py中:

import codecs
import json
class JsonSavePipeline(object):
    """
    json文件的导出
    """
    def __init__(self):
        self.file = codecs.open('article.json', 'w', encoding="utf-8")

    def process_item(self, item, spider):
        lines = json.dumps(dict(item), ensure_ascii=False) + "\n"
        self.file.write(lines)
        return item

    def close_spider(self, spider):
        self.file.close()

其中,process_item是主要的处理函数,item需要在此return,以供下一个pipeline使用;close_spider是scrapy的一个信号量,当spider停止时会被调用。

在ITEM_PIPELINES中配置这个pipeline:

ITEM_PIPELINES = {
    'Spider.pipelines.SpiderPipeline': 300,
    # 'scrapy.pipelines.images.ImagesPipeline': 200,
    'Spider.pipelines.ArticleImagesPipeline': 200,
    'Spider.pipelines.JsonSavePipeline': 210,
}

启动,发现多了一个article.json文件,内容为:

实际上,scrapy为我们提供了多种格式数据的exporter,我们先以JSON格式为例,在pipelines.py中,引入:

from scrapy.exporters import JsonItemExporter

跟踪到exporters.py文件中,发现提供了一下几种格式的Exporter:

__all__ = ['BaseItemExporter', 'PprintItemExporter', 'PickleItemExporter',
           'CsvItemExporter', 'XmlItemExporter', 'JsonLinesItemExporter',
           'JsonItemExporter', 'MarshalItemExporter']

为了实现使用scrapy提供的Exporter实现数据的导出,在pipelines.py中自定义一个pipeline:

class JsonExporterPipleline(object):
    """
    调用scrapy提供的JsonExporter导出json文件
    """
    def __init__(self):
        self.file = open('article-exporter.json', 'wb')
        self.exporter = JsonItemExporter(self.file, encoding="utf-8", ensure_ascii=False)
        self.exporter.start_exporting()

    def close_spider(self, spider):
        self.exporter.finish_exporting()
        self.file.close()

    def process_item(self, item, spider):
        self.exporter.export_item(item)
        return item

实际上,都是在调用JsonItemExporter对象的方法。注意,这里不是继承了JsonItemExporter,而是生成它的实例并使用它的方法。

在ITEM_PIPELINES中配置它:

ITEM_PIPELINES = {
    'Spider.pipelines.SpiderPipeline': 300,
    # 'scrapy.pipelines.images.ImagesPipeline': 200,
    'Spider.pipelines.ArticleImagesPipeline': 200,
    'Spider.pipelines.JsonSavePipeline': 210,
    'Spider.pipelines.JsonExporterPipleline': 220,
}

删除图片和刚刚生成的article.json文件,再次启动项目。

发现都没有问题,只是通过JsonExporter输出的json文件,被放在了一个数组中,这更符合常理,此外每个json对象之间都有一个逗号分隔,这实际上都是我们调用的JsonExporter对象的方法中进行的:

我们可以借鉴着JsonExporter,完善我们自定义的JsonSavePipeline:

class JsonSavePipeline(object):
    """
    自定义json文件的导出
    """
    def __init__(self):
        self.file = codecs.open('article.json', 'w', encoding="utf-8")
        self.first_item = True
        self.file.write("[")

    def process_item(self, item, spider):
        if self.first_item:
            self.first_item = False
        else:
            self.file.write(', ')
        lines = json.dumps(dict(item), ensure_ascii=False)
        self.file.write(lines)
        return item

    def close_spider(self, spider):
        self.file.write("]\n")
        self.file.close()

需要说明的是,这是json格式,是很简单的,其他一些格式的数据需要考虑的东西更多,此时使用scrapy提供的JsonExporter的优势就很明显了。

发布了101 篇原创文章 · 获赞 26 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/liujh_990807/article/details/100057826