Feed导出
在实现爬虫时最常需要的功能之一是能够正确地存储爬取到的数据,通常这意味着生成一个包含爬取到的数据的“导出文件”(通常称为“导出 Feed”),以供其他系统消费。
Scrapy 通过 Feed Exports 开箱即用地提供了此功能,它允许您使用多种序列化格式和存储后端生成包含爬取到的 Item 的 Feed。
本页提供了所有 Feed 导出功能的详细文档。如果您正在寻找分步指南,请查看 Zyte 的导出指南。
序列化格式
为了序列化爬取到的数据,Feed Exports 使用 Item 导出器。以下格式开箱即用
但您也可以通过 FEED_EXPORTERS 设置扩展支持的格式。
JSON
在
FEEDS设置中的format键的值:json使用的导出器:
JsonItemExporter如果您将 JSON 用于大型 Feed,请参阅 此警告。
JSON lines
在
FEEDS设置中的format键的值:jsonlines使用的导出器:
JsonLinesItemExporter
CSV
在
FEEDS设置中的format键的值:csv使用的导出器:
CsvItemExporter要指定要导出的列、它们的顺序及其列名,请使用
FEED_EXPORT_FIELDS。其他 Feed 导出器也可以使用此选项,但这对于 CSV 很重要,因为与许多其他导出格式不同,CSV 使用固定的头部。
XML
在
FEEDS设置中的format键的值:xml使用的导出器:
XmlItemExporter
Pickle
在
FEEDS设置中的format键的值:pickle使用的导出器:
PickleItemExporter
Marshal
在
FEEDS设置中的format键的值:marshal使用的导出器:
MarshalItemExporter
存储后端
在使用 Feed Exports 时,您可以通过 FEEDS 设置定义使用一个或多个 URI 存储 Feed 的位置。Feed Exports 支持多种存储后端类型,这些类型由 URI Scheme 定义。
开箱即用的存储后端包括
如果所需的外部库不可用,某些存储后端可能无法使用。例如,仅当安装了 boto3 库时,S3 后端才可用。
存储 URI 参数
存储 URI 还可以包含在创建 Feed 时会被替换的参数。这些参数包括
%(time)s- 在创建 Feed 时被替换为时间戳%(name)s- 被替换为爬虫名称
任何其他命名参数都会被同名的爬虫属性替换。例如,%(site_id)s 在创建 Feed 时会被替换为 spider.site_id 属性。
以下是一些示例说明
使用每个爬虫一个目录的方式存储到 FTP
ftp://user:password@ftp.example.com/scraping/feeds/%(name)s/%(time)s.json
使用每个爬虫一个目录的方式存储到 S3
s3://mybucket/scraping/feeds/%(name)s/%(time)s.json
注意
爬虫参数成为爬虫属性,因此它们也可以用作存储 URI 参数。
存储后端
本地文件系统
Feed 存储在本地文件系统中。
URI Scheme:
file示例 URI:
file:///tmp/export.csv所需外部库:无
请注意,对于本地文件系统存储(仅限),如果您指定绝对路径,例如 /tmp/export.csv,则可以省略 Scheme(仅限 Unix 系统)。或者,您也可以使用 pathlib.Path 对象。
FTP
Feed 存储在 FTP 服务器中。
URI Scheme:
ftp示例 URI:
ftp://user:pass@ftp.example.com/path/to/export.csv所需外部库:无
FTP 支持两种不同的连接模式:主动或被动。Scrapy 默认使用被动连接模式。要改用主动连接模式,请将 FEED_STORAGE_FTP_ACTIVE 设置为 True。
对于此存储后端,FEEDS 设置中 overwrite 键的默认值为:True。
注意
overwrite 中的 True 值将导致您丢失之前版本的数据。
此存储后端使用 延迟文件传输。
S3
Feed 存储在 Amazon S3 上。
URI Scheme:
s3示例 URI
s3://mybucket/path/to/export.csvs3://aws_key:aws_secret@mybucket/path/to/export.csv
所需外部库:boto3 >= 1.20.0
AWS 凭据可以通过 URI 中的用户/密码形式传递,也可以通过以下设置传递
您还可以使用以下设置定义导出 Feed 的自定义 ACL、自定义 endpoint 和区域名称
对于此存储后端,FEEDS 设置中 overwrite 键的默认值为:True。
注意
overwrite 中的 True 值将导致您丢失之前版本的数据。
此存储后端使用 延迟文件传输。
Google Cloud Storage (GCS)
在 2.3 版本中添加。
Feed 存储在 Google Cloud Storage 上。
URI Scheme:
gs示例 URI
gs://mybucket/path/to/export.csv
所需外部库:google-cloud-storage。
有关身份验证的更多信息,请参阅 Google Cloud 文档。
您可以通过以下设置设置 项目 ID 和 访问控制列表 (ACL)
对于此存储后端,FEEDS 设置中 overwrite 键的默认值为:True。
注意
overwrite 中的 True 值将导致您丢失之前版本的数据。
此存储后端使用 延迟文件传输。
标准输出
Feed 被写入 Scrapy 进程的标准输出。
URI Scheme:
stdout示例 URI:
stdout:所需外部库:无
延迟文件传输
如上所述,某些描述的存储后端使用延迟文件传输。
这些存储后端不会在 Item 被爬取时立即将它们上传到 Feed URI。而是,Scrapy 将 Item 写入一个临时本地文件,只有当所有文件内容都写入完毕后(即在爬取结束时),才会将该文件上传到 Feed URI。
如果您在使用这些存储后端之一时希望 Item 传输更快开始,请使用 FEED_EXPORT_BATCH_ITEM_COUNT 将输出 Item 分割到多个文件中,每个文件包含指定的 Item 最大数量。这样,一旦文件达到最大 Item 数量,该文件就会被传输到 Feed URI,从而使 Item 传输在爬取结束之前很久就开始。
Item 过滤
在 2.6.0 版本中添加。
您可以使用 Feed 选项 中的 item_classes 选项过滤您想允许导出到特定 Feed 的 Item。只有指定类型的 Item 会被添加到 Feed 中。
item_filter 选项由 ItemFilter 类实现,它是 Feed 选项 item_filter 的默认值。
您可以通过实现 ItemFilter 类的方法 accepts 并以 feed_options 作为参数来创建自己的自定义过滤类。
例如
class MyCustomFilter:
def __init__(self, feed_options):
self.feed_options = feed_options
def accepts(self, item):
if "field1" in item and item["field1"] == "expected_data":
return True
return False
您可以将您的自定义过滤类分配给 Feed 的 item_filter 选项。有关示例,请参阅 FEEDS。
ItemFilter
后处理
在 2.6.0 版本中添加。
Scrapy 提供一个选项来激活插件,在将 Feed 导出到 Feed 存储之前对其进行后处理。除了使用 内置插件,您还可以创建自己的 插件。
这些插件可以通过 Feed 的 postprocessing 选项激活。此选项必须传递一个后处理插件列表,顺序即为您希望处理 Feed 的顺序。这些插件可以声明为导入字符串,也可以是插件的导入类。插件的参数可以通过 Feed 选项传递。有关示例,请参阅 Feed 选项。
内置插件
- class scrapy.extensions.postprocessing.GzipPlugin(file: BinaryIO, feed_options: dict[str, Any])[source]
使用 gzip 压缩接收到的数据。
接受的
feed_options参数gzip_compresslevel
gzip_mtime
gzip_filename
有关参数的更多信息,请参阅
gzip.GzipFile。
自定义插件
每个插件都是一个类,必须实现以下方法
- __init__(self, file, feed_options)
初始化插件。
- write(self, data)
处理并写入 data (
bytes或memoryview) 到插件的目标文件中。它必须返回写入的字节数。
- close(self)
清理插件。
例如,您可能需要关闭一个文件包装器,该包装器可能用于压缩写入
__init__方法中接收到的文件的数据。警告
不要从
__init__方法中关闭文件。
要将参数传递给您的插件,请使用 Feed 选项。然后您可以从您的插件的 __init__ 方法中访问这些参数。
设置
以下是用于配置 Feed Exports 的设置
FEEDS(强制)
FEEDS
在 2.1 版本中添加。
默认值: {}
一个字典,其中每个键都是一个 Feed URI(或 pathlib.Path 对象),每个值都是一个嵌套字典,包含特定 Feed 的配置参数。
此设置是启用 Feed 导出功能所必需的。
有关支持的 URI Scheme,请参阅 存储后端。
例如
{
'items.json': {
'format': 'json',
'encoding': 'utf8',
'store_empty': False,
'item_classes': [MyItemClass1, 'myproject.items.MyItemClass2'],
'fields': None,
'indent': 4,
'item_export_kwargs': {
'export_empty_fields': True,
},
},
'/home/user/documents/items.xml': {
'format': 'xml',
'fields': ['name', 'price'],
'item_filter': MyCustomFilter1,
'encoding': 'latin1',
'indent': 8,
},
pathlib.Path('items.csv.gz'): {
'format': 'csv',
'fields': ['price', 'name'],
'item_filter': 'myproject.filters.MyCustomFilter2',
'postprocessing': [MyPlugin1, 'scrapy.extensions.postprocessing.GzipPlugin'],
'gzip_compresslevel': 5,
},
}
以下是接受的键列表以及在特定 Feed 定义未提供该键时用作回退值的设置
format: 序列化格式。此设置是强制的,没有回退值。
batch_item_count: 回退到FEED_EXPORT_BATCH_ITEM_COUNT。在 2.3.0 版本中添加。
encoding: 回退到FEED_EXPORT_ENCODING。fields: 回退到FEED_EXPORT_FIELDS。item_classes: 要导出的 Item 类 列表。如果未定义或为空,所有 Item 都会被导出。
在 2.6.0 版本中添加。
item_filter: 用于过滤要导出 Item 的 过滤类。ItemFilter默认使用。在 2.6.0 版本中添加。
indent: 回退到FEED_EXPORT_INDENT。item_export_kwargs: 包含对应 Item 导出器类 的关键字参数的dict。在 2.4.0 版本中添加。
overwrite:如果文件已存在,是覆盖文件(True)还是追加到其内容(False)。默认值取决于存储后端
本地文件系统:
FalseFTP:
True注意
一些FTP服务器可能不支持文件追加(
APPEFTP命令)。S3:
True(不支持追加)Google Cloud Storage (GCS):
True(不支持追加)标准输出:
False(不支持覆盖)
在 2.4.0 版本中添加。
store_empty:回退到FEED_STORE_EMPTY。uri_params:回退到FEED_URI_PARAMS。postprocessing:用于后处理的插件列表。插件将按照列表中传入的顺序使用。
在 2.6.0 版本中添加。
FEED_EXPORT_ENCODING
默认值:"utf-8"(回退:None)
用于导出 feed 的编码。
如果设置为 None,除了JSON输出外,所有都使用UTF-8。JSON输出出于历史原因使用安全的数字编码(\uXXXX序列)。
如果您想JSON也使用UTF-8,请使用 "utf-8"。
在 2.8 版本中有所变动: startproject 命令现在会在生成的 settings.py 文件中将此设置设为 "utf-8"。
FEED_EXPORT_FIELDS
默认值:None
使用 FEED_EXPORT_FIELDS 设置定义要导出的字段、它们的顺序和输出名称。有关更多信息,请参阅 BaseItemExporter.fields_to_export。
FEED_EXPORT_INDENT
默认值:0
在每个层级缩进输出的空格数。如果 FEED_EXPORT_INDENT 是一个非负整数,则数组元素和对象成员将以该缩进级别进行美观打印。缩进级别为 0(默认值)或负数,会将每个项目放在新行上。None 选择最紧凑的表示形式。
目前仅由 JsonItemExporter 和 XmlItemExporter 实现,即当您导出到 .json 或 .xml 时。
FEED_STORE_EMPTY
默认值:True
是否导出空 feed(即不包含任何 item 的 feed)。如果设置为 False,并且没有 item 可导出,则不会创建新文件,也不会修改现有文件,即使覆盖 feed 选项已启用。
FEED_STORAGES
默认值: {}
一个字典,包含您的项目支持的其他 feed 存储后端。键是 URI 方案,值是存储类的路径。
FEED_STORAGE_FTP_ACTIVE
默认值:False
导出 feed 到 FTP 服务器时,是使用主动连接模式(True)还是使用被动连接模式(False,默认值)。
有关 FTP 连接模式的信息,请参阅主动和被动FTP有什么区别?。
FEED_STORAGE_S3_ACL
默认值:''(空字符串)
一个字符串,包含您的项目导出到 Amazon S3 的 feed 的自定义 ACL。
有关可用值的完整列表,请访问 Amazon S3 文档中的预设 ACL 部分。
FEED_STORAGES_BASE
默认
{
"": "scrapy.extensions.feedexport.FileFeedStorage",
"file": "scrapy.extensions.feedexport.FileFeedStorage",
"stdout": "scrapy.extensions.feedexport.StdoutFeedStorage",
"s3": "scrapy.extensions.feedexport.S3FeedStorage",
"ftp": "scrapy.extensions.feedexport.FTPFeedStorage",
}
一个字典,包含 Scrapy 支持的内置 feed 存储后端。您可以通过在 FEED_STORAGES 中将它们的 URI 方案赋值为 None 来禁用它们中的任何一个。例如,要在不替换的情况下禁用内置的 FTP 存储后端,请将其放在您的 settings.py 文件中
FEED_STORAGES = {
"ftp": None,
}
FEED_EXPORTERS
默认值: {}
一个字典,包含您的项目支持的其他导出器。键是序列化格式,值是 Item exporter 类的路径。
FEED_EXPORTERS_BASE
默认
{
"json": "scrapy.exporters.JsonItemExporter",
"jsonlines": "scrapy.exporters.JsonLinesItemExporter",
"jsonl": "scrapy.exporters.JsonLinesItemExporter",
"jl": "scrapy.exporters.JsonLinesItemExporter",
"csv": "scrapy.exporters.CsvItemExporter",
"xml": "scrapy.exporters.XmlItemExporter",
"marshal": "scrapy.exporters.MarshalItemExporter",
"pickle": "scrapy.exporters.PickleItemExporter",
}
一个字典,包含 Scrapy 支持的内置 feed 导出器。您可以通过在 FEED_EXPORTERS 中将它们的序列化格式赋值为 None 来禁用它们中的任何一个。例如,要在不替换的情况下禁用内置的 CSV 导出器,请将其放在您的 settings.py 文件中
FEED_EXPORTERS = {
"csv": None,
}
FEED_EXPORT_BATCH_ITEM_COUNT
在 2.3.0 版本中添加。
默认值:0
如果指定一个大于 0 的整数,Scrapy 将生成多个输出文件,每个文件最多存储指定数量的 item。
生成多个输出文件时,必须在 feed URI 中使用至少一个以下占位符来指示如何生成不同的输出文件名
%(batch_time)s- 在创建 feed 时替换为时间戳(例如2020-03-28T14-45-08.237134)%(batch_id)d- 替换为批次的基于 1 的序号。使用printf 风格的字符串格式化来改变数字格式。例如,通过根据需要添加前导零,将批次 ID 变为 5 位数字,使用
%(batch_id)05d(例如,3变为00003,123变为00123)。
例如,如果您的设置包含
FEED_EXPORT_BATCH_ITEM_COUNT = 100
并且您的 crawl 命令行是
scrapy crawl spidername -o "dirname/%(batch_id)d-filename%(batch_time)s.json"
上面的命令行可以生成一个目录树,如下所示
->projectname
-->dirname
--->1-filename2020-03-28T14-45-08.237134.json
--->2-filename2020-03-28T14-45-09.148903.json
--->3-filename2020-03-28T14-45-10.046092.json
其中第一个和第二个文件都包含恰好 100 个 item。最后一个文件包含 100 个或更少的 item。
FEED_URI_PARAMS
默认值:None
一个字符串,包含一个函数的导入路径,用于设置使用printf 风格的字符串格式化应用于 feed URI 的参数。
函数签名应如下所示
- scrapy.extensions.feedexport.uri_params(params, spider)
返回一个
dict,包含要使用printf 风格的字符串格式化应用于 feed URI 的键值对。- 参数:
params (dict) –
默认键值对
具体如下
batch_id:文件批次的 ID。请参阅FEED_EXPORT_BATCH_ITEM_COUNT。如果
FEED_EXPORT_BATCH_ITEM_COUNT是0,则batch_id总是1。在 2.3.0 版本中添加。
batch_time:UTC 日期和时间,ISO 格式,其中:替换为-。请参阅
FEED_EXPORT_BATCH_ITEM_COUNT。在 2.3.0 版本中添加。
time:batch_time,微秒设置为0。
spider (scrapy.Spider) – feed item 的源爬虫
注意
函数应该返回一个新字典,原地修改接收到的
params已被弃用。
例如,要在 feed URI 中包含源爬虫的 name
在您的项目中的某个位置定义以下函数
# myproject/utils.py def uri_params(params, spider): return {**params, "spider_name": spider.name}
在您的设置中将
FEED_URI_PARAMS指向该函数# myproject/settings.py FEED_URI_PARAMS = "myproject.utils.uri_params"
在您的 feed URI 中使用
%(spider_name)sscrapy crawl <spider_name> -o "%(spider_name)s.jsonl"