Как создать пользовательский экспортер Scrapy Item?
Я пытаюсь создать пользовательский экспортер Scrapy Item на основе jsonlinesitemexporter, чтобы я мог немного изменить структуру, которую он производит.
Я прочитал документацию здесь http://doc.scrapy.org/en/latest/topics/exporters.html но в нем не указано, как создать пользовательского экспортера, где его хранить или как связать его с конвейером.
Я определил, как идти на заказ с экспортерами корма, но это не будет соответствовать моим требованиям, как я хочу назвать этого экспортера из моего конвейера.
вот код, который я придумал, который был сохранен в файле в корне проекта под названием exporters.py
from scrapy.contrib.exporter import JsonLinesItemExporter
class FanItemExporter(JsonLinesItemExporter):
def __init__(self, file, **kwargs):
self._configure(kwargs, dont_fail=True)
self.file = file
self.encoder = ScrapyJSONEncoder(**kwargs)
self.first_item = True
def start_exporting(self):
self.file.write("""{
'product': [""")
def finish_exporting(self):
self.file.write("]}")
def export_item(self, item):
if self.first_item:
self.first_item = False
else:
self.file.write(',n')
itemdict = dict(self._get_serialized_fields(item))
self.file.write(self.encoder.encode(itemdict))
Я просто попытался вызвать это из моего конвейера с помощью FanItemExporter и попробовать варианты импорта, но это ни к чему не приводит.
1 ответов
это правда, что в документации Scrapy четко не указано, где разместить экспортера номенклатуры. Чтобы использовать экспортер номенклатуры, выполните следующие действия.
- выберите класс экспортера товара и импортируйте его в
pipeline.py
в каталоге проекта. Это может быть заранее определенный экспортер товара (ex.XmlItemExporter
) или определенные пользователем (например,FanItemExporter
определено в вопросе) - создайте класс конвейера элементов в
pipeline.py
. Экземпляр импортного экспортером товара в этой класс. Подробности будут объяснены в более поздней части ответа. - теперь зарегистрируйте этот класс конвейера в .
Ниже приводится подробное объяснение каждого шага. Решение вопроса включено в каждый этап.
Шаг 1
если используется предварительно определенный класс экспортера номенклатур, импортируйте его из
scrapy.exporters
модуль.
Бывший:from scrapy.exporters import XmlItemExporter
-
Если вам нужен изготовленный на заказ экспортер, определите пользовательский класс в файле. Я предлагаю разместить класс в . Поместите этот файл в папку проекта (где
settings.py
,items.py
проживают).при создании нового подкласса всегда полезно импортировать
BaseItemExporter
. Было бы уместно, если бы мы намеревались полностью изменить функциональность. Однако в этом вопросе большая часть функциональности близка кJsonLinesItemExporter
.
следовательно, я прикрепляю две версии одного и того же ItemExporter. Один выдвигается версия BaseItemExporter
класс и другой расширяется JsonLinesItemExporter
класс
Вариант 1 расширение BaseItemExporter
С BaseItemExporter
является родительским классом,start_exporting()
, finish_exporting()
, export_item()
должно быть переопределено в соответствии с нашими потребностями.
from scrapy.exporters import BaseItemExporter
from scrapy.utils.serialize import ScrapyJSONEncoder
from scrapy.utils.python import to_bytes
class FanItemExporter(BaseItemExporter):
def __init__(self, file, **kwargs):
self._configure(kwargs, dont_fail=True)
self.file = file
self.encoder = ScrapyJSONEncoder(**kwargs)
self.first_item = True
def start_exporting(self):
self.file.write(b'{\'product\': [')
def finish_exporting(self):
self.file.write(b'\n]}')
def export_item(self, item):
if self.first_item:
self.first_item = False
else:
self.file.write(b',\n')
itemdict = dict(self._get_serialized_fields(item))
self.file.write(to_bytes(self.encoder.encode(itemdict)))
Вариант 2 расширение JsonLinesItemExporter
JsonLinesItemExporter
обеспечивает точно такую же реализацию export_item()
метод. Поэтому только start_exporting()
и finish_exporting()
методы отмененный.
реализация JsonLinesItemExporter
можно увидеть в папке python_dir\pkgs\scrapy-1.1.0-py35_0\Lib\site-packages\scrapy\exporters.py
from scrapy.exporters import JsonItemExporter
class FanItemExporter(JsonItemExporter):
def __init__(self, file, **kwargs):
# To initialize the object we use JsonItemExporter's constructor
super().__init__(file)
def start_exporting(self):
self.file.write(b'{\'product\': [')
def finish_exporting(self):
self.file.write(b'\n]}')
Примечание: при записи данных в файл важно отметить, что стандартные классы экспортеров номенклатур ожидают двоичные файлы. Следовательно, мы должны открыть файл в двоичном режиме (b
). По той же причине, write()
метод в обеих версиях write bytes
в файл.
Шаг 2
создание конвейера элементов класс.
from project_name.exporters import FanItemExporter
class FanExportPipeline(object):
def __init__(self, file_name):
# Storing output filename
self.file_name = file_name
# Creating a file handle and setting it to None
self.file_handle = None
@classmethod
def from_crawler(cls, crawler):
# getting the value of FILE_NAME field from settings.py
output_file_name = crawler.settings.get('FILE_NAME')
# cls() calls FanExportPipeline's constructor
# Returning a FanExportPipeline object
return cls(output_file_name)
def open_spider(self, spider):
print('Custom export opened')
# Opening file in binary-write mode
file = open(self.file_name, 'wb')
self.file_handle = file
# Creating a FanItemExporter object and initiating export
self.exporter = FanItemExporter(file)
self.exporter.start_exporting()
def close_spider(self, spider):
print('Custom Exporter closed')
# Ending the export to file from FanItemExport object
self.exporter.finish_exporting()
# Closing the opened output file
self.file_handle.close()
def process_item(self, item, spider):
# passing the item to FanItemExporter object for expoting to file
self.exporter.export_item(item)
return item
Шаг 3
теперь, когда мы определили конвейер экспорта товара, мы должны зарегистрировать конвейер в . Мы также используем поле FILE_NAME
С . В этом поле содержится имя выходного файла.
добавьте следующие строки в .
FILE_NAME = 'path/outputfile.ext'
ITEM_PIPELINES = {
'project_name.pipelines.FanExportPipeline' : 600,
}
если ITEM_PIPELINES
уже раскомментирован, затем добавьте следующую строку в ITEM_PIPELINES
словарь.
'project_name.pipelines.FanExportPipeline' : 600,
этот путь, мы можем создать изготовленные на заказ трубопроводы экспорта деталя и использовать их в нашем проекте.