Web Scraping con Python y BeautifulSoup: Tutorial 2026
Tutoriales

Web Scraping con Python y BeautifulSoup: Tutorial 2026

14 min de lectura
51 Vistas
Compartir:

Que es web scraping y para que sirve

Web scraping es la tecnica de extraer datos de paginas web de forma automatizada. En lugar de copiar informacion manualmente, escribes un script que visita la pagina, encuentra los datos que necesitas y los guarda en un formato util como CSV, JSON o una base de datos.

En mi experiencia, los casos de uso mas comunes son: monitorear precios de competidores, recopilar datos para analisis, extraer listados de productos, y automatizar la recopilacion de informacion publica. Llevo 3 anos usando Python para scraping y es, sin duda, el lenguaje mas adecuado para esta tarea gracias a su ecosistema de librerias.

Instalacion y setup

# Crear entorno virtual (recomendado)
python -m venv scraping_env
source scraping_env/bin/activate  # Linux/Mac
# scraping_env\Scripts\activate   # Windows

# Instalar dependencias
pip install requests beautifulsoup4 lxml pandas

# Verificar instalacion
python -c "import requests; import bs4; print('Todo instalado correctamente')"

Tu primer scraper: paso a paso

Vamos a construir un scraper que extrae titulos de noticias de un sitio web publico. Usaremos requests para descargar el HTML y BeautifulSoup para parsearlo.

import requests
from bs4 import BeautifulSoup

# Paso 1: Descargar el HTML
url = "https://news.ycombinator.com/"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
response = requests.get(url, headers=headers)

# Verificar que la peticion fue exitosa
if response.status_code != 200:
    print(f"Error: {response.status_code}")
    exit()

# Paso 2: Parsear el HTML
soup = BeautifulSoup(response.text, "lxml")

# Paso 3: Encontrar los elementos
titles = soup.find_all("span", class_="titleline")

# Paso 4: Extraer datos
for i, title in enumerate(titles[:10], 1):
    link = title.find("a")
    print(f"{i}. {link.text}")
    print(f"   URL: {link.get('href', 'N/A')}")
    print()

Selectores: como encontrar elementos

Despues de trabajar con cientos de paginas, puedo decirte que el 90% del trabajo en scraping es encontrar los selectores correctos. BeautifulSoup ofrece multiples formas:

MetodoUsoEjemplo
find()Primer elemento que coincidesoup.find("h1")
find_all()Todos los elementossoup.find_all("a", class_="link")
select_one()Primer match CSS selectorsoup.select_one("div.product > h2")
select()Todos con CSS selectorsoup.select("ul.menu li a")
find(attrs={})Por atributossoup.find("div", attrs={"data-id": "123"})
# Ejemplos practicos de selectores
soup = BeautifulSoup(html, "lxml")

# Por tag y clase
products = soup.find_all("div", class_="product-card")

# CSS selector (como en el navegador)
prices = soup.select("div.product-card span.price")

# Por atributo personalizado
items = soup.find_all("div", attrs={"data-category": "electronics"})

# Texto dentro del elemento
title = element.get_text(strip=True)

# Atributo href de un link
url = link.get("href", "")

# Navegar al padre o hermano
parent = element.parent
next_sibling = element.find_next_sibling("div")

Proyecto completo: scraper de productos con paginacion

import requests
from bs4 import BeautifulSoup
import csv
import time

def scrape_products(base_url, max_pages=5):
    all_products = []

    for page in range(1, max_pages + 1):
        url = f"{base_url}?page={page}"
        print(f"Scraping pagina {page}...")

        response = requests.get(url, headers={
            "User-Agent": "Mozilla/5.0 (compatible; MyScraper/1.0)"
        })

        if response.status_code != 200:
            print(f"Error en pagina {page}: {response.status_code}")
            break

        soup = BeautifulSoup(response.text, "lxml")
        products = soup.select("div.product-item")

        if not products:
            print("No mas productos encontrados")
            break

        for product in products:
            name = product.select_one("h3.name")
            price = product.select_one("span.price")
            rating = product.select_one("span.rating")

            all_products.append({
                "name": name.get_text(strip=True) if name else "N/A",
                "price": price.get_text(strip=True) if price else "N/A",
                "rating": rating.get_text(strip=True) if rating else "N/A",
            })

        # Respetar el servidor: esperar entre peticiones
        time.sleep(2)

    return all_products

def save_to_csv(products, filename="productos.csv"):
    if not products:
        print("No hay datos para guardar")
        return

    with open(filename, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=products[0].keys())
        writer.writeheader()
        writer.writerows(products)

    print(f"Guardados {len(products)} productos en {filename}")

# Ejecutar
products = scrape_products("https://example.com/products")
save_to_csv(products)

Buenas practicas y etica del scraping

Un error que cometi al principio fue no respetar las politicas de los sitios web. Estas son las reglas que todo scraper responsable debe seguir:

1. Revisa el robots.txt. Antes de scrapear un sitio, visita sitio.com/robots.txt. Si dice Disallow: /seccion/, no scrapees esa seccion.

2. Agrega delays entre peticiones. Nunca bombardees un servidor. Un time.sleep(2) entre peticiones es lo minimo responsable.

3. Identifica tu scraper. Usa un User-Agent descriptivo con tu contacto para que el administrador pueda comunicarse contigo si hay problemas.

4. Revisa los terminos de servicio. Algunos sitios prohiben explicitamente el scraping. Respeta esos terminos.

Errores comunes y soluciones

Error 1: "Connection refused" o status 403. El servidor te esta bloqueando. Solucion: agrega headers realistas (User-Agent, Accept, Accept-Language). Si persiste, el sitio probablemente bloquea scrapers activamente.

Error 2: El scraper no encuentra elementos. La pagina puede cargar contenido con JavaScript. BeautifulSoup solo ve el HTML estatico. Solucion: usa Selenium o Playwright para paginas con JavaScript.

Error 3: Datos incompletos o None. Siempre verifica que el elemento existe antes de extraer texto: element.text if element else "N/A". Las paginas web cambian estructura frecuentemente.

Error 4: Encoding roto (caracteres raros). Usa response.encoding = "utf-8" antes de parsear, o usa response.content en lugar de response.text.

Recursos adicionales

J
Escrito por
Jesús García

Apasionado por la tecnologia y las finanzas personales. Escribo sobre innovacion, inteligencia artificial, inversiones y estrategias para mejorar tu economia. Mi objetivo es hacer que temas complejos sean accesibles para todos.

Compartir artículo:

Artículos relacionados

Comentarios

Deja un comentario

Herramientas Recomendadas

Las que usamos en nuestros proyectos

Enlaces de afiliado. Sin costo adicional para ti.

¿Necesitas servicios de tecnología?

Ofrecemos soluciones integrales de desarrollo web, aplicaciones móviles, consultoría y más.

Desarrollo Web Apps Móviles Consultoría