Python 在芹菜任务中运行刮擦蜘蛛

Python 在芹菜任务中运行刮擦蜘蛛,python,django,scrapy,celery,Python,Django,Scrapy,Celery,我有一个Django站点,当用户请求时,会发生刮擦,我的代码在一个新进程中启动了一个刮擦蜘蛛独立脚本。当然,这并不能满足用户数量的增加 大概是这样的: class StandAloneSpider(Spider): #a regular spider settings.overrides['LOG_ENABLED'] = True #more settings can be changed... crawler = CrawlerProcess( settings ) crawler

我有一个Django站点,当用户请求时,会发生刮擦,我的代码在一个新进程中启动了一个刮擦蜘蛛独立脚本。当然,这并不能满足用户数量的增加

大概是这样的:

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()
我决定用芹菜和工人来排队抓取请求

然而,我遇到了龙卷风反应堆无法重启的问题。第一个和第二个爬行器成功运行,但后续爬行器将抛出ReactorNotRestartable错误


任何人都可以在芹菜框架内与正在运行的爬行器分享任何技巧?

好的,下面是我如何在Django项目中使用芹菜排队爬行的过程。实际的解决方法主要来自joehillen的代码(位于此处)

首先是
tasks.py
文件

from celery import task

@task()
def crawl_domain(domain_pk):
    from crawl import domain_crawl
    return domain_crawl(domain_pk)
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)
然后是
crawl.py
文件

from celery import task

@task()
def crawl_domain(domain_pk):
    from crawl import domain_crawl
    return domain_crawl(domain_pk)
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”问题。因此基本上芹菜任务调用“domain_crawl”函数,该函数反复重用“DomainCrawlerScript”对象,以与您的Scrapy spider接口。(我知道我的示例有点多余,但我之所以这样做是因为我的设置中使用了多个版本的python[我的django Web服务器实际上使用的是python2.4,我的工作服务器使用的是python2.7])

在我这里的示例中,“DomainSpider”只是一个经过修改的Scrapy Spider,它接受一个URL列表,然后将它们设置为“start_URL”


希望这有帮助

我在设置文件中设置为1,这解决了问题。worker守护进程在每次spider运行后启动一个新进程,负责处理反应器。

是否使用Postgresql?我从芹菜中得到了最奇怪的“InterfaceError:连接已经关闭”。是的,我正在使用postgresql,如果你想提供错误,我可以尝试帮助你解决,我确实有一个听起来类似的错误,但我不记得它到底是什么,也不记得我做了什么。(我目前正在将11077910个项目加载到我的队列中,我有5台工作机器从中拉出,因此此设置确实有效)我发现了问题,这与在postgres中存储结果有关。我想是这样的:我使用的解决方法是设置芹菜结果后端。你遇到过这个问题吗?是的,你可能是对的,最新版本的芹菜非常棒,所以当我重写这个项目以使用最新版本时,我会让你知道如何解决这个问题well@byoungb我也有同样的问题。此解决方案是否仍适用于scrapy 1.0?你发布的链接现在被破坏了。这是个聪明的主意,不知道芹菜总是重新启动一项任务会有多少开销。但这是有道理的。所以,是的,对于未来的用户,你可能想试试这个。这些设置在最近的芹菜版本中被重命名了。您还可以使用以下标志从命令行应用它:
--max tasks per child 1
当前芹菜4.3.0版的设置名称为
WORKER\u max\u tasks\u per\u child
。见文件:&