A veces los datos que necesitas están en una página web, pero no hay botón de descarga ni API. Quizás es una lista de precios de productos, una tabla de resultados deportivos o un directorio de negocios. Podrías copiarlos y pegarlos a mano, pero eso se vuelve tedioso después de unas diez filas.

El web scraping es la solución: un programa corto de Python visita la página, lee el HTML, selecciona las partes que te interesan y las guarda en un archivo ordenado. En esta guía construirás un scraper funcional desde cero, paso a paso, y aprenderás a hacerlo de forma respetuosa y legal.

¿Qué Es el Web Scraping?

El web scraping es el proceso automatizado de recopilar datos de páginas web. Un scraper hace lo mismo que tu navegador: solicita una página y recibe HTML. Pero en lugar de mostrarla en pantalla, el programa lee el HTML y extrae las piezas que le pides.

Usos comunes:

  • Seguir precios en tiendas en línea
  • Recopilar ofertas de empleo o anuncios inmobiliarios
  • Reunir datos para investigación o proyectos de análisis de datos
  • Monitorear titulares de noticias o blogs
  • Crear un conjunto de datos pequeño para practicar

Antes de Hacer Scraping: Revisa las Reglas

El scraping es una herramienta y puede usarse mal. Antes de extraer datos de cualquier sitio, revisa lo siguiente:

  1. Busca primero una API. Si el sitio ofrece una API oficial o un conjunto de datos descargable, úsalo. Es más confiable y está permitido.
  2. Lee los Términos de Servicio. Algunos sitios prohíben el acceso automatizado.
  3. Revisa robots.txt. Visita https://example.com/robots.txt para ver qué rutas el sitio pide que los bots no visiten.
  4. Sé amable. Haz pausas entre solicitudes para no sobrecargar el servidor. Un scraper que bombardea un sitio pequeño puede parecer un ataque.
  5. Evita datos personales. No recopiles información privada de personas, y nunca extraigas contenido detrás de un inicio de sesión que no estés autorizado a usar.
  6. Identifícate. Envía un User-Agent descriptivo para que los dueños del sitio sepan quién los visita.

Para practicar, esta guía usa books.toscrape.com, una librería ficticia creada específicamente para aprender scraping. Es seguro y legal usarla.

Paso 1: Configura tu Entorno

Necesitas tener Python 3 instalado. Crea una carpeta de proyecto y un entorno virtual para aislar los paquetes (consulta entornos virtuales de Python para más detalles):

mkdir scraper-demo
cd scraper-demo
python -m venv venv

Actívalo:

# macOS / Linux
source venv/bin/activate

# Windows (PowerShell)
venv\Scripts\Activate.ps1

Instala las dos bibliotecas que necesitas:

pip install requests beautifulsoup4
  • Requests descarga páginas web.
  • Beautiful Soup (beautifulsoup4) analiza el HTML para que puedas buscar dentro de él.

Paso 2: Entiende la Página que Quieres Extraer

El scraping depende de entender HTML. Si necesitas un repaso, lee cómo usar HTML y CSS.

Abre https://books.toscrape.com en tu navegador, haz clic derecho sobre el título de un libro y elige Inspeccionar. Esto abre las herramientas de desarrollo y muestra el HTML detrás de la página. Verás que cada libro se ve más o menos así:

<article class="product_pod">
  <h3><a href="catalogue/a-light-in-the-attic_1000/index.html" title="A Light in the Attic">A Light in the ...</a></h3>
  <div class="product_price">
    <p class="price_color">£51.77</p>
  </div>
</article>

Observa el patrón: cada libro es un <article> con la clase product_pod, el título completo está en el atributo title del enlace, y el precio está en un párrafo con la clase price_color. Tu scraper usará estas etiquetas y clases como señales.

Paso 3: Descarga la Página

Crea un archivo llamado scrape.py y empieza descargando la página:

import requests

URL = "https://books.toscrape.com/"
headers = {"User-Agent": "learning-scraper/1.0 (personal practice project)"}

response = requests.get(URL, headers=headers, timeout=10)
response.raise_for_status()  # detiene el script con un error si la solicitud falló

print(response.status_code)
print(response.text[:300])

Ejecútalo con python scrape.py. Un código de estado 200 significa éxito, y deberías ver el comienzo del HTML de la página. raise_for_status() convierte errores como 404 o 500 en excepciones claras de Python, en lugar de dejar que tu script continúe en silencio con datos incorrectos.

Paso 4: Analiza el HTML con Beautiful Soup

Ahora entrega el HTML a Beautiful Soup y extrae los libros:

from bs4 import BeautifulSoup

soup = BeautifulSoup(response.text, "html.parser")

for book in soup.select("article.product_pod"):
    title = book.h3.a["title"]
    price = book.select_one("p.price_color").get_text(strip=True)
    print(title, price)

Esto es lo que sucede:

  • soup.select("article.product_pod") usa un selector CSS para encontrar todos los libros de la página. Si conoces CSS, te resultará familiar.
  • book.h3.a["title"] lee el atributo title del enlace dentro del <h3>.
  • select_one(...) devuelve la primera coincidencia, y .get_text(strip=True) devuelve su texto sin espacios extra.

Ejecuta el script otra vez y deberías ver una lista de 20 títulos de libros con sus precios.

Paso 5: Extrae Varias Páginas

El sitio tiene 50 páginas de libros. La mayoría tiene un botón “next” (siguiente), así que un buen enfoque es seguir ese enlace hasta que no haya más páginas. Este es el script completo, con una pausa cortés entre solicitudes:

import time
from urllib.parse import urljoin

import requests
from bs4 import BeautifulSoup

START_URL = "https://books.toscrape.com/"
HEADERS = {"User-Agent": "learning-scraper/1.0 (personal practice project)"}


def scrape_page(url):
    response = requests.get(url, headers=HEADERS, timeout=10)
    response.raise_for_status()
    soup = BeautifulSoup(response.text, "html.parser")

    books = []
    for book in soup.select("article.product_pod"):
        books.append({
            "title": book.h3.a["title"],
            "price": book.select_one("p.price_color").get_text(strip=True),
        })

    next_link = soup.select_one("li.next a")
    next_url = urljoin(url, next_link["href"]) if next_link else None
    return books, next_url


all_books = []
url = START_URL
while url:
    print(f"Scraping {url}")
    books, url = scrape_page(url)
    all_books.extend(books)
    time.sleep(1)  # sé amable: espera un segundo entre solicitudes

print(f"Collected {len(all_books)} books")

urljoin construye una dirección web completa a partir del enlace relativo del botón “next”, así que no tienes que armar las URL a mano. Cuando la última página no tiene botón “next”, next_url pasa a ser None y el ciclo termina.

Paso 6: Guarda los Datos en un Archivo CSV

Los datos en memoria desaparecen cuando el script termina. Guardarlos en un archivo CSV te permite abrirlos en Excel o analizarlos después:

import csv

with open("books.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=["title", "price"])
    writer.writeheader()
    writer.writerows(all_books)

Agrégalo al final de tu script. Al ejecutarlo se crea books.csv en la carpeta de tu proyecto. Desde ahí puedes cargarlo en Pandas y continuar con la limpieza de datos con Python Pandas. Los precios son texto como £51.77, así que quitar el símbolo y convertirlos a números es un ejercicio de limpieza perfecto para empezar.

Problemas Comunes y Cómo Solucionarlos

ProblemaCausa probableQué intentar
Tus resultados están vacíosEl selector no coincide con el HTMLRevisa de nuevo la página con Inspeccionar; prueba tu selector en la consola del navegador
Recibes un error 403 ForbiddenEl sitio bloquea bots desconocidosDefine un User-Agent claro; si el sitio aún te rechaza, respétalo
Los datos que ves en el navegador no están en tu HTMLLa página carga los datos con JavaScriptBusca una API oculta en la pestaña Network del navegador, o usa una herramienta de automatización de navegador
429 Too Many RequestsVas demasiado rápidoAgrega pausas más largas entre solicitudes
Caracteres extraños en el textoProblema de codificaciónGuarda los archivos con encoding="utf-8"
El script falla cuando el sitio se rediseñaLos selectores dependen del diseño del HTMLLos scrapers necesitan mantenimiento ocasional; usa una API cuando puedas

Cuando Beautiful Soup No Es Suficiente

Beautiful Soup solo ve el HTML que envía el servidor. Algunos sitios modernos construyen su contenido en tu navegador con JavaScript, así que los datos nunca aparecen en el HTML descargado. En ese caso tienes algunas opciones:

  • Busca la API de los datos. Abre las herramientas de desarrollo de tu navegador, ve a la pestaña Network y recarga la página. A menudo la página solicita datos JSON limpios que puedes pedir directamente, lo cual es más fácil que extraer HTML.
  • Usa una herramienta de automatización de navegador como Selenium o Playwright. Controlan un navegador real, por lo que el JavaScript se ejecuta igual que para un visitante humano. Son más lentas y complejas, así que úsalas solo cuando sea necesario.
  • Usa un framework de scraping como Scrapy cuando necesites rastrear miles de páginas con limitación de velocidad, reintentos y herramientas de exportación integradas.

Lista de Buenas Prácticas

  • Prefiere una API oficial o un conjunto de datos descargable en lugar del scraping.
  • Respeta robots.txt y los términos del sitio.
  • Agrega pausas e identifica tu scraper con un User-Agent.
  • Maneja errores con raise_for_status() y tiempos de espera para que tu script no se quede colgado.
  • Guarda en caché las páginas que ya descargaste durante el desarrollo, para no solicitarlas una y otra vez.
  • Extrae solo lo que necesitas y almacénalo de forma responsable.
  • Mantén tu código en funciones pequeñas para actualizarlo fácilmente cuando el sitio cambie.

Conclusión

El web scraping convierte la web en una fuente de datos. Con Requests para descargar páginas y Beautiful Soup para leer el HTML, puedes recopilar listas, precios, titulares y más en menos de cincuenta líneas de Python. La receta es siempre la misma: inspeccionar la página, encontrar el patrón, extraer los datos, guardarlos y hacerlo con respeto.

Practica en un sitio hecho para el scraping, como books.toscrape.com, antes de apuntar tu scraper a sitios reales. Cuando te sientas cómodo, intenta recopilar un pequeño conjunto de datos que te interese y analizarlo con Pandas. Si el lenguaje es nuevo para ti, comienza con Fundamentos de Python: Lo que Todo Principiante Debe Saber y la guía de 10 bibliotecas de Python que todo principiante debe conocer.