Scrapy并发蜘蛛示例变量

w46czmvw  于 2022-11-09  发布在  其他
关注(0)|答案(1)|浏览(170)

我有一些Scrapy蜘蛛运行,最近有一个奇怪的bug。我有一个基类和一些子类:

class MyBaseSpider(scrapy.Spider):
    new_items = []

    def spider_closed(self):
        #Email any new items that weren't in the last run

class MySpiderImpl1(MyBaseSpider):
    def parse(self):
        #Implement site specific checks
        self.new_items.append(new_found_item)

class MySpiderImpl2(MyBaseSpider):
    def parse(self):
        #Implement site specific checks
        self.new_items.append(new_found_item)

这似乎一直运行良好,新的项目得到电子邮件给我的每个网站的基础上。但我最近有一些电子邮件从MySpiderImpl 1包含项目从网站2。
我按照文档从脚本运行:

scraper_settings = get_project_settings()
    runner = CrawlerRunner(scraper_settings)
    configure_logging()
    sites = get_spider_names()
    for site in sites:
        runner.crawl(site.spider_name)
    d = runner.join()
    d.addBoth(lambda _: reactor.stop())
    reactor.run()

我怀疑这里的解决方案是切换到一个管道,它整理一个站点的项目,并在调用pipeline.close_spider时通过电子邮件将它们发送出去,但我惊讶地看到new_items变量在蜘蛛之间泄漏。
是否有关于并发运行的文档?将变量保存在基类中是否是不好的做法?我还跟踪了变量中蜘蛛的其他信息,如运行编号-是否应该在其他地方跟踪?

6tqwzwtp

6tqwzwtp1#

在python中,所有的类变量都在所有的示例和子类之间共享,所以你的MyBaseSpider.new_itemsMySpiderImpl1.new_itemsMySpiderImpl2.new_items使用的列表是完全一样的。
正如您所建议的,您可以实现一个管道,尽管这可能需要对当前代码进行大量重构。
pipelines.py

class MyPipeline:
    def process_item(self, item, spider):
        if spider.name == 'site1':
            ... email item
        elif spider.name == 'site2':
            ... do something different

我想你们所有的蜘蛛都有名字...我想这是一个要求。
另一个可能需要较少工作的选项是覆盖基类中的start_requests方法,以便在爬网过程开始时分配一个唯一列表。

相关问题