Scrapy项目管道为多蜘蛛

时间:2015-08-14 13:27:34

标签: python scrapy scrapy-pipeline

我有2只蜘蛛在这里运行:

from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings

settings = get_project_settings()

process1 = CrawlerProcess(settings)
process1.crawl('spider1')
process1.crawl('spider2')

process1.start()

我想让这些蜘蛛写一个共同的文件。

这是Pipeline类:

class FilePipeline(object):

    def __init__(self):
        self.file  = codecs.open('data.txt', 'w', encoding='utf-8')
        self.spiders = []

    def open_spider(self, spider):
        self.spiders.append(spider.name)

    def process_item(self, item, spider):
        line = json.dumps(OrderedDict(item), ensure_ascii=False, sort_keys=False) + "\n"
        self.file.write(line)

        return item

    def spider_closed(self, spider):
        self.spiders.remove(spider.name)
        if len(self.spiders) == 0:
            self.file.close()

但是虽然我没有收到错误消息,但是当所有蜘蛛都在公共文件中写入时,我的行(项目)比scrapy日志少。切几条线。也许有一些练习同时从两个蜘蛛写入一个文件?

更新:

谢谢大家!) 我这样实现了它:

class FilePipeline1(object):
    lock = threading.Lock()
    datafile = codecs.open('myfile.txt', 'w', encoding='utf-8')

    def __init__(self):
        pass

    def open_spider(self, spider):
        pass

    def process_item(self, item, spider):
        line = json.dumps(OrderedDict(item), ensure_ascii=False, sort_keys=False) + "\n"
        try:
            FilePipeline1.lock.acquire()
            if isinstance(item, VehicleItem):            
                FilePipeline1.datafile.write(line)
        except:
            pass
        finally:
            FilePipeline1.lock.release()

        return item

    def spider_closed(self, spider):
        pass

2 个答案:

答案 0 :(得分:2)

我同意A. Abramov的回答。

这只是我的想法。您可以在您选择的数据库中创建两个表,然后在两个蜘蛛完成爬网后合并它们。您必须跟踪日志进入的时间,以便您可以根据收到的时间订购日志。然后,您可以将db转储到您想要的任何文件类型。这样,程序在写入文件之前不必等待一个进程完成,并且您不必进行任何多线程编程。

更新:

实际上,根据蜘蛛运行的时间长短,您可以将日志输出和时间存储到字典中。时间是键,日志输出是值。这比初始化db更容易。然后,您可以按键将dict转储到文件中。

答案 1 :(得分:1)

你在单独的线程中拥有的两个蜘蛛同时写入文件。正如past所说,会导致诸如线路切断等问题,如果你不处理同步问题,其中一些会丢失。为了做到这一点,你需要同步文件访问并只写整个记录/行,或者有一个策略来分配文件的区域到不同的线程,例如重新构建具有已知偏移和大小的文件,默认情况下,您没有这些文件。一般来说,同时从两个不同的线程写入同一个文件并不是一种常用的方法,除非你真的知道你在做什么,否则我不建议你这样做。

相反,我要分离蜘蛛IO功能,等待一个人的行动完成,然后才开始另一个 - 考虑到你的线程没有同步,这将使程序更多高效的让它工作:)如果你想要一个代码示例,说明如何在你的上下文中这样做,只需要它,我会乐意提供它。