Экспортёры элементов

После того, как вы получили свои элементы, вы часто хотите сохранить или экспортировать данные элементы, чтобы использовать данные в каком-либо другом приложении. В этом, в конце концов, и вся цель процесса сканирования.

Для этой цели Scrapy предоставляет множество модулей экспорта элементов для различных форматов вывода, таких как XML, CSV или JSON.

Использование экспортёров элементов

Если вы торопитесь и просто хотите использовать экспортёр элементов для вывода очищенных данных, см. Экспорт фидов. В противном случае, если вы хотите узнать, как работают экспортёры элементов, или вам нужны дополнительные настраиваемые функции (не охватываемые экспортом по умолчанию), продолжайте читать ниже.

Чтобы использовать Item Exporter, вы должны создать его экземпляр с его обязательными аргументами. Для каждого экспортёра элементов требуются разные аргументы, поэтому обязательно проверить документацию каждого экспортёра в Справочник по встроенным экспортёрам элементов. После того, как вы создали экземпляр своего экспортёра, вам необходимо сделать:

1. call the method start_exporting() in order to signal the beginning of the exporting process

2. call the export_item() method for each item you want to export

3. and finally call the finish_exporting() to signal the end of the exporting process

Здесь вы можете увидеть Конвейер элементов, который использует несколько экспортеров элементов для группировки извлечённых элементов в разные файлы в соответствии со значением одного из их полей:

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.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_export, export_empty_fields, encoding, indent.

Добавлено в версии 2.0: Параметр dont_fail.

export_item(item)

Экспортирует данный элемент. Данный метод должен быть реализован в подклассах.

serialize_field(field, name, value)

Возвращает сериализованное значение для данного поля. Вы можете переопределить данный метод (в своих пользовательских модулях экспорта элементов), если хотите контролировать, как конкретное поле или значение будут сериализованы/экспортированы.

По умолчанию данный метод ищет сериализатор объявленный в поле элемента и возвращает результат применения этого сериализатора к значению. Если сериализатор не найден, он возвращает значение без изменений.

Параметры
  • field (Field object or a dict instance) – сериализуемое поле. Если источник объект элемента не определяет метаданные поля, поле является пустым dict.

  • name (str) – имя сериализуемого поля

  • value – сериализуемое значение

start_exporting()

Подать сигнал о начале процесса экспорта. Некоторые экспортёры могут использовать это для создания необходимого заголовка (например, XmlItemExporter). Вы должны вызвать данный метод перед экспортом каких-либо элементов.

finish_exporting()

Просигнализировать об окончании процесса экспорта. Некоторые экспортёры могут использовать это для создания необходимого нижнего колонтитула (например, XmlItemExporter). Вы должны всегда вызывать данный метод после того, как у вас больше нет элементов для экспорта.

fields_to_export

Список с именами полей, которые будут экспортированы, или None, если вы хотите экспортировать все поля. По умолчанию None.

Некоторые экспортёры (например, CsvItemExporter) соблюдают порядок полей, определенных в этом атрибуте.

При использовании объектов элементов, которые не раскрывают все возможные поля, экспортёры, которые не поддерживают экспорт другого подмножества полей для каждого элемента, будут экспортировать только поля, найденные в первом экспортированном элементе. Используйте 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.

Дополнительные ключевые аргументы данного метода __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)

Экспортирует элементы в формате пикл в заданный файловый объект.

Параметры
  • file – файловый объект, используемый для экспорта данных. Его метод write должен принимать bytes (файл на диске, открытый в двоичном режиме, объект io.BytesIO и т. д.)

  • protocol (int) – Используемый протокол пикл.

Для получения дополнительной информации см. 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 — очень простой и гибкий формат сериализации, но он плохо масштабируется для больших объемов данных, поскольку инкрементный (также известный как потоковый режим) парсинг не поддерживается (если вообще) среди парсеров 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