Prácticas responsables de scraping
Cumplimiento de robots.txt, cabeceras de agente de usuario, pausas entre solicitudes y caché.
Prácticas responsables de scraping es una lección gratuita de AI Agents en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de AI Agents, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de AI Agents incluye 4 lecciones en total.
Por qué es importante hacer scraping de forma responsable
El scraping web puede sobrecargar los servidores, infringir los términos de servicio y hacer que se bloquee la IP de su agente. Quienes hacen scraping de forma responsable respetan los límites de frecuencia, se identifican y cumplen las reglas que publican los sitios web.
Esta lección aborda las herramientas y técnicas para hacer scraping de forma ética y sostenible.
Comprobación de robots.txt
Cada sitio web puede publicar un archivo robots.txt que especifique a qué rutas pueden o no acceder los agentes automatizados. La biblioteca estándar de Python incluye urllib.robotparser para analizar este archivo.
Compruebe siempre robots.txt antes de hacer scraping de un sitio.
import urllib.robotparser
rp = urllib.robotparser.RobotFileParser()
rp.set_url('https://example.com/robots.txt')
rp.read()
# Check if our bot can fetch a specific path
can_fetch = rp.can_fetch('MyAgent/1.0', 'https://example.com/public-data')
print(f'Can fetch: {can_fetch}') # True or False
cannot_fetch = rp.can_fetch('*', 'https://example.com/private/admin')
print(f'Admin allowed: {cannot_fetch}') # Often FalseConfiguración de un User-Agent descriptivo
La cabecera HTTP User-Agent identifica quién realiza una solicitud. Un User-Agent honesto permite a los administradores del sitio saber qué es su bot y cómo ponerse en contacto con usted si surge algún problema. Hacerse pasar por un navegador para eludir bloqueos plantea problemas éticos.
import httpx
headers = {
# Honest, descriptive User-Agent
'User-Agent': 'MyResearchBot/1.0 (contact: me@example.com; purpose: academic research)'
}
response = httpx.get(
'https://example.com/data',
headers=headers,
timeout=10.0
)
print(response.status_code)Limitación de frecuencia con time.sleep()
Enviar cientos de solicitudes por segundo puede sobrecargar un servidor y a menudo se considera un ataque de denegación de servicio. Añada pausas entre las solicitudes mediante time.sleep(). Use random.uniform() para que la pausa sea menos robótica y más parecida al comportamiento humano.
import time
import random
import httpx
urls = [
'https://example.com/page/1',
'https://example.com/page/2',
'https://example.com/page/3'
]
for url in urls:
response = httpx.get(url, timeout=10.0)
print(f'Fetched {url}: {response.status_code}')
# Wait between 1 and 3 seconds before the next request
delay = random.uniform(1, 3)
print(f'Sleeping {delay:.1f}s...')
time.sleep(delay)Respeto de las cabeceras Retry-After
Cuando un servidor responde con 429 Too Many Requests, a menudo incluye una cabecera Retry-After que especifica cuántos segundos debe esperar. Su agente debe leerla y respetarla en lugar de volver a intentarlo de inmediato.
import time
import httpx
def fetch_with_retry(url: str) -> httpx.Response:
while True:
response = httpx.get(url, timeout=10.0)
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 5))
print(f'Rate limited. Waiting {retry_after}s...')
time.sleep(retry_after)
continue # retry
response.raise_for_status()
return responseAlmacenamiento en caché de respuestas para evitar solicitudes repetidas
requests-cache almacena automáticamente en caché las respuestas HTTP en el disco. Si su agente necesita obtener la misma URL varias veces (por ejemplo, durante el desarrollo o al volver a ejecutar el programa), las respuestas almacenadas en caché se devuelven al instante sin acceder al servidor.
# pip install requests-cache
import requests_cache
# Install the cache globally — cached responses expire after 1 hour
requests_cache.install_cache(
'agent_cache',
backend='sqlite',
expire_after=3600 # seconds
)
import requests
# First call: fetches from network and caches
response = requests.get('https://api.example.com/data')
print(response.from_cache) # False
# Second call: returns cached result instantly
response2 = requests.get('https://api.example.com/data')
print(response2.from_cache) # TrueAlmacenamiento en caché manual basado en archivos con httpx
Si prefiere no utilizar requests-cache, una caché sencilla basada en archivos funciona bien. Almacene las respuestas como archivos JSON identificados mediante el hash de la URL y vuelva a cargarlas si el archivo aún es suficientemente reciente.
import hashlib
import json
import os
import time
import httpx
CACHE_DIR = '/tmp/agent_cache'
os.makedirs(CACHE_DIR, exist_ok=True)
def cached_get(url: str, ttl_seconds: int = 3600) -> dict:
key = hashlib.md5(url.encode()).hexdigest()
cache_file = os.path.join(CACHE_DIR, key + '.json')
if os.path.exists(cache_file):
age = time.time() - os.path.getmtime(cache_file)
if age < ttl_seconds:
with open(cache_file) as f:
return json.load(f)
response = httpx.get(url, timeout=10.0)
response.raise_for_status()
data = response.json()
with open(cache_file, 'w') as f:
json.dump(data, f)
return dataLectura de los términos de servicio
Antes de hacer scraping de un sitio, lea sus términos de servicio. Muchos prohíben explícitamente el acceso automatizado o el uso comercial de sus datos. Incumplir los términos de servicio puede dar lugar a acciones legales, no solo al bloqueo de la IP.
Si existe una API oficial, prefíérala siempre al scraping del HTML: es más rápida, estable y legalmente más segura.
Backoff exponencial ante errores
Cuando falla una solicitud, no la reintente de inmediato. Use un backoff exponencial: espere 1 s, luego 2 s, después 4 s, etc. Esto evita sobrecargar un servidor con problemas y es un patrón profesional en agentes de producción.
import time
import httpx
def fetch_with_backoff(url: str, max_retries: int = 4) -> dict:
for attempt in range(max_retries):
try:
response = httpx.get(url, timeout=10.0)
response.raise_for_status()
return response.json()
except (httpx.HTTPStatusError, httpx.RequestError) as e:
if attempt == max_retries - 1:
raise
wait = 2 ** attempt # 1, 2, 4, 8 seconds
print(f'Attempt {attempt+1} failed: {e}. Retrying in {wait}s...')
time.sleep(wait)
return {}Hacer scraping solo de lo necesario
Minimice la carga del servidor obteniendo únicamente lo que su agente necesita realmente. Evite descargar páginas completas cuando un pequeño endpoint de API devuelve los mismos datos. Use solicitudes HEAD para comprobar si un recurso ha cambiado antes de obtener el cuerpo completo.
import httpx
def has_page_changed(url: str, last_etag: str = None) -> bool:
headers = {}
if last_etag:
headers['If-None-Match'] = last_etag
response = httpx.head(url, headers=headers, timeout=5.0)
if response.status_code == 304: # Not Modified
return False
new_etag = response.headers.get('ETag')
print(f'New ETag: {new_etag}')
return TrueResumen de las reglas para hacer scraping de forma responsable
Una lista de comprobación rápida antes de que su agente haga scraping de un sitio:
- Compruebe
robots.txty respete las reglas de exclusión - Configure un
User-Agenthonesto y descriptivo - Añada pausas aleatorias entre las solicitudes (
time.sleep(random.uniform(1,3))) - Respete las cabeceras
Retry-Afteren las respuestas 429 - Almacene las respuestas en caché para evitar solicitudes redundantes
- Lea los términos de servicio del sitio
- Prefiera las API oficiales al scraping de HTML cuando estén disponibles
Comprobación de conocimientos: scraping responsable
Compruebe sus conocimientos sobre las prácticas éticas y responsables de scraping.
Resumen: prácticas de scraping responsable
Ahora dispone de un conjunto completo de herramientas para hacer scraping de forma responsable:
robotparserpara comprobar a qué puede acceder- Cabeceras
User-Agentdescriptivas que identifican su bot time.sleep(random.uniform(1,3))entre las solicitudesrequests-cacheo almacenamiento en caché manual para evitar solicitudes duplicadas- Backoff exponencial para gestionar errores
- Conocimiento de los aspectos legales: compruebe siempre los términos de servicio
El scraping responsable contribuye a una web más saludable y permite que sus agentes sigan funcionando sin bloqueos.
Preguntas frecuentes
¿La lección «Prácticas responsables de scraping» es gratis?
Sí — el texto completo de «Prácticas responsables de scraping» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de AI Agents, actualiza a CoddyKit PRO. El curso de AI Agents incluye 4 lecciones en total.
¿Qué aprenderé en «Prácticas responsables de scraping»?
Cumplimiento de robots.txt, cabeceras de agente de usuario, pausas entre solicitudes y caché. Practicas AI Agents con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar AI Agents?
No se requiere experiencia previa. AI Agents en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.
¿Cuánto tiempo toma la lección «Prácticas responsables de scraping»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de AI Agents?
Sí. Cada lección de AI Agents incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Clientes HTTP para agentes: httpx y requests
- Análisis de HTML con BeautifulSoup
- Gestión de la paginación y el contenido dinámico
- Prácticas responsables de scraping