Volver al blog
Guías
Mihnea-Octavian ManolacheLast updated on Mar 31, 202612 min read

Cómo ejecutar un navegador sin interfaz gráfica con Python para el scraping web: consejos y trucos

Cómo ejecutar un navegador sin interfaz gráfica con Python para el scraping web: consejos y trucos

El uso de un navegador sin interfaz gráfica (headless) en Python con Selenium es casi la norma en el web scraping. Pero, ¿qué es realmente un navegador sin interfaz gráfica? ¿Cuál es el mejor navegador sin interfaz gráfica para Selenium? ¿Y por qué utilizar un navegador sin interfaz gráfica en Python cuando se dispone de `requests`? Bueno, hay muchas preguntas en torno a este tema. Lo que significa que tenemos muchas respuestas que descubrir juntos. Pero antes de profundizar más, definamos algunos objetivos de aprendizaje. Al final de este artículo, deberías ser capaz de:

  • Entender qué es un navegador sin interfaz gráfica y sus casos de uso
  • Saber cómo abrir un navegador sin interfaz gráfica en Python
  • Crear un rastreador web con Python y Selenium

Y, por último, también hablaremos de alternativas a los navegadores sin interfaz gráfica de Python. Aunque nos centremos en Python, mi objetivo es descubrir la mejor solución de scraping. Y eso tiene en cuenta el tiempo de respuesta, los recursos utilizados, etc. Así que, sin más preámbulos, ¡vamos a entrar en materia!

¿Qué significa «navegador sin interfaz gráfica» en Python?

A grandes rasgos, un navegador es un programa informático que permite a los usuarios navegar e interactuar con una página web. Un navegador sin interfaz gráfica es exactamente eso, pero sin interfaz gráfica de usuario. Esto significa que un navegador sin interfaz gráfica de Python es un programa que puede:

  • Navegar a cualquier sitio web en Internet
  • Representar archivos JavaScript servidos por el sitio web
  • Interactuar con los componentes de esa página web

Entender que no hay una interfaz gráfica de usuario (GUI) asociada a él plantea algunas preguntas sobre la interacción. Sin embargo, la respuesta es bastante sencilla. Al no haber GUI, los humanos no pueden interactuar directamente con la página. Y ahí es donde entran en juego los controladores web. Un controlador web es una interfaz que permite la introspección y el control. En pocas palabras, los controladores web son marcos de trabajo que nos permiten controlar mediante programación diversos navegadores web.

Existen varios marcos que permiten la automatización de navegadores en Python. Pero el principal es Selenium. Selenium es un conjunto de herramientas creado principalmente para pruebas automatizadas. Pero, en la práctica, también se utiliza ampliamente para el web scraping.

¿Por qué utilizar un navegador sin interfaz gráfica en Python?

Según el encabezado de la página principal de Selenium:

«Selenium automatiza los navegadores. ¡Eso es todo! Lo que hagas con ese poder depende totalmente de ti».

Esto nos lleva a creer que los navegadores automatizados tienen diversos casos de uso. Pero, ¿por qué ejecutarlos en modo sin interfaz gráfica? Bueno, la respuesta es, una vez más, sencilla. Un navegador sin interfaz gráfica en Python consume menos recursos (CPU y memoria) en comparación con un navegador con interfaz gráfica. Y eso se debe principalmente a que no hay elementos gráficos que renderizar.

Una vez más, menos sigue siendo más si lo comparamos con un cliente HTTP básico como `requests` de Python, por ejemplo. Y eso se debe a que el navegador sin interfaz gráfica sigue abriendo muchos procesos para interactuar con la página y renderizar archivos JavaScript. Como sabes, `requests` no es capaz de renderizar JavaScript. Solo puedes obtener HTML sin procesar con él. Y hoy en día, eso no es ni de lejos suficiente para el web scraping. La mayoría de las plataformas web modernas dependen en gran medida de JavaScript para poblar el DOM. Por ejemplo, si intentas ejecutar `curl` en una aplicación React, obtendrás una página web vacía que te pedirá que «actives JavaScript»:

<!doctype html>

<html lang="en">

  <head>

 	...

  </head>

  <body>

 	<noscript> You need to enable JavaScript to run this app. </noscript>

 	<div id="root"></div>

  </body>

</html>

Aunque no puedes hacer eso con `requests`, sí puedes hacerlo con un navegador sin interfaz gráfica. Y eso responde a una de nuestras preguntas iniciales. Los extractores web modernos utilizan navegadores sin interfaz gráfica en lugar de `requests` porque, de lo contrario, la respuesta sería inconclusa.

¿Cuáles son los inconvenientes de un navegador sin interfaz gráfica?

La principal desventaja de un navegador sin interfaz gráfica de Python (y de casi todos los navegadores automatizados) es su huella digital. Si sigues mis artículos, sabes que a veces hablo de sigilo. Esa es la capacidad de un navegador automatizado para pasar desapercibido.

Y en Python, los navegadores sin interfaz son fácilmente distinguibles. Para empezar, comprobar una propiedad sencilla del navegador como `navigator.webdriver` es una señal inmediata de que un navegador está controlado por un controlador web. En el web scraping, uno de los principales retos es encontrar formas de evitar la detección. A esto lo llamamos métodos o técnicas de evasión. Puedes leer más al respecto aquí.

En Web Scraping API, por ejemplo, contamos con un equipo dedicado que trabaja constantemente en nuestro Modo Sigiloso. Esto es para garantizar que la huella digital de nuestro navegador sea única e indetectable en cada solicitud.

En primer lugar, hay que saber que Selenium es muy potente. Y ni siquiera se limita a Python. Existen clientes de Selenium y controladores web para C#, Ruby, Java, Python e incluso JavaScript. Y la compatibilidad del controlador web de Selenium es aún más impresionante. Es compatible con todos los principales navegadores:

En el mundo del web scraping, los navegadores sin interfaz gráfica de Python más utilizados son Chrome y Firefox. Creo que esto se debe principalmente a que ambos navegadores ofrecen un buen rendimiento y son multiplataforma. Por ejemplo, puedes desarrollar tu proyecto de web scraping en un entorno MacOS y luego implementarlo fácilmente en Linux.

Cómo abrir un navegador sin interfaz gráfica en Python

Ahora que hemos cubierto algunos conceptos teóricos, creo que es el momento de pasar a la parte práctica. En esta sección, te mostraré cómo crear un scraper web con Selenium. Para este proyecto, asegúrate de que tu equipo tiene instalado Python y Chrome.

#1: Configurar el entorno

Como es habitual, en Python debemos encapsular todo dentro de un entorno virtual. Si no estás familiarizado con los entornos virtuales, lee esto primero. Ahora abramos una nueva ventana de terminal y:

  • Crearemos una nueva carpeta
  • Navegar hasta la carpeta
  • Crearemos un nuevo entorno virtual
  • Activar el entorno virtual

~ mkdir headless_scraper

~ cd headless_scraper

~ python3 -m venv env

~ source env/bin/activate

#2: Instalar las dependencias

Es bastante obvio que necesitamos Selenium y un controlador web para nuestro proyecto. Por suerte, podemos instalar ambos utilizando el gestor de paquetes de Python, `pip`. Dentro de la misma ventana de terminal, escribe el siguiente comando:

~ pip install selenium webdriver-manager

¡Ya está todo listo para el éxito! Podemos pasar a la programación propiamente dicha. Una breve advertencia: este artículo se centra en la interacción con un navegador sin interfaz gráfica. Una solución completa de web scraping requiere mucho más esfuerzo. Pero estoy seguro de que, si sigues nuestras entradas del blog, podrás hacerlo en muy poco tiempo.

#3: Abrir un navegador automatizado

Hasta ahora, tenemos el proyecto, pero no hay ningún archivo que podamos ejecutar. Creemos un nuevo archivo `.py` y abrámoslo en nuestro IDE:

~ touch headles_scraper.py

~ code .

Ahora deberías estar dentro de Visual Studio Code o de tu IDE. Puedes empezar importando los paquetes necesarios dentro de `handle_scraper.py`:

from selenium import webdriver

from webdriver_manager.chrome import ChromeDriverManager

Este último es un paquete que te ayuda a gestionar fácilmente los controladores web para los diferentes navegadores compatibles con Selenium. Puedes leer más al respecto aquí. A continuación, queremos crear un nuevo navegador con Selenium y abrir un sitio web:

driver = webdriver.Chrome(ChromeDriverManager().install())

driver.get('https://webscrapingapi.com')

Ejecuta este archivo ahora y verás que funciona. Pero en lugar de utilizar un navegador sin interfaz gráfica de Python, se abre una ventana de Chrome con interfaz gráfica:

#4: Crear en modo sin interfaz gráfica

Nos hemos propuesto crear un rastreador web que consuma pocos recursos. Así que, idealmente, queremos abrir un navegador sin interfaz gráfica con Selenium. Afortunadamente, hay un método sencillo que podemos usar para cambiar Selenium de modo con interfaz gráfica a modo sin interfaz gráfica. Solo tenemos que utilizar las opciones del controlador web de Chrome. Así que importemos `Options` y añadamos dos líneas más de código:

...

from selenium.webdriver.chrome.options import Options

...

options = Options()

options.headless = True

driver = webdriver.Chrome(ChromeDriverManager().install(), options=options)

driver.get('https://webscrapingapi.com')

Ejecuta tu script de nuevo. Como puedes ver, esta vez no aparece ninguna ventana. Pero, ¿realmente está funcionando en segundo plano? Una forma rápida de visualizarlo y comprobarlo es hacer una captura de pantalla con Selenium. Solo tienes que añadir esta línea al final de tu script:

driver.get_screenshot_as_file('headless.png')

Si todo ha ido bien, deberías tener la misma imagen que yo:

#5: Añadir capacidades de scraping

¿Qué es un web scraper? Bueno, en esencia, un web scraper es un programa que llama a un punto final de un servidor y recopila datos de él. En el caso de los sitios web, estos datos suelen consistir en archivos HTML. Pero hoy en día algunos servidores también sirven objetos JSON. Así que quedémonos con este término: datos. Para la siguiente sección, fijemos unos objetivos más ambiciosos. ¡Usemos algo de programación orientada a objetos! Nuestros objetivos son:

  • Crear una clase Scraper
  • Añadir un método para extraer datos sin procesar
  • Añadir un método para extraer datos de un único elemento
  • Añadir un método para extraer datos de elementos de la misma clase

Así que tenemos tres métodos básicos que queremos crear. Sin embargo, con fines de aprendizaje, estos tres métodos nos abren el camino no solo al web scraping, sino también a la programación orientada a objetos (OOP) con Python. ¡Y creo que eso es genial! Ahora vamos a borrar todo lo que hemos programado y empezaremos desde cero:

from selenium import webdriver

from selenium.webdriver.chrome.options import Options

from selenium.webdriver.common.by import By

from selenium.webdriver.remote.webelement import WebElement

class Scraper:

   def __init__(self, headless: bool = True) -> None:

       self.headless = headless

       pass

   def setup_scraper(self) -> None:

       self.options = Options()

       self.options.headless = self.headless

       self.driver = webdriver.Chrome(options=self.options)

   def navigate(self, target) -> None:

       self.driver.get(target) if target else print('[!] No target given. Please specify a URL.')

   def extract_raw_data(self) -> str:

       return self.driver.page_source

   def extract_single_element(self,  selector: str, selector_type: By = By.CSS_SELECTOR) -> WebElement:

      return self.driver.find_element(selector_type, selector)

  

   def extract_all_elements(self, selector: str, selector_type: By = By.CSS_SELECTOR) -> list[WebElement]:

       return self.driver.find_elements(selector_type, selector)

He añadido anotaciones de tipo para facilitar la comprensión, más que para mejorar el rendimiento. De esta forma, puedes visualizar la aplicación desde una perspectiva de E/S. Ahora bien, los métodos se explican por sí mismos. No estamos realizando ningún tipo de acción sobre los datos, solo los estamos devolviendo. Si quieres, esto puede ser un punto de partida para crear un scraper complejo con un navegador sin interfaz gráfica de Python.

Hasta ahora, al ejecutar el archivo no pasa nada. Eso es porque solo hemos declarado nuestro Scraper y sus métodos. Ahora tenemos que usarlos. Así que añadamos los siguientes fragmentos de código:

# Initialize a new Scraper and navigate to a target

scraper = Scraper()

scraper.setup_scraper()

scraper.navigate('https://httpbin.org')

# Extract and print the entire HTML document

raw_data = scraper.extract_raw_data()

print(raw_data)

# Extract and print an element by its class name

single_element = scraper.extract_single_element('title', By.CLASS_NAME)

print(single_element.text)

# Extract and print all elements belonging to a tag type

all_elements = scraper.extract_all_elements('a', By.TAG_NAME)

print([el.get_attribute('href') for el in all_elements])

Y eso es todo. Si ejecutas tu script ahora, podrás ver que ocurre algo. De nuevo, esto es simplemente un prototipo diseñado para que puedas empezar. Si quieres aprender más sobre cómo se puede utilizar un navegador sin interfaz gráfica de Python en el scraping web, te reto a que:

De esta forma, podrás adquirir conocimientos y añadir un proyecto a tu portfolio.

¿Cuáles son las mejores alternativas a los navegadores sin interfaz gráfica de Python?

Python es uno de los lenguajes de programación más populares para crear rastreadores web. Sin embargo, no es la única solución. ¡Ni es la mejor! En esta sección, analizaremos alternativas a un navegador sin interfaz gráfica de Python. Empezaremos por explicar por qué buscar soluciones alternativas y también veremos ejemplos concretos.

La razón principal por la que optarías por una alternativa a crear tú mismo un rastreador web en Python son los recursos. Una solución completa de rastreo web requiere que implementes un sistema de rotación de IP, algunas técnicas de evasión, que tengas en cuenta el rendimiento, y eso solo por nombrar algunos aspectos. Por lo tanto, crear un rastreador web no solo es caro, sino que también lleva mucho tiempo. Por no mencionar que mantener la infraestructura genera aún más costes.

El segundo inconveniente del navegador sin interfaz gráfica de Python tiene que ver con el rendimiento. Aunque Python es un lenguaje estupendo y muy fácil de usar, no destaca precisamente por su velocidad. A diferencia de Java, por ejemplo (que también cuenta con un paquete Selenium), Python es un lenguaje de tipado dinámico e interpretado. Estas dos características lo hacen mucho más lento en comparación con otros lenguajes. Ahora que tenemos una idea general, vayamos al grano. Estas son las 5 mejores alternativas a Selenium y al navegador sin interfaz gráfica de Python:

N.º 1: API de web scraping

Si quieres solucionar el primer inconveniente que hemos identificado, debes buscar proveedores de scraping externos. Y Web Scraping API ofrece un conjunto completo de herramientas de scraping. Además, nuestro servicio incluye características como:

  • Sistema de rotación de IP tanto para proxies de centros de datos como residenciales
  • Modo sigiloso
  • Solucionadores de captchas

Solo estas tres características hacen que sea casi imposible que un sitio web detecte nuestro scraper y lo bloquee. Y luego están las funciones de scraping. Con la API de Web Scraping, puedes extraer datos basándote en selectores, cambiar entre tipos de dispositivos, hacer capturas de pantalla y mucho más. Puedes encontrar la lista completa de funciones aquí.

N.º 2: Puppeteer

Puppeteer es el equivalente a Selenium para JavaScript. Es una de las bibliotecas más utilizadas para la automatización web. A diferencia de Selenium, el estado predeterminado de Puppeteer es sin interfaz gráfica. Por lo tanto, no es necesario añadir código adicional para que funcione sin interfaz gráfica. Lo que es aún más interesante es que también existe una implementación de la API de Puppeteer para Python. Puedes echar un vistazo a este blog, donde explico en profundidad cómo crear un rastreador web con Puppeteer.

#3: Playwright

Playwright es otra herramienta de automatización web desarrollada por colaboradores de Microsoft. Es popular principalmente porque ofrece compatibilidad con varios lenguajes y plataformas. De hecho, su lema es «Cualquier navegador, cualquier plataforma». Se puede acceder a su API en cualquier sistema operativo y con cualquiera de los siguientes lenguajes:

Estas son las principales alternativas a un navegador sin interfaz gráfica de Python. Pero también hay otras herramientas disponibles. ZombieJS o HtmlUnit son solo dos más de una lista muy amplia. Supongo que elegir una tecnología es tanto una cuestión de rendimiento como de preferencia personal. Así que te animo a que las pruebes todas y elijas tu favorita.

Conclusiones

El uso de un navegador sin interfaz gráfica de Python tiene sus pros y sus contras. Por un lado, te permite crear una solución personalizada a la que siempre puedes añadir más funciones. Por otro lado, el desarrollo y el mantenimiento pueden resultar bastante caros. Y también está la cuestión de la discreción. Si necesitas una solución profesional, creo que lo mejor es recurrir a un proveedor externo. Por el contrario, con fines de aprendizaje, siempre te animaré a que experimentes con la tecnología.

Acerca del autor
Mihnea-Octavian Manolache, Desarrollador Full Stack @ 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.