你知道在 scrapy 中,可以定制化导出数据格式吗?scrapy 导出器学习

举报
梦想橡皮擦 发表于 2022/02/15 16:04:16 2022/02/15
【摘要】 本篇博客将系统的复习一下 scrapy 保存数据相关内容,即 导出器(Exporter)相关知识。 使用 Exporter 导出数据编写 scrapy 爬虫是非常便捷的,而且可以快速的保存采集的结果,只需要运行爬虫时,在命令行输入如下代码:scrapy crawl 爬虫文件名 -o 保存文件名在 Scrapy 中,导出数据的中间件叫做 Exporter,即导出器,它内置了 6 种可导出格式,...

本篇博客将系统的复习一下 scrapy 保存数据相关内容,即 导出器(Exporter)相关知识。

使用 Exporter 导出数据

编写 scrapy 爬虫是非常便捷的,而且可以快速的保存采集的结果,只需要运行爬虫时,在命令行输入如下代码:

scrapy crawl 爬虫文件名 -o 保存文件名

在 Scrapy 中,导出数据的中间件叫做 Exporter,即导出器,它内置了 6 种可导出格式,分别是 JSONJSON LINESCSVXMLPickleMatshal

一般使用上述的内置格式,就可以满足各种场景需求了。
在存储的时候,只需要在命令行下输入 -o 文件名.后缀,即可基于文件后缀名区分存储文件格式。

也可以通过 -t 文件类型 进行格式的选择,例如下述命令行:

scrapy crawl 爬虫名称 -t csv -o mydata.data

Scrapy 项目的全局配置default_settings.py 文件中,关于导出器的配置如下,其中可以看到内置的 6 种导出器,并且它们都在 scrapy.exporters 模块中。

FEED_EXPORTERS = {}
FEED_EXPORTERS_BASE = {
    'json': 'scrapy.exporters.JsonItemExporter',
    'jsonlines': 'scrapy.exporters.JsonLinesItemExporter',
    'jl': 'scrapy.exporters.JsonLinesItemExporter',
    'csv': 'scrapy.exporters.CsvItemExporter',
    'xml': 'scrapy.exporters.XmlItemExporter',
    'marshal': 'scrapy.exporters.MarshalItemExporter',
    'pickle': 'scrapy.exporters.PickleItemExporter',
}
FEED_EXPORT_INDENT = 0

因为导出格式可以配置,所以我们也可以编写定制化的导出器,添加到 scrapy 中使用。

编写爬虫实现导出器实操

本次直接进入案例实操环节,用于解释导出器相关使用技巧。

爬虫文件代码

import scrapy


class YySpider(scrapy.Spider):
    name = 'yy'
    allowed_domains = ['pharmnet.com.cn']
    start_urls = ['http://www.pharmnet.com.cn/product/1111/1/1.html']

    def parse(self, response):
        all_items = response.css('a.green.fb.f13::text').getall()
        for item in all_items:
            yield {
                "name": item
            }

运行爬虫可以使用下述两个命令,都可以获取到 CSV 文件。

scrapy crawl yy -o data.csv
scrapy crawl yy -t csv -o data.d

在导出文件时,还可以使用两个特殊参数,如下所示:

scrapy crawl yy -t csv -o data/%(name)s/%(time)s.csv

其中 %(name)s 对应爬虫名字,%(time)s 对应文件创建时间。

如果不想在导出文件的时候,通过命令进行配置,可以将这些内容写到 settings.py 文件中,这里用到的配置字段是 FEEDS

FEEDS = {
    'items.csv': {
        'format': 'csv',
        'encoding': 'utf8',
    },
}

该配置是字典类型,键名就是文件名,键值是文件的具体配置,常用内容如下所示:

  • format:导出类型,就是内置的几种类型;
  • batch_item_count:如果设置了一个整数,表示每个文件存储的数据条目,scrapy 会生成多个文件,设置了该值还要设置一个文件名生成规则,代码在下面;
  • encoding:编码;
  • fields:展示的字段;
  • indent:每一层用于缩进的空格数量;

batch_item_count 相关规则,其中 %(batch_time)s 获取时间戳,%(batch_id)d 获取序号。

FEEDS = {
    '%(batch_id)d.csv': {
        'format': 'csv',
        'encoding': 'utf8',
        'batch_item_count': 2,
    },
}

default_settings.py 中有哪些与 FEEDS 相关的配置,可以查看下述内容。

FEED_TEMPDIR = None
FEEDS = {}
FEED_URI_PARAMS = None  # a function to extend uri arguments
FEED_STORE_EMPTY = False
FEED_EXPORT_ENCODING = None
FEED_EXPORT_FIELDS = None
FEED_STORAGES = {}

自己实现一个导出器

如果 scrapy 内置的 6 种导出器无法满足要求,就可以自定义一个导出器。
实现方式非常简单,只需要在导出器类中,实现基类 BaseItemExporter 的接口即可。

自定义导出器主要涉及如下三个方法。

  • start_exporting():导出器的初始化方法;
  • finish_exporting():导出器结束时调用的方法;
  • export_item():核心方法,对 item 中的每一项导出时,都会执行。

接下来我们就实现一个自己定义的导出器。

settings.py 文件同级目录创建一个 my_ext.py 文件,然后创建一个 TXTItemExporter 类,其继承 BaseItemExporter

其余代码如下所示:

from scrapy.exporters import BaseItemExporter


class TXTItemExporter(BaseItemExporter):

    def __init__(self, file, **kwargs):
        super().__init__(dont_fail=True, **kwargs)
        self.file = file

    def export_item(self, item):
        # _get_serialized_fields 方法可以获得 item 所有字段,并返回迭代器
        print(self._get_serialized_fields(item, default_value=''))
        print(self.file)
        for name, value in self._get_serialized_fields(item, default_value=''):
            self.file.write(bytes("\nname:" + value, encoding="utf-8"))

本篇博客的案例计划是采集网站 http://www.pharmnet.com.cn/,但由于其是一个医药平台,不好过审,所以大家自行采集吧。

写在后面

今天是持续写作的第 257 / 365 天。
期待 关注点赞评论收藏

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。