2012-06-17 7 views
9

Attualmente sto lavorando a un progetto di raschiamento che è molto importante per garantire che OGNI richiesta sia stata gestita correttamente, ovvero per registrare un errore o per salvare un risultato positivo. Ho già implementato lo spider di base e ora posso elaborare il 99% delle richieste con successo, ma potrei ottenere errori come captcha, 50x, 30x, o anche campi non sufficienti nel risultato (quindi cercherò un altro sito web per trova i campi mancanti).come elaborare tutti i tipi di eccezione in un progetto scrapy, in errback e callback?

In un primo momento, ho pensato che fosse più "logico" sollevare eccezioni nel richiamo dell'analisi e elaborarle tutte in errore, questo potrebbe rendere il codice più leggibile. Ma ho cercato solo di scoprire che l'errback può solo intrappolare gli errori nel modulo downloader, come gli stati di risposta non-200. Se sollevo un ParseError auto-implementato nel callback, lo spider lo solleva e si ferma.

Anche se dovrò elaborare la richiesta di parsing direttamente nel callback, non so come riprovare immediatamente la richiesta nel callback in modo pulito. Sai, potrei dover includere un proxy diverso per inviare un'altra richiesta o modificare l'intestazione di una richiesta.

Ammetto che sono relativamente nuovo alla scrapy ma ho provato avanti e indietro per giorni e ancora non riesco a farlo funzionare ... Ho controllato ogni singola domanda su SO e nessuno corrisponde, grazie in anticipo per Aiuto.

UPDATE: Mi rendo conto che questo potrebbe essere una questione molto complessa e così cerco di illustrare lo scenario nel seguente pseudo codice, speriamo che questo aiuta:

from scraper.myexceptions import * 

def parseRound1(self, response): 

    .... some parsing routines ... 
    if something wrong happened: 
     # this causes the spider raises a SpiderException and stops 
     raise CaptchaError 
    ... 

    if no enough fields scraped: 
     raise ParseError(task, "no enough fields") 
    else: 
     return items 

def parseRound2(self, response): 
    ...some other parsing routines... 

def errHandler(self, failure): 
    # how to trap all the exceptions? 
    r = failure.trap() 
    # cannot trap ParseError here 
    if r == CaptchaError: 
     # how to enqueue the original request here? 
     retry 
    elif r == ParseError: 
     if raised from parseRound1: 
      new request for Round2 
     else: 
      some other retry mechanism 
    elif r == HTTPError: 
     ignore or retry 

risposta

0

In un primo momento, ho pensato che sia più "logica "per aumentare le eccezioni nel callback dell'analisi ed elaborarle tutte in errore, questo potrebbe rendere il codice più leggibile. Ma ho provato solo a scoprire che errback può solo intrappolare gli errori nel modulo downloader, come gli stati di risposta non-200. Se rilevo un ParseError auto-implementato nel callback, lo spider solo lo alza e si ferma.

Sì, hai ragione - callback e errback sono destinati ad essere utilizzati solo con downloader, come twisted viene utilizzato per il download di una risorsa, e hanno subito una torsione utilizza deffereds - è per questo che sono necessari callback.

L'unica parte asincrona in scrapy di solito è il downloader, tutte le altre parti funzionano in modo sincrono.

Quindi, se si vuole catturare tutti gli errori non downloader - fai da te:

  • fare una grande try/tranne che nel callback
  • o fare un decoratore per le funzioni di callback, che faranno questo (mi piace questa idea più)
+0

grazie per aver chiarito le responsabilità di 'callback' e' err back'! Questo mi ha lasciato perplesso per molto tempo .. immagino che avrei dovuto capirlo scrivendo qualche spider di prova in precedenza ... –

8

EDIT 16 nov 2012: Scrapy> = 0.16 utilizza un metodo diverso per fissare metodi ai segnali, ad esempio in più ha aggiunto

Il più semplice soluzione sarebbe quello di scrivere un'estensione in cui si catturano i fallimenti, utilizzando i segnali Scrapy. Ad esempio; la seguente estensione cattura tutti gli errori e stampa un traceback.

Si può fare qualsiasi cosa con il salvataggio come nel database, o inviare una e-mail - che di per sé è un'istanza di twisted.python.failure.Failure.

Per le versioni Scrapy fino a 0.16:

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

class FailLogger(object): 
    def __init__(self): 
    """ 
    Attach appropriate handlers to the signals 
    """ 
    dispatcher.connect(self.spider_error, signal=signals.spider_error) 

    def spider_error(self, failure, response, spider): 
    print "Error on {0}, traceback: {1}".format(response.url, failure.getTraceback()) 

Per le versioni Scrapy da 0,16 e fino:

from scrapy import signals 

class FailLogger(object): 

    @classmethod 
    def from_crawler(cls, crawler): 
    ext = cls() 

    crawler.signals.connect(ext.spider_error, signal=signals.spider_error) 

    return ext 

    def spider_error(self, failure, response, spider): 
    print "Error on {0}, traceback: {1}".format(response.url, failure.getTraceback()) 

Si potrebbe abilitare l'estensione nelle impostazioni, con qualcosa di simile:

EXTENSIONS = { 
'spiders.extensions.faillog.FailLogger': 599, 
} 
+0

Grazie Sjaak, ho dato un'occhiata alla documentazione riguardante l'estensione di scrapy con più attenzione, questo sembra giusto adattarsi le mie esigenze! Peccato non l'ho capito bene una settimana fa, quando ho iniziato a fare i cattivi. Darò un colpo dopo, sto pensando di utilizzare una lista redis per la pianificazione. –

+0

Non sono sicuro se questo richiede un'altra domanda, ma potresti spiegare quali modifiche devono essere apportate per incorporare la classe 'FailLogger' nel resto di scrapy? Ho modificato 'EXTENSIONS' in' settings.py' e ho aggiunto 'faillog.py' alla directory' extensions'. Scrapy outputs '2016-01-29 16:24:07 [scrapy] INFO: Estensioni abilitate: FailLogger', quindi penso che la mia implementazione sia ok. Sto testando [questo link] (https://www.release.tdnet.info/inbs/140120160122493328.pdf), che restituisce un 'DNSLookupError', ma l'istruzione print nella classe' FailLogger' non viene restituita. .. – JSB

Problemi correlati