¿Cómo procesar todo tipo de excepción en un proyecto desechable, en errback y callback?

Actualmente estoy trabajando en un proyecto de raspado que es muy importante para garantizar que TODAS las solicitudes se manejen correctamente, es decir, para registrar un error o para guardar un resultado exitoso. Ya implementé la araña básica, y ahora puedo procesar el 99% de las solicitudes con éxito, pero puedo obtener errores como captcha, 50x, 30x o incluso no hay suficientes campos en el resultado (luego intentaré con otro sitio web para encontrar los campos que faltan).

Al principio, pensé que es más "lógico" generar excepciones en el retorno de llamada de análisis y procesarlas todas en error, esto podría hacer que el código sea más legible. Pero intenté solo descubrir que el error de retorno solo puede atrapar errores en el módulo de descarga, como los estados de respuesta que no son 200. Si levanto un ParseError autoimplantado en la devolución de llamada, la araña simplemente lo levanta y se detiene.

Incluso si tengo que procesar la solicitud de análisis directamente en la devolución de llamada, no sé cómo volver a intentar la solicitud inmediatamente en la devolución de llamada de forma limpia. Sabes, es posible que tenga que incluir un proxy diferente para enviar otra solicitud o modificar un encabezado de solicitud.

Admito que soy relativamente nuevo en scrapy pero lo he intentado durante días y todavía no puedo hacer que esto funcione ... He revisado todas las preguntas sobre SO y nadie concuerda, gracias de antemano por la ayuda.

ACTUALIZACIÓN: Me doy cuenta de que esta podría ser una pregunta muy compleja, así que trato de ilustrar el escenario en el siguiente pseudo código, espero que esto ayude:

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

Respuestas a la pregunta(2)

Su respuesta a la pregunta