Lzh on GitHub

Feed exports (数据导出)

在实现爬虫时,最常需要的功能之一是能够妥善存储抓取到的数据,而通常这意味着生成一个包含抓取数据(通常称为“导出 feed”)的“导出文件”供其他系统使用。

Scrapy 通过 Feed Exports (数据导出) 功能开箱即用地提供了此功能,它允许您使用多种序列化格式和存储后端生成包含抓取项的 feed。

本页面提供了所有数据导出功能的详细文档。如果您正在寻找分步指南,请查看 Zyte 的导出指南

Serialization formats (序列化格式)

对于抓取数据的序列化,数据导出使用 Item exporters (项目导出器)。这些格式是开箱即用的:

  • JSON
  • JSON lines
  • CSV
  • XML

但您也可以通过 FEED_EXPORTERS 设置扩展支持的格式。

JSON

FEEDS 设置中 format 键的值:json 使用的导出器:JsonItemExporter 如果您将 JSON 与大型 feed 一起使用,请参阅此警告

JSON lines

FEEDS 设置中 format 键的值:jsonlines 使用的导出器:JsonLinesItemExporter

CSV

FEEDS 设置中 format`` 键的值:csv` 使用的导出器:CsvItemExporter 要指定要导出的列、它们的顺序和它们的列名,请使用 FEED_EXPORT_FIELDS。其他数据导出器也可以使用此选项,但它对 CSV 很重要,因为与许多其他导出格式不同,CSV 使用固定的头部。

XML

FEEDS 设置中 format 键的值:xml 使用的导出器:XmlItemExporter

Pickle

FEEDS 设置中 format 键的值:pickle 使用的导出器:PickleItemExporter

Marshal

FEEDS 设置中 format 键的值:marshal 使用的导出器:MarshalItemExporter

Storages (存储)

当使用数据导出时,您可以使用一个或多个 URI(通过 FEEDS 设置)定义存储 feed 的位置。数据导出支持多种存储后端类型,这些类型由 URI 方案定义。

开箱即用的存储后端支持:

  • 本地文件系统
  • FTP
  • S3(需要 boto3
  • Google Cloud Storage (GCS)(需要 google-cloud-storage
  • 标准输出

如果所需的外部库不可用,某些存储后端可能不可用。例如,S3 后端仅在安装了 boto3 库时才可用。

Storage URI parameters (存储 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 参数。

Storage backends (存储后端)

Local filesystem (本地文件系统)

feed 存储在本地文件系统中。

URI 方案:file URI 示例:file:///tmp/export.csv 所需外部库:无

请注意,对于本地文件系统存储(仅限),如果指定了 /tmp/export.csv(仅限 Unix 系统)之类的绝对路径,则可以省略方案。或者,您也可以使用 pathlib.Path 对象。

FTP

feed 存储在 FTP 服务器中。

URI 方案:ftp URI 示例:ftp://user:pass@ftp.example.com/path/to/export.csv 所需外部库:无

FTP 支持两种不同的连接模式:主动或被动。Scrapy 默认使用被动连接模式。要使用主动连接模式,请将 FEED_STORAGE_FTP_ACTIVE 设置为 True

此存储后端在 FEEDSoverwrite 键的默认值为:True

警告

overwrite 中的 True 值将导致您丢失以前版本的数据。

此存储后端使用延迟文件交付

S3

feed 存储在 Amazon S3 上。

URI 方案:s3 URI 示例: s3://mybucket/path/to/export.csvs3://aws_key:aws_secret@mybucket/path/to/export.csv 所需外部库:boto3 >= 1.20.0

AWS 凭据可以作为用户名/密码在 URI 中传递,也可以通过以下设置传递:

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • AWS_SESSION_TOKEN(仅在临时安全凭据时需要)

您还可以使用以下设置定义导出 feed 的自定义 ACL、自定义端点和区域名称:

  • FEED_STORAGE_S3_ACL
  • AWS_ENDPOINT_URL
  • AWS_REGION_NAME

此存储后端在 FEEDSoverwrite 键的默认值为:True

警告

overwrite 中的 True 值将导致您丢失以前版本的数据。

此存储后端使用延迟文件交付

Google Cloud Storage (GCS)

从 2.3 版开始新增。

feed 存储在 Google Cloud Storage 上。

URI 方案:gs URI 示例: gs://mybucket/path/to/export.csv 所需外部库:google-cloud-storage。 有关身份验证的更多信息,请参阅 Google Cloud 文档

您可以通过以下设置设置 Project IDAccess Control List (ACL)

  • FEED_STORAGE_GCS_ACL
  • GCS_PROJECT_ID

此存储后端在 FEEDSoverwrite 键的默认值为:True

警告

overwrite 中的 True 值将导致您丢失以前版本的数据。

此存储后端使用延迟文件交付

Standard output (标准输出)

feed 被写入 Scrapy 进程的标准输出。

URI 方案:stdout URI 示例:stdout: 所需外部库:无

Delayed file delivery (延迟文件交付)

如上所述,某些描述的存储后端使用延迟文件交付。

这些存储后端不会在抓取项时将项上传到 feed URI。相反,Scrapy 会将项写入临时本地文件,并且只有在写入所有文件内容(即在抓取结束时)后,该文件才会被上传到 feed URI。

如果您希望在使用这些存储后端之一时提前开始项交付,请使用 FEED_EXPORT_BATCH_ITEM_COUNT 将输出项拆分为多个文件,每个文件包含指定的最大项数。这样,一旦文件达到最大项数,该文件就会交付到 feed URI,从而允许项交付在抓取结束之前开始。

Item filtering (项目过滤)

从 2.6.0 版开始新增。

您可以使用 feed 选项中的 item_classes 选项过滤要允许特定 feed 使用的项目。只有指定类型的项目才会添加到 feed 中。

item_classes 选项由 ItemFilter 类实现,该类是 item_filter feed 选项的默认值。

您可以通过实现 ItemFilteraccepts 方法并以 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

class scrapy.extensions.feedexport.ItemFilter(feed_options: dict[str, Any] | None)[source]

这将由 FeedExporter 使用,以决定是否允许将项目导出到特定 feed。

参数:

  • feed_options (dict) – 从 FeedExporter 传递的 feed 特定选项

accepts(item: Any) -> bool[source]

如果 item 应该导出,则返回 True,否则返回 False

参数:

  • item (Scrapy items) – 用户想要检查是否可接受的抓取项目

返回:

如果接受,则为 True,否则为 False

返回类型:

bool

Post-Processing (后处理)

从 2.6.0 版开始新增。

Scrapy 提供了一个选项来激活插件,以便在将 feed 导出到 feed 存储之前对其进行后处理。除了使用内置插件外,您还可以创建自己的插件

这些插件可以通过 feed 的 postprocessing 选项激活。该选项必须传递一个后处理插件列表,按您希望处理 feed 的顺序排列。这些插件可以声明为导入字符串或插件的导入类。插件的参数可以通过 feed 选项传递。有关示例,请参阅feed 选项

Built-in Plugins (内置插件)

class scrapy.extensions.postprocessing.GzipPlugin(file: BinaryIO, feed_options: dict[str, Any])[source]

使用 gzip 压缩接收到的数据。

接受的 feed_options 参数:

  • gzip_compresslevel
  • gzip_mtime
  • gzip_filename

有关参数的更多信息,请参阅 gzip.GzipFile

class scrapy.extensions.postprocessing.LZMAPlugin(file: BinaryIO, feed_options: dict[str, Any])[source]

使用 lzma 压缩接收到的数据。

接受的 feed_options 参数:

  • lzma_format
  • lzma_check
  • lzma_preset
  • lzma_filters

注意

lzma_filters 不能在 pypy 7.3.1 及更早版本中使用。

有关参数的更多信息,请参阅 lzma.LZMAFile

class scrapy.extensions.postprocessing.Bz2Plugin(file: BinaryIO, feed_options: dict[str, Any])[source]

使用 bz2 压缩接收到的数据。

接受的 feed_options 参数:

  • bz2_compresslevel

有关参数的更多信息,请参阅 bz2.BZ2File

Custom Plugins (自定义插件)

每个插件都是一个类,必须实现以下方法:

__init__(self, file, feed_options)

初始化插件。

参数:

  • file – 至少实现 writetellclose 方法的文件类对象
  • feed_options (dict) – feed 特定选项

write(self, data)

处理并将 databytesmemoryview)写入插件的目标文件。它必须返回写入的字节数。

close(self)

清理插件。

例如,您可能希望关闭一个文件包装器,您可能已使用该文件包装器压缩写入 __init__ 方法中接收到的文件的数据。

警告

不要从 __init__ 方法关闭文件。

要向您的插件传递参数,请使用feed 选项。然后,您可以从插件的 __init__ 方法中访问这些参数。

Settings (设置)

以下是用于配置数据导出的设置:

  • FEEDS(强制)
  • FEED_EXPORT_ENCODING
  • FEED_STORE_EMPTY
  • FEED_EXPORT_FIELDS
  • FEED_EXPORT_INDENT
  • FEED_STORAGES
  • FEED_STORAGE_FTP_ACTIVE
  • FEED_STORAGE_S3_ACL
  • FEED_EXPORTERS
  • FEED_EXPORT_BATCH_ITEM_COUNT

FEEDS

从 2.1 版开始新增。

默认值:{} 一个字典,其中每个键都是一个 feed URI(或 pathlib.Path 对象),每个值是一个包含特定 feed 配置参数的嵌套字典。

此设置对于启用数据导出功能是必需的。

有关支持的 URI 方案,请参阅存储后端

例如:

{
    '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: 要导出的项目类列表。 如果未定义或为空,则导出所有项目。 从 2.6.0 版开始新增。
  • item_filter: 用于过滤要导出的项目的过滤类。 默认使用 ItemFilter。 从 2.6.0 版开始新增。
  • indent: 默认值为 FEED_EXPORT_INDENT
  • item_export_kwargs: 包含相应项目导出器类的关键字参数的 dict。 从 2.4.0 版开始新增。
  • overwrite: 如果文件已存在(True)则覆盖文件,或者追加到其内容(False)。 默认值取决于存储后端
    • 本地文件系统:False
    • FTP:True注意 某些 FTP 服务器可能不支持追加文件(APPE FTP 命令)。
    • 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 选择最紧凑的表示。 目前仅由 JsonItemExporterXmlItemExporter 实现,即当您导出到 .json.xml 时。

FEED_STORE_EMPTY

默认值:True 是否导出空 feed(即没有项目的 feed)。如果为 False,并且没有项目要导出,则不会创建新文件,也不会修改现有文件,即使启用了覆盖 feed 选项

FEED_STORAGES

默认值:{} 一个字典,包含项目支持的其他 feed 存储后端。键是 URI 方案,值是存储类的路径。

FEED_STORAGE_FTP_ACTIVE

默认值:False 当将 feed 导出到 FTP 服务器时,是否使用主动连接模式(True)或使用被动连接模式(False,默认)。 有关 FTP 连接模式的信息,请参阅主动 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 将生成多个输出文件,每个输出文件最多存储指定数量的项目。

当生成多个输出文件时,您必须在 feed URI 中至少使用以下占位符之一来指示如何生成不同的输出文件名:

  • %(batch_time)s - 在创建 feed 时被时间戳替换(例如 2020-03-28T14-45-08.237134
  • %(batch_id)d - 被批次的基于 1 的序列号替换。 使用 printf 风格的字符串格式更改数字格式。例如,要通过在需要时引入前导零使批次 ID 为 5 位数字,请使用 %(batch_id)05d(例如 3 变为 00003123 变为 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 个项目。最后一个文件包含 100 个或更少的项目。

FEED_URI_PARAMS

默认值:None 一个字符串,包含一个函数的导入路径,用于设置要应用于 feed URI 的参数,使用 printf 风格的字符串格式

函数签名应如下所示:

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_COUNT0,则 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 项的源爬虫

警告

该函数应返回一个新的字典,修改收到的 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)s

scrapy crawl <spider_name> -o "%(spider_name)s.jsonl"