定期从python运行Scrapy导致ReactorAlreadyRunning

时间:2014-08-31 00:45:32

标签: python scrapy twisted reactor

经过几个小时的修补和尝试片段后,我发现在stackoverflow中,我终于设法定期运行scrapy:

timeout = 60.0 # seconds

class UrlCrawlerScript(Process):
    def __init__(self, spider):
        Process.__init__(self)
        settings = get_project_settings()
        self.crawler = Crawler(settings)

        if not hasattr(project, 'crawler'):
            self.crawler.install()
            self.crawler.configure()
            self.crawler.signals.connect(reactor.stop, signal=signals.spider_closed)
        self.spider = spider

    def run(self):
        self.crawler.crawl(self.spider)
        self.crawler.start()
        reactor.run()


def run_spider():
    spider = MarketSpider()
    crawler = UrlCrawlerScript(spider)
    crawler.start()
    crawler.join()
    print 'finished'


l = task.LoopingCall(run_spider)
l.start(timeout) # call every sixty seconds

reactor.run()

我的问题是,在第二轮比赛后我仍然得到ReactorAlreadyRunning。 我该如何解决这个问题?

1 个答案:

答案 0 :(得分:2)

请注意,您的程序在两个地方调用reactor.run - 其中一个地方被重复调用,有效地在循环中调用(因为LoopingCall(间接)调用它)。

Twisted的反应堆无法重启。你可以运行和停止一次。如果您尝试再次运行它们,那么您将获得一个例外。如果你试图在它们运行时运行它们,那么你会得到另一个例外 - ReactorAlreadyRunning - 如你所见。

这里的解决方案是仅运行一次反应器。因此,您也应该只停止反应堆一次。

至少,这意味着您只能从程序中的某个位置拨打reactor.run。我建议,作为一个开始,程序最后的调用是你要保留的调用,run方法中的调用(每次运行蜘蛛时调用一次)应该是消除。

蜘蛛完成后,您还需要避免停止反应堆。如果您将reactor.stop连接到spider_done,那么在蜘蛛第一次运行后反应堆将停止并且您将无法再次运行蜘蛛。我想你可以简单地删除你程序的这一部分。