certmundo.
es‑mx

6 min de lectura

¿Cómo hacer web scraping con Python para extraer datos?

El web scraping es la técnica de extraer información de páginas web de forma automática usando código.

Con Python puedes descargar el contenido HTML de cualquier página y luego buscar los datos que necesitas. Las bibliotecas requests y BeautifulSoup hacen este proceso sencillo y eficiente.


Instalación de las bibliotecas necesarias

Antes de escribir código, instala las dos bibliotecas principales.

pip install requests beautifulsoup4

requests descarga el contenido de la página. BeautifulSoup analiza el HTML y te permite buscar elementos específicos.


Estructura básica de un script de web scraping

Todo script de scraping sigue el mismo patrón de tres pasos.

Paso 1: Descargar el HTML con requests.get(). Paso 2: Parsear el HTML con BeautifulSoup. Paso 3: Buscar y extraer los datos que necesitas.

import requests
from bs4 import BeautifulSoup

# Paso 1: Descargar la página
url = "https://ejemplo.com"
respuesta = requests.get(url)

# Paso 2: Parsear el HTML
sopa = BeautifulSoup(respuesta.text, "html.parser")

# Paso 3: Extraer datos
titulo = sopa.find("h1").text
print(titulo)

El argumento "html.parser" le dice a BeautifulSoup qué motor usar para leer el HTML. Es el parser estándar incluido en Python.


Ejemplo 1: Extraer el precio de un producto en Liverpool

Imagina que quieres monitorear el precio de un televisor en Liverpool. El HTML de la página del producto tiene una estructura similar a esta:

<div class="price">
  <span class="current-price">$18,500</span>
</div>

Tu script de Python para extraer ese precio sería:

import requests
from bs4 import BeautifulSoup

url = "https://www.liverpool.com.mx/tienda/pdp/televisor-55/12345"
encabezados = {"User-Agent": "Mozilla/5.0"}

respuesta = requests.get(url, headers=encabezados)
sopa = BeautifulSoup(respuesta.text, "html.parser")

precio_tag = sopa.find("span", class_="current-price")
if precio_tag:
    precio = precio_tag.text.strip()
    print(f"Precio actual: {precio}")
else:
    print("No se encontró el precio.")

Salida esperada:

Precio actual: $18,500

El parámetro headers con User-Agent es importante. Sin él, muchos sitios bloquean las solicitudes automáticas.


Ejemplo 2: Extraer múltiples productos de una lista

En Mercado Libre, los resultados de búsqueda muestran varios productos en una lista. Puedes usar find_all() para extraer todos los elementos de una sola vez.

import requests
from bs4 import BeautifulSoup

url = "https://listado.mercadolibre.com.mx/laptops"
encabezados = {"User-Agent": "Mozilla/5.0"}

respuesta = requests.get(url, headers=encabezados)
sopa = BeautifulSoup(respuesta.text, "html.parser")

productos = sopa.find_all("li", class_="ui-search-layout__item")

for producto in productos:
    nombre_tag = producto.find("h2", class_="ui-search-item__title")
    precio_tag = producto.find("span", class_="andes-money-amount__fraction")

    nombre = nombre_tag.text.strip() if nombre_tag else "Sin nombre"
    precio = f"${precio_tag.text.strip()}" if precio_tag else "Sin precio"

    print(f"{nombre} — {precio}")

Salida esperada:

Laptop HP 15 Core i5 — $12,500
Laptop Lenovo IdeaPad 3 — $9,800
Laptop Dell Inspiron 15 — $14,200

find_all() regresa una lista con todos los elementos que coinciden con el selector. Luego iteras sobre esa lista para procesar cada uno.


Ejemplo 3: Guardar los datos en un archivo CSV

Extraer datos y mostrarlos en pantalla es útil. Guardarlos en un archivo CSV te permite analizarlos después con Excel o pandas.

import requests
from bs4 import BeautifulSoup
import csv

url = "https://listado.mercadolibre.com.mx/laptops"
encabezados = {"User-Agent": "Mozilla/5.0"}

respuesta = requests.get(url, headers=encabezados)
sopa = BeautifulSoup(respuesta.text, "html.parser")
productos = sopa.find_all("li", class_="ui-search-layout__item")

with open("productos.csv", "w", newline="", encoding="utf-8") as archivo:
    escritor = csv.writer(archivo)
    escritor.writerow(["Nombre", "Precio"])

    for producto in productos:
        nombre_tag = producto.find("h2", class_="ui-search-item__title")
        precio_tag = producto.find("span", class_="andes-money-amount__fraction")

        nombre = nombre_tag.text.strip() if nombre_tag else "Sin nombre"
        precio = precio_tag.text.strip() if precio_tag else "0"

        escritor.writerow([nombre, precio])

print("Datos guardados en productos.csv")

Este script crea un archivo productos.csv con dos columnas: Nombre y Precio. Puedes abrirlo directamente en Excel.


Selectores de BeautifulSoup: referencia rápida

Método Uso Ejemplo
find(tag) Primer elemento que coincide sopa.find("h1")
find_all(tag) Todos los elementos que coinciden sopa.find_all("li")
find(tag, class_=) Por etiqueta y clase CSS sopa.find("span", class_="precio")
find(id=) Por atributo ID sopa.find(id="main-title")
select(selector) Selector CSS completo sopa.select(".lista > li")
.text Texto visible del elemento tag.text.strip()
.get("href") Valor de un atributo tag.get("href")

El método select() acepta selectores CSS exactamente igual que en JavaScript. Es útil cuando los selectores son complejos.


Consideraciones legales y buenas prácticas

El web scraping tiene implicaciones legales que debes conocer antes de usarlo.

Revisa el archivo robots.txt: Toda página web tiene un archivo en https://sitio.com/robots.txt que indica qué rutas están permitidas para bots. Respetarlo es una buena práctica profesional.

Respeta los Términos de Servicio: Algunos sitios prohíben expresamente el scraping automatizado en sus TOS. Hacer scraping en esos sitios puede derivar en bloqueos de IP o problemas legales.

Agrega pausas entre solicitudes: Hacer cientos de solicitudes seguidas puede saturar el servidor del sitio. Usa time.sleep() para agregar un retraso entre cada solicitud.

import time

for pagina in range(1, 6):
    url = f"https://ejemplo.com/productos?pagina={pagina}"
    respuesta = requests.get(url, headers=encabezados)
    # ... procesar datos ...
    time.sleep(2)  # Espera 2 segundos entre cada solicitud

Usa solo datos públicos: No extraigas información privada, datos personales o contenido detrás de un login sin autorización expresa.


Errores comunes

Error 1: Acceder a .text sin verificar si el elemento existe.

Si find() no encuentra el elemento, regresa None. Llamar .text sobre None genera un error AttributeError.

# Incorrecto
precio = sopa.find("span", class_="precio").text

# Correcto
precio_tag = sopa.find("span", class_="precio")
precio = precio_tag.text.strip() if precio_tag else "No disponible"

Siempre verifica que el tag no sea None antes de acceder a sus propiedades.

Error 2: No incluir el encabezado User-Agent.

Sin este encabezado, el servidor identifica tu script como un bot y puede bloquear la solicitud con un error 403. Siempre incluye headers={"User-Agent": "Mozilla/5.0"} en tus solicitudes.

Error 3: Asumir que el HTML no cambia.

Los sitios web actualizan su diseño y clases CSS con frecuencia. Un scraper que funciona hoy puede fallar mañana si el sitio cambia su estructura. Agrega manejo de errores con try/except para que tu script falle de forma controlada.

try:
    precio = sopa.find("span", class_="precio").text.strip()
except AttributeError:
    precio = "No encontrado"
    print("Advertencia: la estructura del HTML cambió.")

Error 4: No manejar el código de respuesta HTTP.

Una solicitud puede fallar con errores 404 o 500. Verifica siempre que la respuesta fue exitosa antes de parsear.

respuesta = requests.get(url, headers=encabezados)

if respuesta.status_code == 200:
    sopa = BeautifulSoup(respuesta.text, "html.parser")
else:
    print(f"Error al acceder a la página: {respuesta.status_code}")

Puntos clave

  • requests.get() descarga el HTML y BeautifulSoup lo analiza. Siempre incluye headers={"User-Agent": "Mozilla/5.0"} para evitar bloqueos.
  • Usa find() para el primer elemento y find_all() para obtener una lista completa de elementos coincidentes.
  • Verifica siempre que find() no regrese None antes de acceder a .text o cualquier atributo del tag.
  • Agrega time.sleep() entre solicitudes para no saturar el servidor y reducir el riesgo de ser bloqueado por IP.
  • Revisa el archivo robots.txt y los Términos de Servicio del sitio antes de hacer scraping. El uso responsable protege tu proyecto y evita consecuencias legales.

Puntos clave

  • Usa `requests.get()` para descargar el HTML y `BeautifulSoup` para analizarlo. Incluye siempre el encabezado `User-Agent` para evitar bloqueos del servidor.
  • Usa `find()` para obtener el primer elemento que coincide y `find_all()` para obtener una lista completa. Verifica que el resultado no sea `None` antes de acceder a `.text`.
  • Agrega `time.sleep()` entre solicitudes consecutivas para no saturar el servidor y reducir el riesgo de que tu IP sea bloqueada.
  • Revisa el archivo `robots.txt` y los Términos de Servicio del sitio antes de hacer scraping. Extrae solo datos públicos y nunca información personal sin autorización.
  • Combina `BeautifulSoup` con el módulo `csv` o `pandas` para guardar los datos extraídos en archivos que puedas analizar en Excel o en otros scripts.

Comparte esta lección: