# 條目導出器
> 譯者:[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穩定性