【问题标题】:ReactorNotRestartable error in while loop with scrapy带有scrapy的while循环中的ReactorNotRestartable错误
【发布时间】:2017-02-18 04:30:31
【问题描述】:

执行以下代码时出现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变量,那有什么问题?

【问题讨论】:

    标签: python python-2.7 scrapy twisted


    【解决方案1】:

    默认情况下,CrawlerProcess.start() 将在所有爬虫完成后停止它创建的 Twisted reactor。

    如果您在每次迭代中创建process,您应该调用process.start(stop_after_crawl=False)

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

    【讨论】:

    • process.start(stop_after_crawl=False) — 将阻塞主进程
    • @Iliaw495Nikitin,CrawlerProcess.start() 将运行反应器并在抓取完成时将控制权交还给线程,正确。这是一个问题吗?替代scrapy.crawler.CrawlerRunner's .crawl() “返回一个在爬取完成时触发的延迟。”
    • 阻塞对于 AWS Lambda 来说不是一个好主意,不是吗?我确实花了半天时间才弄清楚如何在 AWS Lambda 上运行它,但仍然一无所获。
    • 我不知道 AWS Lambda 是如何工作的。您可能想发布一个新问题。
    【解决方案2】:

    我能够像这样解决这个问题。 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()
    

    【讨论】:

      【解决方案3】:

      参考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】:

        我能够通过这个简单的代码使用包钩针来缓解这个问题,这个简单的代码基于 Christian Aichinger 对这个问题的副本Scrapy - Reactor not Restartable 的回答。 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】:

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

          Spyder 似乎第一次可以工作,但之后就不行了。也许反应堆保持打开而不关闭?

          【讨论】:

            【解决方案6】:

            我可以建议你使用 subprocess 模块运行爬虫

            from subprocess import Popen, PIPE
            
            spider = Popen(["scrapy", "crawl", "spider_name", "-a", "argument=value"], stdout=PIPE)
            
            spider.wait()
            

            【讨论】:

              【解决方案7】:

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

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

              您可以将 while 循环的内容添加到函数中(例如 execute_crawling)。 然后,您可以使用不同的子进程简单地运行它。对于这个 python Process 模块可以使用。 代码如下。

              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
              

              【讨论】:

                【解决方案8】:

                我在 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)

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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2013-08-31
                  • 2020-07-19
                  • 1970-01-01
                  • 2018-12-13
                  • 1970-01-01
                  相关资源
                  最近更新 更多