tutorial spider example español python flask scrapy python-multithreading

python - spider - Ejecutando una araña scrapy en el fondo en una aplicación Flask



scrapy spider (1)

No es la mejor idea tener frascos de larga duración como este.

Yo recomendaría usar un sistema de cola como apio o rabbitmq. La aplicación del matraz puede poner las tareas en la cola que le gustaría hacer en segundo plano y luego regresar inmediatamente.

Luego, puede hacer que los trabajadores que se encuentren fuera de su aplicación principal procesen esas tareas y se encarguen de todos sus raspados.

Estoy construyendo una aplicación que usa Flask and Scrapy . Cuando se accede a la URL raíz de mi aplicación, procesa algunos datos y los muestra. Además, también quiero (re) iniciar mi araña si aún no se está ejecutando. Como mi araña tarda aproximadamente 1,5 horas en terminar de ejecutarla, la ejecuto como proceso en segundo plano utilizando el enhebrado . Aquí hay un ejemplo mínimo (también necesitarás pruebas de araña ):

import os from flask import Flask, render_template import threading from twisted.internet import reactor from scrapy import log, signals from scrapy.crawler import Crawler from scrapy.settings import Settings from testspiders.spiders.followall import FollowAllSpider def crawl(): spider = FollowAllSpider(domain=''scrapinghub.com'') crawler = Crawler(Settings()) crawler.configure() crawler.signals.connect(reactor.stop, signal=signals.spider_closed) crawler.crawl(spider) crawler.start() log.start() reactor.run() app = Flask(__name__) @app.route(''/'') def main(): run_in_bg = threading.Thread(target=crawl, name=''crawler'') thread_names = [t.name for t in threading.enumerate() if isinstance(t, threading.Thread)] if ''crawler'' not in thread_names: run_in_bg.start() return ''hello world'' if __name__ == "__main__": port = int(os.environ.get(''PORT'', 5000)) app.run(host=''0.0.0.0'', port=port)

Como nota al margen, las siguientes líneas fueron mi enfoque ad hoc para tratar de identificar si el hilo de mi rastreador aún se está ejecutando. Si hay un enfoque más idiomático, agradecería alguna orientación.

run_in_bg = threading.Thread(target=crawl, name=''crawler'') thread_names = [t.name for t in threading.enumerate() if isinstance(t, threading.Thread)] if ''crawler'' not in thread_names: run_in_bg.start()

Pasando al problema: si crawler.py script anterior como crawler.py , ejecuto python crawler.py y python crawler.py a localhost:5000 , aparece el siguiente error (ignore los errores de HtmlXPathSelector HtmlXPathSelector de HtmlXPathSelector ):

exceptions.ValueError: signal only works in main thread

Aunque la araña se ejecuta, no se detiene porque la señal de signals.spider_closed solo funciona en el hilo principal (según este error). Como era de esperar, las solicitudes posteriores a la URL raíz generan numerosos errores.

¿Cómo puedo diseñar mi aplicación para iniciar mi araña si aún no se está rastreando, mientras que al mismo tiempo devuelvo el control a mi aplicación inmediatamente (es decir, no quiero esperar a que el rastreador termine) para otras cosas?