/ / Die einfachste Möglichkeit, Scrapy Crawler auszuführen, damit das Skript nicht blockiert wird - Python, Scrapy

Der einfachste Weg, Scrapy Crawler zu starten, damit das Skript nicht blockiert wird - Python, Scrapy

Die offiziellen Dokumente viele Wege zum Laufen geben scrapy Crawler vom Code:

import scrapy
from scrapy.crawler import CrawlerProcess

class MySpider(scrapy.Spider):
# Your spider definition
...

process = CrawlerProcess({
"USER_AGENT": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)"
})

process.crawl(MySpider)
process.start() # the script will block here until the crawling is finished

Aber alle blockieren das Skript, bis das Crawlen beendet ist. Was ist der einfachste Weg in Python, den Crawler asynchron auf blockierende Weise auszuführen?

Antworten:

4 für die Antwort № 1

Ich habe jede Lösung ausprobiert, die ich finden konnte, und die einzige, die für mich funktionierte, war Dies. Aber damit es funktioniert scrapy 1.1rc1 Ich musste es ein bisschen anpassen:

from scrapy.crawler import Crawler
from scrapy import signals
from scrapy.utils.project import get_project_settings
from twisted.internet import reactor
from billiard import Process

class CrawlerScript(Process):
def __init__(self, spider):
Process.__init__(self)
settings = get_project_settings()
self.crawler = Crawler(spider.__class__, settings)
self.crawler.signals.connect(reactor.stop, signal=signals.spider_closed)
self.spider = spider

def run(self):
self.crawler.crawl(self.spider)
reactor.run()

def crawl_async():
spider = MySpider()
crawler = CrawlerScript(spider)
crawler.start()
crawler.join()

Also jetzt, wenn ich anrufe crawl_async, es beginnt zu kriechen und blockiert meinen aktuellen Thread nicht. Ich bin absolut neu bei scrapyVielleicht ist das keine sehr gute Lösung, aber es hat für mich funktioniert.

Ich habe diese Versionen der Bibliotheken verwendet:

cffi==1.5.0
Scrapy==1.1rc1
Twisted==15.5.0
billiard==3.3.0.22

0 für die Antwort № 2

Die Antwort von Netimen ist richtig. process.start() Anrufe reactor.run(), der den Thread blockiert. Nur glaube ich nicht, dass es notwendig ist, eine Unterklasse zu erstellen billiard.Process. Obwohl schlecht dokumentiert, billiard.Process hat eine Reihe von APIs, um eine andere Funktion asynchron ohne Unterklassifizierung aufzurufen.

from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings

from billiard import Process

crawler = CrawlerProcess(get_project_settings())
process = Process(target=crawler.start, stop_after_crawl=False)


def crawl(*args, **kwargs):
crawler.crawl(*args, **kwargs)
process.start()

Beachten Sie, wenn Sie nicht haben stop_after_crawl=False, können Sie stoßen ReactorNotRestartable Ausnahme, wenn Sie den Crawler mehr als zweimal ausführen.