2011-11-03 29 views
10

Mi script de Scrapy parece funcionar bien cuando lo ejecuto en escenarios "únicos" desde la línea de comandos, pero si trato de ejecutar el código dos veces en la misma sesión de Python obtengo este error:Ejecutar tareas de Scrapy en Python

"ReactorNotRestartable"

¿Por qué?

El código erróneo (última línea lanza el error):

crawler = CrawlerProcess(settings) 
crawler.install() 
crawler.configure() 

# schedule spider 
#crawler.crawl(MySpider()) 
spider = MySpider() 
crawler.queue.append_spider(spider) 

# start engine scrapy/twisted 
crawler.start() 

Respuesta

11

Cerca de la respuesta de Joël, pero quiero elaborar un poco más de lo que es posible en los comentarios. Si observa el Crawler source code, verá que la clase CrawlerProcess tiene un start, pero también una función stop. Esta función stop se encarga de limpiar las partes internas del rastreo para que el sistema termine en un estado desde el cual pueda comenzar de nuevo.

Por lo tanto, si desea reiniciar el rastreo sin abandonar su proceso, llame al crawler.stop() en el momento apropiado. Más tarde, simplemente llame al crawler.start() nuevamente para reanudar las operaciones.

Editar: en retrospectiva, esto no es posible (debido al reactor Twisted, como se menciona en una respuesta diferente); el stop solo se ocupa de una terminación limpia. Mirando hacia atrás en mi código, tuve un envoltorio para los procesos de Crawler. A continuación puede encontrar algunos códigos (redactados) para que funcionen utilizando el módulo de multiprocesamiento de Python. De esta forma, puedes reiniciar más fácilmente los rastreadores. (Nota:. He encontrado el código en línea el mes pasado, pero no incluir la fuente ... así que si alguien sabe de dónde viene, voy a actualizar los créditos para la fuente)

from scrapy import project, signals 
from scrapy.conf import settings 
from scrapy.crawler import CrawlerProcess 
from scrapy.xlib.pydispatch import dispatcher 
from multiprocessing.queues import Queue 
from multiprocessing import Process 

class CrawlerWorker(Process): 
    def __init__(self, spider, results): 
     Process.__init__(self) 
     self.results = results 

     self.crawler = CrawlerProcess(settings) 
     if not hasattr(project, 'crawler'): 
      self.crawler.install() 
     self.crawler.configure() 

     self.items = [] 
     self.spider = spider 
     dispatcher.connect(self._item_passed, signals.item_passed) 

    def _item_passed(self, item): 
     self.items.append(item) 

    def run(self): 
     self.crawler.crawl(self.spider) 
     self.crawler.start() 
     self.crawler.stop() 
     self.results.put(self.items) 

# The part below can be called as often as you want 
results = Queue() 
crawler = CrawlerWorker(MySpider(myArgs), results) 
crawler.start() 
for item in results.get(): 
    pass # Do something with item 
+0

añadiendo crawler.stop() inmediatamente después de crawler.start() no ayuda - cómo hacer ¿Descubro el "momento apropiado"? – Trindaz

+0

@Trindaz: No estaba en lo correcto en esa llamada, por favor vea la respuesta actualizada. – jro

+0

Gracias por la actualización @jro. También he visto este fragmento antes y, si lo he interpretado correctamente, el concepto es que puedes raspar todo lo que quieras agregando arañas a un rastreador que nunca muere, en lugar de intentar reiniciar un rastreador en cada intento lo haces en "ejecutar" una araña. Lo he marcado como una solución porque, técnicamente, resuelve mi problema, pero no puedo usarlo porque no quiero confiar en los objetos de rastreo persistentes en la aplicación django en la que estoy usando esto. Terminé escribiendo una solución basada puramente en BeautifulSoup y urllib2. – Trindaz

-1

Me parece que no se puede utilizar crawler.start() comando dos veces: es posible que tenga que volver a crearlo si desea que se ejecute una segunda vez .

2

crawler.start() inicia el reactor torcido. Solo puede haber un reactor

Si desea ejecutar más arañas - utilizo

another_spider = MyAnotherSpider() 
crawler.queue.append_spider(another_spider) 
+0

scrapy 0.14 ya no es compatible con varias arañas en un proceso de rastreo. – goh

+0

no han probado, pero esto podría funcionar (al mirar el código fuente): 'crawler.engine.open_spider (another_spider)' – warvariuc

+0

acaba de probar sus sugerencias. Hmm, no pude detener el proceso ... – goh

0

que he usado para iniciar las discusiones del reactor varias veces en una sola aplicación y evitar errores ReactorNotRestartable.

rosca (target = Process.Start) .start()

Aquí está la explicación detallada: Run a Scrapy spider in a Celery Task

Cuestiones relacionadas