21

我正在抓取一个足球网站,蜘蛛(单个蜘蛛)从该网站的页面中获取多种项目:团队、比赛、俱乐部等。我正在尝试使用 CSVItemExporter 将这些项目存储在单独的 csv 文件中,teams.csv 、matches.csv、clubs.csv 等。

我不确定这样做的正确方法是什么。到目前为止我想到的唯一方法是创建我自己的自定义管道,如示例 http://doc.scrapy.org/en/0.14/topics/exporters.html 并在 spider_opened 方法中打开所有需要的 csv 文件,即为每个 csv 文件创建一个 csv 导出器,并在 process_item 中放置代码以确定“item”参数是什么类型的项目,然后将其发送到相应的导出器对象。

无论如何,我还没有找到任何在scrapy中处理多个csv文件(每个项目类型)的例子,所以我担心我正在以一种不应该使用的方式使用它。(这是我第一次使用 Scrapy)。

迪奥梅德斯

4

5 回答 5

25

我在这里发布了我用来MultiCSVItemPipeline根据上面 drcolossos 的答案生成的代码。

此管道假定所有 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
于 2012-09-03T16:38:53.560 回答
12

你的方法对我来说似乎很好。Piplines 是 Scrapy 的一个很棒的功能,并且是 IMO 为类似您的方法而构建的。

您可以创建多个项目(例如 SoccerItem、MatchItem),并MultiCSVItemPipeline通过检查项目类将每个项目委托给其自己的 CSV 类。

于 2012-09-03T07:31:26.233 回答
2

我已经尝试了答案。它似乎在最新版本(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
    
于 2020-08-13T00:11:12.220 回答
0

我正在使用 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
于 2021-09-15T01:06:45.233 回答
0

这是我用来利用 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()
于 2021-10-28T19:04:12.927 回答