Как я могу использовать атрибут fields_to_export в BaseItemExporter для заказа моих данных CSV Scrapy?

Я сделал простой Scrapy spider, который я использую из командной строки для экспорта моих данных в формат CSV, но порядок данных кажется случайным. Как я могу упорядочить поля CSV в моем выпуске?

Я использую следующую командную строку для получения CSV-данных:

scrapy crawl somwehere -o items.csv -t csv

Согласно this Документация по Scrapy, я должен использовать атрибут fields_to_export для BaseItemExporter для управления порядком. Но я не знаю, как использовать это, поскольку я не нашел простого примера для подражания.

Обратите внимание: Этот вопрос очень похож на ЭТО. Тем не менее, этот вопрос старше 2 лет и не затрагивает многие последние изменения в Scrapy и не дает удовлетворительного ответа, поскольку он требует взломать один или оба из:

для решения некоторых предыдущих проблем, которые, похоже, уже решены...

Большое спасибо заранее.

Ответ 1

Чтобы использовать такой экспортер, вам нужно создать свой собственный конвейер товаров, который будет обрабатывать ваш вывод паук. Предполагая, что у вас простой случай, и вы хотите, чтобы весь паук выводился в одном файле, это конвейер, который вы должны использовать (pipelines.py):

from scrapy import signals
from scrapy.contrib.exporter import CsvItemExporter

class CSVPipeline(object):

  def __init__(self):
    self.files = {}

  @classmethod
  def from_crawler(cls, crawler):
    pipeline = cls()
    crawler.signals.connect(pipeline.spider_opened, signals.spider_opened)
    crawler.signals.connect(pipeline.spider_closed, signals.spider_closed)
    return pipeline

  def spider_opened(self, spider):
    file = open('%s_items.csv' % spider.name, 'w+b')
    self.files[spider] = file
    self.exporter = CsvItemExporter(file)
    self.exporter.fields_to_export = [list with Names of fields to export - order is important]
    self.exporter.start_exporting()

  def spider_closed(self, spider):
    self.exporter.finish_exporting()
    file = self.files.pop(spider)
    file.close()

  def process_item(self, item, spider):
    self.exporter.export_item(item)
    return item

Конечно, вам нужно запомнить этот конвейер в файле конфигурации (settings.py):

ITEM_PIPELINES = {'myproject.pipelines.CSVPipeline': 300 }

Ответ 2

Теперь вы можете указать настройки в самом паук. https://doc.scrapy.org/en/latest/topics/settings.html#settings-per-spider

Чтобы задать порядок полей для экспортированных фидов, установите FEED_EXPORT_FIELDS. https://doc.scrapy.org/en/latest/topics/feed-exports.html#feed-export-fields

Паук ниже сбрасывает все ссылки на веб-сайте (написанный против Scrapy 1.4.0):

import scrapy
from scrapy.http import HtmlResponse

class DumplinksSpider(scrapy.Spider):
  name = 'dumplinks'
  allowed_domains = ['www.example.com']
  start_urls = ['http://www.example.com/']
  custom_settings = {
    # specifies exported fields and order
    'FEED_EXPORT_FIELDS': ["page", "page_ix", "text", "url"],
  }

  def parse(self, response):
    if not isinstance(response, HtmlResponse):
      return

    a_selectors = response.xpath('//a')
    for i, a_selector in enumerate(a_selectors):
      text = a_selector.xpath('normalize-space(text())').extract_first()
      url = a_selector.xpath('@href').extract_first()
      yield {
        'page_ix': i + 1,
        'page': response.url,
        'text': text,
        'url': url,
      }
      yield response.follow(url, callback=self.parse)  # see allowed_domains

Запустить с помощью этой команды:

scrapy crawl dumplinks --loglevel=INFO -o links.csv

Поля в links.csv упорядочены, как указано FEED_EXPORT_FIELDS.