7

我从这里这里阅读,并让多个蜘蛛在同一进程中运行。

但是,我不知道如何设计一个信号系统以在所有蜘蛛完成后停止反应堆

我的代码与以下示例非常相似:

from twisted.internet import reactor
from scrapy.crawler import Crawler
from scrapy.settings import Settings
from scrapy import log
from testspiders.spiders.followall import FollowAllSpider

def setup_crawler(domain):
    spider = FollowAllSpider(domain=domain)
    crawler = Crawler(Settings())
    crawler.configure()
    crawler.crawl(spider)
    crawler.start()

for domain in ['scrapinghub.com', 'insophia.com']:
    setup_crawler(domain)
log.start()
reactor.run()

在所有爬虫停止后,反应堆仍在运行。如果我添加声明

crawler.signals.connect(reactor.stop, signal=signals.spider_closed)

对于 setup_crawler 函数,reactor 在第一个爬虫关闭时停止。

任何人都可以告诉我如何在所有爬虫完成后使反应堆停止吗?

4

2 回答 2

2

除了 shackra 的回答,走这条路确实有效。您可以将信号接收器创建为保留状态的闭包,这意味着它会记录已完成的蜘蛛数量。您的代码应该知道您正在运行多少个蜘蛛,因此只需检查所有蜘蛛何时都已运行,然后运行reactor.stop()​​.

例如

将信号接收器链接到您的爬虫:

crawler.signals.connect(spider_finished, signal=signals.spider_closed)

创建信号接收器:

def spider_finished_count():
    spider_finished_count.count = 0

    def inc_count(spider, reason):
        spider_finished_count.count += 1
        if spider_finished_count.count == NUMBER_OF_SPIDERS:
            reactor.stop()
    return inc_count
spider_finished = spider_finished_count()

NUMBER_OF_SPIDERS 是您在此进程中运行的蜘蛛总数。

或者你可以反过来做,从运行的蜘蛛数倒数到 0。或者更复杂的解决方案可能涉及保留一个 dict 哪些蜘蛛已经完成和没有完成等。

注意:inc_count 被发送spiderreason我们在这个例子中没有使用它,但你可能希望使用这些变量:它们是从信号调度程序发送的,是关闭的蜘蛛以及它关闭的原因(str)。

Scrapy 版本:v0.24.5

于 2015-04-01T18:55:16.040 回答
1

我通常做的,在 PySide 中(我使用QNetworkAccessManager和许多自创的工人进行报废)是维护一个计数器,说明有多少工人已经完成了队列中的工作,当这个计数器达到创建的工人的数量时,会触发一个信号表示没有更多工作要做,应用程序可以做其他事情(比如启用“导出”按钮,以便用户可以将结果导出到文件等)。当然,这个计数器必须在一个方法中,并且必须在爬虫/蜘蛛/工作者发出信号时调用。

这可能不是解决问题的一种优雅方式,但是,你试过了吗?

于 2014-05-11T20:56:54.123 回答