当我在命令行的“一次性”场景中运行时,我的Scrapy脚本似乎工作正常,但如果我尝试在同一个python会话中运行代码两次,我会收到此错误:
“ReactorNotRestartable”
为什么?
违规代码(最后一行抛出错误):
crawler = CrawlerProcess(settings)
crawler.install()
crawler.configure()
# schedule spider
#crawler.crawl(MySpider())
spider = MySpider()
crawler.queue.append_spider(spider)
# start engine scrapy/twisted
crawler.start()
答案 0 :(得分:11)
接近Joël的答案,但我想在评论中详细说明。如果您查看Crawler source code,就会发现CrawlerProcess
类有一个start
,还有一个stop
函数。此stop
函数负责清理爬网内部,以便系统最终处于可以重新启动的状态。
因此,如果您想在不离开流程的情况下重新启动抓取,请在适当的时候致电crawler.stop()
。稍后,只需再次致电crawler.start()
即可恢复运营。
编辑:回想起来,这是不可能的(由于Twisted反应堆,如另一个答案所述); stop
只是照顾干净的终止。回顾我的代码,我碰巧有一个Crawler进程的包装器。下面你可以找到一些(编辑过的)代码,使它可以使用Python的多处理模块。通过这种方式,您可以更轻松地重新启动爬虫。 (注意:我上个月在网上找到了代码,但是我没有包含来源......所以如果有人知道它来自哪里,我会更新来源的信用。)
from scrapy import project, signals
from scrapy.conf import settings
from scrapy.crawler import CrawlerProcess
from scrapy.xlib.pydispatch import dispatcher
from multiprocessing.queues import Queue
from multiprocessing import Process
class CrawlerWorker(Process):
def __init__(self, spider, results):
Process.__init__(self)
self.results = results
self.crawler = CrawlerProcess(settings)
if not hasattr(project, 'crawler'):
self.crawler.install()
self.crawler.configure()
self.items = []
self.spider = spider
dispatcher.connect(self._item_passed, signals.item_passed)
def _item_passed(self, item):
self.items.append(item)
def run(self):
self.crawler.crawl(self.spider)
self.crawler.start()
self.crawler.stop()
self.results.put(self.items)
# The part below can be called as often as you want
results = Queue()
crawler = CrawlerWorker(MySpider(myArgs), results)
crawler.start()
for item in results.get():
pass # Do something with item
答案 1 :(得分:2)
crawler.start()
启动Twisted reactor。只能有一个反应堆。
如果您想运行更多蜘蛛 - 请使用
another_spider = MyAnotherSpider()
crawler.queue.append_spider(another_spider)
答案 2 :(得分:0)
我已经在一个应用程序中使用线程启动了几次reactor并避免了ReactorNotRestartable错误。
主题(目标=的Process.Start)。开始()
答案 3 :(得分:-1)
在我看来,您无法使用crawler.start()
命令两次:如果您希望它再次运行,则可能需要重新创建它。