我正在抓取一个足球网站,蜘蛛(单个蜘蛛)从网站页面获取多种项目:球队、比赛、俱乐部等。 我正在尝试使用 CSVItemExporter 将这些项目存储在单独的 csv 文件中, team.csv、matches.csv、clubs.csv 等
我不确定什么是正确的方法。 到目前为止我想到的唯一方法是创建我自己的自定义管道,如示例中所示 http://doc.scrapy.org/en/0.14/topics/exporters.html并在spider_opened方法中打开所有需要的csv文件,即为每个csv文件创建一个csv导出器,并在process_item中将代码放入图中找出“item”参数是什么类型的item,然后将其发送到相应的exporter对象。
无论如何,我还没有找到任何在 scrapy 中处理多个 csv 文件(每个项目类型)的示例,所以我担心我正在以不应该使用的方式使用它。 (这是我第一次使用 Scrapy)。
狄奥墨得斯
我在这里发布了我用来根据上面 drcolossos 的答案生成
MultiCSVItemPipeline
的代码。
此管道假设所有 Item 类都遵循约定 *Item(例如 TeamItem、EventItem)并创建 team.csv、event.csv 文件并将所有记录发送到相应的 csv 文件。
from scrapy.exporters import CsvItemExporter
from scrapy import signals
from scrapy.xlib.pydispatch import dispatcher
def item_type(item):
return type(item).__name__.replace('Item','').lower() # TeamItem => team
class MultiCSVItemPipeline(object):
SaveTypes = ['team','club','event', 'match']
def __init__(self):
dispatcher.connect(self.spider_opened, signal=signals.spider_opened)
dispatcher.connect(self.spider_closed, signal=signals.spider_closed)
def spider_opened(self, spider):
self.files = dict([ (name, open(CSVDir+name+'.csv','w+b')) for name in self.SaveTypes ])
self.exporters = dict([ (name,CsvItemExporter(self.files[name])) for name in self.SaveTypes])
[e.start_exporting() for e in self.exporters.values()]
def spider_closed(self, spider):
[e.finish_exporting() for e in self.exporters.values()]
[f.close() for f in self.files.values()]
def process_item(self, item, spider):
what = item_type(item)
if what in set(self.SaveTypes):
self.exporters[what].export_item(item)
return item
你的方法对我来说似乎很好。 Piplines 是 Scrapy 的一个很棒的功能,并且在我看来是为像你的方法这样的东西而构建的。
您可以创建多个项目(例如 SoccerItem、MatchItem),并且在您的
MultiCSVItemPipeline
中只需通过检查项目类将每个项目委托给其自己的 CSV 类。
我已经尝试过答案。似乎在最新版本(2.21)中不起作用。
我已包含我的代码供您参考:
class MultiCSVItemPipeline(object):
SaveTypes = ['CentalineTransactionsItem','CentalineTransactionsDetailItem','CentalineBuildingInfo']
def open_spider(self, spider):
self.files = dict([ (name, open(name+'.csv','w+b')) for name in self.SaveTypes ])
self.exporters = dict([ (name,CsvItemExporter(self.files[name])) for name in self.SaveTypes])
[e.start_exporting() for e in self.exporters.values()]
def close_spider(self, spider):
[e.finish_exporting() for e in self.exporters.values()]
[f.close() for f in self.files.values()]
def process_item(self, item, spider):
what = type(item).__name__
if what in set(self.SaveTypes):
self.exporters[what].export_item(item)
return item
我正在使用 Scrapy =“^2.5.0”,并且必须进行一些修改才能正常工作。我还为项目文件中的所有项目设置了动态
SaveTypes
(现在为 defined_items
)。
from scrapy.exporters import CsvItemExporter
from YOUR_PROJECT import items
def item_type(item):
return type(item).__name__
class MultiCSVItemPipeline(object):
defined_items = [name for name, _ in items.__dict__.items() if "Item" in name]
def open_spider(self, spider):
self.files = dict(
[
(name, open("FOLDER_TO_SAVE/" + name + ".csv", "w+b"))
for name in self.defined_items
]
)
self.exporters = dict(
[(name, CsvItemExporter(self.files[name])) for name in self.defined_items]
)
[e.start_exporting() for e in self.exporters.values()]
def close_spider(self, spider):
[e.finish_exporting() for e in self.exporters.values()]
[f.close() for f in self.files.values()]
def process_item(self, item, spider):
item_name = item_type(item)
if item_name in set(self.defined_items):
self.exporters[item_name].export_item(item)
return item
这是我用来利用 scrapy 的 Item Pipline 和 Exporters 为每个抓取的 Item 类类型输出单独的 csv 的代码。逻辑与这个例子非常相似。
from scrapy.exporters import CsvItemExporter
class cvs_per_itemtype_Pipeline:
def open_spider(self, spider):
self.itemType_to_exporterAndCsvFile = {}
def process_item(self, item, spider):
itemType = type(item).__name__ #item class name as str
if itemType not in self.itemType_to_exporterAndCsvFile:
csvFile = open(f'{itemType}.csv', 'wb')
exporter = CsvItemExporter(csvFile)
exporter.start_exporting()
self.itemType_to_exporterAndCsvFile[itemType] = (exporter, csvFile)
exporter = self.itemType_to_exporterAndCsvFile[itemType][0]
exporter.export_item(item)
return item
def close_spider(self, spider):
for exporter, csvFile in self.itemType_to_exporterAndCsvFile.values():
exporter.finish_exporting()
csvFile.close()
现在有一个简单的方法可以实现这一点。我们可以在
settings.py
文件中配置 feed 导出,如下所示 -
FEED = {
'team.csv': {
'format': 'csv',
'encoding': 'utf8',
'store_empty': False,
'item_classes': [MyItemClass1, 'myproject.items.TeamItem'],
'fields': None,
'indent': 4,
'item_export_kwargs': {
'export_empty_fields': True,
},
},
{
'club.csv': {
'format': 'csv',
'encoding': 'utf8',
'store_empty': False,
'item_classes': ['myproject.items.ClubItem'],
'fields': None,
'indent': 4,
'item_export_kwargs': {
'export_empty_fields': True,
},
},
这将生成两个不同的
.csv
文件,并按照上面的 item_classes
键重定向相应的项目。
文档不太清楚,但这是我推断的链接 - Feed Exports