Подтвердить что ты не робот

Запуск пауков Scrapy в задаче Сельдерея

У меня есть сайт 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()

Я решил использовать сельдерей и использовать рабочих для очереди запросов на обход.

Однако я столкнулся с проблемами с реакторами Tornado, которые не могут перезагружаться. Первый и второй пауки успешно выполняются, но последующие пауки будут бросать ошибку ReactorNotRestartable.

Любой может поделиться любыми советами с запущенными пауками в рамках Celery?

4b9b3361

Ответ 1

Хорошо, вот как я получил 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)

Трюк здесь - это "от процесса многопроцессорного импорта", который обходит проблему "ReactorNotRestartable" в структуре Twisted. Таким образом, в основном задача Celery вызывает функцию "domain_crawl", которая снова и снова использует объект DomainCrawlerScript для взаимодействия с вашим пауком Scrapy. (Я знаю, что мой пример немного избыточен, но я сделал это по какой-то причине в моей настройке с несколькими версиями python [мой веб-сервер django на самом деле использует python2.4, а мои рабочие серверы используют python2.7])

В моем примере здесь "DomainSpider" - это всего лишь модифицированный Scrapy Spider, который принимает список URL-адресов, а затем устанавливает их как "start_urls".

Надеюсь, это поможет!

Ответ 2

Я установил CELERYD_MAX_TASKS_PER_CHILD в 1 файл настроек и позаботился об этом. Рабочий демон запускает новый процесс после каждого запуска паука и заботится о реакторе.