Existen dos enfoques principales:
BeautifulSoup → para analizar HTML estático
Selenium → para interactuar con páginas dinámicas (JavaScript)
Vamos paso a paso.
1. Web Scraping con BeautifulSoup
Ideal para páginas estáticas donde el contenido ya está en el HTML.
Instalación
pip install requests beautifulsoup4
Ejemplo básico: extraer títulos de una web
import requests
from bs4 import BeautifulSoup
url = "https://example.com"
respuesta = requests.get(url)
soup = BeautifulSoup(respuesta.text, "html.parser")
titulos = soup.find_all("h2")
for t in titulos:
print(t.text)
Selección de elementos
Por etiqueta
soup.find("p")
soup.find_all("a")
Por clase
soup.find_all("div", class_="producto")
Por id
soup.find(id="precio")
Con selectores CSS
soup.select("div.item > a.link")
2. Web Scraping con Selenium
Selenium permite controlar un navegador real (Chrome, Firefox…) y es ideal para páginas con JavaScript.
Instalación
pip install selenium
Ejemplo básico: abrir una página y extraer texto
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://example.com")
titulo = driver.find_element(By.TAG_NAME, "h1").text
print(titulo)
driver.quit()
Interacciones comunes
Escribir en un campo
driver.find_element(By.ID, "busqueda").send_keys("python")
Hacer clic
driver.find_element(By.CLASS_NAME, "boton").click()
Esperas (muy importante)
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CLASS_NAME, "resultado"))
)
3. Diferencias entre BeautifulSoup y Selenium
| Característica | BeautifulSoup | Selenium |
|---|---|---|
| Velocidad | Muy rápido | Más lento |
| JavaScript | No lo ejecuta | Sí |
| Interacción | No | Sí (clics, formularios…) |
| Uso ideal | Web estática | Web dinámica |
ACTIVIDAD PRÁCTICA: “Scraper de precios con Selenium + BeautifulSoup”
Objetivo: que tus alumnos construyan un scraper real que:
Abra una página de productos con Selenium
Espere a que cargue el contenido dinámico
Obtenga el HTML final
Use BeautifulSoup para extraer:
Nombre del producto
Precio
Enlace
Guarde los datos en un archivo JSON
Pistas
Usa
driver.page_sourcepara obtener el HTML finalUsa
soup.find_all()para recorrer productosUsa
json.dump()para guardar los datos
Solución propuesta
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from bs4 import BeautifulSoup
import json
import time
driver = webdriver.Chrome()
driver.get("https://example.com/productos")
# Esperar a que carguen los productos
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CLASS_NAME, "producto"))
)
# Obtener HTML final
html = driver.page_source
driver.quit()
# Analizar con BeautifulSoup
soup = BeautifulSoup(html, "html.parser")
productos_html = soup.find_all("div", class_="producto")
productos = []
for p in productos_html:
nombre = p.find("h2").text.strip()
precio = p.find("span", class_="precio").text.strip()
enlace = p.find("a")["href"]
productos.append({
"nombre": nombre,
"precio": precio,
"enlace": enlace
})
# Guardar en JSON
with open("productos.json", "w", encoding="utf-8") as f:
json.dump(productos, f, indent=4, ensure_ascii=False)
print("Scraping completado. Datos guardados en productos.json")
Resultado esperado
Un archivo productos.json con contenido como:
[
{
"nombre": "Teclado Mecánico",
"precio": "29.99€",
"enlace": "/producto/teclado"
},
{
"nombre": "Ratón Inalámbrico",
"precio": "14.50€",
"enlace": "/producto/raton"
}
]