python - bypass - ¿Cómo configuro Scrapy para tratar con un captcha
python bypass captcha (1)
Estoy intentando eliminar un sitio que requiere que el usuario ingrese el valor de búsqueda y un captcha. Tengo una rutina de reconocimiento óptico de caracteres (OCR) para el captcha que tiene éxito aproximadamente el 33% del tiempo. Como los captchas son siempre texto alfabético, quiero volver a cargar el captcha si la función OCR devuelve caracteres no alfabéticos. Una vez que tengo una "palabra" de texto, quiero enviar el formulario de búsqueda.
Los resultados vuelven en la misma página, con el formulario listo para una nueva búsqueda y un nuevo captcha. Entonces necesito enjuagarme y repetir hasta que haya agotado mis términos de búsqueda.
Aquí está el algoritmo de nivel superior:
- Cargar la página inicialmente
- Descargue la imagen del captcha, ejecútela a través del OCR
- Si el OCR no regresa con un resultado de solo texto, actualice el captcha y repita este paso
- Envíe el formulario de consulta en la página con el término de búsqueda y captcha
- Verifique la respuesta para ver si el captcha era correcto
- Si fue correcto, raspe los datos
- Ir a 2
Intenté utilizar una canalización para obtener el captcha, pero luego no tengo el valor para el envío del formulario. Si solo busco la imagen sin pasar por el marco, usando urllib o algo así, entonces la cookie con la sesión no se envía, por lo que la validación de captcha en el servidor falla.
¿Cuál es la forma ideal de Scrapy para hacer esto?
Es un tema realmente profundo con un montón de soluciones. Pero si desea aplicar la lógica que ha definido en su publicación, puede usar scrapy Downloader Middlewares .
Algo como:
class CaptchaMiddleware(object):
max_retries = 5
def process_response(request, response, spider):
if not request.meta.get(''solve_captcha'', False):
return response # only solve requests that are marked with meta key
catpcha = find_catpcha(response)
if not captcha: # it might not have captcha at all!
return response
solved = solve_captcha(captcha)
if solved:
response.meta[''catpcha''] = captcha
response.meta[''solved_catpcha''] = solved
return response
else:
# retry page for new captcha
# prevent endless loop
if request.meta.get(''catpcha_retries'', 0) == 5:
logging.warning(''max retries for captcha reached for {}''.format(request.url))
raise IgnoreRequest
request.meta[''dont_filter''] = True
request.meta[''captcha_retries''] = request.meta.get(''captcha_retries'', 0) + 1
return request
Este ejemplo interceptará cada respuesta e intentará resolver el captcha. Si falla, volverá a intentar la página para el nuevo captcha, si es exitoso agregará algunas claves meta a la respuesta con valores de captcha resueltos.
En tu araña lo usarías así:
class MySpider(scrapy.Spider):
def parse(self, response):
url = ''''# url that requires captcha
yield Request(url, callback=self.parse_captchad, meta={''solve_captcha'': True},
errback=self.parse_fail)
def parse_captchad(self, response):
solved = response[''solved'']
# do stuff
def parse_fail(self, response):
# failed to retrieve captcha in 5 tries :(
# do stuff