项目导出器¶
一旦你抓取了你的项目,你通常希望持久化或导出这些项目,以便在其他应用程序中使用这些数据。毕竟,这是整个抓取过程的全部目的。
为此,Scrapy 提供了一系列用于不同输出格式的 Item Exporters,例如 XML、CSV 或 JSON。
使用项目导出器¶
如果您很着急,只想使用项目导出器输出抓取的数据,请参阅Feed exports。否则,如果您想了解项目导出器的工作原理或需要更多自定义功能(默认导出未涵盖的),请继续阅读下文。
为了使用项目导出器,您必须使用其必需的参数实例化它。每个项目导出器需要不同的参数,因此请检查每个导出器的文档以确保,在内置项目导出器参考中。在实例化导出器之后,您必须:
1. 调用方法 start_exporting() 以
发出导出过程开始的信号
2. 调用 export_item() 方法来导出每个你想要的项目
3. 最后调用 finish_exporting() 来发出导出过程结束的信号
在这里,你可以看到一个Item Pipeline,它使用多个 Item Exporters 根据其中一个字段的值将抓取的项目分组到不同的文件中:
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,你可以在字段元数据中声明一个序列化器。序列化器必须是一个可调用的对象,它接收一个值并返回其序列化形式。
示例:
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.exporters 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_export,export_empty_fields,encoding,indent。版本2.0新增:dont_fail 参数。
- serialize_field(field, name, value)[源代码]¶
返回给定字段的序列化值。如果您想控制特定字段或值的序列化/导出方式,可以覆盖此方法(在您的自定义项目导出器中)。
默认情况下,此方法会查找在项目字段中声明的序列化器,并返回将该序列化器应用于值的结果。如果未找到序列化器,则返回未更改的值。
- Parameters:
field (
Field对象或dict实例) – 正在序列化的字段。如果源 item object 没有定义字段元数据,field 是一个空的dict。name (str) – 正在序列化的字段的名称
value – 正在被序列化的值
- start_exporting()[source]¶
标志着导出过程的开始。一些导出器可能会使用此方法来生成一些必要的头部信息(例如,
XmlItemExporter)。在导出任何项目之前,您必须调用此方法。
- finish_exporting()[source]¶
表示导出过程结束。一些导出器可能会使用这个方法来生成一些必需的页脚(例如,
XmlItemExporter)。在你没有更多项目要导出后,你必须始终调用这个方法。
- fields_to_export¶
要导出的字段,它们的顺序[1]以及它们的输出名称。
可能的值为:
None(所有字段 [2],默认)字段列表:
['field1', 'field2']
一个字典,其中键是字段,值是输出名称:
{'field1': 'Field 1', 'field2': 'Field 2'}
- export_empty_fields¶
是否在导出的数据中包含空/未填充的项字段。 默认为
False。一些导出器(如CsvItemExporter) 忽略此属性并始终导出所有空字段。此选项对字典项无效。
- encoding¶
输出字符编码。
- indent¶
用于在每个级别上缩进输出的空格数。默认为
0。indent=None选择最紧凑的表示方式, 所有项目在同一行,没有缩进indent<=0每个项目在自己的行上,没有缩进indent>0每个项目在自己的行上,使用提供的数值进行缩进
PythonItemExporter¶
XmlItemExporter¶
- class scrapy.exporters.XmlItemExporter(file, item_element='item', root_element='items', **kwargs)[source]¶
将项目以XML格式导出到指定的文件对象。
- Parameters:
此
__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()方法中被覆盖,多值字段通过将每个值序列化在元素内来导出。这是为了方便,因为多值字段非常常见。例如,项目:
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属性对此导出器没有影响。- Parameters:
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)[source]¶
将项目以pickle格式导出到给定的类文件对象。
- Parameters:
file – 用于导出数据的类文件对象。它的
write方法应接受bytes(以二进制模式打开的磁盘文件、io.BytesIO对象等)protocol (int) – 使用的pickle协议。
欲了解更多信息,请参阅
pickle。此
__init__方法的额外关键字参数传递给BaseItemExporter的__init__方法。Pickle 不是人类可读的格式,因此没有提供输出示例。
PprintItemExporter¶
- class scrapy.exporters.PprintItemExporter(file, **kwargs)[source]¶
以漂亮的打印格式将项目导出到指定的文件对象。
- Parameters:
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__方法参数来自定义此导出器。- Parameters:
file – 用于导出数据的类文件对象。它的
write方法应接受bytes(以二进制模式打开的磁盘文件、io.BytesIO对象等)
这个导出器的典型输出将是:
[{"name": "Color TV", "price": "1200"}, {"name": "DVD player", "price": "200"}]警告
JSON 是一种非常简单且灵活的序列化格式,但由于增量(即流模式)解析在 JSON 解析器(任何语言中)中支持不佳(如果有的话),大多数解析器只是将整个对象解析到内存中,因此它不适用于大量数据。如果您想要 JSON 的强大功能和简单性,同时希望使用更友好的流格式,请考虑使用
JsonLinesItemExporter,或者将输出拆分为多个块。
JsonLinesItemExporter¶
- class scrapy.exporters.JsonLinesItemExporter(file, **kwargs)[source]¶
将JSON格式的项目导出到指定的类文件对象中,每行写入一个JSON编码的项目。额外的
__init__方法参数传递给BaseItemExporter的__init__方法,剩余的参数传递给JSONEncoder的__init__方法,因此您可以使用任何JSONEncoder的__init__方法参数来自定义此导出器。- Parameters:
file – 用于导出数据的类文件对象。它的
write方法应接受bytes(以二进制模式打开的磁盘文件、io.BytesIO对象等)
这个导出器的典型输出将是:
{"name": "Color TV", "price": "1200"} {"name": "DVD player", "price": "200"}与
JsonItemExporter生成的格式不同,此导出器生成的格式非常适合序列化大量数据。