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
変数を作成するので、問題は何ですか?
デフォルトでは、 CrawlerProcess
の .start()
は、すべてのクローラーが終了したときに作成するTwistedリアクターを停止します。
各反復でprocess
を作成する場合は、process.start(stop_after_crawl=False)
を呼び出す必要があります。
もう1つのオプションは、Twistedリアクタを自分で処理し、 CrawlerRunner
を使用することです。 ドキュメントには例があります その上で。
このようにしてこの問題を解決することができました。 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()
参照 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()
私は、この質問の複製に対する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)
Spyderを使用して同様の問題が発生しました。コマンドラインからファイルを実行すると、代わりに修正されました。
Spyderは初めて機能するようですが、その後は機能しません。たぶん、リアクターは開いたままで閉じないのでしょうか?
シーケンスを使用するだけです:
process.crawl(...)
process.stop()
process.start()
より良い方法がない場合。これは奇妙に見えますが、私の側でうまくいきました。