Volver al blog

Cómo configurar un proxy en AWS Lambda para scraping y API: guía completa con ejemplos

Instrucciones paso a paso para configurar un proxy en AWS Lambda para scraping, solicitudes API y automatización. Ejemplos de código en Python y Node.js, solución de problemas comunes.

📅18 de febrero de 2026
```html

AWS Lambda es una plataforma sin servidor que permite ejecutar código sin gestionar servidores. Sin embargo, al trabajar con scraping de sitios web, API de marketplaces o automatización de tareas, a menudo surge un problema: las funciones Lambda utilizan direcciones IP de AWS que son fácilmente detectables y bloqueadas. En esta guía, veremos cómo integrar proxies en Lambda, configurar la rotación de IP y evitar errores comunes.

El artículo está dirigido a desarrolladores que automatizan tareas a través de AWS Lambda: scraping de datos de sitios protegidos, monitoreo de precios de competidores, trabajo con API de redes sociales o marketplaces. Obtendrás ejemplos de código listos para usar en Python y Node.js que puedes utilizar inmediatamente después de leer.

¿Por qué se necesitan proxies en AWS Lambda?

AWS Lambda, por defecto, utiliza direcciones IP del pool de Amazon Web Services. Estas direcciones están en listas públicas y son fácilmente identificables por los sistemas de protección contra bots. Aquí están los principales escenarios en los que los proxies se vuelven necesarios:

Caso real: Un desarrollador configuró Lambda para monitorear precios en Wildberries cada 15 minutos. Después de 2 días, el marketplace comenzó a devolver el error 403 Forbidden: la IP de AWS fue incluida en la lista negra. Tras conectar proxies residenciales, el scraping ha funcionado de manera estable durante 6 meses.

Principales razones para usar proxies en Lambda:

  • Scraping de sitios protegidos: Muchos sitios bloquean solicitudes desde IPs de centros de datos de AWS. Los proxies permiten enmascarar Lambda como usuarios normales.
  • Restricciones geolocalizadas: Si necesitas obtener datos de un sitio accesible solo desde un país específico (por ejemplo, precios regionales en Ozon), los proxies con la geolocalización adecuada resuelven el problema.
  • Eludir limitaciones de tasa: Las API de muchos servicios limitan la cantidad de solicitudes desde una sola IP. La rotación de proxies permite distribuir la carga.
  • Pruebas A/B de publicidad: Verificación de la visualización de anuncios publicitarios desde diferentes regiones para el análisis de competidores.
  • Monitoreo de marketplaces: Seguimiento de posiciones de productos, precios de competidores en Wildberries, Ozon, Avito sin bloqueos.

Las funciones Lambda a menudo se ejecutan según un horario (a través de CloudWatch Events) o activadores, lo que las convierte en una herramienta ideal para la automatización. Sin embargo, sin proxies, tales tareas rápidamente se encuentran con bloqueos por parte de los recursos objetivo.

¿Qué tipo de proxy elegir para Lambda?

La elección del tipo de proxy depende de la tarea que resuelve tu función Lambda. Analicemos tres tipos principales y su aplicación en arquitecturas sin servidor:

Tipo de proxy Velocidad Anonimato Mejores escenarios para Lambda
Proxies de centros de datos Muy alta (50-200 ms) Media Scraping de API sin protección estricta, verificaciones masivas de disponibilidad de sitios, monitoreo SEO
Proxies residenciales Media (300-800 ms) Muy alta Scraping de sitios protegidos (marketplaces, redes sociales), eludir Cloudflare, trabajar con API de Instagram/Facebook
Proxies móviles Media (400-1000 ms) Máxima Trabajo con API móviles (TikTok, Instagram), pruebas de publicidad móvil, eludir las protecciones más estrictas

Recomendaciones para la elección:

  • Para scraping de Wildberries, Ozon, Avito: Utiliza proxies residenciales con geolocalización rusa. Estas plataformas bloquean activamente las IPs de centros de datos.
  • Para monitoreo de API sin protección estricta: Los proxies de centros de datos son suficientes, son más baratos y rápidos.
  • Para trabajar con API de Instagram, Facebook, TikTok: Solo proxies móviles o residenciales: estas plataformas detectan y bloquean los centros de datos.
  • Para eludir Cloudflare, PerimeterX: Proxies residenciales con rotación, preferiblemente con sesiones pegajosas (manteniendo la IP durante 5-30 minutos).

Importante: Las funciones Lambda tienen un límite de tiempo de ejecución (máximo 15 minutos). Al utilizar proxies lentos (residenciales/móviles), ten en cuenta las latencias: si una solicitud a través de un proxy toma 2 segundos, en 15 minutos podrás hacer un máximo de ~450 solicitudes.

Configuración de proxies en Lambda con Python (requests, urllib3)

Python es el lenguaje más popular para funciones Lambda, especialmente para tareas de scraping y automatización. Veamos cómo configurar proxies con la biblioteca requests, que se utiliza en el 90% de los casos.

Configuración básica de proxy HTTP

La forma más sencilla de conectar un proxy es pasar el parámetro proxies al método requests.get():

import requests
import os

def lambda_handler(event, context):
    # Obtenemos las credenciales del proxy de las variables de entorno
    proxy_host = os.environ['PROXY_HOST']  # Por ejemplo: proxy.example.com
    proxy_port = os.environ['PROXY_PORT']  # Por ejemplo: 8080
    proxy_user = os.environ['PROXY_USER']
    proxy_pass = os.environ['PROXY_PASS']
    
    # Formamos la URL del proxy con autorización
    proxy_url = f"http://{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}"
    
    proxies = {
        'http': proxy_url,
        'https': proxy_url
    }
    
    try:
        # Hacemos la solicitud a través del proxy
        response = requests.get(
            'https://api.example.com/data',
            proxies=proxies,
            timeout=10  # ¡Importante! Establece un tiempo de espera
        )
        
        return {
            'statusCode': 200,
            'body': response.text
        }
    
    except requests.exceptions.ProxyError as e:
        print(f"Error de proxy: {e}")
        return {
            'statusCode': 500,
            'body': 'Fallo en la conexión del proxy'
        }
    
    except requests.exceptions.Timeout as e:
        print(f"Error de tiempo de espera: {e}")
        return {
            'statusCode': 504,
            'body': 'Tiempo de espera de la solicitud'
        }

Puntos clave de este código:

  • Variables de entorno: ¡Nunca almacenes las credenciales del proxy directamente en el código! Utiliza Variables de Entorno en la configuración de Lambda.
  • Tiempo de espera: Asegúrate de establecer un tiempo de espera (10-30 segundos). Sin él, Lambda puede colgarse hasta que se agote el tiempo máximo de ejecución.
  • Manejo de errores: Los proxies pueden estar inactivos o ser lentos: siempre maneja las excepciones ProxyError y Timeout.
  • HTTP y HTTPS: Especifica ambos protocolos en el diccionario proxies, incluso si solo utilizas HTTPS.

Configuración de proxy SOCKS5

Los proxies SOCKS5 ofrecen un mayor nivel de anonimato y funcionan a nivel TCP, lo que los hace invisibles para algunos sistemas de protección. Para trabajar con SOCKS5 en requests, necesitas la biblioteca requests[socks]:

import requests
import os

def lambda_handler(event, context):
    proxy_host = os.environ['PROXY_HOST']
    proxy_port = os.environ['PROXY_PORT']
    proxy_user = os.environ['PROXY_USER']
    proxy_pass = os.environ['PROXY_PASS']
    
    # Proxy SOCKS5 con autorización
    proxy_url = f"socks5://{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}"
    
    proxies = {
        'http': proxy_url,
        'https': proxy_url
    }
    
    try:
        response = requests.get(
            'https://www.wildberries.ru/catalog/12345/detail.aspx',
            proxies=proxies,
            timeout=15
        )
        
        # Parseamos los datos
        return {
            'statusCode': 200,
            'body': response.text
        }
    
    except Exception as e:
        print(f"Error: {e}")
        return {
            'statusCode': 500,
            'body': str(e)
        }

Importante para el despliegue en Lambda: Al usar SOCKS5, añade a requirements.txt:

requests[socks]
PySocks

Verificación de IP a través del proxy

Antes de ejecutar la lógica principal, es útil verificar que el proxy funciona y devuelve la IP correcta:

def check_proxy_ip(proxies):
    """Verifica la IP que ve el mundo exterior a través del proxy"""
    try:
        response = requests.get(
            'https://api.ipify.org?format=json',
            proxies=proxies,
            timeout=10
        )
        ip_data = response.json()
        print(f"IP actual a través del proxy: {ip_data['ip']}")
        return ip_data['ip']
    except Exception as e:
        print(f"Fallo en la verificación del proxy: {e}")
        return None

def lambda_handler(event, context):
    # ... configuración del proxy ...
    
    # Verificamos la IP antes de la lógica principal
    current_ip = check_proxy_ip(proxies)
    if not current_ip:
        return {
            'statusCode': 500,
            'body': 'Fallo en la verificación del proxy'
        }
    
    # Lógica principal de scraping
    # ...

Configuración de proxies en Lambda con Node.js (axios, got)

Node.js es el segundo lenguaje más popular para funciones Lambda, especialmente cuando se necesita un alto rendimiento al trabajar con API. Veamos cómo configurar proxies con las bibliotecas axios y got.

Configuración con axios

Axios es la biblioteca HTTP más popular para Node.js. Para trabajar con proxies, necesitarás un paquete adicional https-proxy-agent:

const axios = require('axios');
const HttpsProxyAgent = require('https-proxy-agent');

exports.handler = async (event) => {
    // Obtenemos las credenciales de las variables de entorno
    const proxyHost = process.env.PROXY_HOST;
    const proxyPort = process.env.PROXY_PORT;
    const proxyUser = process.env.PROXY_USER;
    const proxyPass = process.env.PROXY_PASS;
    
    // Formamos la URL del proxy
    const proxyUrl = `http://${proxyUser}:${proxyPass}@${proxyHost}:${proxyPort}`;
    
    // Creamos un agente para el proxy
    const agent = new HttpsProxyAgent(proxyUrl);
    
    try {
        const response = await axios.get('https://api.example.com/data', {
            httpsAgent: agent,
            timeout: 10000  // 10 segundos
        });
        
        return {
            statusCode: 200,
            body: JSON.stringify(response.data)
        };
    } catch (error) {
        console.error('La solicitud falló:', error.message);
        
        return {
            statusCode: 500,
            body: JSON.stringify({
                error: error.message
            })
        };
    }
};

Instalación de dependencias: Añade a package.json:

{
  "dependencies": {
    "axios": "^1.6.0",
    "https-proxy-agent": "^7.0.0"
  }
}

Configuración SOCKS5 con axios

Para proxies SOCKS5, utiliza el paquete socks-proxy-agent:

const axios = require('axios');
const { SocksProxyAgent } = require('socks-proxy-agent');

exports.handler = async (event) => {
    const proxyUrl = `socks5://${process.env.PROXY_USER}:${process.env.PROXY_PASS}@${process.env.PROXY_HOST}:${process.env.PROXY_PORT}`;
    
    const agent = new SocksProxyAgent(proxyUrl);
    
    try {
        const response = await axios.get('https://www.ozon.ru/api/products', {
            httpAgent: agent,
            httpsAgent: agent,
            timeout: 15000
        });
        
        return {
            statusCode: 200,
            body: JSON.stringify(response.data)
        };
    } catch (error) {
        console.error('Error:', error.message);
        return {
            statusCode: 500,
            body: JSON.stringify({ error: error.message })
        };
    }
};

Alternativa: biblioteca got

Got es una biblioteca HTTP moderna con soporte nativo para proxies (no requiere agentes separados):

const got = require('got');

exports.handler = async (event) => {
    const proxyUrl = `http://${process.env.PROXY_USER}:${process.env.PROXY_PASS}@${process.env.PROXY_HOST}:${process.env.PROXY_PORT}`;
    
    try {
        const response = await got('https://api.example.com/data', {
            agent: {
                http: new (require('http-proxy-agent'))(proxyUrl),
                https: new (require('https-proxy-agent'))(proxyUrl)
            },
            timeout: {
                request: 10000
            },
            responseType: 'json'
        });
        
        return {
            statusCode: 200,
            body: JSON.stringify(response.body)
        };
    } catch (error) {
        console.error('Error:', error.message);
        return {
            statusCode: 500,
            body: JSON.stringify({ error: error.message })
        };
    }
};

Rotación de proxies en Lambda: cómo cambiar IP automáticamente

La rotación de proxies es críticamente importante para tareas donde se necesitan hacer muchas solicitudes sin bloqueos. Hay dos enfoques principales: usar servicios de proxies con rotación automática o gestionar manualmente un pool de proxies.

Rotación automática a través del proveedor

La mayoría de los proveedores de proxies residenciales (incluyendo ProxyCove) ofrecen un endpoint con rotación automática: cada solicitud o cada N minutos, la IP cambia automáticamente:

import requests
import os

def lambda_handler(event, context):
    # Proxy con rotación automática
    # Formato: rotating.proxy.com:port
    # Cada solicitud = nueva IP
    proxy_url = f"http://{os.environ['PROXY_USER']}:{os.environ['PROXY_PASS']}@rotating.proxycove.com:8080"
    
    proxies = {
        'http': proxy_url,
        'https': proxy_url
    }
    
    results = []
    
    # Hacemos 10 solicitudes: cada una con una nueva IP
    for i in range(10):
        try:
            response = requests.get(
                f'https://api.wildberries.ru/products/{i}',
                proxies=proxies,
                timeout=10
            )
            results.append({
                'product_id': i,
                'status': response.status_code,
                'data': response.json()
            })
        except Exception as e:
            results.append({
                'product_id': i,
                'error': str(e)
            })
    
    return {
        'statusCode': 200,
        'body': json.dumps(results)
    }

Rotación manual desde el pool de proxies

Si tienes una lista de proxies, puedes implementar la rotación manualmente. Esto es útil cuando necesitas control sobre qué proxy se utiliza para cada solicitud:

import requests
import random
import json

def lambda_handler(event, context):
    # Lista de proxies (puede almacenarse en DynamoDB o S3)
    proxy_pool = [
        {
            'host': 'proxy1.example.com',
            'port': '8080',
            'user': 'user1',
            'pass': 'pass1'
        },
        {
            'host': 'proxy2.example.com',
            'port': '8080',
            'user': 'user2',
            'pass': 'pass2'
        },
        {
            'host': 'proxy3.example.com',
            'port': '8080',
            'user': 'user3',
            'pass': 'pass3'
        }
    ]
    
    results = []
    
    for i in range(10):
        # Elegimos un proxy aleatorio del pool
        proxy = random.choice(proxy_pool)
        proxy_url = f"http://{proxy['user']}:{proxy['pass']}@{proxy['host']}:{proxy['port']}"
        
        proxies = {
            'http': proxy_url,
            'https': proxy_url
        }
        
        try:
            response = requests.get(
                f'https://api.example.com/item/{i}',
                proxies=proxies,
                timeout=10
            )
            results.append({
                'item': i,
                'proxy_used': proxy['host'],
                'status': response.status_code
            })
        except Exception as e:
            results.append({
                'item': i,
                'proxy_used': proxy['host'],
                'error': str(e)
            })
    
    return {
        'statusCode': 200,
        'body': json.dumps(results)
    }

Sesiones pegajosas para mantener la IP

Algunas tareas requieren mantener una IP durante la sesión (por ejemplo, autenticación en un sitio). Los proveedores de proxies ofrecen sesiones pegajosas a través de un parámetro en la URL:

import requests
import uuid

def lambda_handler(event, context):
    # Generamos un unique session_id
    session_id = str(uuid.uuid4())
    
    # Proxy con sesión pegajosa (la IP se mantiene durante 10 minutos)
    proxy_url = f"http://{os.environ['PROXY_USER']}-session-{session_id}:{os.environ['PROXY_PASS']}@sticky.proxycove.com:8080"
    
    proxies = {
        'http': proxy_url,
        'https': proxy_url
    }
    
    # Todas las solicitudes en esta Lambda se ejecutarán con una IP
    # 1. Autenticación
    login_response = requests.post(
        'https://example.com/login',
        data={'user': 'test', 'pass': 'test'},
        proxies=proxies
    )
    
    # 2. Obtención de datos (se utiliza la misma IP)
    data_response = requests.get(
        'https://example.com/dashboard',
        proxies=proxies,
        cookies=login_response.cookies
    )
    
    return {
        'statusCode': 200,
        'body': data_response.text
    }

Almacenamiento de credenciales de proxy a través de Variables de Entorno

Nunca almacenes las credenciales del proxy (nombre de usuario, contraseña, host) directamente en el código de la función Lambda. AWS proporciona varias formas seguras de almacenar datos confidenciales:

1. Variables de Entorno (forma básica)

En la consola de AWS Lambda → Configuración → Variables de entorno, añade:

  • PROXY_HOST = proxy.example.com
  • PROXY_PORT = 8080
  • PROXY_USER = your_username
  • PROXY_PASS = your_password

AWS cifra automáticamente las Variables de Entorno en reposo. Acceso a ellas en el código:

# Python
import os
proxy_host = os.environ['PROXY_HOST']

// Node.js
const proxyHost = process.env.PROXY_HOST;

2. AWS Secrets Manager (recomendado para producción)

Para máxima seguridad, utiliza AWS Secrets Manager: proporciona rotación automática de secretos y control detallado de acceso:

import boto3
import json
from botocore.exceptions import ClientError

def get_proxy_credentials():
    secret_name = "proxy-credentials"
    region_name = "us-east-1"
    
    session = boto3.session.Session()
    client = session.client(
        service_name='secretsmanager',
        region_name=region_name
    )
    
    try:
        get_secret_value_response = client.get_secret_value(
            SecretId=secret_name
        )
        secret = json.loads(get_secret_value_response['SecretString'])
        return secret
    except ClientError as e:
        print(f"Error al recuperar el secreto: {e}")
        raise e

def lambda_handler(event, context):
    # Obtenemos las credenciales de Secrets Manager
    creds = get_proxy_credentials()
    
    proxy_url = f"http://{creds['user']}:{creds['password']}@{creds['host']}:{creds['port']}"
    
    # Usamos el proxy
    # ...

Importante: No olvides añadir permisos IAM a la función Lambda para acceder a Secrets Manager:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "secretsmanager:GetSecretValue"
      ],
      "Resource": "arn:aws:secretsmanager:us-east-1:123456789:secret:proxy-credentials-*"
    }
  ]
}

Errores comunes y su solución

Al trabajar con proxies en Lambda, los desarrolladores a menudo se encuentran con los mismos problemas. Analicemos los más comunes y cómo solucionarlos:

Error: ProxyError / Tiempo de conexión agotado

Síntoma: requests.exceptions.ProxyError: HTTPConnectionPool(host='proxy.example.com', port=8080): Se superaron los intentos máximos

Causas:

  • Credenciales del proxy incorrectas (nombre de usuario/contraseña)
  • El servidor proxy no está disponible o está sobrecargado
  • El firewall bloquea las conexiones salientes de Lambda
  • Tiempo de espera demasiado corto

Solución:

# 1. Verifica las credenciales
print(f"Usando proxy: {proxy_host}:{proxy_port}")
print(f"Usuario: {proxy_user}")

# 2. Aumenta el tiempo de espera
response = requests.get(url, proxies=proxies, timeout=30)

# 3. Añade lógica de reintento
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry

session = requests.Session()
retry = Retry(
    total=3,
    backoff_factor=1,
    status_forcelist=[500, 502, 503, 504]
)
adapter = HTTPAdapter(max_retries=retry)
session.mount('http://', adapter)
session.mount('https://', adapter)

response = session.get(url, proxies=proxies, timeout=30)

Error: Verificación de certificado SSL fallida

Síntoma: SSLError: [SSL: CERTIFICATE_VERIFY_FAILED]

Causa: Algunos proxies (especialmente los baratos) utilizan certificados SSL autofirmados.

Solución (usar con precaución!):

# Desactivar la verificación SSL (¡solo para pruebas!)
response = requests.get(
    url,
    proxies=proxies,
    verify=False  # ¡NO usar en producción!
)

# Mejor: especifica la ruta al certificado CA
response = requests.get(
    url,
    proxies=proxies,
    verify='/path/to/ca-bundle.crt'
)

Importante: Desactivar la verificación SSL (verify=False) hace que la conexión sea vulnerable a ataques de intermediarios. ¡Usar solo para depuración en un entorno de desarrollo!

Error: Tiempo de espera de Lambda (La tarea se agotó después de X segundos)

Síntoma: La función Lambda termina con un error de tiempo de espera, sin esperar la respuesta del proxy.

Causa: Proxies lentos (especialmente residenciales/móviles) + gran cantidad de solicitudes.

Solución:

  • Aumenta el tiempo de espera de la función Lambda: Configuración → Configuración general → Tiempo de espera (máximo 15 minutos)
  • Reduce la cantidad de solicitudes por ejecución
  • Utiliza solicitudes asíncronas (asyncio en Python, Promise.all en Node.js)
  • Cambia a proxies más rápidos para tareas no críticas
# Python: solicitudes asíncronas para acelerar
import asyncio
import aiohttp

async def fetch_url(session, url, proxy):
    async with session.get(url, proxy=proxy, timeout=10) as response:
        return await response.text()

async def lambda_handler_async(event, context):
    proxy_url = f"http://{os.environ['PROXY_USER']}:{os.environ['PROXY_PASS']}@{os.environ['PROXY_HOST']}:{os.environ['PROXY_PORT']}"
    
    urls = [f'https://api.example.com/item/{i}' for i in range(50)]
    
    async with aiohttp.ClientSession() as session:
        tasks = [fetch_url(session, url, proxy_url) for url in urls]
        results = await asyncio.gather(*tasks)
    
    return {
        'statusCode': 200,
        'body': json.dumps({'count': len(results)})
    }

def lambda_handler(event, context):
    return asyncio.run(lambda_handler_async(event, context))

Error: 407 Se requiere autenticación de proxy

Síntoma: Error HTTP 407 al intentar usar el proxy.

Causa: Formato incorrecto para pasar las credenciales o el proxy requiere autenticación por IP en lugar de nombre de usuario/contraseña.

Solución:

# Verifica el formato de la URL del proxy
# Correcto:
proxy_url = f"http://{user}:{password}@{host}:{port}"

# Incorrecto (falta el protocolo):
proxy_url = f"{user}:{password}@{host}:{port}"  # ❌

# Si el proxy requiere autenticación por IP:
# 1. Averigua la IP externa de tu Lambda (puede cambiar)
# 2. Añade esta IP a la lista blanca del proveedor de proxies
# 3. Usa el proxy sin user:pass

# Obtener la IP externa de Lambda:
response = requests.get('https://api.ipify.org?format=json')
lambda_ip = response.json()['ip']
print(f"IP externa de Lambda: {lambda_ip}")

Optimización del rendimiento de Lambda con proxies

El uso de proxies añade latencia a cada solicitud. Aquí hay formas probadas de minimizar el impacto en el rendimiento:

1. Pooling de conexiones

Reutiliza conexiones TCP en lugar de crear una nueva para cada solicitud:

# Python: usa Session en lugar de requests.get()
import requests

# Crea la sesión una vez (puedes sacarla fuera del handler)
session = requests.Session()
session.proxies = {
    'http': proxy_url,
    'https': proxy_url
}

def lambda_handler(event, context):
    # Todas las solicitudes reutilizan conexiones
    for i in range(100):
        response = session.get(f'https://api.example.com/item/{i}')
        # procesar respuesta...

2. Solicitudes paralelas

Si necesitas hacer muchas solicitudes independientes, ejecútalas en paralelo:

// Node.js: solicitudes paralelas con Promise.all
const axios = require('axios');
const HttpsProxyAgent = require('https-proxy-agent');

const agent = new HttpsProxyAgent(proxyUrl);

exports.handler = async (event) => {
    const urls = Array.from({length: 50}, (_, i) => 
        `https://api.example.com/item/${i}`
    );
    
    // Todas las solicitudes se ejecutan en paralelo
    const promises = urls.map(url => 
        axios.get(url, { 
            httpsAgent: agent,
            timeout: 10000
        })
    );
    
    try {
        const results = await Promise.all(promises);
        return {
            statusCode: 200,
            body: JSON.stringify({
                count: results.length,
                data: results.map(r => r.data)
            })
        };
    } catch (error) {
        console.error('Error:', error.message);
        return {
            statusCode: 500,
            body: JSON.stringify({ error: error.message })
        };
    }
};

3. Caché de resultados

Si los datos cambian raramente, almacena en caché los resultados en DynamoDB o S3:

import boto3
import json
import time

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('proxy-cache')

def get_cached_or_fetch(url, proxies, cache_ttl=3600):
    """Devuelve datos de la caché o hace una solicitud a través del proxy"""
    
    # Verificamos la caché
    try:
        response = table.get_item(Key={'url': url})
        if 'Item' in response:
            item = response['Item']
            if time.time() - item['timestamp'] < cache_ttl:
                print(f"Cache hit para {url}")
                return item['data']
    except Exception as e:
        print(f"Error de caché: {e}")
    
    # Caché vacía o caducada — hacemos la solicitud
    print(f"Cache miss para {url}, obteniendo...")
    response = requests.get(url, proxies=proxies, timeout=10)
    data = response.text
    
    # Almacenamos en caché
    try:
        table.put_item(Item={
            'url': url,
            'data': data,
            'timestamp': int(time.time())
        })
    except Exception as e:
        print(f"Error al guardar en caché: {e}")
    
    return data

4. Elección del tipo de proxy correcto

Comparación de la velocidad de diferentes tipos de proxies en condiciones reales:

Tipo de proxy Latencia media Solicitudes/minuto (Lambda 1GB RAM) Recomendación
Centros de datos 50-200 ms 300-600 Scraping masivo de API
Residenciales 300-800 ms 100-200 Sitios protegidos
Móviles 500-1500 ms 50-100 Scraping de aplicaciones móviles

Conclusión: La elección del tipo de proxy adecuado es crucial para el éxito de tus tareas de scraping y automatización en AWS Lambda. Asegúrate de considerar la velocidad, el anonimato y los requisitos específicos de tu proyecto al seleccionar el proxy más adecuado.

```