你知道在 scrapy 中,可以定制化导出数据格式吗?scrapy 导出器学习
本篇博客将系统的复习一下 scrapy 保存数据相关内容,即 导出器(Exporter)相关知识。
使用 Exporter 导出数据
编写 scrapy 爬虫是非常便捷的,而且可以快速的保存采集的结果,只需要运行爬虫时,在命令行输入如下代码:
scrapy crawl 爬虫文件名 -o 保存文件名
在 Scrapy 中,导出数据的中间件叫做 Exporter
,即导出器,它内置了 6 种可导出格式,分别是 JSON
,JSON LINES
,CSV
,XML
,Pickle
,Matshal
。
一般使用上述的内置格式,就可以满足各种场景需求了。
在存储的时候,只需要在命令行下输入 -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 天。
期待 关注,点赞、评论、收藏。
- 点赞
- 收藏
- 关注作者
评论(0)