Impossibile eliminare alcuni errori sollevati da process_exception

Sep 21 2020

Sto cercando di non mostrare / ricevere qualche errore generato da scrapy all'interno process_responsedi RetryMiddleware. L'errore che lo script incontra quando viene superato il limite massimo di tentativi. Ho usato proxy all'interno del middleware. La cosa strana è che l'eccezione generata dallo script si trova già EXCEPTIONS_TO_RETRYnell'elenco. È del tutto normale che lo script a volte possa superare il numero massimo di tentativi senza alcun successo. Tuttavia, semplicemente non desidero vedere quell'errore anche quando è presente, il che significa sopprimerlo o aggirarlo.

L'errore è come:

Traceback (most recent call last):
  File "middleware.py", line 43, in process_request
    defer.returnValue((yield download_func(request=request,spider=spider)))
twisted.internet.error.TCPTimedOutError: TCP connection timed out: 10060: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond..

Ecco come appare process_responseall'interno RetryMiddleware:

class RetryMiddleware(object):
    cus_retry = 3
    EXCEPTIONS_TO_RETRY = (defer.TimeoutError, TimeoutError, DNSLookupError, \
        ConnectionRefusedError, ConnectionDone, ConnectError, \
        ConnectionLost, TCPTimedOutError, TunnelError, ResponseFailed)

    def process_exception(self, request, exception, spider):
        if isinstance(exception, self.EXCEPTIONS_TO_RETRY) \
                and not request.meta.get('dont_retry', False):
            return self._retry(request, exception, spider)

    def _retry(self, request, reason, spider):
        retries = request.meta.get('cus_retry',0) + 1
        if retries<=self.cus_retry:
            r = request.copy()
            r.meta['cus_retry'] = retries
            r.meta['proxy'] = f'https://{ip:port}'
            r.dont_filter = True
            return r
        else:
            print("done retrying")

Come posso eliminare gli errori in EXCEPTIONS_TO_RETRY?

PS: l'errore che lo script incontra quando viene raggiunto il limite massimo di tentativi, indipendentemente dal sito scelto.

Risposte

1 robots.txt Sep 27 2020 at 14:55

Quando viene raggiunto il numero massimo di tentativi, il metodo come parse_error()dovrebbe gestire qualsiasi errore se è presente nel tuo spider:

def start_requests(self):
    for start_url in self.start_urls:
        yield scrapy.Request(start_url,errback=self.parse_error,callback=self.parse,dont_filter=True)

def parse_error(self, failure):
    # print(repr(failure))
    pass

Tuttavia, ho pensato di suggerire un approccio completamente diverso qui. Se segui il percorso seguente, non hai bisogno di alcun middleware personalizzato. Tutto, incluso il nuovo tentativo di logica, è già presente nello spider.

class mySpider(scrapy.Spider):
    name = "myspider"
    start_urls = [
        "some url",
    ]

    proxies = [] #list of proxies here
    max_retries = 5
    retry_urls = {}

    def parse_error(self, failure):
        proxy = f'https://{ip:port}'
        retry_url = failure.request.url
        if retry_url not in self.retry_urls:
            self.retry_urls[retry_url] = 1
        else:
            self.retry_urls[retry_url] += 1
        
        if self.retry_urls[retry_url] <= self.max_retries:
            yield scrapy.Request(retry_url,callback=self.parse,meta={"proxy":proxy,"download_timeout":10}, errback=self.parse_error,dont_filter=True)
        else:
            print("gave up retrying")

    def start_requests(self):
        for start_url in self.start_urls:
            proxy = f'https://{ip:port}'
            yield scrapy.Request(start_url,callback=self.parse,meta={"proxy":proxy,"download_timeout":10},errback=self.parse_error,dont_filter=True)

    def parse(self,response):
        for item in response.css().getall():
            print(item)

Non dimenticare di aggiungere la seguente riga per ottenere il suddetto risultato dal suggerimento sopra:

custom_settings = {
    'DOWNLOADER_MIDDLEWARES': {
        'scrapy.downloadermiddlewares.retry.RetryMiddleware': None,
    }
}

A proposito, sto usando scrapy 2.3.0.

Noname Sep 26 2020 at 22:19

Forse il problema non è dalla tua parte, ma potrebbe esserci qualcosa di sbagliato nel sito di terze parti. Forse c'è un errore di connessione sul loro server o forse è sicuro in modo che nessuno possa accedervi.

Perché l'errore dice anche che l'errore è con la parte in grado di spegnerlo o non funziona correttamente, forse prima controlla se il sito di terze parti funziona quando richiesto. Prova a contattarli se puoi.

Perché l'errore non è da parte tua, è dalla fine della festa come dice l'errore.

Questa domanda è simile a Scrapy - Imposta timeout connessione TCP

ta_duke Sep 29 2020 at 06:07

Prova a correggere il codice nel raschietto stesso. A volte avere una cattiva funzione di analisi può portare a un errore del tipo che stai descrivendo. Una volta corretto il codice, è andato via per me.