Automatizar

Web scraping básico con Python y BeautifulSoup

Cómo extraer datos de una página web con requests y BeautifulSoup: descargar el HTML, encontrar los elementos y sacar el texto. Con las buenas prácticas para no romper nada ni que te bloqueen.

El web scraping es extraer datos de páginas web de forma automática: precios, titulares, listados, cualquier información que esté en una web pero no en un archivo descargable. Con Python son dos librerías y unas pocas líneas. Aquí lo básico bien hecho, incluyendo las prácticas que evitan que te bloqueen.

pip install requests beautifulsoup4

requests descarga la página; beautifulsoup4 (que se importa como bs4) analiza el HTML y te deja buscar dentro.

Descargar y analizar una página

import requests
from bs4 import BeautifulSoup

url = "https://ejemplo.com/articulos"
respuesta = requests.get(url)
respuesta.raise_for_status()   # avisa si la página falló

sopa = BeautifulSoup(respuesta.text, "html.parser")

El raise_for_status() es importante: si la página devuelve un error (404, 500, etc.), te avisa de inmediato en vez de dejarte procesar HTML vacío y volverte loco buscando por qué no encuentras nada.

Encontrar elementos

BeautifulSoup busca por etiqueta, clase o id. Los métodos principales:

# Un solo elemento (el primero que encuentre)
titulo = sopa.find("h1")
print(titulo.text)

# Todos los elementos de un tipo
enlaces = sopa.find_all("a")
for enlace in enlaces:
    print(enlace.text, "->", enlace.get("href"))

# Por clase CSS
articulos = sopa.find_all("div", class_="articulo")

# Por id
cabecera = sopa.find(id="cabecera")

Fíjate en class_ con guion bajo: se escribe así porque class es una palabra reservada de Python. Es un detalle que confunde a todos la primera vez.

Y .text saca el contenido de texto del elemento, mientras .get("href") saca el valor de un atributo (aquí, la dirección del enlace).

Un ejemplo real: extraer una lista

Digamos que quieres los títulos y enlaces de una lista de artículos:

import requests
from bs4 import BeautifulSoup

url = "https://ejemplo.com/blog"
respuesta = requests.get(url)
respuesta.raise_for_status()
sopa = BeautifulSoup(respuesta.text, "html.parser")

articulos = sopa.find_all("article", class_="post")

for articulo in articulos:
    titulo = articulo.find("h2")
    enlace = articulo.find("a")
    if titulo and enlace:          # comprobar que existen
        print(titulo.text.strip(), "->", enlace.get("href"))

El if titulo and enlace es clave: no todos los elementos tendrán siempre lo que buscas, y si intentas .text sobre un resultado que fue None, obtienes el error 'NoneType' object has no attribute 'text'. Comprobar antes de acceder evita que el script reviente a mitad de camino. Y .strip() limpia los espacios y saltos de línea que el HTML suele arrastrar.

Las buenas prácticas que evitan bloqueos

Aquí lo que separa un scraper responsable de uno que acaba bloqueado. Primero, identifícate con un User-Agent, porque muchos sitios rechazan las peticiones sin él:

cabeceras = {"User-Agent": "Mozilla/5.0 (mi-script de datos)"}
respuesta = requests.get(url, headers=cabeceras)

Segundo, si vas a pedir varias páginas, espera entre una y otra. Bombardear un servidor con cientos de peticiones seguidas es la forma más rápida de que te bloqueen la IP, y además es de mala educación:

import time

for pagina in range(1, 6):
    respuesta = requests.get(f"{url}?page={pagina}", headers=cabeceras)
    # ...procesar...
    time.sleep(2)   # dos segundos entre peticiones

Tercero, y esto es tanto ético como legal: revisa el archivo robots.txt del sitio (por ejemplo ejemplo.com/robots.txt) para ver qué permiten rastrear, y respeta los términos de uso. Hacer scraping de datos públicos para uso personal suele estar bien; revender datos ajenos o saturar un servidor no. El scraping responsable te mantiene fuera de problemas.

Con esto puedes extraer datos de casi cualquier página estática. Para sitios que cargan su contenido con JavaScript después (donde el HTML inicial viene vacío) hará falta otra herramienta como Selenium o Playwright, pero eso es tema de otro artículo.


¿La página que quieres raspar carga con JavaScript, o necesitas guardar los datos en Excel o base de datos? Escríbeme desde contacto y lo vemos.

← Más de Automatizar