web-dev-qa-db-ja.com

スクラップでのwhileループでのReactorNotRestartableエラー

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変数を作成するので、問題は何ですか?

23
k_wit

デフォルトでは、 CrawlerProcess.start() は、すべてのクローラーが終了したときに作成するTwistedリアクターを停止します。

各反復でprocessを作成する場合は、process.start(stop_after_crawl=False)を呼び出す必要があります。

もう1つのオプションは、Twistedリアクタを自分で処理し、 CrawlerRunner を使用することです。 ドキュメントには例があります その上で。

12
paul trmbrth

このようにしてこの問題を解決することができました。 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
Sagun Shrestha

参照 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()
2
Alexis Mejía

私は、この質問の複製に対する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)
0
Gibron

Spyderを使用して同様の問題が発生しました。コマンドラインからファイルを実行すると、代わりに修正されました。

Spyderは初めて機能するようですが、その後は機能しません。たぶん、リアクターは開いたままで閉じないのでしょうか?

0
Daniel Wyatt

シーケンスを使用するだけです:

process.crawl(...)
process.stop()
process.start()

より良い方法がない場合。これは奇妙に見えますが、私の側でうまくいきました。

0
prosti