条目导出器

一旦抓取了项目,您通常希望保留或导出这些项目,以便在其他应用程序中使用数据。这毕竟是抓取过程的全部目的。

为此,Scrapy为不同的输出格式(如XML、CSV或JSON)提供了一组项目导出器。

使用项目导出器

如果您很着急,只想使用项目导出器输出 爬取 的数据,请参见 Feed 导出 . 否则,如果您想知道项目导出器是如何工作的,或者需要更多的自定义功能(不包括在默认导出中),请继续阅读下面的内容。

为了使用项导出器,必须用它所需的参数实例化它。每个项目导出器需要不同的参数,因此请检查每个导出器文档以确保 内置项导出器引用 . 在实例化导出器之后,必须:

1。调用方法 start_exporting() 以便发出出口过程开始的信号

2。打电话给 export_item() 要导出的每个项的方法

三。最后打电话给 finish_exporting() 发出输出过程结束的信号

在这里你可以看到 Item Pipeline 它使用多个项目导出器,根据其中一个字段的值将 爬取 的项目分组到不同的文件中:

from itemadapter import ItemAdapter
from scrapy.exporters import XmlItemExporter

class PerYearXmlExportPipeline:
    """Distribute items across multiple XML files according to their 'year' field"""

    def open_spider(self, spider):
        self.year_to_exporter = {}

    def close_spider(self, spider):
        for exporter, xml_file in self.year_to_exporter.values():
            exporter.finish_exporting()
            xml_file.close()

    def _exporter_for_item(self, item):
        adapter = ItemAdapter(item)
        year = adapter['year']
        if year not in self.year_to_exporter:
            xml_file = open(f'{year}.xml', 'wb')
            exporter = XmlItemExporter(xml_file)
            exporter.start_exporting()
            self.year_to_exporter[year] = (exporter, xml_file)
        return self.year_to_exporter[year][0]

    def process_item(self, item, spider):
        exporter = self._exporter_for_item(item)
        exporter.export_item(item)
        return item

项字段的序列化

默认情况下,字段值是未修改地传递给基础序列化库的,如何序列化字段值的决定被委托给每个特定的序列化库。

但是,您可以自定义每个字段值的序列化方式。 在传递到序列化库之前 .

有两种方法可以自定义字段序列化的方式,下面将介绍这两种方法。

1。在字段中声明序列化程序

如果您使用 Item 中声明序列化程序。 field metadata 。序列化程序必须是可调用的,它接收值并返回其序列化形式。

例子::

import scrapy

def serialize_price(value):
    return f'$ {str(value)}'

class Product(scrapy.Item):
    name = scrapy.Field()
    price = scrapy.Field(serializer=serialize_price)

2。重写serialize_field()方法

您还可以覆盖 serialize_field() 方法自定义字段值的导出方式。

确保调用基类 serialize_field() 方法。

例子::

from scrapy.exporter import XmlItemExporter

class ProductXmlExporter(XmlItemExporter):

    def serialize_field(self, field, name, value):
        if name == 'price':
            return f'$ {str(value)}'
        return super().serialize_field(field, name, value)

内置项导出器引用

这是与 Scrapy 捆绑在一起的物品出口商名单。其中一些包含输出示例,假设您正在导出这两个项:

Item(name='Color TV', price='1200')
Item(name='DVD player', price='200')

BaseItemExporter

class scrapy.exporters.BaseItemExporter(fields_to_export=None, export_empty_fields=False, encoding='utf-8', indent=0, dont_fail=False)

这是所有项目导出器的(抽象)基类。它支持所有(具体)项目导出器使用的公共特性,例如定义要导出的字段、是否导出空字段或要使用的编码。

这些功能可以通过 __init__ 填充各自实例属性的方法参数: fields_to_exportexport_empty_fieldsencodingindent .

2.0 新版功能: 这个 dont_fail 参数。

export_item(item)

导出给定项。此方法必须在子类中实现。

serialize_field(field, name, value)

返回给定字段的序列化值。如果要控制特定字段或值的序列化/导出方式,可以重写此方法(在自定义项导出器中)。

默认情况下,此方法查找序列化程序 declared in the item field 并返回将该序列化程序应用于值的结果。如果找不到序列化程序,则返回未更改的值。

参数
  • field (Field object or a dict instance) -- 正在序列化的字段。如果来源 item object 不定义字段元数据, 领域 是空的 dict .

  • name (str) -- 正在序列化的字段的名称

  • value -- 正在序列化的值

start_exporting()

指示导出过程的开始。某些导出器可能会使用此命令生成某些必需的头(例如, XmlItemExporter )在导出任何项之前必须调用此方法。

finish_exporting()

发出输出过程结束的信号。一些导出器可能会使用此命令生成一些必需的页脚(例如, XmlItemExporter )在没有其他要导出的项之后,必须始终调用此方法。

fields_to_export

包含要导出的字段名称的列表,或 None 如果要导出所有字段。默认为 None .

一些出口商(如 CsvItemExporter )遵守此属性中定义的字段的顺序。

使用时 item objects 如果不公开所有可能的字段,则不支持导出每个项目的不同字段子集的导出器将只导出在导出的第一个项目中找到的字段。使用 fields_to_export 定义要导出的所有字段。

export_empty_fields

是否在导出的数据中包含空/未填充的项字段。默认为 False . 一些出口商(如 CsvItemExporter )忽略此属性并始终导出所有空字段。

对dict项忽略此选项。

encoding

输出字符编码。

indent

用于在每个级别上缩进输出的空间量。默认为 0 .

  • indent=None 选择最紧凑的表示形式,同一行中的所有项都没有缩进

  • indent<=0 每个项目都在自己的行上,没有缩进

  • indent>0 每一项都在自己的行上,用提供的数值缩进

PythonItemExporter

XmlItemExporter

class scrapy.exporters.XmlItemExporter(file, item_element='item', root_element='items', **kwargs)

将XML格式的项导出到指定的文件对象。

参数
  • file -- 用于导出数据的类似文件的对象。它的 write 方法应接受 bytes (以二进制模式打开的磁盘文件, io.BytesIO 物体等)

  • root_element (str) -- 导出的XML中根元素的名称。

  • item_element (str) -- 导出的XML中每个item元素的名称。

此的其他关键字参数 __init__ 方法传递给 BaseItemExporter __init__ 方法。

该出口商的典型产出为:

<?xml version="1.0" encoding="utf-8"?>
<items>
  <item>
    <name>Color TV</name>
    <price>1200</price>
 </item>
  <item>
    <name>DVD player</name>
    <price>200</price>
 </item>
</items>

除非在 serialize_field() 方法,多值字段通过序列化 <value> 元素。这是为了方便起见,因为多值字段非常常见。

例如,项目:

Item(name=['John', 'Doe'], age='23')

将序列化为:

<?xml version="1.0" encoding="utf-8"?>
<items>
  <item>
    <name>
      <value>John</value>
      <value>Doe</value>
    </name>
    <age>23</age>
  </item>
</items>

CsvItemExporter

class scrapy.exporters.CsvItemExporter(file, include_headers_line=True, join_multivalued=',', errors=None, **kwargs)

将CSV格式的项目导出到给定的类似文件的对象。如果 fields_to_export 属性已设置,将用于定义csv列及其顺序。这个 export_empty_fields 属性对此导出程序没有影响。

参数
  • file -- 用于导出数据的类似文件的对象。它的 write 方法应接受 bytes (以二进制模式打开的磁盘文件, io.BytesIO 物体等)

  • include_headers_line (str) -- 如果启用,则使导出器输出一个标题行,其中字段名取自 BaseItemExporter.fields_to_export 或第一个导出项字段。

  • join_multivalued -- 如果找到,将用于联接多值字段的字符。

  • errors (str) -- 指定如何处理编码和解码错误的可选字符串。有关详细信息,请参阅 io.TextIOWrapper .

此的其他关键字参数 __init__ 方法传递给 BaseItemExporter __init__ 方法,以及对 csv.writer() 函数,因此您可以使用任何 csv.writer() 自定义此导出器的函数参数。

该出口商的典型产出为:

product,price
Color TV,1200
DVD player,200

PickleItemExporter

class scrapy.exporters.PickleItemExporter(file, protocol=0, **kwargs)

将pickle格式的项导出到给定的类文件对象。

参数
  • file -- 用于导出数据的类似文件的对象。它的 write 方法应接受 bytes (以二进制模式打开的磁盘文件, io.BytesIO 物体等)

  • protocol (int) -- 要使用的pickle协议。

有关详细信息,请参阅 pickle .

此的其他关键字参数 __init__ 方法传递给 BaseItemExporter __init__ 方法。

pickle不是人类可读的格式,因此没有提供输出示例。

PprintItemExporter

class scrapy.exporters.PprintItemExporter(file, **kwargs)

以漂亮的打印格式将项导出到指定的文件对象。

参数

file -- 用于导出数据的类似文件的对象。它的 write 方法应接受 bytes (以二进制模式打开的磁盘文件, io.BytesIO 物体等)

此的其他关键字参数 __init__ 方法传递给 BaseItemExporter __init__ 方法。

该出口商的典型产出为:

{'name': 'Color TV', 'price': '1200'}
{'name': 'DVD player', 'price': '200'}

较长的行(如果存在)的格式很好。

JsonItemExporter

class scrapy.exporters.JsonItemExporter(file, **kwargs)

将JSON格式的项导出到指定的类文件对象,将所有对象作为对象列表写入。额外的 __init__ 方法参数传递给 BaseItemExporter __init__ 方法,以及对 JSONEncoder __init__ 方法,因此可以使用任何 JSONEncoder __init__ 方法参数自定义此导出器。

参数

file -- 用于导出数据的类似文件的对象。它的 write 方法应接受 bytes (以二进制模式打开的磁盘文件, io.BytesIO 物体等)

该出口商的典型产出为:

[{"name": "Color TV", "price": "1200"},
{"name": "DVD player", "price": "200"}]

警告

JSON是一种非常简单和灵活的序列化格式,但是由于是增量的(aka),它不能很好地扩展到大量的数据中。流模式)解析在JSON解析器(在任何语言上)中都不受很好的支持(如果有),而且大多数解析器只是解析内存中的整个对象。如果您希望JSON的强大性和简单性具有更流友好的格式,请考虑使用 JsonLinesItemExporter 或者将输出分成多个块。

JsonLinesItemExporter

class scrapy.exporters.JsonLinesItemExporter(file, **kwargs)

将JSON格式的项导出到指定的类似文件的对象,每行写入一个JSON编码的项。额外的 __init__ 方法参数传递给 BaseItemExporter __init__ 方法,以及对 JSONEncoder __init__ 方法,因此可以使用任何 JSONEncoder __init__ 方法参数自定义此导出器。

参数

file -- 用于导出数据的类似文件的对象。它的 write 方法应接受 bytes (以二进制模式打开的磁盘文件, io.BytesIO 物体等)

该出口商的典型产出为:

{"name": "Color TV", "price": "1200"}
{"name": "DVD player", "price": "200"}

不同于 JsonItemExporter ,此导出程序生成的格式非常适合序列化大量数据。

MarshalItemExporter