Scrapy – Continúa obteniendo urls para rastrear desde la base de datos

Me gustaría obtener continuamente las URL para rastrear desde una base de datos. Hasta ahora he tenido éxito en recuperar las URL de la base, pero me gustaría que mi araña siguiera leyendo desde esa base, ya que la tabla estará poblada por otra hebra.

Tengo una canalización que elimina la url de la tabla una vez que se rastrea (funciona). En otras palabras, me gustaría usar mi base de datos como una cola. Probé diferentes enfoques sin suerte.

Aquí está mi spider.py

class MySpider(scrapy.Spider): MAX_RETRY = 10 logger = logging.getLogger(__name__) name = 'myspider' start_urls = [ ] @classmethod def from_crawler(cls, crawler, *args, **kwargs): spider = super(MySpider, cls).from_crawler(crawler, *args, **kwargs) crawler.signals.connect(spider.spider_closed, signals.spider_closed) return spider def __init__(self): db = MySQLdb.connect( user='myuser', passwd='mypassword', db='mydatabase', host='myhost', charset='utf8', use_unicode=True ) self.db = db self.logger.info('Connection to database opened') super(MySpider, self) def spider_closed(self, spider): self.db.close() self.logger.info('Connection to database closed') def start_requests(self): cursor = self.db.cursor() cursor.execute('SELECT * FROM mytable WHERE nbErrors < %s', (self.MAX_RETRY,)) rows = cursor.fetchall() for row in rows: yield Request(row[0], self.parse, meta={ 'splash': { 'args':{ 'html': 1, 'wait': 2 } } }, errback=self.errback_httpbin) cursor.close() 

Muchas gracias

EDITAR

Aquí está mi nuevo código.

 @classmethod def from_crawler(cls, crawler, *args, **kwargs): spider = super(MySpider, cls).from_crawler(crawler, *args, **kwargs) crawler.signals.connect(spider.spider_closed, signals.spider_closed) crawler.signals.connect(spider.spider_idle, signals.spider_idle) return spider def spider_idle(self, spider): self.logger.info('IDLE') time.sleep(5) for url in self.getUrlsToCrawl(): self.logger.info(url[1]) self.crawler.engine.crawl(Request(url[1], self.parse, meta={ 'splash': { 'args':{ 'html': 1, 'wait': 5 } }, 'dbId': url[0] }, errback=self.errback_httpbin), self) raise DontCloseSpider def getUrlsToCrawl(self): dateNowUtc = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S") cursor = self.db.cursor() cursor.execute('SELECT id, url FROM mytable WHERE nbErrors < %s AND domain = %s and nextCrawl < %s', (self.MAX_RETRY, self.domain, dateNowUtc)) urls = cursor.fetchall() cursor.close() return urls 

En mis registros puedo ver:
INFO: IDLE
INFO: someurl
INFO: IDLE
INFO: someurl

Pero cuando actualizo los datos en mi tabla para obtener más o menos urls, la salida nunca cambia. Parece que los datos recostackdos no son nuevos y nunca rastreo las solicitudes realizadas en el método spider_idle

Personalmente recomendaría comenzar una nueva araña cada vez que tengas que rastrear algo, pero si quieres mantener vivo el proceso, te recomendaría usar la señal spider_idle :

 @classmethod def from_crawler(cls, crawler, *args, **kwargs): spider = super(MySpider, cls).from_crawler(crawler, *args, **kwargs) crawler.signals.connect(spider.spider_closed, signals.spider_closed) crawler.signals.connect(spider.spider_idle, signals.spider_idle) return spider ... def spider_idle(self, spider): # read database again and send new requests # check that sending new requests here is different self.crawler.engine.crawl( Request( new_url, callback=self.parse), spider ) 

Aquí está enviando nuevas solicitudes antes de que la araña en realidad se cierre.