2011-11-03 12 views
10

Il mio script Scrapy sembra funzionare correttamente quando lo eseguo in scenari "una tantum" dalla riga di comando, ma se provo a eseguire il codice due volte nella stessa sessione python ottengo questo errore:Esecuzione di attività Scrapy in Python

"ReactorNotRestartable"

Perché?

Il codice incriminato (ultima riga genera l'errore):

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() 

risposta

11

Vicino alla risposta di Joël, ma voglio elaborare un po 'più di quanto sia possibile nei commenti. Se si guarda allo Crawler source code, si vede che la classe CrawlerProcess ha una start, ma anche una funzione stop. Questa funzione stop si occupa della pulizia degli interni della scansione in modo che il sistema finisca in uno stato da cui è possibile ricominciare.

Quindi, se si desidera riavviare la scansione senza uscire dal processo, chiamare crawler.stop() al momento opportuno. Più tardi, chiama semplicemente crawler.start() per riprendere le operazioni.

Modifica: in retrospettiva, questo non è possibile (a causa del reattore Twisted, come menzionato in una risposta diversa); il stop si occupa solo di una terminazione pulita. Guardando indietro al mio codice, mi è capitato di avere un wrapper per i processi Crawler. Qui di seguito puoi trovare un codice (redatto) per farlo funzionare usando il modulo multiprocessing di Python. In questo modo puoi riavviare più facilmente i crawler. (Nota:. Ho trovato il codice online il mese scorso, ma non ho incluso la fonte ... quindi se qualcuno sa dove è venuto, io aggiornare i crediti per la fonte)

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

aggiungendo crawler.stop() immediatamente dopo crawler.start() non ha aiutato - come si fa Scopro il "tempo appropriato"? – Trindaz

+0

@Trindaz: Non ero corretto in quella chiamata, per favore vedi la risposta aggiornata. – jro

+0

Grazie per l'aggiornamento @jro. Ho visto questo frammento anche prima e, se l'ho interpretato correttamente, il concetto è che puoi raggirare quanto vuoi aggiungendo gli spider a un crawler che non muore mai, piuttosto che provare a riavviare un crawler per ogni tentativo fai a "eseguire" un ragno. Ho contrassegnato questo come una soluzione perché tecnicamente risolve il mio problema ma è inutilizzabile per me perché non voglio fare affidamento sugli oggetti persistenti del crawler nell'applicazione django che sto usando. Ho finito per scrivere una soluzione basata puramente su BeautifulSoup e urllib2. – Trindaz

-1

mi sembra che non è possibile utilizzare crawler.start() comando due volte: potrebbe essere necessario ricrearlo, se si desidera che venga eseguito una seconda volta .

2

crawler.start() avvia il reattore contorto. Ci può essere solo un reattore.

Se si desidera eseguire più ragni - uso

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

scrapy 0.14 non supporta più spider in un processo di scansione. – goh

+0

non sono stati testati, ma questo potrebbe funzionare (osservando il codice sorgente): 'crawler.engine.open_spider (another_spider)' – warvariuc

+0

ha appena provato i tuoi suggerimenti. Hmm non ho potuto fermare il processo ... – goh

0

ho usato per iniziare le discussioni reattore più volte in un'unica applicazione e di evitare errori ReactorNotRestartable.

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

Ecco la spiegazione dettagliata: Run a Scrapy spider in a Celery Task

Problemi correlati