El proxy devuelve datos incorrectos: causas y soluciones
Configuraste el parser, iniciaste la recopilación de datos y, como resultado, obtienes precios de otra región, contenido desactualizado o una página completamente diferente. Analicemos por qué un proxy puede devolver datos incorrectos y cómo solucionarlo.
1. Almacenamiento en caché del lado del proxy
La causa más común de datos obsoletos es el almacenamiento en caché. Algunos servidores proxy guardan las respuestas de los sitios web para reducir la carga y acelerar el rendimiento. Como resultado, recibes datos de hace una semana en lugar de los actuales.
Cómo identificar el problema
- Los datos no cambian con solicitudes repetidas
- Los precios o la disponibilidad de los productos no coinciden con la realidad
- El encabezado
Ageen la respuesta muestra un valor alto
Solución
Añade encabezados que prohíban el almacenamiento en caché:
import requests
headers = {
'Cache-Control': 'no-cache, no-store, must-revalidate',
'Pragma': 'no-cache',
'Expires': '0'
}
response = requests.get(
'https://example.com/prices',
proxies={'http': proxy, 'https': proxy},
headers=headers
)
Si el proveedor sigue almacenando en caché, añade un parámetro aleatorio a la URL:
import time
url = f'https://example.com/prices?_nocache={int(time.time())}'
2. Desajuste de geolocalización
Solicitas un proxy desde Alemania, pero obtienes precios en rublos. O al revés: necesitas datos rusos, pero el sitio muestra contenido para EE. UU. Esto sucede por varias razones.
Por qué no coincide la geolocalización
| Causa | Descripción |
|---|---|
| Bases de datos GeoIP obsoletas | La IP se ha movido recientemente a otra región, pero las bases de datos aún no se han actualizado |
| El sitio usa su propia base | El sitio web de destino determina la geografía de manera diferente al proveedor de proxy |
| Cookies de una sesión anterior | El sitio recordó tu región de una visita anterior |
| Accept-Language | El encabezado de idioma no coincide con la geografía del proxy |
Solución
Sincroniza todos los parámetros de la solicitud con la geolocalización deseada:
# Para hacer scraping de un sitio alemán
headers = {
'Accept-Language': 'de-DE,de;q=0.9,en;q=0.8',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)...'
}
# Sesión limpia sin cookies
session = requests.Session()
session.cookies.clear()
response = session.get(
'https://example.de/preise',
proxies={'http': german_proxy, 'https': german_proxy},
headers=headers
)
Antes de hacer scraping, verifica la geolocalización real de la IP:
def check_proxy_geo(proxy):
response = requests.get(
'http://ip-api.com/json/',
proxies={'http': proxy, 'https': proxy},
timeout=10
)
data = response.json()
return data.get('country'), data.get('city')
3. Problemas con la rotación de IP
Al utilizar proxies residenciales con rotación automática de IP, la IP cambia entre solicitudes. Esto es útil para evitar límites, pero crea problemas cuando se necesita consistencia de datos.
Síntomas típicos
- La paginación devuelve duplicados o salta elementos
- El carrito de compras se vacía entre solicitudes
- La autenticación se pierde a mitad de la sesión
- Las pruebas A/B del sitio muestran diferentes versiones de la página
Solución: sesiones "sticky" (pegajosas)
La mayoría de los proveedores de proxy admiten sesiones "sticky": la IP se mantiene durante un tiempo determinado. Generalmente, esto se configura mediante un parámetro en la cadena de conexión:
# Ejemplo de formato con ID de sesión (la sintaxis depende del proveedor)
proxy = 'http://user-session-abc123:pass@gate.provider.com:7777'
# Todas las solicitudes con el mismo ID de sesión pasan por la misma IP
for page in range(1, 10):
response = requests.get(
f'https://example.com/catalog?page={page}',
proxies={'http': proxy, 'https': proxy}
)
Importante: Una sesión "sticky" suele durar entre 1 y 30 minutos. Planifica tu recopilación de datos para que las solicitudes relacionadas se completen dentro de esta ventana.
4. Interrupción de sesiones y cookies
Los sitios web modernos utilizan activamente las cookies para la personalización. Si tu parser no las maneja correctamente, obtendrás datos incorrectos o serás bloqueado.
Errores comunes
- Ignorar Set-Cookie: el sitio no puede rastrear la sesión
- Reutilizar cookies con una IP diferente: comportamiento sospechoso
- Falta de solicitud inicial: acceder directamente a una página interna sin "entrar" a través de la página principal
El enfoque correcto
import requests
def create_browser_session(proxy):
session = requests.Session()
session.proxies = {'http': proxy, 'https': proxy}
# Imitamos la primera visita: obtenemos cookies
session.get('https://example.com/', headers={
'User-Agent': 'Mozilla/5.0...',
'Accept': 'text/html,application/xhtml+xml...',
'Accept-Language': 'en-US,en;q=0.9'
})
# Ahora podemos hacer scraping con una sesión válida
return session
session = create_browser_session(proxy)
data = session.get('https://example.com/api/prices').json()
5. Errores de codificación y compresión
A veces los datos llegan correctos, pero se muestran incorrectamente debido a problemas de codificación o compresión. Esto es especialmente relevante al trabajar con cirílico e idiomas asiáticos.
Síntomas
- Caracteres ilegibles en lugar de texto:
Ценаen lugar de «Цена» - Respuesta vacía cuando gzip está activado
- Basura binaria en lugar de HTML
Solución
import requests
response = requests.get(url, proxies=proxies)
# Método 1: Autodetección de codificación
response.encoding = response.apparent_encoding
text = response.text
# Método 2: Codificación forzada
text = response.content.decode('utf-8')
# Método 3: Desactivar la compresión (si el proxy rompe gzip)
headers = {'Accept-Encoding': 'identity'}
response = requests.get(url, proxies=proxies, headers=headers)
6. Bloqueos ocultos y CAPTCHAs
No todos los bloqueos son obvios. Un sitio puede devolver un HTTP 200, pero en lugar de los datos reales, insertar una página de relleno, un caché obsoleto o una página con CAPTCHA dentro del HTML normal.
Señales de bloqueo oculto
- El tamaño de la respuesta es sospechosamente pequeño o idéntico para diferentes páginas
- El HTML contiene palabras como: captcha, challenge, blocked, access denied
- Faltan elementos esperados (precios, descripciones, botones)
- Redirección JavaScript a otra página
Validación de la respuesta
def is_valid_response(response, expected_markers):
"""Verifica que la respuesta contenga datos reales"""
text = response.text.lower()
# Verificación de bloqueo
block_signals = ['captcha', 'blocked', 'access denied',
'rate limit', 'try again later']
for signal in block_signals:
if signal in text:
return False, f'Bloqueado: {signal}'
# Verificación de contenido esperado
for marker in expected_markers:
if marker.lower() not in text:
return False, f'Falta: {marker}'
# Verificación de tamaño (demasiado pequeño = relleno)
if len(response.content) < 5000:
return False, 'Respuesta demasiado pequeña'
return True, 'OK'
# Uso
valid, reason = is_valid_response(response, ['price', 'add to cart'])
if not valid:
print(f'Respuesta inválida: {reason}')
# Cambiar proxy, esperar, reintentar
Para sitios con protección avanzada contra bots, los proxies móviles ofrecen un mejor nivel de confianza que los de centro de datos.
7. Diagnóstico paso a paso
Cuando un proxy devuelve datos incorrectos, utiliza este algoritmo para encontrar la causa:
Paso 1: Aislar el problema
# Compara las respuestas: sin proxy vs con proxy
def compare_responses(url, proxy):
direct = requests.get(url)
proxied = requests.get(url, proxies={'http': proxy, 'https': proxy})
print(f'Directo: {len(direct.content)} bytes, estado {direct.status_code}')
print(f'Proxy: {len(proxied.content)} bytes, estado {proxied.status_code}')
# Guarda ambas respuestas para comparar
with open('direct.html', 'w') as f:
f.write(direct.text)
with open('proxied.html', 'w') as f:
f.write(proxied.text)
Paso 2: Revisar los encabezados de respuesta
response = requests.get(url, proxies=proxies)
# Encabezados clave para el diagnóstico
important_headers = ['content-type', 'content-encoding',
'cache-control', 'age', 'x-cache',
'cf-ray', 'server']
for header in important_headers:
value = response.headers.get(header, 'no establecido')
print(f'{header}: {value}')
Paso 3: Lista de verificación de comprobaciones
| Comprobación | Comando/método |
|---|---|
| IP real del proxy | curl -x proxy:port ifconfig.me |
| Geolocalización de la IP | ip-api.com/json |
| Almacenamiento en caché | Encabezados Age, X-Cache |
| Bloqueo | Búsqueda de "captcha", "blocked" en HTML |
| Codificación | Content-Type charset |
Paso 4: Script de diagnóstico completo
import requests
import json
def diagnose_proxy(proxy, target_url):
report = {}
# 1. Verificación de funcionamiento
try:
r = requests.get('http://httpbin.org/ip',
proxies={'http': proxy, 'https': proxy},
timeout=15)
report['proxy_ip'] = r.json().get('origin')
report['proxy_works'] = True
except Exception as e:
report['proxy_works'] = False
report['error'] = str(e)
return report
# 2. Geolocalización
r = requests.get('http://ip-api.com/json/',
proxies={'http': proxy, 'https': proxy})
geo = r.json()
report['country'] = geo.get('country')
report['city'] = geo.get('city')
# 3. Solicitud al sitio de destino
r = requests.get(target_url,
proxies={'http': proxy, 'https': proxy},
timeout=30)
report['status_code'] = r.status_code
report['content_length'] = len(r.content)
report['cached'] = 'age' in r.headers or 'x-cache' in r.headers
# 4. Verificación de bloqueo
block_words = ['captcha', 'blocked', 'denied', 'cloudflare']
report['possibly_blocked'] = any(w in r.text.lower() for w in block_words)
return report
# Uso
result = diagnose_proxy('http://user:pass@proxy:port', 'https://target-site.com')
print(json.dumps(result, indent=2))
Conclusión
Los datos incorrectos devueltos por un proxy son casi siempre un problema solucionable. En la mayoría de los casos, la causa es el almacenamiento en caché, el desajuste de geolocalización o el manejo incorrecto de las sesiones. Utiliza el script de diagnóstico de este artículo para encontrar rápidamente la fuente del problema.
Para tareas donde la precisión de la geolocalización y una baja tasa de bloqueo son críticas, los proxies residenciales con soporte para sesiones "sticky" son la mejor opción; obtén más detalles en proxycove.com.