Запуск задач Scrapy в Python

My Scrapy script, похоже, отлично работает, когда я запускаю его в сценариях "один выкл" из командной строки, но если я попытаюсь дважды запустить код в том же сеансе python, я получу эту ошибку:

"ReactorNotRestartable"

Почему?

Код нарушения (последняя строка вызывает ошибку):

crawler = CrawlerProcess(settings)
crawler.install()
crawler.configure()

# schedule spider
#crawler.crawl(MySpider())
spider = MySpider()
crawler.queue.append_spider(spider)

# start engine scrapy/twisted
crawler.start()

Ответ 1

Близко к Joël ответу, но я хочу уточнить немного больше, чем это возможно в комментариях. Если вы посмотрите Исходный код искателя, вы увидите, что класс CrawlerProcess имеет функцию start, но также и функцию stop. Эта функция stop выполняет очистку внутренних частей обхода, чтобы система попала в состояние, из которого оно может начать снова.

Итак, если вы хотите перезапустить обход, не выходя из своего процесса, вызовите crawler.stop() в соответствующее время. Позже просто вызовите crawler.start() для возобновления операций.

Изменить: в ретроспективе, это невозможно (из-за реактора Twisted, как упоминалось в другом ответе); stop просто заботится о чистое завершение. Оглядываясь назад на мой код, у меня была обертка для процессов Crawler. Ниже вы можете найти код (отредактированный), чтобы заставить его работать с использованием модуля многопроцессорности Python. Таким образом, вы можете более легко перезапустить сканеры. (Примечание: я нашел код в Интернете в прошлом месяце, но я не включил источник... поэтому, если кто-то знает, откуда он появился, я обновлю кредиты для источника.)

from scrapy import project, signals
from scrapy.conf import settings
from scrapy.crawler import CrawlerProcess
from scrapy.xlib.pydispatch import dispatcher
from multiprocessing.queues import Queue
from multiprocessing import Process

class CrawlerWorker(Process):
    def __init__(self, spider, results):
        Process.__init__(self)
        self.results = results

        self.crawler = CrawlerProcess(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)
        self.crawler.start()
        self.crawler.stop()
        self.results.put(self.items)

# The part below can be called as often as you want
results = Queue()
crawler = CrawlerWorker(MySpider(myArgs), results)
crawler.start()
for item in results.get():
    pass # Do something with item

Ответ 2

crawler.start() запускается витой реактор. Может быть только один реактор.

Если вы хотите запустить больше пауков - используйте

another_spider = MyAnotherSpider()
crawler.queue.append_spider(another_spider)

Ответ 3

Я использовал потоки, чтобы запустить реактор несколько раз в одном приложении и избежать ошибки ReactorNotRestartable.

резьбы (мишень = Process.Start).start()

Вот подробное объяснение: Запустите паук Scrapy в Задаче Сельдерея

Ответ 4

Мне кажется, что вы не можете использовать команду crawler.start() дважды: возможно, вам придется заново создать ее, если вы хотите, чтобы она выполнялась во второй раз.