Volver al blog
Guías
Mihnea-Octavian Manolache2 de mayo de 202310 min de lectura

Aprenda a eludir la detección de Cloudflare con el mejor navegador Selenium

Aprenda a eludir la detección de Cloudflare con el mejor navegador Selenium

¿Cómo detecta Cloudflare los navegadores headless?

Cloudflare es una empresa tecnológica con una red gigantesca. Se centran en servicios como CDN, DNS y varios sistemas de seguridad en línea. Su cortafuegos de aplicaciones web suele estar diseñado para proteger frente a ataques como DDoS o cross site scripting. En los últimos años, Cloudflare añadió y otros proveedores en el campo introdujeron sistemas de huellas dactilares, capaces de detectar navegadores sin cabeza. Como es de suponer, uno de los primeros afectados por estas técnicas es Selenium. Y puesto que la industria del web scraping depende en gran medida de esta tecnología, los scrapers también se ven directamente afectados.

Antes de pasar a las técnicas anti-bot, creo que es importante discutir cómo cloudflare detecta Selenium. El sistema puede ser muy complejo. Por ejemplo, hay propiedades en un navegador de las que carece un controlador web. La interfaz `navigator` de un navegador tiene incluso una propiedad llamada `webdriver` que indica si un navegador está controlado por automatización. Y eso te delata al instante. Si quieres experimentar con ello:

  • Abra las herramientas de desarrollo de su navegador
  • Navegar a la consola
  • Escriba el siguiente comando: `navigator.webdriver`

En tu caso, debería devolver `false`. Pero si lo intentas con Puppeteer o Selenium, obtendrás `true`. Si te estás preguntando cómo Cloudflare aprovecha esto para detectar bots, pues es bastante sencillo. Todo lo que necesitan hacer es inyectar un script como el siguiente en el sitio web de su socio:

// detection-script.js

const webdriver = navigator.webdriver

// If webdriver returns true, display a reCaptcha

// In this example, I am transferring the user to a Cloudflare challenge page.

// But you get the idea

if ( webdriver ) location.replace('https://cloudflarechallenge.com')

Por supuesto, en la vida real, hay muchos más niveles de detección que utilizan estos proveedores. Incluso el tamaño de la pantalla, la distribución del teclado o los complementos utilizados por los navegadores se utilizan para identificar específicamente un navegador. Si te interesa saber cómo funciona la detección sin navegador, echa un vistazo a mi sencilla prueba de trabajador de servicios. Y eso sólo si te ciñes al navegador. También puedes detectar la actividad de los bots mirando la dirección IP desde la que se origina la petición. Por ejemplo, si estás usando IPs de centros de datos, tus posibilidades de ser bloqueado aumentan con cada petición. Por eso se recomienda usar proxies residenciales o ISP cuando estés construyendo un web scraper.

Cómo evitar Cloudflare con Selenium

Afortunadamente, la comunidad de web scraping es muy activa. Y como hay tanta demanda para eludir Cloudflare y otros proveedores anti-bot, existen soluciones de código abierto en ese ámbito. Se pueden conseguir grandes cosas cuando las comunidades de programadores trabajan juntas. Para avanzar, sugiero que sigamos estos pasos:

  • Realice algunas pruebas para ver si Selenium por defecto puede eludir Cloudflare
  • Añade algunas evasiones adicionales para que nuestros scripts sean más sigilosos

Así que empecemos con nuestro primer paso:

#1: ¿Puede Selenium por defecto eludir Cloudflare?

No soy de los que hacen suposiciones. Y eso es especialmente porque no sabemos con certeza cómo funcionan los sistemas de Cloudflare. Utilizan todo tipo de ofuscación con su código, lo que dificulta la ingeniería inversa. Por eso, a lo largo de mi experiencia como desarrollador, aprendí que probar es la mejor manera de entender cómo funciona un sistema. Así que vamos a construir un scraper básico y ver cómo se comporta en un objetivo real, protegido por Cloudflare.

1.1. Configurar el entorno

Con Python, es mejor aislar nuestros proyectos dentro de un único directorio. Así que vamos a crear una nueva carpeta, abrir una ventana de terminal y navegar hasta ella:

# Crea un nuevo entorno virtual y actívalo

~ » python3 -m venv env && source env/bin/activate

# Instala las dependencias

~ » python3 -m pip install selenium

# Crea un nuevo archivo .py y abre el proyecto en tu IDE

~ » touch app.py && code .

1.2. Construir un raspador web simple con Selenium

Ahora que has configurado con éxito tu proyecto, es hora de añadir algo de código. No vamos a construir nada lujoso aquí. Sólo necesitamos este script para propósitos de prueba. Si quieres aprender sobre scraping avanzado, echa un vistazo a este [LINK] tutorial sobre Pyppeteer.

from selenium import webdriver

from selenium.webdriver.chrome.options import Options

# Configurar Chrome para que se abra en modo sin interfaz gráfica

options = Options()

options.headless = True

# Crear una nueva instancia de Chrome y navegar hasta la página de destino

driver = webdriver.Chrome(options=options)

driver.get('https://www.snipesusa.com/')

# Espera un momento a que se cargue

time.sleep(10)

# Haz una captura de pantalla de la página

driver.get_screenshot_as_file('screenshot.png')

# Cierra el navegador

driver.quit()

Ahora echa un vistazo a la captura de pantalla. Esto es lo que tengo:

Pantalla de verificación contra bots en la página web de Snipes en la que se pide al usuario que mantenga pulsado para confirmar que es humano

Creo que podemos concluir que la prueba ha fallado. El sitio web objetivo está protegido por Cloudflare y, como puede ver, se nos bloquea. Así que por defecto, Selenium no es capaz de eludir Cloudflare. No voy a profundizar y comprobar con otros proveedores de detección de bots. Si quieres hacer más pruebas, aquí tienes algunos objetivos y sus proveedores:

Tabla en la que se enumeran los sitios web y el proveedor de protección contra bots que utilizan, como Kasada, Akamai, DataDome e Incapsula

#2: ¿Puede el sigiloso selenio eludir Cloudflare?

En primer lugar, permítanme aclarar los términos. Por Selenium sigiloso me refiero a una versión de Selenium que puede pasar desapercibida y eludir Cloudflare. No me refiero a ninguna técnica específica de sigilo. Hay un par de maneras de implementar técnicas de evasión en Selenium. Hay paquetes que se encargan de ello, o puedes usar el `execute_cdp_cmd` para interactuar directamente con la API de Chrome. Esto último te permite más control pero requiere más trabajo. Aquí tienes un ejemplo de cómo podrías usarlo para cambiar el valor del agente de usuario:

driver.execute_cdp_cmd('Emulation.setUserAgentOverride', {

               "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win32; x86) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36",

               "platform": "Win32",

               "acceptLanguage":"ro-RO"

       })

Pero tendrías que pasar por CDP e identificar las APIs que te permiten hacer todos los cambios necesarios. Así que por el momento, vamos a probar con algunos paquetes.

1.1. Selenio sigiloso

Hay al menos dos paquetes que puede utilizar para hacer que Selenium sea sigiloso. Hasta este punto, sin embargo, ninguno de ellos está garantizado para eludir Cloudflare. Una vez más, tenemos que probar y ver si alguno de ellos funciona. En primer lugar, echemos un vistazo a `selenium-stealth`. Este paquete es un wrapper alrededor de `puppeteer-extra-plugin-stealth`, haciendo posible usar las evasiones de Puppeteer con Selenium de Python. Para usarlo, tienes que instalarlo primero. Abre una ventana de terminal e introduce este comando

# Instalar selenium-stealth

~ » python3 -m pip install selenium-stealth

Ya está todo listo. Podemos usarlo para hacer nuestro raspador anterior más sigiloso:

from selenium import webdriver

from selenium.webdriver.chrome.options import Options

from selenium_stealth import stealth

import time

# Configurar Chrome para que se abra en modo sin interfaz gráfica

options = Options()

options.headless = True

# Crear una nueva instancia de Chrome

driver = webdriver.Chrome(options=options)

# Aplicar stealth a tu webdriver

stealth(driver,

   languages=["en-US", "en"],

   vendor="Google Inc.",

   platform="Win32",

   webgl_vendor="Intel Inc.",

   renderer="Intel Iris OpenGL Engine",

   fix_hairline=True,

)

# Navega hasta el destino

driver.get('https://www.snipesusa.com/')

# Dale un poco de tiempo para que se cargue

time.sleep(10)

# Haz una captura de pantalla de la página

driver.get_screenshot_as_file('stealth.png')

# Cierra el navegador

driver.quit()

Esta vez, al ejecutar el script, obtuve resultados diferentes a los de la configuración predeterminada de Selenium:

Captura de pantalla de la página web de Snipes en la que aparece un banner promocional de The North Face

La segunda opción que puede utilizar es `undetected_chromedriver`. Este se describe como un `chromedriver optimizado de Selenium`. Vamos a probarlo:

# Instalar undetected_chromedriver

~ » python3 -m pip install undetected_chromedriver

El código es muy similar a nuestro script por defecto. La principal diferencia está en el nombre del paquete. Aquí tenemos un scraper básico con `undetected_chromedriver` y veamos si puede evitar Cloudflare:

import undetected_chromedriver como uc

import time

# Configurar Chrome para que se abra en modo sin interfaz gráfica

options = uc.ChromeOptions()

options.headless = True

# Crear una nueva instancia de Chrome y maximizar la ventana

driver = uc.Chrome(options=options, executable_path='/Applications/Google Chrome.app/Contents/MacOS/Google Chrome')

driver.maximize_window()

# Navegar al destino

driver.get('https://www.snipesusa.com/')

# Esperar un poco a que se cargue

time.sleep(10)

# Hacer una captura de pantalla de la página

driver.get_screenshot_as_file('stealth-uc.png')

# Cerrar el navegador

driver.quit()

Una vez más, la ejecución del script me da buenos resultados. Parece que al menos estos dos paquetes pueden eludir con éxito la protección de Cloudflare. Al menos a corto plazo. A decir verdad, lo más probable es que, si utilizas estos scripts de forma extensiva, Cloudflare se dé cuenta de tu dirección IP y la bloquee. Así que déjame presentarte una tercera opción: Web Scraping API.

1.2. Selenium con API de Web Scraping

Web Scraping API tiene esta increíble característica llamada Modo Proxy. Puedes leer más sobre ello aquí. Pero lo que quiero destacar aquí es que nuestro Modo Proxy puede integrarse exitosamente con Selenium. De esta manera, obtienes acceso a todas las características de evasión que hemos implementado. Y déjame decirte que tenemos un equipo dedicado trabajando en técnicas de evasión personalizadas. En términos técnicos, estamos manejando rotaciones de IP, estamos usando varios proxies, estamos resolviendo captchas y estamos usando la API de Chrome para cambiar continuamente nuestra huella digital. En términos no técnicos, esto se traduce en menos complicaciones por tu parte y una mayor tasa de éxito. Básicamente obtienes la versión más sigilosa de Selenium que existe. Y así es como se hace:

# Instalar selenium-wire

~ » python3 -m pip install selenium-wire

Estamos usando `selenium-wire` para usar Selenium con un proxy. Ahora aquí está el script:

from seleniumwire import webdriver

import time

# Method to encode parameters

def get_params(object):

   params = ''

   for key,value in object.items():

       if list(object).index(key) < len(object) - 1:

           params += f"{key}={value}."

       else:

           params += f"{key}={value}"

   return params

# Your WSA API key

API_KEY = '<YOUR_API_KEY>'

# Default proxy mode parameters

PARAMETERS = {

   "proxy_type":"datacenter",

   "device":"desktop",

   "render_js":1

}

# Set Selenium to use a proxy

options = {

   'proxy': {

       "http": f"http://webscrapingapi.{ get_params(PARAMETERS) }:{ API_KEY }@proxy.webscrapingapi.com:80",

   }

}

# Create a new Chrome instance

driver = webdriver.Chrome(seleniumwire_options=options)

# Navigate to target

driver.get('https://www.httpbin.org/get')

# Retrieve the HTML documeent from the page

html = driver.page_source

print(html)

# Close browser

driver.quit()

Si ejecutas este script un par de veces, verás como la dirección IP cambia cada vez. Ese es nuestro sistema de rotación de IP. En segundo plano, también añade técnicas de evasión. Ni siquiera necesitas preocuparte por ellas. Nosotros nos encargamos de la parte de evasión de Cloudflare para que puedas centrarte más en analizar los datos.

Conclusiones

Si quieres construir un scraper que pueda eludir Cloudflare, tienes que tener en cuenta muchas cosas. Un equipo dedicado puede trabajar 24/7 y aún así no hay garantía de que las evasiones funcionen siempre. Eso es porque, con cada lanzamiento de versión del navegador, existe la posibilidad de que se añadan nuevas características a la API. Y algunas de estas funciones pueden utilizarse para identificar y detectar bots.

Incluso diría que el mejor navegador para evitar Cloudflare y otros proveedores es el que construyes tú mismo. Y nosotros construimos uno en Web Scraping API. Ahora lo compartimos contigo. Así que ¡disfruta del scraping!

Acerca del autor
Mihnea-Octavian Manolache, desarrollador full stack en WebScrapingAPI
Mihnea-Octavian ManolacheDesarrollador Full Stack

Mihnea-Octavian Manolache es ingeniero Full Stack y DevOps en WebScrapingAPI, donde se encarga de desarrollar funciones para los productos y de mantener la infraestructura que garantiza el buen funcionamiento de la plataforma.

Empieza a crear

¿Estás listo para ampliar tu recopilación de datos?

Únete a más de 2000 empresas que utilizan WebScrapingAPI para extraer datos de la web a escala empresarial sin ningún gasto de infraestructura.