web-dev-qa-db-ja.com

CrawlerProcessとCrawlerRunner

Scrapy 1.xのドキュメント は、スクリプトからScrapyスパイダーを実行する方法が2つあることを説明しています:

2つの違いは何ですか? 「プロセス」と「ランナー」はいつ使用する必要がありますか?

25
alecxe

Scrapyのドキュメントは、両方の実際のアプリケーションの例を示すのにかなり悪い仕事をしています。

CrawlerProcessは、ツイストのリアクターを使用するのはスクレイピーだけであると想定しています。他のコードを実行するためにpython=でスレッドを使用している場合、これは必ずしも正しいとは限りません。例としてこれを取り上げましょう。

from scrapy.crawler import CrawlerProcess
import scrapy
def notThreadSafe(x):
    """do something that isn't thread-safe"""
    # ...
class MySpider1(scrapy.Spider):
    # Your first spider definition
    ...

class MySpider2(scrapy.Spider):
    # Your second spider definition
    ...

process = CrawlerProcess()
process.crawl(MySpider1)
process.crawl(MySpider2)
process.start() # the script will block here until all crawling jobs are finished
notThreadSafe(3) # it will get executed when the crawlers stop

ご覧のとおり、クローラーが停止したときにのみ関数が実行されます。同じリアクター内でクローラーがクロールしている間に関数を実行したい場合はどうなりますか?

from twisted.internet import reactor
from scrapy.crawler import CrawlerRunner
import scrapy

def notThreadSafe(x):
    """do something that isn't thread-safe"""
    # ...

class MySpider1(scrapy.Spider):
    # Your first spider definition
    ...

class MySpider2(scrapy.Spider):
    # Your second spider definition
    ...
runner = CrawlerRunner()
runner.crawl(MySpider1)
runner.crawl(MySpider2)
d = runner.join()
d.addBoth(lambda _: reactor.stop())
reactor.callFromThread(notThreadSafe, 3)
reactor.run() #it will run both crawlers and code inside the function

Runnerクラスはこの機能に限定されず、reactorでいくつかのカスタム設定が必要になる場合があります(defer、threads、getPage、カスタムエラーレポートなど)。

36
Rafael Almeida

CrawlerRunner:

クロールプロセスを手動で処理するスクリプトを記述しない限り、このクラスは必要ありません(Scrapyがそれに応じて使用するため)。例については、スクリプトからScrapyを実行するをご覧ください。

CrawlerProcess:

アプリケーション内で別のツイストリアクターを実行していない場合、このユーティリティはCrawlerRunnerよりも適しています。

既存のTwistedアプリケーションにクローラーを追加しない限り、CrawlerProcessが必要なようです。

2
Adam Taylor