使用scrapy进行while循环时出现ReactorNotRestartable错误

时间:2016-10-09 17:47:46

标签: python python-2.7 scrapy twisted

执行以下代码时出现twisted.internet.error.ReactorNotRestartable错误:

from time import sleep
from scrapy import signals
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings
from scrapy.xlib.pydispatch import dispatcher

result = None

def set_result(item):
    result = item

while True:
    process = CrawlerProcess(get_project_settings())
    dispatcher.connect(set_result, signals.item_scraped)

    process.crawl('my_spider')
    process.start()

    if result:
        break
    sleep(3)

它第一次有效,然后我收到错误。我每次创建process变量,那么问题是什么?

8 个答案:

答案 0 :(得分:5)

默认情况下,CrawlerProcess' .start()将停止在所有抓取工具完成后创建的扭曲反应堆。

如果您在每次迭代中创建process.start(stop_after_crawl=False),则应致电process

另一种选择是自己处理Twisted反应器并使用CrawlerRunnerThe docs have an example这样做。

答案 1 :(得分:1)

我能够这样解决这个问题。 process.start()应该只被调用一次。

from time import sleep
from scrapy import signals
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings
from scrapy.xlib.pydispatch import dispatcher

result = None

def set_result(item):
    result = item

while True:
    process = CrawlerProcess(get_project_settings())
    dispatcher.connect(set_result, signals.item_scraped)

    process.crawl('my_spider')

process.start()

答案 2 :(得分:1)

对于特定的进程,一旦调用react.run()或process.start(),就无法重新运行这些命令。原因是电抗器无法重启。一旦脚本完成执行,反应堆将停止执行。

因此,如果您需要多次运行反应堆,最好的选择是使用不同的子流程。

您可以将while循环的内容添加到函数中(例如execute_crawling)。 然后,您可以简单地使用不同的子流程来运行它。为此,可以使用python处理模块。 代码如下。

from multiprocessing import Process
def execute_crawling():
    process = CrawlerProcess(get_project_settings())#same way can be done for Crawlrunner
    dispatcher.connect(set_result, signals.item_scraped)
    process.crawl('my_spider')
    process.start()

if __name__ == '__main__':
for k in range(Number_of_times_you_want):
    p = Process(target=execute_crawling)
    p.start()
    p.join() # this blocks until the process terminates

答案 3 :(得分:0)

参考http://crawl.blog/scrapy-loop/

 import scrapy
 from scrapy.crawler import CrawlerProcess
 from scrapy.utils.project import get_project_settings     
 from twisted.internet import reactor
 from twisted.internet.task import deferLater

 def sleep(self, *args, seconds):
    """Non blocking sleep callback"""
    return deferLater(reactor, seconds, lambda: None)

 process = CrawlerProcess(get_project_settings())

 def _crawl(result, spider):
    deferred = process.crawl(spider)
    deferred.addCallback(lambda results: print('waiting 100 seconds before 
    restart...'))
    deferred.addCallback(sleep, seconds=100)
    deferred.addCallback(_crawl, spider)
    return deferred


_crawl(None, MySpider)
process.start()

答案 4 :(得分:0)

基于克里斯蒂安·艾辛格(Christian Aichinger)对这个问题Scrapy - Reactor not Restartable重复项的回答,我能够使用crochet程序包通过此简单代码缓解此问题。 Spiders的初始化在主线程中完成,而特定的爬网在不同的线程中完成。我正在使用Anaconda(Windows)。

import time
import scrapy
from scrapy.crawler import CrawlerRunner
from crochet import setup

class MySpider(scrapy.Spider):
    name = "MySpider"
    allowed_domains = ['httpbin.org']
    start_urls = ['http://httpbin.org/ip']

    def parse(self, response):
        print(response.text)
        for i in range(1,6):
            time.sleep(1)
            print("Spider "+str(self.name)+" waited "+str(i)+" seconds.")

def run_spider(number):
    crawler = CrawlerRunner()
    crawler.crawl(MySpider,name=str(number))

setup()
for i in range(1,6):
    time.sleep(1)
    print("Initialization of Spider #"+str(i))
    run_spider(i)

答案 5 :(得分:0)

我在使用Spyder时遇到了类似的问题。从命令行运行文件反而是为我修复了该文件。

Spyder似乎第一次起作用,但之后没有起作用。也许反应堆保持打开且没有关闭?

答案 6 :(得分:0)

我建议您使用subprocess模块运行刮板

from subprocess import Popen, PIPE

spider = Popen(["scrapy", "crawl", "spider_name", "-a", "argument=value"], stdout=PIPE)

spider.wait()

答案 7 :(得分:0)

我在 AWS lambda 上遇到错误 ReactorNotRestartable,在我使用此解决方案后

默认情况下,scrapy 的异步特性不适用于 Cloud Functions,因为我们需要一种方法来阻止抓取以防止函数提前返回和实例在之前被杀死进程终止。

相反,我们可以使用`

import scrapy
import scrapy.crawler as crawler
rom scrapy.spiders import CrawlSpider
import scrapydo

scrapydo.setup()

# your spider
class QuotesSpider(scrapy.Spider):
    name = "quotes"
    start_urls = ['http://quotes.toscrape.com/tag/humor/']

    def parse(self, response):
        for quote in response.css('div.quote'):
            print(quote.css('span.text::text').extract_first())

scrapydo.run_spider(QuotesSpider)

` 以阻塞方式运行您现有的蜘蛛: