如何使用BaseItemExporter中的fields_to_export属性来订购我的Scrapy CSV数据?

 痞子343 发布于 2023-02-08 13:28

我创建了一个简单的Scrapy蜘蛛,我从命令行使用它将数据导出为CSV格式,但数据的顺序似乎是随机的.如何在输出中订购CSV字段?

我使用以下命令行来获取CSV数据:

scrapy crawl somwehere -o items.csv -t csv

根据这个 Scrapy文档,我应该能够使用类的fields_to_export属性BaseItemExporter来控制顺序.但我对如何使用它毫无头绪,因为我没有找到任何简单的例子.

请注意:这个问题很相似,这一个.然而,这个问题已经超过2年,并没有解决最近 Scrapy 的许多变化,也没有提供令人满意的答案,因为它需要黑客攻击其中一个或两个:

contrib/exporter/init .py

的contrib/feedexport.py

解决以前的一些问题,似乎已经解决了......

提前谢谢了.

2 个回答
  • 您现在可以在蜘蛛本身中指定设置. https://doc.scrapy.org/en/latest/topics/settings.html#settings-per-spider

    要设置导出的Feed的字段顺序,请设置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.

    2023-02-08 13:30 回答
  • 要使用这样的导出器,您需要创建自己的Item管道来处理您的蜘蛛输出.假设你有简单的情况,并且你希望将所有的蜘蛛输出都放在一个文件中,这就是你应该使用的管道(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 }
    

    2023-02-08 13:30 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有