10 Stimmen

Scrapy-Aufgaben in Python ausführen

Mein Scrapy-Skript scheint zu funktionieren, wenn ich es in "one-off"-Szenarien von der Kommandozeile ausführen, aber wenn ich versuche, den Code zweimal in der gleichen Python-Sitzung bekomme ich diesen Fehler:

"ReactorNotRestartable"

Warum?

Der beanstandete Code (die letzte Zeile löst den Fehler aus):

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()

11voto

jro Punkte 9070

Das kommt der Antwort von Joël sehr nahe, aber ich möchte etwas ausführlicher werden, als es in den Kommentaren möglich ist. Wenn Sie sich die Crawler-Quellcode sehen Sie, dass die CrawlerProcess Klasse hat eine start sondern auch eine stop Funktion. Diese stop Funktion kümmert sich um die Bereinigung der Interna des Crawlings, so dass das System in einem Zustand endet, von dem aus es wieder starten kann.

Wenn Sie also das Crawling neu starten wollen, ohne Ihren Prozess zu verlassen, rufen Sie crawler.stop() zu gegebener Zeit. Später rufen Sie einfach crawler.start() um den Betrieb wieder aufzunehmen.

Editer : im Nachhinein ist dies nicht möglich (wegen des Twisted Reactors, wie in einer anderen Antwort erwähnt); die stop sorgt einfach für einen sauberen Abschluss. Wenn ich auf meinen Code zurückblicke, habe ich zufällig einen Wrapper für die Crawler-Prozesse. Unten finden Sie einen (unkenntlich gemachten) Code, der das Multiprocessing-Modul von Python verwendet. Auf diese Weise können Sie Crawler leichter neu starten. (Anmerkung: Ich habe den Code letzten Monat online gefunden, aber ich habe die Quelle nicht angegeben... wenn also jemand weiß, woher er stammt, werde ich die Quellenangaben aktualisieren).

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

1voto

warvariuc Punkte 53231

crawler.start() startet Twisted Reactor. Es kann nur einen Reaktor geben.

Wenn Sie mehr Spider einsetzen wollen - verwenden Sie

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

0voto

Ich habe Threads verwendet, um den Reaktor mehrmals in einer Anwendung zu starten und den Fehler ReactorNotRestartable zu vermeiden.

Thread(target=process.start).start()

Hier ist die ausführliche Erklärung: Eine Scrapy-Spinne in einem Celery-Task ausführen

-1voto

Joël Punkte 2569

Es scheint mir, dass Sie nicht crawler.start() Befehl zweimal: Sie müssen ihn möglicherweise neu erstellen, wenn Sie ihn ein zweites Mal ausführen wollen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X