好的,这就是我如何让 Scrapy 与我的 Django 项目一起工作,该项目使用 Celery 对要抓取的内容进行排队。实际的解决方法主要来自 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 时这样做是有原因的 [我的 django 网络服务器实际上使用的是 python2.4,而我的工作服务器使用的是 python2.7])
在我的示例中,“DomainSpider”只是一个修改过的 Scrapy Spider,它接受一个 url 列表,然后将它们设置为“start_urls”。
希望这可以帮助!