文章目录
- 使用 Exporter 导出数据
- 1. 指定数据导出方法
- (1)命令行参数指定数据导出方式
- (2)配置文件指定数据导出方式
- 2. 添加数据导出格式
使用 Exporter 导出数据
在 Scrapy 中,负责导出数据的组件被称为 Exporter(导出器),Scrapy 内部实现了多个 Exporter,每个 Exporter 实现一种数据格式的导出,支持的数据格式如下(括号中为相应的 Exporter):
- JSON (JsonItemExporter)
- JSON lines (JsonLinesItemExporter)
- CSV (CsvItemExporter)
- XML (XmlItemExporter)
- Pickle (PickleItemExporter)
- Marshal (MarshalItemExporter)
其中,前 4 种是极为常用的文本数据格式,而后两种是 Python 特有的。在大多数情况下,使用 Scrapy 内部提供的 Exporter 就足够 了,需要以其他数据格式(上述6种以外)导出数据时,可以自行实现 Exporter。
1. 指定数据导出方法
在导出数据时,需向Scrapy爬虫提供以下信息:导出文件路径和导出数据格式(即选用哪个Exporter)。
可以通过以下两种方式指定爬虫如何导出数据:① 通过命令行参数指定;② 通过配置文件指定。
(1)命令行参数指定数据导出方式
在运行 scrapy crawl
命令时,可以分别使用 -o
和 -t
参数指定导出文件路径以及导出数据格式。 -o
参数我们并不陌生,前面我们已经在多个实例中运用过。使用方式如下:
$ scrapy crawl books -o books.csv
其中,-o books.csv
指定了导出文件的路径,在这里虽然没有使用 -t
参数指定导出数据格式,但 Scrapy 爬虫通过文件后缀名推断出我们想以 CSV 作为导出数据格式。同样的道理,如果将参数改为 -o books.json
,Scrapy 爬虫就会以 json 作为导出数据格式。
需要明确地指定导出数据格式时,使用 -t
参数,例如:
$ scrapy crawl books -t csv -o books1.data
...
$ scrapy crawl books -t json -o books2.data
...
$ scrapy crawl books -t xml -o books3.data
...
运行以上命令后,Scrapy 爬虫会以 -t
参数中的数据格式字符串(如csv、json、xml)为键,在配置字典FEED_EXPORTERS
中搜索 Exporter,FEED_EXPORTERS
的内容由以下两个字典的内容合并而成:
- 默认配置文件中的 FEED_EXPORTERS_BASE
- 用户配置文件中的 FEED_EXPORTERS
前者包含内部支持的导出数据格式,后者包含用户自定义的导出数据格式。以下是 Scrapy 源码中定义的 FEED_EXPORTERS_BASE
,它位于 scrapy.settings.default_settings
模块:
python">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',
}
如果用户添加了新的导出数据格式(即实现了新的 Exporter),可在配置文件 settings.py 中定义 FEED_EXPORTERS
,例如:
python">FEED_EXPORTERS = {'excel': 'my_project.my_exporters.ExcelItemExporter'}
另外,指定导出文件路径时,还可以使用 %(name)s
和 %(time)s
两个特殊变量:
%(name)s
:会被替换为 Spider 的名字%(time)s
:会被替换为文件创建时间
$ scrapy crawl books -o 'export_data/%(name)s/%(time)s.csv'
使用命令行参数指定如何导出数据很方便,但命令行参数只能指定导出文件路径以及导出数据格式,并且每次都在命令行里输入很长的参数让人很烦躁,使用配置文件可以弥补这些不足。
(2)配置文件指定数据导出方式
接下来,我们在配置文件中指定如何导出数据。下面依次说明几个常用选项:
-
FEED_URI:导出文件路径。
python">FEED_URI = 'export_data/%(name)s.data'
-
FEED_FORMAT:导出数据格式。
python">FEED_FORMAT = 'csv'
-
FEED_EXPORT_ENCODING:导出文件编码(默认情况下 json 文件使用数字编码,其他使用 utf-8 编码)。
python">FEED_EXPORT_ENCODING = 'gbk'
-
FEED_EXPORT_FIELDS:导出数据包含的字段(默认情况下导出所有字段),并指定次序。
python">FEED_EXPORT_FIELDS = ['name', 'author', 'price']
-
FEED_EXPORTERS:用户自定义 Exporter 字典,添加新的导出数据格式时使用。
python">FEED_EXPORTERS = {'excel': 'my_project.my_exporters.ExcelItemExporter'}
2. 添加数据导出格式
在某些需求下,我们想要添加新的导出数据格式,此时需要实现新的 Exporter 类。
接下来,我们参照 JsonItemExporter
的源码,在 toscrapy 项目中实现一个能将数据以 Excel 格式导出的 Exporter。在项目中创建一个 excel_exporter.py
(与 settings.py
同级目录),在其中实现 ExcelItemExporter
,代码如下:
python">from scrapy.exporters import BaseItemExporter
import xlwt
class ExcelItemExporter(BaseItemExporter):
def __init__(self, file, **kwargs):
self._configure(kwargs)
self.file = file
self.wbook = xlwt.Workbook()
self.wsheet = self.wbook.add_sheet('scrapy')
self.row = 0
def finish_exporting(self):
self.wbook.save(self.file)
def export_item(self, item):
fields = self._get_serialized_fields(item)
for col, v in enumerate(x for _, x in fields):
self.wsheet.write(self.row, col, v)
self.row += 1
上述代码解析如下:
- Step 1:在构造器方法中创建 Workbook 对象和 Worksheet 对象,并初始化用来记录写入行坐标的 self.row 。
- Step 2:在 export_item 方法中调用基类的
_get_serialized_fields
方法,获得 item 所有字段的迭代器,然后调用self.wsheet.write
方法将各字段写入 Excel 表格。 - Step 3:
finish_exporting
方法在所有数据都被写入 Excel 表格后被调用,在该方法中调用self.wbook.save
方法将 Excel 表格写 入 Excel 文件。
完成 ExcelItemExporter 后,在配置文件 settings.py
中添加如下代码:
python">FEED_EXPORTERS = {'excel': 'example.excel_exporter.ExcelItemExporter'}
现在,可以使用 ExcelItemExporter 导出数据了,以 -t excel
为参数重新运行爬虫:
$ scrapy crawl books -t excel -o books.xls
如下图所示,我们成功地使用 ExcelItemExporter 将爬取到的数据存入了 Excel 文件中。