Volver al blog

Trampas Comunes y Soluciones para Crawlers Web (Con Ejemplos de Código)

Emily Chen
Emily Chen

Advanced Data Extraction Specialist

16-Sep-2025

Los rastreadores web no solo se tratan de enviar solicitudes HTTP; deben lidiar con la representación de JavaScript, defensas contra bots, escalabilidad y manejo de errores. En este artículo, examinaremos los errores comunes que enfrentan los desarrolladores al construir rastreadores y proporcionaremos soluciones prácticas con fragmentos de código.


1. Ignorar Robots.txt y Políticas de Rastreo

Si tu rastreador ignora robots.txt, te arriesgas a problemas legales o bloqueos de IP.

Mala práctica:

python Copy
import requests

html = requests.get("https://example.com").text
# Sin verificación de robots.txt

Mejor enfoque:

python Copy
import urllib.robotparser

rp = urllib.robotparser.RobotFileParser()
rp.set_url("https://example.com/robots.txt")
rp.read()

if rp.can_fetch("*", "https://example.com/page"):
    print("Permitido rastrear")
else:
    print("Prohibido por robots.txt")

✅ Siempre respeta las políticas de rastreo e implementa límites de velocidad.


2. Rastrear Demasiado Agresivamente

Enviar miles de solicitudes por segundo es una forma rápida de ser bloqueado.

Solución:

  • Agregar retrasos
  • Usar rastreo asíncrono para mayor eficiencia
python Copy
import asyncio, aiohttp, random

async def fetch(session, url):
    async with session.get(url) as resp:
        return await resp.text()

async def main():
    urls = ["https://example.com/page1", "https://example.com/page2"]
    async with aiohttp.ClientSession() as session:
        for url in urls:
            html = await fetch(session, url)
            print(len(html))
            await asyncio.sleep(random.uniform(1, 3))  # retraso cortés

asyncio.run(main())

3. Manejo de Contenido Renderizado por JavaScript

Los rastreadores estáticos no detectan páginas con mucho JS (React, Vue, Angular).

Solución: Usar un navegador sin cabeza (por ejemplo, Playwright, Puppeteer).

python Copy
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    page = browser.new_page()
    page.goto("https://quotes.toscrape.com/js/")
    print(page.content())  # ahora incluye contenido renderizado por JS
    browser.close()

4. Extracción de Datos Ineficiente

Codificar selectores frágiles lleva a rastreadores rotos.

Mejor enfoque con BeautifulSoup + alternativas:

python Copy
from bs4 import BeautifulSoup

html = "<div><h1 class='title'>Hola</h1></div>"
soup = BeautifulSoup(html, "lxml")

# Selector primario
title = soup.select_one("h1.title")

# Alternativa
if not title:
    title = soup.find("h1")

print(title.text)

5. Recolección de Contenido Duplicado

URLs como /page?id=123&session=abc pueden causar duplicados.

Solución: Normalizar URLs

python Copy
from urllib.parse import urlparse, urlunparse

def normalize(url):
    parsed = urlparse(url)
    clean = parsed._replace(query="")
    return urlunparse(clean)

print(normalize("https://example.com/page?id=1&session=xyz"))
# -> https://example.com/page

6. Bloqueo de IP y Mecanismos Anti-Bot

Los sitios web detectan bots con anomalías de tasa, huellas digitales y CAPTCHAs.

Rotación básica con Scrapy:

python Copy
class RotateUserAgentMiddleware:
    user_agents = [
        "Mozilla/5.0 ...",
        "Chrome/91.0 ...",
        "Safari/537.36 ..."
    ]

    def process_request(self, request, spider):
        import random
        request.headers['User-Agent'] = random.choice(self.user_agents)

Stack de solución:

  • Rotar proxies y agentes de usuario
  • Usar proxies residenciales/móviles
  • Integrar solucionadores de CAPTCHA cuando sea necesario

7. Manejo de Errores

Los errores de red son inevitables. Sin reintentos, los rastreadores fallan silenciosamente.

Ejemplo con reintentos:

python Copy
import requests, time

def fetch(url, retries=3):
    for i in range(retries):
        try:
            return requests.get(url, timeout=5)
        except requests.exceptions.RequestException as e:
            print(f"Error: {e}, reintentando {i+1}")
            time.sleep(2**i)
    return None

8. Desafíos de Escalabilidad

Un rastreador que funciona para 1,000 páginas puede fallar en 10M.

Ejemplo de rastreo distribuido con Scrapy + Redis:

bash Copy
scrapy runspider crawler.py -s JOBDIR=crawls/job1

Usar:

  • Redis/Kafka para colas de tareas distribuidas
  • Scrapy Cluster / Nutch para escalar
  • Almacenamiento en la nube para resultados de rastreo

9. Problemas de Calidad de Datos

Los datos rastreados pueden contener duplicados, campos vacíos o formatos inválidos.

Solución: Validación de esquema

python Copy
from pydantic import BaseModel, ValidationError

class Product(BaseModel):
    name: str
    price: float

try:
    item = Product(name="Laptop", price="no es un número")
except ValidationError as e:
    print(e)

10. Seguridad y Cumplimiento

Los rastreadores deben evitar raspar PII o datos restringidos. Siempre verifica el cumplimiento con GDPR/CCPA antes de almacenar datos de usuarios.


Conclusión

Construir un rastreador robusto requiere precisión técnica y responsabilidad ética. Al abordar problemas como el rastreo agresivo, la representación de JavaScript, las defensas contra bots y la escalabilidad, los desarrolladores pueden diseñar rastreadores que sean:

  • Eficiente (uso óptimo de recursos)
  • Resiliente (tolerante a errores)
  • Cumplidor (legal y ético)

En Scrapeless, solo accedemos a datos disponibles públicamente y cumplimos estrictamente con las leyes, regulaciones y políticas de privacidad del sitio web aplicables. El contenido de este blog es sólo para fines de demostración y no implica ninguna actividad ilegal o infractora. No ofrecemos garantías y renunciamos a toda responsabilidad por el uso de la información de este blog o enlaces de terceros. Antes de realizar cualquier actividad de scraping, consulte a su asesor legal y revise los términos de servicio del sitio web de destino u obtenga los permisos necesarios.

Artículos más populares

Catalogar