Saltar a contenido

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í:

ReCaptcha

Info

Esta guía fue construida utilizando el servicio AntiCaptcha como referencia.

Obtén más detalles accediendo a la documentación de AntiCaptcha.