39

ユーザーが要求したときにスクレイプが発生する 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 を使用し、ワーカーを使用してクロール リクエストをキューに入れることにしました。

ただし、Tornado リアクターが再起動できないという問題が発生しています。最初と 2 番目のスパイダーは正常に実行されますが、後続のスパイダーは ReactorNotRestartable エラーをスローします。

Celery フレームワーク内でスパイダーを実行する際のヒントを誰でも共有できますか?

4

2 に答える 2

37

さて、これは、Celery を使用して何をクロールするかをキューに入れる Django プロジェクトで Scrapy を使用する方法です。実際の回避策は、主にhttp://snippets.scrapy.org/snippets/13/にある joehillen のコードから来ました。

まずは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 タスクは「DomainCrawlerScript」オブジェクトを何度も再利用して Scrapy スパイダーとやり取りする「domain_crawl」関数を呼び出します。(私の例が少し冗長であることは承知していますが、複数のバージョンの Python を使用したセットアップでこれを行ったのは理由があります [私の django Web サーバーは実際には python2.4 を使用しており、私のワーカー サーバーは python2.7 を使用しています])

ここでの私の例では、「DomainSpider」は、URL のリストを取得して「start_urls」として設定する変更された Scrapy Spider です。

お役に立てれば!

于 2012-07-25T19:34:37.950 に答える
13

設定ファイルでCELERYD_MAX_TASKS_PER_CHILDを 1 に設定すると、問題は解決しました。ワーカーデーモンは、スパイダーが実行されるたびに新しいプロセスを開始し、リアクターを処理します。

于 2013-08-12T23:43:37.860 に答える