2012-09-12 16 views
27

C'è un modo per attivare un metodo in una classe Spider appena prima che termini?scrapy: chiama una funzione quando un ragno si interrompe

posso terminare il ragno me stesso, in questo modo:

class MySpider(CrawlSpider): 
    #Config stuff goes here... 

    def quit(self): 
     #Do some stuff... 
     raise CloseSpider('MySpider is quitting now.') 

    def my_parser(self, response): 
     if termination_condition: 
      self.quit() 

     #Parsing stuff goes here... 

Ma non riesco a trovare tutte le informazioni su come determinare quando il ragno sta per uscire in modo naturale.

risposta

50

Sembra che sia possibile registrare un listener di segnali tramite dispatcher.

vorrei provare qualcosa di simile:

from scrapy import signals 
from scrapy.xlib.pydispatch import dispatcher 

class MySpider(CrawlSpider): 
    def __init__(self): 
     dispatcher.connect(self.spider_closed, signals.spider_closed) 

    def spider_closed(self, spider): 
     # second param is instance of spder about to be closed. 
+3

funziona perfettamente. Ma suggerirei di nominare il metodo MySpider.quit() o qualcosa di simile, per evitare confusione con il nome del segnale. Grazie! – Abe

+0

Ottima soluzione. E sì, l'esempio dovrebbe funzionare esattamente allo stesso modo con un 'CrawlSpider'. –

+0

Anche questa soluzione funziona bene su Scrapy ** 0.20.0 **, contrariamente a quanto detto da @Chris in seguito. – not2qubit

7

Per me quanto sopra non ha funzionato/è obsoleto almeno per Scrapy 0,19. ho preso a lavorare con il seguente però:

from scrapy.signalmanager import SignalManager 
from scrapy.xlib.pydispatch import dispatcher 

class MySpider(CrawlSpider): 
    def __init__(self, *args, **kwargs): 
     super(MySpider, self).__init__(*args, **kwargs) 
     SignalManager(dispatcher.Any).connect(
      self.closed_handler, signal=signals.spider_closed) 

    def closed_handler(self, spider): 
     # do stuff here 
26

solo per aggiornare, si può chiamare closed funzione come questa:

class MySpider(CrawlSpider): 
    def closed(self, reason): 
     do-something() 
+3

Nel mio scrapy è 'def close (auto, ragione):', non 'chiuso' –

+2

@AminahNuraini Scrapy 1.0.4' def chiuso (ragione) ' –

4

Per Scrapy versione 1.0.0+ (essa può funziona anche per le versioni precedenti).

from scrapy import signals 

class MySpider(CrawlSpider): 
    name = 'myspider' 

    @classmethod 
    def from_crawler(cls, crawler, *args, **kwargs): 
     spider = super(MySpider, cls).from_crawler(crawler, *args, **kwargs) 
     crawler.signals.connect(spider.spider_opened, signals.spider_opened) 
     crawler.signals.connect(spider.spider_closed, signals.spider_closed) 
     return spider 

    def spider_opened(self, spider): 
     print('Opening {} spider'.format(spider.name)) 

    def spider_closed(self, spider): 
     print('Closing {} spider'.format(spider.name)) 

Un buon utilizzo è quello di aggiungere tqdm barra di avanzamento per Scrapy ragno.

# -*- coding: utf-8 -*- 
from scrapy import signals 
from scrapy.linkextractors import LinkExtractor 
from scrapy.spiders import CrawlSpider, Rule 
from tqdm import tqdm 


class MySpider(CrawlSpider): 
    name = 'myspider' 
    allowed_domains = ['somedomain.comm'] 
    start_urls = ['http://www.somedomain.comm/ccid.php'] 

    rules = (
     Rule(LinkExtractor(allow=r'^http://www.somedomain.comm/ccds.php\?id=.*'), 
      callback='parse_item', 
      ), 
     Rule(LinkExtractor(allow=r'^http://www.somedomain.comm/ccid.php$', 
          restrict_xpaths='//table/tr[contains(., "SMTH")]'), follow=True), 
    ) 

    def parse_item(self, response): 
     self.pbar.update() # update progress bar by 1 
     item = MyItem() 
     # parse response 
     return item 

    @classmethod 
    def from_crawler(cls, crawler, *args, **kwargs): 
     spider = super(MySpider, cls).from_crawler(crawler, *args, **kwargs) 
     crawler.signals.connect(spider.spider_opened, signals.spider_opened) 
     crawler.signals.connect(spider.spider_closed, signals.spider_closed) 
     return spider 

    def spider_opened(self, spider): 
     self.pbar = tqdm() # initialize progress bar 
     self.pbar.clear() 
     self.pbar.write('Opening {} spider'.format(spider.name)) 

    def spider_closed(self, spider): 
     self.pbar.clear() 
     self.pbar.write('Closing {} spider'.format(spider.name)) 
     self.pbar.close() # close progress bar 
+0

questa risposta deve essere selezionata, grazie Levon –

0

se si dispone di molti ragni e volete fare qualcosa prima che ognuno di loro chiusura, forse sarà conveniente aggiungere statscollector nel progetto.

nelle impostazioni:

STATS_CLASS = 'scraper.stats.MyStatsCollector' 

e collezionista:

from scrapy.statscollectors import StatsCollector 

class MyStatsCollector(StatsCollector): 
    def _persist_stats(self, stats, spider): 
     do something here 
Problemi correlati