Un recolector en Python empieza con cinco líneas que funcionan a la primera. El problema llega después: en la tercera semana, cuando el sitio cambia un div; en el segundo mes, cuando empiezan a llegar respuestas de error; en el sexto, cuando alguien pregunta de dónde salió ese dato.
Este artículo trata de esa segunda parte. Si todavía estás decidiendo si necesitas recolectar, empieza por qué es el web scraping, que trata la base legal y los casos en los que la fuente oficial lo resuelve sin raspar nada.
Antes de la primera línea: ¿hay una API?
Sigue siendo la pregunta que más trabajo ahorra. Un endpoint oficial devuelve datos estructurados, no se rompe cuando el sitio cambia de diseño, consume una fracción del tráfico y no abre ninguna discusión sobre términos de uso.
En muchos países, buena parte de lo que la gente intenta raspar ya está publicado como dato abierto: contratación pública, registros de empresas, estadísticas oficiales. Conviene revisar la fuente antes de escribir el recolector.
La pareja que resuelve la mayoría de los casos
Para una página que ya llega completa en el HTML, requests descarga y BeautifulSoup extrae:
import requests
from bs4 import BeautifulSoup
sessao = requests.Session()
sessao.headers.update({
"User-Agent": "MeuColetor/1.0 ([email protected])",
"Accept-Language": "pt-BR,pt;q=0.9",
})
resposta = sessao.get("https://exemplo.com.br/produtos", timeout=20)
resposta.raise_for_status()
pagina = BeautifulSoup(resposta.text, "html.parser")
for item in pagina.select(".produto"):
nome = item.select_one(".nome")
preco = item.select_one(".preco")
print(nome.get_text(strip=True), preco.get_text(strip=True))
En tu caso, cambia el User-Agent por el nombre de tu recolector y un contacto tuyo, Accept-Language por el idioma del sitio (por ejemplo, es-ES,es;q=0.9), la URL por la de tu destino y los selectores .produto, .nome y .preco (producto, nombre y precio) por los de la página.
Tres detalles de este fragmento son los que separan un script de un recolector:
Session() en lugar de requests.get suelto. Reutiliza la conexión, lo que reduce el tiempo y el consumo. En una recolección grande, la diferencia es grande.
Un User-Agent que dice quién eres. Un agente honesto, con una forma de contacto, es lo que permite al administrador del sitio hablar contigo en lugar de bloquearte sin más. Es la diferencia entre ser un socio pesado y un problema anónimo.
timeout siempre. Sin él, una petición colgada bloquea el recolector por tiempo indefinido.
Selecciona por lo que es estable
Un motivo muy común de un recolector roto es un selector frágil. Las clases generadas automáticamente cambian con cada publicación del sitio.
Prioriza, en este orden: atributos de datos (data-produto-id), identificadores semánticos, estructura de tabla y, solo al final, clases de estilo. Y mucho antes de eso, busca un bloque <script type="application/ld+json"> en la página: muchos sitios de comercio publican ahí el precio y el nombre del producto en JSON limpio, listos para leer sin ningún selector.
Despacio es más rápido
La tentación es ejecutarlo todo en paralelo. El resultado suele ser un bloqueo el primer día.
import time, random
for url in urls:
resposta = sessao.get(url, timeout=20)
if resposta.status_code == 429:
espera = int(resposta.headers.get("Retry-After", 60))
time.sleep(espera)
continue
processa(resposta)
time.sleep(random.uniform(1.5, 4.0))
Este código hace dos cosas que casi ningún recolector aficionado hace: lee Retry-After en lugar de reintentar al instante, y varía el intervalo en lugar de ir al compás del reloj. El significado exacto del 429 y la estrategia de espera creciente están en error 429 Too Many Requests.
Antes que nada, lee el robots.txt del sitio y sus términos de uso. No es una formalidad: es lo que define si tu recolección es aceptable.
Cuándo hace falta el navegador (y por qué evitarlo)
Si el contenido solo aparece después de ejecutarse el JavaScript, requests no sirve y entra un navegador automatizado. Antes de aceptar ese coste, abre las herramientas de desarrollo en la pestaña de red y busca la llamada que hace la propia página: en muchos casos hay un endpoint JSON detrás, que devuelve el mismo dato sin renderizar nada.
Cuando el navegador es inevitable, el coste cambia de escala: cada página carga imágenes, fuentes y scripts, y el consumo de tráfico se dispara. Las cuentas están en consumo de GB en scraping, y conviene bloquear imágenes y fuentes en la carga. Qué herramienta elegir está en Selenium, Puppeteer o Playwright.
Dónde entra de verdad el proxy
Al principio, no entra. Una recolección pequeña de páginas públicas sale por tu propia conexión sin ningún problema.
Empieza a tener sentido en tres situaciones:
- El servidor cuenta por dirección. El volumen ha crecido y empiezas a tocar el límite. La salida es repartir, siempre junto con la reducción de la frecuencia, nunca en su lugar.
- El contenido cambia según el origen. El precio, el catálogo y los resultados de búsqueda varían según el país o la ciudad de quien pide. Ahí una dirección del país correcto no es una optimización: es un requisito para que el dato sea correcto.
- La recolección tiene que mantener la sesión iniciada. En ese caso, cambiar de dirección en mitad de la sesión es justo lo que dispara la alerta, y lo correcto es una dirección fija.
La configuración en requests, httpx y aiohttp, con usuario y contraseña y el tratamiento de contraseñas con caracteres especiales, está en la guía de proxy en Python. La elección entre dirección fija, por sesión o por petición está en proxy rotativo: fija, por sesión o por petición.
Conviene medir antes de contratar: ejecuta cien elementos, mide el tráfico consumido y proyecta. La página de proxy para web scraping muestra los productos por escenario: nuestro residencial rotativo por GB sale con IP de Brasil, y para otros países vendemos IP fija por país (IPv4, ISP e IPv6), que eliges en el checkout.
La lista del recolector que dura
- Comprobaste si hay API o dato abierto en la fuente.
- Leíste el
robots.txty los términos de uso. - Definiste la base legal si hay datos personales (RGPD en la UE y las leyes locales de protección de datos).
- Usas
Session,timeouty un User-Agent identificable. - Seleccionas por atributos estables, no por clases de estilo.
- Respetas
Retry-Aftery varías el intervalo. - Registras la tasa de errores y avisas cuando sube.
- Solo entonces valoras el proxy, según el tipo de límite que apareció.
Un recolector montado en este orden cuesta menos en tráfico, se rompe menos cuando el sitio cambia y no pone a nadie en una situación difícil.