Djangoユーザーが要求するとスクレイピングが発生するサイトがあり、私のコードは新しいプロセスでScrapyスパイダーのスタンドアロンスクリプトを開始します。当然、これはユーザー。
このようなもの:
class StandAloneSpider(Spider):
#a regular spider
settings.overrides['LOG_ENABLED'] = True
#more settings can be changed...
crawler = CrawlerProcess( settings )
crawler.install()
crawler.configure()
spider = StandAloneSpider()
crawler.crawl( spider )
crawler.start()
Celeryを使用し、ワーカーを使用してクロール要求をキューに入れることにしました。
しかし、トルネードリアクターが再起動できないという問題が発生しています。最初と2番目のスパイダーは正常に実行されますが、後続のスパイダーはReactorNotRestartableエラーをスローします。
誰でも、Celeryフレームワーク内でSpidersを実行する際のヒントを共有できますか?
さて、ここで私がScrapyを自分のDjangoプロジェクトでクロールする対象をキューイングするために使用する方法を紹介します。実際の回避策は、主にここにあるjoehillenのコード http:// snippets .scrapy.org/snippets/13 /
まずtasks.py
ファイル
from celery import task
@task()
def crawl_domain(domain_pk):
from crawl import domain_crawl
return domain_crawl(domain_pk)
そうして crawl.py
ファイル
from multiprocessing import Process
from scrapy.crawler import CrawlerProcess
from scrapy.conf import settings
from spider import DomainSpider
from models import Domain
class DomainCrawlerScript():
def __init__(self):
self.crawler = CrawlerProcess(settings)
self.crawler.install()
self.crawler.configure()
def _crawl(self, domain_pk):
domain = Domain.objects.get(
pk = domain_pk,
)
urls = []
for page in domain.pages.all():
urls.append(page.url())
self.crawler.crawl(DomainSpider(urls))
self.crawler.start()
self.crawler.stop()
def crawl(self, domain_pk):
p = Process(target=self._crawl, args=[domain_pk])
p.start()
p.join()
crawler = DomainCrawlerScript()
def domain_crawl(domain_pk):
crawler.crawl(domain_pk)
ここでのトリックは、「マルチプロセッシングインポートプロセスから」であり、これがTwistedフレームワークの「ReactorNotRestartable」問題を回避します。したがって、基本的には、Celeryタスクは「domain_crawl」関数を呼び出し、「DomainCrawlerScript」オブジェクトを繰り返し再利用して、Scrapyスパイダーとのインターフェースを確立します。 (私は私の例が少し冗長であることを認識していますが、python [my Django webserver is実際にpython2.4を使用していて、ワーカーサーバーはpython2.7を使用しています])
私の例では、「DomainSpider」は、URLのリストを取得して「start_urls」として設定する、変更されたScrapy Spiderです。
お役に立てれば!
設定ファイルで CELERYD_MAX_TASKS_PER_CHILD を1に設定して、問題を解決しました。ワーカーデーモンは、スパイダーが実行されるたびに新しいプロセスを開始し、リアクターを処理します。