Volver al blog
Guías
Robert SfichiLast updated on Mar 31, 20267 min read

Cómo crear un rastreador web con Python y Selenium

Cómo crear un rastreador web con Python y Selenium

Muchos desarrolladores optan por crear su propio rastreador web en lugar de utilizar los productos disponibles. Si les preguntas a la mayoría de ellos qué lenguaje de programación prefieren, lo más probable es que oigas mencionar Python un montón de veces.

Python se ha convertido en el favorito del público gracias a su sintaxis flexible y a la gran cantidad de bibliotecas que simplifican la tarea de extraer datos de la web. Hoy vamos a hablar de una de esas bibliotecas.

Esta guía te explicará cómo empezar a extraer datos con Selenium y Python. Crearemos un script en Python que iniciará sesión en un sitio web, extraerá algunos datos, los formateará de forma clara y los guardará en un archivo CSV.

Si quieres una visión general más amplia de cómo se puede utilizar Python en el web scraping, echa un vistazo a nuestra guía definitiva para crear un scraper con Python. Después, vuelve aquí para que podamos profundizar aún más en los detalles.

Una visión general de Selenium

Tal y como indica la página web oficial de Selenium, Selenium es un conjunto de herramientas para automatizar navegadores web que se presentó inicialmente como una herramienta para realizar pruebas en distintos navegadores.

La API creada por el equipo de Selenium utiliza el protocolo WebDriver para tomar el control de un navegador web, como Chrome o Firefox, y realizar diferentes tareas, como:

  • Rellenar formularios
  • Desplazarse
  • Hacer capturas de pantalla
  • Hacer clic en botones

Ahora quizá te preguntes cómo se traduce todo esto en el web scraping. En realidad, es sencillo.

La extracción de datos puede ser un verdadero dolor de cabeza a veces. Hoy en día, los sitios web se construyen como aplicaciones de página única incluso cuando no hay necesidad de ello. Muestran CAPTCHAs con más frecuencia de la necesaria e incluso bloquean las direcciones IP de los usuarios habituales.

En resumen, la detección de bots es una función muy frustrante que parece un error.

Selenium puede ayudar en estos casos al interpretar y ejecutar código JavaScript y automatizar muchos procesos tediosos del web scraping, como desplazarse por la página, capturar elementos HTML o exportar los datos obtenidos.

Instalación

Para mostrar el verdadero potencial de Selenium y Python, vamos a extraer información del subreddit /r/learnprogramming. Además de extraer datos, también te mostraré cómo se puede implementar el inicio de sesión. Ahora que ya conocemos la herramienta principal y el sitio web que vamos a utilizar, veamos qué otros requisitos debemos tener instalados:

1. Python. Usaremos Python 3.0. Sin embargo, puedes usar Python 2.0 si haces algunos pequeños ajustes. Puedes descargarlo e instalarlo desde aquí.

2. Paquete Selenium. Puedes instalar el paquete Selenium con el siguiente comando:

pip3 install selenium

3. Paquete Pandas. Se utilizará para extraer y almacenar los datos recopilados en un archivo .csv. Ejecuta el siguiente comando para instalarlo en tu dispositivo.

pip3 install pandas

4. Paquete BeautifulSoup. Se utiliza para analizar documentos HTML y XML. Solo tienes que ejecutar esta línea:

pip3 install beautifulsoup

5. Google Chrome. Consulta este enlace para obtener más información sobre cómo descargarlo e instalarlo.

6. Chrome Driver. Nos ayudará a configurar el controlador web para Selenium. Sigue este enlace para descargar e instalar la última versión de Chrome Driver. No olvides guardar la ruta en la que lo has instalado.

Iniciar el navegador

Empecemos. Crea un nuevo archivo scraper.py e importa el paquete Selenium copiando la siguiente línea:

from selenium import webdriver

Ahora crearemos una nueva instancia de Google Chrome escribiendo:

driver = webdriver.Chrome(LOCATION)

Sustituye LOCATION por la ruta donde se encuentra el controlador de Chrome en tu ordenador. Consulta la documentación de Selenium para encontrar la ruta más precisa para el controlador web, según el sistema operativo que utilices.

El último paso es acceder al sitio web del que queremos extraer datos. En nuestro caso, es https://www.reddit.com/r/learnprogramming/top/?t=month. Copia la siguiente línea en el archivo Python recién creado:

driver.get("https://www.reddit.com/r/learnprogramming/top/?t=month")

Ejecutando el siguiente comando en una ventana de terminal:

python3 scraper.py

Ahora deberíamos tener abierta una nueva instancia de Google Chrome que especifique «Chrome está siendo controlado por un software de pruebas automatizadas» en la parte superior de nuestra página.

Localización de datos específicos

Como probablemente ya habrás deducido, en este tutorial extraeremos datos del subreddit /r/learnprogramming. Guardaremos el título de las publicaciones, el autor y el número de votos positivos, y los almacenaremos en un nuevo archivo .csv. Veamos dónde se encuentran en la página HTML y cómo podemos extraerlos.

Una vez que Google Chrome haya cargado finalmente la página, haz clic con el botón derecho en cualquier publicación y selecciona «Inspeccionar». Podemos encontrar el contenedor HTML de la publicación bajo el nombre de clase _1oQyIsiPHYt6nx7VOmd1sz.

También puedes ejecutar Google Chrome sin interfaz gráfica de usuario y registrar el contenido HTML de la página añadiendo un par de líneas de código. Estableceremos la opción headless en true para el controlador de Chrome (para eliminar la interfaz gráfica) y un tamaño de ventana de 1080 píxeles (para obtener el código HTML correcto para nuestro caso de uso).

Las dos últimas líneas de código cierran Chrome justo después de terminar de registrar el HTML de la página.

El nuevo archivo scraper.py tendrá este aspecto:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.headless = True
options.add_argument("--window-size=1920,1080")

driver = webdriver.Chrome("./chromedriver")
driver.get("https://www.reddit.com/r/learnprogramming/top/?t=month")

print(driver.page_source)
driver.quit()

WebElement

Un WebElement es un objeto de Selenium que representa un elemento HTML. Como verás en el siguiente tutorial, podemos realizar muchas acciones en estos elementos. Algunas de ellas son:

  • Hacer clic en él utilizando el método .click()
  • Introducir texto en un elemento de entrada específico llamando al método .send_keys()
  • Leer el texto de un elemento utilizando element.text
  • Comprobar si un elemento se muestra en la página llamando a .is_displayed() sobre él

Un ejemplo de Selenium en acción

Ahora que tenemos nuestro proyecto configurado, por fin podemos ponernos a extraer datos.

Iniciar sesión

Vamos a demostrar el potencial de Selenium iniciando sesión en nuestra cuenta de Reddit y extrayendo los datos presentados anteriormente. Empecemos haciendo que Selenium haga clic en el botón de inicio de sesión situado en la parte superior de la página. Tras inspeccionar el código HTML de la página, vemos que el nombre de clase del botón de inicio de sesión es _2tU8R9NTqhvBrhoNAXWWcP.

login_button = driver.find_element_by_class_name('_2tU8R9NTqhvBrhoNAXWWcP')
login_button.click()

Esto abrirá la ventana modal de inicio de sesión, donde podemos ver los campos de usuario y contraseña que debemos rellenar. Continuemos con las siguientes líneas:

driver.switch_to_frame(driver.find_element_by_class_name('_25r3t_lrPF3M6zD2YkWvZU'))

driver.find_element_by_id("loginUsername").send_keys('USERNAME')
driver.find_element_by_id("loginPassword").send_keys('PASSWORD')

driver.find_element_by_xpath("//button[@type='submit']").click()

Si inspeccionamos el elemento modal, vemos que su contenedor es un iframe. Por eso tenemos que cambiar a frame en la primera parte del código, ya que seleccionar los campos de entrada sin ello provocará un error.

A continuación, obtenemos los campos de entrada y les proporcionamos las credenciales adecuadas antes de pulsar el botón de enviar. Esto nos llevará de vuelta a la página /r/learnprogramming, ¡pero ahora hemos iniciado sesión y estamos listos para votar a favor!

Hacer una captura de pantalla

Hacer una captura de pantalla con Selenium y Python es bastante fácil. Solo tienes que escribir el siguiente comando en el archivo scraper.py después de declarar el controlador web.

driver.save_screenshot('screenshot.png')

Es útil saber que puedes ajustar el tamaño de la ventana de Google Chrome añadiendo las siguientes líneas de código:

from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--window-size=1920,1080")

Así es como quedará la captura de pantalla en nuestro caso:

Extraer datos

Como hemos dicho antes, necesitamos obtener el título de las publicaciones, el autor y el número de votos positivos. Empecemos importando los paquetes BeautifulSoup y Pandas y creando tres matrices vacías para cada tipo de información que necesitamos.

from bs4 import BeautifulSoup
import pandas as pd

titles = []
upvotes=[]
authors = []

Vamos a utilizar BeautifulSoup para analizar el documento HTML escribiendo las siguientes líneas:

content = driver.page_source
soup = BeautifulSoup(content, features="html.parser")

Tras inspeccionar con éxito el documento HTML y elegir los selectores adecuados, ahora vamos a recuperar los títulos, los votos positivos y los autores, y asignarlos a la matriz correspondiente:

for element in soup.findAll('div', attrs={'class': '_1oQyIsiPHYt6nx7VOmd1sz'}):
   title = element.find('h3', attrs={'class': '_eYtD2XCVieq6emjKBH3m'})
   upvote = element.find('div', attrs={'class': '_3a2ZHWaih05DgAOtvu6cIo'})
   author = element.find('a', attrs={'class': '_23wugcdiaj44hdfugIAlnX'})
   titles.append(title.text)
   upvotes.append(upvote.text)
   authors.append(author.text)

Por último, almacenaremos la información en un archivo CSV utilizando el paquete Pandas que importamos anteriormente.

df = pd.DataFrame({'Post title': titles, 'Author': authors, 'Number of upvotes': upvotes})
df.to_csv('posts.csv', index=False, encoding='utf-8')

¡Eso es todo! Echemos un vistazo al archivo exportado:

Parece que tiene toda la información que necesitamos.

Consejo extra: A veces, necesitamos más datos de los que proporciona el sitio web en la primera carga. La mayoría de las veces, la acción de obtención de datos se activa cuando el usuario se desplaza hacia abajo. Si necesitas desplazarte hacia abajo para obtener más datos, puedes utilizar el método .execute_script() de esta manera:

scrollDown = "window.scrollBy(0,2000);"
driver.execute_script(scrollDown)

Reflexiones finales

Espero que hayas disfrutado creando el rastreador web tanto como yo. Programar no siempre es divertido, pero crear pequeños scripts como este me recuerda a cuando estaba empezando, y hace que el proceso sea mucho más entretenido.

Aun así, el script que hemos conseguido crear en este tutorial no puede hacer un trabajo muy complejo. Carece de un par de características esenciales que hacen que el web scraping resulte impecable. Conectarse mediante proxies móviles o residenciales y resolver CAPTCHAs son solo algunas de ellas.

Si buscas una forma más profesional de extraer datos, echa un vistazo a lo que WebScrapingAPI puede hacer y comprueba por ti mismo si te conviene. Hay un paquete gratuito, así que la única inversión son 30 minutos de tu tiempo.

Gracias por tomarte el tiempo de leer esto. ¡Feliz scraping!

Acerca del autor
Robert Sfichi, Desarrollador full-stack @ WebScrapingAPI
Robert SfichiDesarrollador full-stack

Robert Sfichi forma parte del equipo de WebScrapingAPI, donde contribuye al desarrollo del producto y ayuda a crear soluciones fiables que dan soporte a la plataforma y a sus usuarios.

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.