tutorial spider retry follow example create python database asynchronous scrapy twisted

spider - scrapy python 3 tutorial



Base de datos de consulta asĂ­ncrona para claves para usar en mĂșltiples solicitudes (2)

No ha proporcionado ningún caso de uso para que las consultas asincrónicas de la base de datos sean una necesidad. Supongo que no puede comenzar a raspar sus URL a menos que consulte primero la base de datos. Si ese es el caso, es mejor que solo haga la consulta de forma síncrona, itere sobre los resultados de la consulta, extraiga lo que necesita y luego Request objetos de Request . Tiene poco sentido consultar un archivo db de forma asincrónica y simplemente esperar que la consulta termine.

Quiero consultar asincrónicamente una base de datos para claves, luego realizar solicitudes a varias URL para cada clave.

Tengo una función que devuelve un Deferred de la base de datos cuyo valor es la clave para varias solicitudes. Idealmente, llamaría a esta función y devolvería un generador de Deferreds desde start_requests .

@inlineCallbacks def get_request_deferred(self): d = yield engine.execute(select([table])) # async d.addCallback(make_url) d.addCallback(Request) return d def start_requests(self): ????

Pero intentar esto de varias maneras plantea

builtins.AttributeError: ''Deferred'' object has no attribute ''dont_filter''

lo cual quiero decir que start_requests debe devolver objetos Request , no Deferreds cuyos valores son objetos Request . Lo mismo parece ser cierto de process_start_requests() middleware de spider.

Alternativamente, puedo hacer solicitudes iniciales a, por ejemplo, http://localhost/ y cambiarlas a la url real una vez que la clave esté disponible desde la base de datos a través del middleware del descargador, process_request() . Sin embargo, process_request solo devuelve un objeto Request ; no puede generar Solicitudes a varias páginas con la clave: intentar aumentar la yield Request(url) aumenta

AssertionError: Middleware myDownloaderMiddleware.process_request must return None, Response or Request, got generator

Cuál es la solución más limpia para

  • obtener la clave asincrónicamente de la base de datos
  • para cada clave, genera varias solicitudes

Puede dejar que la devolución de llamada para el objeto Diferido pase las URL a un generador de algún tipo. El generador convertirá las URL recibidas en objetos de Request scrapy y los cederá. A continuación se muestra un ejemplo con el código que ha vinculado (no probado):

import scrapy from Queue import Queue from pdb import set_trace as st from twisted.internet.defer import Deferred, inlineCallbacks class ExampleSpider(scrapy.Spider): name = ''example'' def __init__(self): self.urls = Queue() self.stop = False self.requests = request_generator() self.deferred = deferred_generator() def deferred_generator(self): d = Deferred() d.addCallback(self.deferred_callback) yield d def request_generator(self): while not self.stop: url = self.urls.get() yield scrapy.Request(url=url, callback=self.parse) def start_requests(self): return self.requests.next() def parse(self, response): st() # when you need to parse the next url from the callback yield self.requests.next() @static_method def deferred_callback(url): self.urls.put(url) if no_more_urls(): self.stop = True

No olvide detener el generador de solicitudes cuando haya terminado.