2

スクレイピー スパイダーを別のスクリプトで実行しようとしていますが、このスクリプトをループで実行すると (たとえば、同じスパイダーを異なるパラメーターで実行すると) ReactorAlreadyRunning、. 私のスニペット:

from celery import task
from episode.skywalker.crawlers import settings
from multiprocessing.queues import Queue
from scrapy import log, project, signals
from scrapy.settings import CrawlerSettings
from scrapy.spider import BaseSpider
from scrapy.spidermanager import SpiderManager
from scrapy.xlib.pydispatch import dispatcher
import multiprocessing
from twisted.internet.error import ReactorAlreadyRunning


class CrawlerWorker(multiprocessing.Process):

    def __init__(self, spider, result_queue):
        from scrapy.crawler import CrawlerProcess
        multiprocessing.Process.__init__(self)
        self.result_queue = result_queue
        self.crawler = CrawlerProcess(CrawlerSettings(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)
        try:
            self.crawler.start()
        except ReactorAlreadyRunning:
            pass

        self.crawler.stop()
        self.result_queue.put(self.items)


@task
def execute_spider(spider, **spider__kwargs):
    '''
    Execute spider within separate process
    @param spider: spider class to crawl or the name (check if instance)
    '''

    if not isinstance(spider, BaseSpider):
        manager = SpiderManager(settings.SPIDER_MODULES)
        spider = manager.create(spider, **spider__kwargs)
    result_queue = Queue()
    crawler = CrawlerWorker(spider, result_queue)
    crawler.start()
    items = []

    for item in result_queue.get():
        items.append(item)

私の提案は、それが複数のねじれたリアクターの実行によって引き起こされたということです。どうすれば回避できますか?一般に、リアクターなしでスパイダーを実行する方法はありますか?

4

1 に答える 1

1

問題の原因を突き止めました。メソッドを何らかの方法でプロセス内で呼び出すとexecute_spiderCrawlerWorker(たとえば recursion を介して)、2 番目のリアクターが作成されますが、これは不可能です。

私の解決策:すべてのステートメントを移動し、再帰呼び出しをexecute_spidermethodで実行して、secondary ではなく同じプロセスでスパイダーの実行をトリガーするようにしCrawlerWorkerます。私もそのような声明を組み込みました

try:
        self.crawler.start()
except ReactorAlreadyRunning:
        raise RecursiveSpiderCall("Spider %s was called from another spider recursively. Such behavior is not allowed" % (self.spider))

スパイダーの意図しない再帰呼び出しをキャッチします。

于 2013-05-25T18:08:54.253 に答える