Pregunta Ejecutar arañas Scrapy en una tarea de apio


Tengo un sitio de Django donde ocurre un robo cuando un usuario lo solicita, y mi código inicia una secuencia de comandos independiente araña Scrapy en un nuevo proceso. Naturalmente, esto no funciona con un aumento de usuarios.

Algo como esto:

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()

Decidí usar Apio y usar a los trabajadores para poner en cola las solicitudes de rastreo.

Sin embargo, estoy teniendo problemas con los reactores Tornado que no pueden reiniciarse. La primera y la segunda spider se ejecutan correctamente, pero las arañas subsiguientes arrojarán el error ReactorNotRestartable.

¿Alguien puede compartir algún consejo con la ejecución de arañas dentro del marco de Apio?


32
2017-07-17 18:36


origen


Respuestas:


Bien, aquí es cómo conseguí que Scrapy trabaje con mi proyecto Django que usa Aplery para hacer cola y qué gatear. La solución real provino principalmente del código de joehillen ubicado aquí http://snippets.scrapy.org/snippets/13/

Primero el tasks.py archivo

from celery import task

@task()
def crawl_domain(domain_pk):
    from crawl import domain_crawl
    return domain_crawl(domain_pk)

Entonces el crawl.py archivo

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)

El truco aquí es el "del proceso de importación de multiprocesamiento", que trata el tema "ReactorNotRestartable" en el marco de Twisted. Así que, básicamente, la tarea de Apio llama a la función "domain_crawl" que reutiliza el objeto "DomainCrawlerScript" una y otra vez para interactuar con su araña Scrapy. (Soy consciente de que mi ejemplo es un poco redundante, pero hice esto por una razón en mi configuración con múltiples versiones de python [mi servidor web django está realmente usando python2.4 y mis servidores de trabajo usan python2.7])

En mi ejemplo aquí, "DomainSpider" es solo una Scrapy Spider modificada que toma una lista de URL y luego las establece como las "start_urls".

¡Espero que esto ayude!


35
2017-07-25 19:34



lo puse CELERYD_MAX_TASKS_PER_CHILD a 1 en el archivo de configuración y que se encargó del problema. El daemon worker comienza un nuevo proceso después de cada ejecución de araña y eso cuida el reactor.


8
2017-08-12 23:43