Automatización Web y Captchas¶
Encontrar diferentes tipos de captcha durante un proceso es una situación común cuando estamos desarrollando automatizaciones web.
Pueden presentar diferentes complejidades, lo que hace necesario utilizar diferentes alternativas para resolver cada caso.
Esta guía demostrará las alternativas existentes y las formas más sencillas de resolver diferentes tipos de captcha en automatizaciones web.
Servicios de Resolución de Captchas¶
Actualmente, existen varios servicios para resolver captchas, generalmente estos servicios ofrecen una API y también una extensión para ser utilizada en el navegador.
El plugin de Captcha de BotCity actualmente admite los servicios AntiCaptcha y DeathByCaptcha, el plugin se basa en el uso de la API de estos servicios y es simplemente una forma de facilitar la integración con tu bot.
Si tienes una cuenta en otro servicio, también es posible integrarlo con tu bot. Solo utiliza el código que se refiere a este servicio en lugar de utilizar el plugin.
En los siguientes ejemplos, utilizaremos el servicio AntiCaptcha y demostraremos cómo podemos utilizar la API o la extensión del navegador para resolver captchas.
¿Cuándo utilizar la API o la Extensión del Navegador?¶
Como se mencionó anteriormente, la mayoría de los servicios de resolución de captchas ofrecen, además de una API, una extensión para ser utilizada en el navegador.
A continuación, enumeramos los pros y los contras de cada alternativa:
API¶
-
Pros:
- Por lo general, la resolución se realiza más rápidamente
- No se requiere configuración del navegador, solo realizar las llamadas a la API
- Funciona normalmente con o sin el modo sin cabeza
- La mejor alternativa para Captchas de Imagen
-
Contras:
- Algunas limitaciones para validar captchas invisibles (hCaptcha o reCaptcha)
- Los captchas que utilizan una función de devolución de llamada pueden causar problemas al inyectar la respuesta en la página
Extensión del Navegador¶
-
Pros:
- Identifica y resuelve el captcha automáticamente
- Resuelve el captcha de una manera más "humana", es más difícil que la página lo bloquee
- La mejor alternativa para captchas que utilizan una función de devolución de llamada
-
Contras:
- La resolución del captcha puede llevar tiempo en algunos casos
- En algunos casos, puede no funcionar en el modo sin cabeza (limitación de Chrome)
Resolución de Captchas utilizando la API¶
La resolución de captchas utilizando la API se divide básicamente en dos pasos.
El primer paso es recopilar cierta información de la página y realizar la solicitud. El segundo paso es inyectar la respuesta que se devolvió en la página.
reCaptcha y hCaptcha¶
Para resolver estos tipos de captchas, generalmente siempre necesitaremos la propiedad data-sitekey
de la página.
En la mayoría de los casos, puedes ver el elemento que contiene esta propiedad cuando inspeccionas la página.
Una vez que la API resuelve el captcha, insertaremos el token de respuesta en la página.
Normalmente, esta respuesta se inyectará en el elemento g-recaptcha-response
.
from botcity.web import WebBot
from botcity.plugins.captcha import BotAntiCaptchaPlugin
def main():
bot = WebBot()
bot.headless = False
bot.driver_path = r"<chromedriver path>"
url = "https://www.google.com/recaptcha/api2/demo"
# Opens the website.
bot.browse(url)
# Find element with data-sitekey
captcha_id = bot.find_element('.g-recaptcha').get_attribute('data-sitekey')
# Using plugin with your AntiCaptcha api key
anti_captcha = BotAntiCaptchaPlugin("<API_KEY>")
# Solving Captcha
response = anti_captcha.solve_re(url, captcha_id)
# Inserting response in the recaptcha component of the page
bot.execute_javascript('document.getElementById("g-recaptcha-response").innerHTML = "%s"' % response)
# Clicking the submit button
submit = bot.find_element("#recaptcha-demo-submit")
submit.click()
# Verifying that the resolution worked
assert bot.find_element(".recaptcha-success")
print("Success!")
# Stop the browser and clean up
bot.wait(3000)
bot.stop_browser()
if __name__ == '__main__':
main()
Important
Por lo general, los elementos utilizados siempre aparecen con estos nombres: data-sitekey
y g-recaptcha-response
.
Presta atención a que la página que estás automatizando también utilice este patrón.
Captcha de Imagen¶
Para resolver un Captcha de Imagen, primero debemos guardar el archivo .png
de la imagen.
Cuando la API devuelve el resultado, lo insertaremos en el campo de respuesta de la página.
from botcity.web import WebBot, By
from botcity.plugins.captcha import BotAntiCaptchaPlugin
def main():
bot = WebBot()
bot.headless = False
bot.driver_path = r"<chromedriver path>"
# Opens the website
bot.browse("https://democaptcha.com/demo-form-eng/image.html")
bot.find_element("message", By.NAME).send_keys("Solving captcha!")
# Saving captcha image
captcha_img = bot.find_element("htest_image", By.ID)
captcha_img.screenshot("captcha.png")
# Using plugin with your AntiCaptcha api key
anti_captcha = BotAntiCaptchaPlugin("<API_KEY>")
# Solving Captcha
response = anti_captcha.solve_text("captcha.png")
# Inserting response in the input
captcha_input = bot.find_element("vericode", By.ID)
captcha_input.send_keys(response)
bot.wait(2000)
# Clicking to check captcha
btn_send = bot.find_element("btn.btn-install", By.CLASS_NAME)
btn_send.click()
# Stop the browser and clean up
bot.wait(5000)
bot.stop_browser()
def not_found(label):
print(f"Element not found: {label}")
if __name__ == '__main__':
main()
Tip
Por lo general, la extensión del navegador no identifica automáticamente este tipo de captcha, por lo que utilizar la API es la mejor alternativa para resolver Captchas de Imagen.
Resolución de Captchas utilizando la Extensión del Navegador¶
En el caso del servicio AntiCaptcha, además de utilizar la API, también es posible utilizar una extensión del navegador para resolver captchas automáticamente.
Todo lo que necesitamos hacer es cargar la extensión y enviar un mensaje al navegador para configurar la clave de la API.
Utilizando la Extensión AntiCaptcha con Chrome¶
El primer paso es descargar la extensión .crx
desde el enlace proporcionado por la documentación de AntiCaptcha.
Warning
Para poder descargar correctamente el archivo .crx
y evitar bloqueos, AntiCaptcha recomienda utilizar algunas configuraciones.
Obtén más detalles en este enlace.
Con el archivo descargado, insertemos la siguiente configuración en el código de automatización:
from botcity.web import WebBot, By
from botcity.web.browsers.chrome import default_options
import json
def main():
bot = WebBot()
bot.headless = False
bot.driver_path = r"<chromedriver path>"
# Loading the .crx extension
def_options = default_options()
def_options.add_extension('anticaptcha-plugin_v0.63.crx')
bot.options = def_options
# Opens the website
bot.browse("https://www.google.com/recaptcha/api2/demo")
bot.wait(1000)
# Configuration that will be passed to the extension, adjust for your api key
message = {
'receiver': 'antiCaptchaPlugin',
'type': 'setOptions',
'options': {'antiCaptchaApiKey': '<API_KEY>'}
}
# Run JS code in the web page context and perform a postMessage
bot.driver.execute_script("""
return window.postMessage({});
""".format(json.dumps(message))
)
# Refreshing the page to update the configuration
bot.wait(2000)
bot.refresh()
# Checking result, waits for the "Solved" message
if bot.find_element('.antigate_solver.solved', By.CSS_SELECTOR, waiting_time=180000):
submit = bot.find_element("#recaptcha-demo-submit")
submit.click()
# Stop the browser and clean up
bot.wait(3000)
bot.stop_browser()
def not_found(label):
print(f"Element not found: {label}")
if __name__ == '__main__':
main()
Info
Utilizando Chrome, también es posible realizar esta configuración manualmente utilizando el formato .zip
de la extensión en lugar del archivo .crx
.
Obtén más detalles sobre cómo utilizar la extensión en formato .zip
en este enlace.
Utilizando la Extensión AntiCaptcha con Firefox¶
Utilizando Firefox, la configuración que necesitamos hacer en el navegador es la misma que cuando utilizamos Chrome. La única diferencia es que utilizaremos la extensión en formato .xpi
.
Puedes descargar el archivo .xpi
desde el enlace proporcionado por la documentación de AntiCaptcha.
from botcity.web import WebBot, Browser, By
import json
def main():
bot = WebBot()
bot.headless = False
bot.browser = Browser.FIREFOX
bot.driver_path = r"<geckodriver path>"
# Loading the .xpi extension
bot.install_firefox_extension("anticaptcha-plugin_v0.60.xpi")
# Opens the website
bot.browse("https://www.google.com/recaptcha/api2/demo")
bot.wait(1000)
# Configuration that will be passed to the extension, adjust for your api key
message = {
'receiver': 'antiCaptchaPlugin',
'type': 'setOptions',
'options': {'antiCaptchaApiKey': '<API_KEY>'}
}
# Run JS code in the web page context and perform a postMessage
bot.driver.execute_script("""
return window.postMessage({});
""".format(json.dumps(message))
)
# Refreshing the page to update the configuration
bot.wait(2000)
bot.refresh()
# Checking result, waits for the "Solved" message
if bot.find_element('.antigate_solver.solved', By.CSS_SELECTOR, waiting_time=180000):
submit = bot.find_element("#recaptcha-demo-submit")
submit.click()
# Stop the browser and clean up
bot.wait(3000)
bot.stop_browser()
def not_found(label):
print(f"Element not found: {label}")
if __name__ == '__main__':
main()
Al ejecutar este código, el resultado se verá así:
Info
Esta guía fue construida utilizando el servicio AntiCaptcha como referencia.
Obtén más detalles accediendo a la documentación de AntiCaptcha.