在scrapy CSV Export Pipeline中关闭打开的csv文件

时间:2020-05-26 05:43:08

标签: python scrapy scrapy-pipeline

我正在尝试抓取100家公司的文章,并且我希望将多篇文章的内容保存到每个公司的单独的csv文件中。我已经构建了scraper和一个csv导出管道,并且工作正常,但是,蜘蛛程序为每个公司打开了一个新的csv文件(应该如此),而没有关闭为先前公司打开的文件。

csd文件在蜘蛛关闭后关闭,但是由于我要为每个公司抓取的数据量大,因此文件大小很大,并且会给我的计算机内存造成压力,并且如果我愿意的话,无法实际扩展为了增加公司的数量(我最终想做的事情),我最终会因为一次打开太多文件而遇到错误。以下是我的csv导出程序管道。我想找到一种方法来关闭当前公司的一个csv文件,然后再转到同一蜘蛛中的下一个公司:

我猜,从理论上讲,我可以打开每篇文章的文件,将内容写入新行,然后关闭它,然后为下一篇文章再次将其重新打开,但这会大大降低Spider的速度。我想在蜘蛛仍在浏览该公司的文章的同时保持该公司的文件打开状态,然后在蜘蛛移至下一个公司时关闭该文件。

我确定有解决方案,但我无法解决。非常感谢帮助解决此问题。

class PerTickerCsvExportPipeline:
    """Distribute items across multiple CSV files according to their 'ticker' field"""

    def open_spider(self, spider):
        self.ticker_to_exporter = {}

    def close_spider(self, spider):
        for exporter in self.ticker_to_exporter.values():
            exporter.finish_exporting()

    def _exporter_for_item(self, item):
        ticker = item['ticker']
        if ticker not in self.ticker_to_exporter:
            f = open('{}_article_content.csv'.format(ticker), 'wb')
            exporter = CsvItemExporter(f)
            exporter.start_exporting()
            self.ticker_to_exporter[ticker] = exporter
        return self.ticker_to_exporter[ticker]

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

1 个答案:

答案 0 :(得分:0)

问题可能是您打开了所有ItemExporter和文件,直到蜘蛛网关闭为止。我建议您在打开新公司之前,应尝试关闭上一家公司的CsvItemExporter和相应文件。

def open_spider(self, spider):
    self.ticker_to_exporter = {}
    self.files = []

def close_exporters(self):
    for ticker, exporter in self.ticker_to_exporter.items():
        exporter.finish_exporting()
        del self.ticker_to_exporter[ticker]

def close_files(self):
    for i, f in enumerate(self.files):
        f.close()
        del self.files[i]

def close_spider(self, spider):
    self.close_exporters()
    self.close_files()

def _exporter_for_item(self, item):
    ticker = item['ticker']
    if ticker not in self.ticker_to_exporter:
        self.close_exporters()
        self.close_files()
        f = open('{}_article_content.csv'.format(ticker), 'a')
        self.files.append(f)
        exporter = CsvItemExporter(f)
        exporter.start_exporting()
        self.ticker_to_exporter[ticker] = exporter
    return self.ticker_to_exporter[ticker]
相关问题