2012-10-24 16 views
5

Ho scritto uno spider che utilizza scrapy, uno che fa un sacco di richieste HtmlXPathSelector per separare i siti. Crea una riga di dati in un file .csv dopo che ciascuna richiesta è (in modo asincrono) soddisfatta. È impossibile vedere quale richiesta è soddisfatta per ultimo, perché la richiesta viene ripetuta se non sono stati ancora estratti dati (occasionalmente i dati vengono saltati alcune volte). Anche se inizio con una lista ordinata, l'output è confuso perché le righe vengono scritte immediatamente dopo l'estrazione dei dati.La funzione di Python Scrapy deve essere richiamata appena prima che venga inviato il segnale spider_closed?

Ora mi piacerebbe ordinare quell'elenco in base a una colonna, ma dopo ogni richiesta è fatta. È possibile utilizzare il segnale "spider_closed" per attivare una funzione reale? Come di seguito, ho provato a connettere il segnale con il dispatcher, ma questa funzione sembra stampare solo cose, piuttosto che lavorare con variabili o persino chiamare altre funzioni.

def start_requests(self) 
    ... dispatcher.connect(self.spider_closed, signal=signals.engine_stopped) .... 


def spider_closed(spider): 
    print 'this gets printed alright' # <-only if the next line is omitted... 
    out = self.AnotherFunction(in)  # <-This doesn't seem to run 
+0

Penso che sia possibile collegare più di 1 funzione a un segnale. Questo risolverebbe il tuo problema? –

+0

Puoi, infatti, collegare una funzione al segnale ... Credo che il mio vero problema fosse con la struttura di 'scrapy' - questo è stato risolto creando un file .py da eseguire prima attraverso lo spider, quindi ordina il file di output in seguito. Questo ha aiutato immensamente: http://snipplr.com/view/67012/selfcontained-script-to-crawl-a-site-updated-scrapy-130dev/ – corg

+1

Non dovresti dispatcher.connect (...) essere in __init __ () invece di start_requests()? – imwilsonxu

risposta

0

Ho violato una pipeline per risolvere questo problema per voi.

di file: Project.middleware_module.SortedCSVPipeline

import csv 
from scrapy import signals 


class SortedCSVPipeline(object): 

    def __init__(self): 
     self.items = [] 
     self.file_name = r'YOUR_FILE_PATH_HERE' 
     self.key = 'YOUR_KEY_HERE' 

    @classmethod 
    def from_crawler(cls, crawler): 
     pipeline = cls() 
     crawler.signals.connect(pipeline.spider_closed, signals.spider_closed) 
     return pipeline 

    def spider_closed(self, spider): 
     for item in sorted(self.items, key=lambda k: k[self.key]): 
      self.write_to_csv(item) 

    def process_item(self, item, spider): 
     self.items.append(item) 
     return item 

    def write_to_csv(self, item): 
     writer = csv.writer(open(self.file_name, 'a'), lineterminator='\n') 
     writer.writerow([item[key] for key in item.keys()]) 

di file: settings.py

ITEM_PIPELINES = {"Project.middleware_module.SortedCSVPipeline.SortedCSVPipeline" : 1000} 

Quando si esegue questo non sarà necessario utilizzare più un esportatore elemento perché questo gasdotto farà il csv scrivendo per te. Inoltre, il 1000 nella voce della pipeline nelle impostazioni deve essere un valore superiore rispetto a tutte le altre pipeline che si desidera eseguire prima di questa. Ho provato questo nel mio progetto e ha portato a un file csv ordinato dalla colonna che ho specificato! HTH

Cheers

+0

Beh, non ho notato che questo era del 2012 ... Spero che aiuti qualcuno fuori lol – rocktheartsm4l

+0

Grazie per resuscitare questo hah - non ho più il progetto, ma mi fido che questo avrebbe funzionato – corg

Problemi correlati