Empieza por las alternativas
Antes de escribir un scraper, busca:
- Una API oficial o una exportación de datos. Es más estable, está documentada y su uso está claramente permitido.
- Un feed: RSS, Atom, JSON Feed, sitemaps.
- Un conjunto de datos abierto: Common Crawl, portales de datos abiertos, Wikidata.
- Preguntar. Muchos propietarios ceden datos si explicas el propósito.
Las preguntas que deciden si es aceptable
- ¿El contenido es público? Lo que está tras un inicio de sesión, un muro de pago o un control de acceso queda fuera. Eludir esos controles puede ser acceso no autorizado según las leyes de delitos informáticos, no solo un incumplimiento de términos.
- ¿Qué dicen los términos de servicio? Pueden prohibir el acceso automatizado. Incumplirlos puede tener consecuencias contractuales y acabar en bloqueo.
- ¿Hay datos personales? Nombres, perfiles, fotos y datos de contacto están protegidos por leyes de privacidad como el RGPD en muchos lugares, aunque sean visibles públicamente. Necesitas una base legal, un propósito, minimización y límites de retención.
- ¿Tiene derechos de autor? Los hechos suelen ser libres; copiar artículos, imágenes o bases de datos de forma sustancial puede no serlo. Republicar es más arriesgado que analizar.
- ¿Perjudica al sitio? Una carga que degrade el servicio para usuarios reales nunca es aceptable.
Esto no es asesoramiento legal; las leyes varían según el país y cambian. Si la respuesta importa, consulta a un abogado.
robots.txt
El protocolo de exclusión de robots, estandarizado como RFC 9309, permite a los sitios indicar qué rutas deben evitar los rastreadores. No es un control de acceso, pero respetarlo es el mínimo del buen comportamiento. Descarga /robots.txt, busca el grupo de tu user agent, respeta Disallow y trata Crawl-delay (no estándar) como una indicación para ir más despacio.
Un descargador educado
import time, urllib.robotparser, httpx
from urllib.parse import urlsplit
UA = "ExampleResearchBot/1.0 (+https://example.com/bot; bot@example.com)"
robots = {}
def allowed(url):
root = "{0.scheme}://{0.netloc}".format(urlsplit(url))
if root not in robots:
rp = urllib.robotparser.RobotFileParser(root + "/robots.txt"); rp.read(); robots[root] = rp
return robots[root].can_fetch(UA, url)
client = httpx.Client(headers={"User-Agent": UA}, timeout=20, follow_redirects=True)
last = {}
def fetch(url, min_interval=5.0):
if not allowed(url):
return None
host = urlsplit(url).netloc
wait = min_interval - (time.monotonic() - last.get(host, 0))
if wait > 0: time.sleep(wait)
r = client.get(url)
last[host] = time.monotonic()
if r.status_code in (429, 503):
time.sleep(int(r.headers.get("Retry-After", 60)))
return r
Principios de ese código: un user agent honesto con datos de contacto, comprobación de robots.txt, una petición cada vez por host con pausa, y retroceder cuando el servidor indica sobrecarga.
Más buenos hábitos
- Guarda en caché las respuestas y usa peticiones condicionales (
If-None-Match,If-Modified-Since). - Rastrea en horas de poco tráfico y detente ante errores repetidos.
- Recoge solo los campos que necesitas y borra las páginas crudas tras extraerlos.
- No rotes IPs ni user agents para evitar bloqueos. Si un sitio te bloquea, esa es la respuesta.
- Nunca resuelvas ni eludas CAPTCHAs o desafíos antibots con servicios automatizados.
- Usa un navegador headless solo cuando el contenido requiera JavaScript de verdad; le cuesta más al sitio que una petición simple.
Rastreadores de IA y datos de entrenamiento
Si recoges datos para entrenar o fundamentar modelos de IA, sé transparente: publica el user agent y el propósito de tu rastreador, respeta las reglas de robots.txt dirigidas a rastreadores de IA y las señales de exclusión. Cada vez más sitios bloquean rastreadores desconocidos; uno documentado y bien educado tiene muchas menos probabilidades de ser bloqueado.
Cuando el sitio es tuyo
Los bots también visitarán tu sitio. Publica un robots.txt claro, ofrece una API o un feed para usos legítimos, limita la tasa por IP y por token, y usa gestión de bots para el tráfico abusivo en lugar de bloquear a todo cliente automatizado.