译者:OSGeo 中国

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

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

使用项目导出器

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

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

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

2。调用给 export_item() 要导出的每个项的方法

三。最后调用给 finish_exporting() 发出输出过程结束的信号

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

  1. from scrapy.exporters import XmlItemExporter
  2. class PerYearXmlExportPipeline(object):
  3. """Distribute items across multiple XML files according to their 'year' field"""
  4. def open_spider(self, spider):
  5. self.year_to_exporter = {}
  6. def close_spider(self, spider):
  7. for exporter in self.year_to_exporter.values():
  8. exporter.finish_exporting()
  9. exporter.file.close()
  10. def _exporter_for_item(self, item):
  11. year = item['year']
  12. if year not in self.year_to_exporter:
  13. f = open('{}.xml'.format(year), 'wb')
  14. exporter = XmlItemExporter(f)
  15. exporter.start_exporting()
  16. self.year_to_exporter[year] = exporter
  17. return self.year_to_exporter[year]
  18. def process_item(self, item, spider):
  19. exporter = self._exporter_for_item(item)
  20. exporter.export_item(item)
  21. return item

项字段的序列化

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

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

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

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

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

例子::

  1. import scrapy
  2. def serialize_price(value):
  3. return '$ %s' % str(value)
  4. class Product(scrapy.Item):
  5. name = scrapy.Field()
  6. price = scrapy.Field(serializer=serialize_price)

2。重写serialize_field()方法

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

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

例子::

  1. from scrapy.exporter import XmlItemExporter
  2. class ProductXmlExporter(XmlItemExporter):
  3. def serialize_field(self, field, name, value):
  4. if field == 'price':
  5. return '$ %s' % str(value)
  6. return super(Product, self).serialize_field(field, name, value)

内置项导出器引用

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

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

BaseItemExporter

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

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

这些特性可以通过填充其各自实例属性的构造函数参数进行配置: fields_to_exportexport_empty_fieldsencodingindent .

  1. export_item(item)

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

  1. serialize_field(field, name, value)

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

默认情况下,此方法查找序列化程序 declared in the item field 并返回将该序列化程序应用于该值的结果。如果找不到序列化程序,它将返回除 unicode 编码到的值 str 使用中声明的编码 encoding 属性。

| 参数: |

  • field (Field object or an empty dict) — 正在序列化的字段。如果正在导出原始dict(不是 Itemfield 值是空的dict。
  • name (str) — 正在序列化的字段的名称
  • value — 正在序列化的值 | | | —- |
  1. start_exporting()

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

  1. finish_exporting()

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

  1. fields_to_export

具有要导出的字段名称的列表,如果要导出所有字段,则为“无”。默认为无。

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

有些导出者可能需要字段“到”导出列表,以便在spider返回dict时正确导出数据(而不是 Item 实例)。

  1. export_empty_fields

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

对dict项忽略此选项。

  1. encoding

将用于编码Unicode值的编码。这只影响unicode值(这些值总是使用此编码序列化到str)。其他值类型不变地传递给特定的序列化库。

  1. indent

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

  • indent=None 选择最紧凑的表示形式,同一行中的所有项都没有缩进
  • indent<=0 每个项目都在自己的行上,没有缩进
  • indent>0 每一项都在自己的行上,用提供的数值缩进

XmlItemExporter

  1. 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元素的名称。 | | | —- |

此构造函数的其他关键字参数将传递给 BaseItemExporter 建造师。

该出口商的典型产出为:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <items>
  3. <item>
  4. <name>Color TV</name>
  5. <price>1200</price>
  6. </item>
  7. <item>
  8. <name>DVD player</name>
  9. <price>200</price>
  10. </item>
  11. </items>

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

例如,项目:

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

将序列化为:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <items>
  3. <item>
  4. <name>
  5. <value>John</value>
  6. <value>Doe</value>
  7. </name>
  8. <age>23</age>
  9. </item>
  10. </items>

CsvItemExporter

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

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

| 参数: |

  • file — 用于导出数据的类似文件的对象。它的 write 方法应接受 bytes (以二进制模式打开的磁盘文件, io.BytesIO 物体等)
  • include_headers_line (str) — 如果启用,则使导出器输出一个标题行,其中字段名取自 BaseItemExporter.fields_to_export 或第一个导出项字段。
  • join_multivalued — 如果找到,将用于联接多值字段的字符。 | | | —- |

此构造函数的其他关键字参数将传递给 BaseItemExporter 构造函数,以及 csv.writer 构造函数,因此可以使用 csv.writer 自定义此导出程序的构造函数参数。

该出口商的典型产出为:

  1. product,price
  2. Color TV,1200
  3. DVD player,200

PickleItemExporter

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

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

| 参数: |

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

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

此构造函数的其他关键字参数将传递给 BaseItemExporter 建造师。

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

PprintItemExporter

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

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

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

此构造函数的其他关键字参数将传递给 BaseItemExporter 建造师。

该出口商的典型产出为:

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

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

JsonItemExporter

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

以JSON格式将项目导出到指定的文件(如对象),将所有对象作为对象列表写入。附加的构造函数参数传递给 BaseItemExporter 构造函数,以及 JSONEncoder 构造函数,因此可以使用 JSONEncoder 自定义此导出程序的构造函数参数。

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

该出口商的典型产出为:

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

警告

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

JsonLinesItemExporter

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

以JSON格式将项目导出到指定的文件(如对象),每行写入一个JSON编码的项目。附加的构造函数参数传递给 BaseItemExporter 构造函数,以及 JSONEncoder 构造函数,因此可以使用 JSONEncoder 自定义此导出程序的构造函数参数。

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

该出口商的典型产出为:

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

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