python - 在scrapy CSV导出管道中关闭打开的csv文件
问题描述
我正在尝试抓取 100 家公司的文章,并且我想将多篇文章中的内容保存到每个公司的单独 csv 文件中。我已经构建了刮刀和一个 csv 导出管道,它工作正常,但是,蜘蛛为每个公司(应该)打开一个新的 csv 文件,而不关闭为前一个公司打开的文件。
csv 文件在蜘蛛关闭后关闭,但由于我为每个公司抓取的数据量很大,文件大小很大,会对我的机器内存造成压力,并且无法实际扩展,因为如果我想增加公司数量(我最终想做的事情),我最终会因为一次打开太多文件而遇到错误。下面是我的 csv 导出器管道。我想找到一种方法来关闭当前公司的一个 csv 文件,然后再转到同一蜘蛛中的下一家公司:
我想,理论上,我可以为每篇文章打开文件,将内容写入新行,然后关闭它并为下一篇文章重新打开它,但这会显着减慢蜘蛛的速度。我想在蜘蛛仍在浏览该公司的文章时为给定公司保持文件打开状态,然后在蜘蛛移动到下一家公司时将其关闭。
我确定有一个解决方案,但我一直无法弄清楚。非常感谢帮助解决这个问题。
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
解决方案
The problem probably is that you keep all the ItemExporter
s and files open until the spider closes. I suggest that you should try to close the CsvItemExporter
and corresponding file for the previous company before you open a new one.
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]
推荐阅读
- json - 无法在 Kotlin 中发布原始 JSON 数据
- typescript - TypeScript Knockout 定义对可观察数组的重大更改?
- python - 如何在不更改前一个条件的结果的情况下对行应用多个条件?
- python-3.x - 在 databricks 中,在不同的笔记本中使用 unittest.mock.patch 函数
- select - 使用 random() 或 tablesample system() 在 impala 中随机采样 n 行
- r - 如何使用累积函数计算 2 个相互交织的变量
- codenameone - ButtonGroup 实例的引用检索
- python - 在 Google Cloud Engine 中将代理与 Chromedriver 一起使用
- apache - 将 www.example.com/some-path/example/ 重定向到 www.example.com/some-path/?ABC=123
- python - 在 yahoo Finance python 上的某些股票和页面出现 404 错误