# 条目导出器
> 译者:[OSGeo 中国](https://www.osgeo.cn/)
一旦抓取了项目,您通常希望保留或导出这些项目,以便在其他应用程序中使用数据。这毕竟是抓取过程的全部目的。
为此,Scrapy为不同的输出格式(如XML、CSV或JSON)提供了一组项目导出器。
## 使用项目导出器
如果您很着急,只想使用项目导出器输出抓取的数据,请参见 [Feed 导出](feed-exports.html#topics-feed-exports) . 否则,如果您想知道项目导出器是如何工作的,或者需要更多的自定义功能(不包括在默认导出中),请继续阅读下面的内容。
为了使用项导出器,必须用它所需的参数实例化它。每个项目导出器需要不同的参数,因此请检查每个导出器文档以确保 [内置项导出器引用](#topics-exporters-reference) . 在实例化导出器之后,必须:
1。调用方法 [`start_exporting()`](#scrapy.exporters.BaseItemExporter.start_exporting "scrapy.exporters.BaseItemExporter.start_exporting") 以便发出出口过程开始的信号
2。调用给 [`export_item()`](#scrapy.exporters.BaseItemExporter.export_item "scrapy.exporters.BaseItemExporter.export_item") 要导出的每个项的方法
三。最后调用给 [`finish_exporting()`](#scrapy.exporters.BaseItemExporter.finish_exporting "scrapy.exporters.BaseItemExporter.finish_exporting") 发出输出过程结束的信号
在这里你可以看到 [Item Pipeline](item-pipeline.html) 它使用多个项目导出器,根据其中一个字段的值将抓取的项目分组到不同的文件中:
```py
from scrapy.exporters import XmlItemExporter
class PerYearXmlExportPipeline(object):
"""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 in self.year_to_exporter.values():
exporter.finish_exporting()
exporter.file.close()
def _exporter_for_item(self, item):
year = item['year']
if year not in self.year_to_exporter:
f = open('{}.xml'.format(year), 'wb')
exporter = XmlItemExporter(f)
exporter.start_exporting()
self.year_to_exporter[year] = exporter
return self.year_to_exporter[year]
def process_item(self, item, spider):
exporter = self._exporter_for_item(item)
exporter.export_item(item)
return item
```
## 项字段的序列化
默认情况下,字段值是未修改地传递给基础序列化库的,如何序列化字段值的决定被委托给每个特定的序列化库。
但是,您可以自定义每个字段值的序列化方式。 在传递到序列化库之前.
有两种方法可以自定义字段序列化的方式,下面将介绍这两种方法。
### 1。在字段中声明序列化程序
如果你使用 [`Item`](items.html#scrapy.item.Item "scrapy.item.Item") 可以在中声明序列化程序 [field metadata](items.html#topics-items-fields) . 序列化程序必须是可调用的,它接收值并返回其序列化形式。
例子::
```py
import scrapy
def serialize_price(value):
return '$ %s' % str(value)
class Product(scrapy.Item):
name = scrapy.Field()
price = scrapy.Field(serializer=serialize_price)
```
### 2。重写serialize_field()方法
您还可以覆盖 [`serialize_field()`](#scrapy.exporters.BaseItemExporter.serialize_field "scrapy.exporters.BaseItemExporter.serialize_field") 方法自定义字段值的导出方式。
确保调用基类 [`serialize_field()`](#scrapy.exporters.BaseItemExporter.serialize_field "scrapy.exporters.BaseItemExporter.serialize_field") 方法。
例子::
```py
from scrapy.exporter import XmlItemExporter
class ProductXmlExporter(XmlItemExporter):
def serialize_field(self, field, name, value):
if field == 'price':
return '$ %s' % str(value)
return super(Product, self).serialize_field(field, name, value)
```
## 内置项导出器引用
这是与废料捆绑在一起的物品出口商名单。其中一些包含输出示例,假设您正在导出这两个项:
```py
Item(name='Color TV', price='1200')
Item(name='DVD player', price='200')
```
### BaseItemExporter
```py
class scrapy.exporters.BaseItemExporter(fields_to_export=None, export_empty_fields=False, encoding='utf-8', indent=0)
```
这是所有项目导出器的(抽象)基类。它支持所有(具体)项目导出器使用的公共特性,例如定义要导出的字段、是否导出空字段或要使用的编码。
这些特性可以通过填充其各自实例属性的构造函数参数进行配置: [`fields_to_export`](#scrapy.exporters.BaseItemExporter.fields_to_export "scrapy.exporters.BaseItemExporter.fields_to_export") , [`export_empty_fields`](#scrapy.exporters.BaseItemExporter.export_empty_fields "scrapy.exporters.BaseItemExporter.export_empty_fields") , [`encoding`](#scrapy.exporters.BaseItemExporter.encoding "scrapy.exporters.BaseItemExporter.encoding") , [`indent`](#scrapy.exporters.BaseItemExporter.indent "scrapy.exporters.BaseItemExporter.indent") .
```py
export_item(item)
```
导出给定项。此方法必须在子类中实现。
```py
serialize_field(field, name, value)
```
返回给定字段的序列化值。如果要控制特定字段或值的序列化/导出方式,可以重写此方法(在自定义项导出器中)。
默认情况下,此方法查找序列化程序 [declared in the item field](#topics-exporters-serializers) 并返回将该序列化程序应用于该值的结果。如果找不到序列化程序,它将返回除 `unicode` 编码到的值 `str` 使用中声明的编码 [`encoding`](#scrapy.exporters.BaseItemExporter.encoding "scrapy.exporters.BaseItemExporter.encoding") 属性。
| 参数: |
* **field** ([`Field`](items.html#scrapy.item.Field "scrapy.item.Field") object or an empty dict) -- 正在序列化的字段。如果正在导出原始dict(不是 [`Item`](items.html#scrapy.item.Item "scrapy.item.Item") ) _field_ 值是空的dict。
* **name** (_str_) -- 正在序列化的字段的名称
* **value** -- 正在序列化的值
|
| --- | --- |
```py
start_exporting()
```
指示导出过程的开始。某些导出器可能会使用此命令生成某些必需的头(例如, [`XmlItemExporter`](#scrapy.exporters.XmlItemExporter "scrapy.exporters.XmlItemExporter") )在导出任何项之前必须调用此方法。
```py
finish_exporting()
```
发出输出过程结束的信号。一些导出器可能会使用此命令生成一些必需的页脚(例如, [`XmlItemExporter`](#scrapy.exporters.XmlItemExporter "scrapy.exporters.XmlItemExporter") )在没有其他要导出的项之后,必须始终调用此方法。
```py
fields_to_export
```
具有要导出的字段名称的列表,如果要导出所有字段,则为“无”。默认为无。
一些出口商(如 [`CsvItemExporter`](#scrapy.exporters.CsvItemExporter "scrapy.exporters.CsvItemExporter") )遵守此属性中定义的字段的顺序。
有些导出者可能需要字段“到”导出列表,以便在spider返回dict时正确导出数据(而不是 `Item` 实例)。
```py
export_empty_fields
```
是否在导出的数据中包含空/未填充的项字段。默认为 `False` . 一些出口商(如 [`CsvItemExporter`](#scrapy.exporters.CsvItemExporter "scrapy.exporters.CsvItemExporter") )忽略此属性并始终导出所有空字段。
对dict项忽略此选项。
```py
encoding
```
将用于编码Unicode值的编码。这只影响unicode值(这些值总是使用此编码序列化到str)。其他值类型不变地传递给特定的序列化库。
```py
indent
```
用于在每个级别上缩进输出的空间量。默认为 `0` .
* `indent=None` 选择最紧凑的表示形式,同一行中的所有项都没有缩进
* `indent<=0` 每个项目都在自己的行上,没有缩进
* `indent>0` 每一项都在自己的行上,用提供的数值缩进
### XmlItemExporter
```py
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`](#scrapy.exporters.BaseItemExporter "scrapy.exporters.BaseItemExporter") 建造师。
该出口商的典型产出为:
```py
<?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>` 元素。这是为了方便起见,因为多值字段非常常见。
例如,项目:
```py
Item(name=['John', 'Doe'], age='23')
```
将序列化为:
```py
<?xml version="1.0" encoding="utf-8"?>
<items>
<item>
<name>
<value>John</value>
<value>Doe</value>
</name>
<age>23</age>
</item>
</items>
```
### CsvItemExporter
```py
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`](#scrapy.exporters.BaseItemExporter.fields_to_export "scrapy.exporters.BaseItemExporter.fields_to_export") 或第一个导出项字段。
* **join_multivalued** -- 如果找到,将用于联接多值字段的字符。
|
| --- | --- |
此构造函数的其他关键字参数将传递给 [`BaseItemExporter`](#scrapy.exporters.BaseItemExporter "scrapy.exporters.BaseItemExporter") 构造函数,以及 [csv.writer](https://docs.python.org/2/library/csv.html#csv.writer) 构造函数,因此可以使用 `csv.writer` 自定义此导出程序的构造函数参数。
该出口商的典型产出为:
```py
product,price
Color TV,1200
DVD player,200
```
### PickleItemExporter
```py
class scrapy.exporters.PickleItemExporter(file, protocol=0, **kwargs)
```
将pickle格式的项导出到给定的文件(如对象)。
| 参数: |
* **file** -- 用于导出数据的类似文件的对象。它的 `write` 方法应接受 `bytes` (以二进制模式打开的磁盘文件, `io.BytesIO` 物体等)
* **protocol** (_int_) -- 要使用的pickle协议。
|
| --- | --- |
有关详细信息,请参阅 [pickle module documentation](https://docs.python.org/2/library/pickle.html) .
此构造函数的其他关键字参数将传递给 [`BaseItemExporter`](#scrapy.exporters.BaseItemExporter "scrapy.exporters.BaseItemExporter") 建造师。
pickle不是人类可读的格式,因此没有提供输出示例。
### PprintItemExporter
```py
class scrapy.exporters.PprintItemExporter(file, **kwargs)
```
以漂亮的打印格式将项目导出到指定的文件对象。
| 参数: | **file** -- 用于导出数据的类似文件的对象。它的 `write` 方法应接受 `bytes` (以二进制模式打开的磁盘文件, `io.BytesIO` 物体等) |
| --- | --- |
此构造函数的其他关键字参数将传递给 [`BaseItemExporter`](#scrapy.exporters.BaseItemExporter "scrapy.exporters.BaseItemExporter") 建造师。
该出口商的典型产出为:
```py
{'name': 'Color TV', 'price': '1200'}
{'name': 'DVD player', 'price': '200'}
```
较长的行(如果存在)的格式很好。
### JsonItemExporter
```py
class scrapy.exporters.JsonItemExporter(file, **kwargs)
```
以JSON格式将项目导出到指定的文件(如对象),将所有对象作为对象列表写入。附加的构造函数参数传递给 [`BaseItemExporter`](#scrapy.exporters.BaseItemExporter "scrapy.exporters.BaseItemExporter") 构造函数,以及 [JSONEncoder](https://docs.python.org/2/library/json.html#json.JSONEncoder) 构造函数,因此可以使用 [JSONEncoder](https://docs.python.org/2/library/json.html#json.JSONEncoder) 自定义此导出程序的构造函数参数。
| 参数: | **file** -- 用于导出数据的类似文件的对象。它的 `write` 方法应接受 `bytes` (以二进制模式打开的磁盘文件, `io.BytesIO` 物体等) |
| --- | --- |
该出口商的典型产出为:
```py
[{"name": "Color TV", "price": "1200"},
{"name": "DVD player", "price": "200"}]
```
警告
JSON是一种非常简单和灵活的序列化格式,但是由于是增量的(aka),它不能很好地扩展到大量的数据中。流模式)解析在JSON解析器(在任何语言上)中都不受很好的支持(如果有),而且大多数解析器只是解析内存中的整个对象。如果您希望JSON的强大性和简单性具有更流友好的格式,请考虑使用 [`JsonLinesItemExporter`](#scrapy.exporters.JsonLinesItemExporter "scrapy.exporters.JsonLinesItemExporter") 或者将输出分成多个块。
### JsonLinesItemExporter
```py
class scrapy.exporters.JsonLinesItemExporter(file, **kwargs)
```
以JSON格式将项目导出到指定的文件(如对象),每行写入一个JSON编码的项目。附加的构造函数参数传递给 [`BaseItemExporter`](#scrapy.exporters.BaseItemExporter "scrapy.exporters.BaseItemExporter") 构造函数,以及 [JSONEncoder](https://docs.python.org/2/library/json.html#json.JSONEncoder) 构造函数,因此可以使用 [JSONEncoder](https://docs.python.org/2/library/json.html#json.JSONEncoder) 自定义此导出程序的构造函数参数。
| 参数: | **file** -- 用于导出数据的类似文件的对象。它的 `write` 方法应接受 `bytes` (以二进制模式打开的磁盘文件, `io.BytesIO` 物体等) |
| --- | --- |
该出口商的典型产出为:
```py
{"name": "Color TV", "price": "1200"}
{"name": "DVD player", "price": "200"}
```
不同于 [`JsonItemExporter`](#scrapy.exporters.JsonItemExporter "scrapy.exporters.JsonItemExporter") ,此导出程序生成的格式非常适合序列化大量数据。
- 简介
- 第一步
- Scrapy at a glance
- 安装指南
- Scrapy 教程
- 实例
- 基本概念
- 命令行工具
- Spider
- 选择器
- 项目
- 项目加载器
- Scrapy shell
- 项目管道
- Feed 导出
- 请求和响应
- 链接提取器
- 设置
- 例外情况
- 内置服务
- Logging
- 统计数据集合
- 发送电子邮件
- 远程登录控制台
- Web服务
- 解决具体问题
- 常见问题
- 调试spiders
- Spider 合约
- 常用做法
- 通用爬虫
- 使用浏览器的开发人员工具进行抓取
- 调试内存泄漏
- 下载和处理文件和图像
- 部署 Spider
- AutoThrottle 扩展
- Benchmarking
- 作业:暂停和恢复爬行
- 延伸 Scrapy
- 体系结构概述
- 下载器中间件
- Spider 中间件
- 扩展
- 核心API
- 信号
- 条目导出器
- 其余所有
- 发行说明
- 为 Scrapy 贡献
- 版本控制和API稳定性