Cómo configurar un proxy personalizado en Scrapy (listo para producción)

Última actualización el August 11, 2026
Hand-drawn Scrapy crawler routing through a proxy pool, retrying a 503 route and completing through a 200 route
Resumen con IA
- Crea un proxy middleware personalizado para Scrapy que asigne rutas aprobadas, añada autenticación de forma segura, registre los motivos de fallo y preserve los metadatos de la petición en los reintentos. - Entiende el orden de ejecución de los downloader middleware, especialmente cómo la lógica de proxy personalizada interactúa con HttpProxyMiddleware, RetryMiddleware, las redirecciones y la gestión de excepciones. - Añade rotación con intentos limitados, periodos de enfriamiento, estado de salud del proxy y políticas sensibles al destino en lugar de elegir un proxy aleatorio para cada petición. - Distingue entre fallos de autenticación del proxy, errores de conexión, problemas de DNS, respuestas 403 del destino y límites de velocidad para aplicar la respuesta correcta a cada caso. - Usa salvaguardas de producción para el almacenamiento de secretos, la concurrencia, la observabilidad, la consistencia de sesión y el comportamiento fail-closed cuando no quede ningún proxy aprobado disponible.

Tu spider de Scrapy vuela en 100 páginas de prueba y luego se desmorona en 10.000. En realidad, casi nunca es un fallo de scraping: es un problema de red disfrazado de bug de scraping. La solución a la que todo el mundo recurre es un proxy, y meterlo en request.meta te lleva apenas treinta segundos.

El problema es que esa solución rápida es justo donde se quedan la mayoría de los tutoriales básicos. Te enseñan meta={"proxy": "http://IP:PORT"}, quizá una clase middleware, y ya. Pero suelen saltarse qué pasa cuando ese proxy se cae a mitad del rastreo, cómo evitar que las credenciales terminen en el historial de Git o por qué un reintento puede volver a usar el mismo proxy fallido. Esas son precisamente las preocupaciones de producción que cubre esta guía: configuración a prueba de fallos, gestión segura de secretos, selección intencional de proxy en reintentos, límites de protocolo y trade-offs de coste que sí se pueden medir.

¿Qué es un proxy middleware en Scrapy?

Un proxy middleware es una pieza de código que se coloca en la canalización de descarga de Scrapy y decide desde qué dirección IP debería parecer que sale una petición antes de tocar la red. Scrapy incluye uno integrado, HttpProxyMiddleware, que lee la clave proxy de request.meta, añade autenticación si hace falta y pasa la petición al handler de descarga que abre la conexión real. El middleware de proxy personalizado no sustituye ese paso de transporte: actúa como un selector que decide qué proxy se inserta antes de que el mecanismo integrado tome el relevo. Esa diferencia importa mucho más de lo que parece, y es la raíz de la mayoría de los errores del tipo “mi middleware personalizado no funciona”.

Por qué los proxies importan en proyectos Scrapy de producción

Un proxy cambia la ruta de red y la IP de origen aparente. Eso puede servir para pruebas geográficas legítimas, repartir tráfico de peticiones autorizado y aislar fallos de red. No da permisos, no se salta límites de velocidad ni garantiza acceso. Que un rastreo necesite proxy o no depende del destino, sus condiciones de uso, la tasa de peticiones y los requisitos de fiabilidad del trabajo.

No todos los proxies son iguales, y elegir la capa equivocada es otra forma de acabar en un incidente de producción:

Tipo de proxyFiabilidadVelocidadRiesgo de detecciónCoste típico
Proxies públicos gratuitosMuy variableVariableA menudo altoSin coste, pero con riesgo operativo y de seguridad importante
Proxies de datacenterDepende del proveedor y del destinoA menudo rápidosDepende del destinoSuelen cobrarse por GB o por IP
Proxies residencialesDepende del proveedor y del destinoVariableDepende del destinoSuelen cobrarse por GB
Proxies ISPDepende del proveedor y del destinoVariableDepende del destinoEspecífico de cada proveedor

Conviene mencionar aparte los proxies gratuitos porque los riesgos medidos son serios. El estudio de 30 meses Free Proxies Unmasked siguió más de 640.000 direcciones de 11 proveedores: el 34,5% estuvo activa al menos una vez y 16.923 manipulaban contenido. Esa población justifica una advertencia de seguridad fuerte para listas públicas; no es una tasa de fallo aplicable a cualquier lista, pool de pago, destino o carga de trabajo.

Además, los proxies no se saltan mágicamente la detección moderna de bots. Servicios como Cloudflare puntúan las peticiones con docenas de señales —huellas TLS, coherencia de cabeceras, ejecución de JavaScript, patrones de comportamiento— donde la IP es solo una entrada más. Un proxy residencial limpio, pero con cabeceras incoherentes y sin cookie jar, seguirá siendo marcado. Conviene tener eso claro antes de montar toda una arquitectura alrededor de “solo rota la IP”.

Antes de empezar

  • Dificultad: Intermedia
  • Tiempo necesario: ~30–45 minutos para la configuración completa de producción, ~5 minutos para la prueba rápida
  • Lo que necesitas: Python 3.9+, Scrapy instalado (esta guía se ha probado con Scrapy 2.17.0, lanzado en julio de 2026), un spider funcional creado con scrapy startproject y al menos un endpoint de proxy (una prueba gratuita de cualquier proveedor de proxies de datacenter sirve perfectamente para probar)

Paso 1: prueba un proxy con el parámetro Request Meta

La forma más rápida de comprobar que un proxy funciona es saltarte por completo la arquitectura de middleware y probarlo directamente.

El HttpProxyMiddleware integrado de Scrapy lee la clave proxy directamente desde request.meta y enruta la petición a través de ella. Sin cambios en settings, sin clase middleware: solo un argumento.

import scrapy

class ProxyTestSpider(scrapy.Spider):
    name = "proxy_test"
    start_urls = ["https://httpbin.org/ip"]

    def start_requests(self):
        for url in self.start_urls:
            yield scrapy.Request(
                url,
                meta={"proxy": "http://203.0.113.10:8080"},
                callback=self.parse,
            )

    def parse(self, response):
        self.logger.info(response.text)

Ejecuta esto con scrapy runspider proxy_test.py. Si el proxy funciona, httpbin.org/ip devolverá la IP del proxy en vez de la tuya; esa es tu confirmación. Si la respuesta se queda colgada y al final da un error TCP connection timed out, el proxy está caído o no responde, algo que —sorpresa— pasa más a menudo de lo que a los proveedores de proxies les gusta reconocer.

Este método va bien para spiders sueltos o pruebas rápidas. Se rompe en cuanto tienes más de un spider, porque entonces acabas copiando la misma cadena de proxy en cinco archivos distintos.

Paso 2: crea un proxy middleware personalizado

Para cualquier escenario que vaya más allá de un solo spider, conviene centralizar la lógica del proxy en un solo sitio. Crea una clase ProxyMiddleware en el archivo middlewares.py del proyecto:

from scrapy.exceptions import NotConfigured

class ProxyMiddleware:
    def __init__(self, proxy_url):
        self.proxy_url = proxy_url

    @classmethod
    def from_crawler(cls, crawler):
        proxy_url = crawler.settings.get("PROXY_URL")
        if not proxy_url:
            raise NotConfigured("PROXY_URL es obligatorio; se rechaza el fallback silencioso a conexión directa")
        return cls(proxy_url=proxy_url)

    def process_request(self, request, spider):
        if "proxy" not in request.meta:
            request.meta["proxy"] = self.proxy_url

Y regístralo en settings.py:

import os

PROXY_URL = os.environ.get("PROXY_URL")

DOWNLOADER_MIDDLEWARES = {
    "myproject.middlewares.ProxyMiddleware": 350,
}

Fíjate en from_crawler en lugar de un __init__ normal. Este es el patrón que Scrapy realmente recomienda para leer settings, y es exactamente el mismo gancho que volveremos a usar en el Paso 4 cuando hablemos de secretos. La ventaja aquí es sencilla: cambias una sola configuración y todos los spiders del proyecto usan el nuevo proxy. Nada de buscar a mano en cinco archivos para cambiar una IP caída.

Paso 3: entiende el orden de ejecución del middleware para que tu proxy no deje de funcionar sin avisar

Esta es la parte que casi todos los demás tutoriales se saltan con un “pon la prioridad en 350 y confía en mí”. El downloader middleware en Scrapy sigue un orden concreto y predecible; si no lo entiendes, tu configuración de proxy generará errores que parecerán no tener nada que ver con los proxies.

Los hooks del lado de la petición (process_request) se ejecutan en orden ascendente de prioridad: primero el número más bajo. Los hooks del lado de la respuesta (process_response, process_exception) se ejecutan en orden descendente: primero el número más alto, desandando la cadena hacia abajo.

Flujo de petición (ascendente):
  Spider → [100] RobotsTxt → [300] HttpAuth → [350] TU PROXY MIDDLEWARE
         → [500] UserAgent → [550] Retry → [700] Cookies → [750] HttpProxy
         → Downloader

Flujo de respuesta (descendente):
  Downloader → [750] HttpProxy → [700] Cookies → [550] Retry
             → [500] UserAgent → [350] TU PROXY MIDDLEWARE → [300] HttpAuth
             → [100] RobotsTxt → Spider

Aquí tienes la tabla real y actual de prioridades por defecto de los middlewares integrados de Scrapy (verificada con 2.17.0):

MiddlewarePrioridad por defecto
RobotsTxtMiddleware100
HttpAuthMiddleware300
DownloadTimeoutMiddleware350
DefaultHeadersMiddleware400
UserAgentMiddleware500
RetryMiddleware550
RedirectMiddleware600
CookiesMiddleware700
HttpProxyMiddleware750
DownloaderStats850
HttpCacheMiddleware900

Cuando RetryMiddleware programa un reintento, copia la petición fallida —incluidos sus metadatos— y esa nueva petición vuelve a entrar en la cadena de middlewares de descarga. La relación numérica del selector con la prioridad 550 no garantiza rotación. La rotación solo ocurre cuando el código del selector reconoce el reintento y sobrescribe de forma deliberada el meta["proxy"] copiado. La prioridad 350 es un buen sitio para un selector porque se ejecuta antes del paso de transporte integrado en 750, pero por sí sola no es un mecanismo de rotación.

Recorridos de petición y respuesta de Scrapy a través de las prioridades 350, 550 y 750, con un reintento de 503 que vuelve a entrar en la cadena de middleware

Errores comunes al ordenar el middleware

  • Poner tu middleware con la misma prioridad que HttpProxyMiddleware (750): esto crea una condición de carrera en la que el orden del diccionario de Scrapy, y no tu lógica, decide qué middleware procesa primero la petición. Síntoma: comportamiento del proxy intermitente e inexplicable.
  • Usar setdefault() o if "proxy" not in request.meta en un selector rotatorio: la copia del reintento conserva el proxy anterior. Síntoma: cada reintento repite la misma ruta fallida. Solución: detecta el reintento (por ejemplo, retry_times > 0) y sustituye explícitamente el valor de proxy que controla el selector.
  • Desactivar por completo HttpProxyMiddleware: algunos tutoriales te dicen que pongas "scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware": None porque “el middleware personalizado se encarga”. No es así: tu middleware personalizado es un selector, no una capa de transporte. Desactivar el integrado hace que nunca se añadan las cabeceras de autenticación del proxy y que tus peticiones salgan sin autenticarse (o ni siquiera salgan).

Paso 4: deja de codificar credenciales de proxy a mano

Cada tutorial de proxy para Scrapy que aparece alto en Google que he visto escribe http://username:password@proxy.example.com:8080 directamente en un archivo Python. Eso deja una credencial viviendo para siempre en tu historial de Git, apareciendo en cada clon, fork y volcado de logs si alguien se despista con print().

En realidad, hay tres niveles para hacerlo:

MétodoSeguridadFlexibilidadMejor para
Codificado en spider/settings.pyMala: los secretos viven en el repoBajaSolo pruebas locales rápidas
Variable de entorno http_proxy (nativa de Scrapy)Mejor: fuera del códigoBaja (un solo proxy)Pipelines de CI/CD, Docker
Archivo .env + python-dotenv + from_crawlerLa mejor: fuera del código, por entornoAlta (varios proxies, rotación)Scrapers de producción

La tercera opción merece hacerse bien. Instala python-dotenv, crea un archivo .env y añádelo de inmediato a .gitignore —lo digo en serio, hazlo ahora:

PROXY_USER=myuser
PROXY_PASSWORD=my$ecret!Pass
PROXY_HOST=proxy.example.com
PROXY_PORT=8080

Cárgalo al principio de settings.py:

from dotenv import load_dotenv
import os

load_dotenv()

PROXY_USER = os.getenv("PROXY_USER")
PROXY_PASSWORD = os.getenv("PROXY_PASSWORD")
PROXY_HOST = os.getenv("PROXY_HOST")
PROXY_PORT = os.getenv("PROXY_PORT")

Luego léelo de forma segura dentro del middleware usando from_crawler; este es el patrón que resuelve exactamente la duda que he visto en foros, donde la gente pregunta “¿cómo configuro esto antes de ejecutar scrapy crawl si las credenciales cambian en cada ejecución?”:

import os
from urllib.parse import quote

class SecureProxyMiddleware:
    def __init__(self, user, password, host, port):
        self.user = quote(user, safe="")
        self.password = quote(password, safe="")
        self.host = host
        self.port = port

    @classmethod
    def from_crawler(cls, crawler):
        settings = crawler.settings
        return cls(
            user=settings.get("PROXY_USER"),
            password=settings.get("PROXY_PASSWORD"),
            host=settings.get("PROXY_HOST"),
            port=settings.get("PROXY_PORT"),
        )

    def process_request(self, request, spider):
        proxy_url = f"http://{self.user}:{self.password}@{self.host}:{self.port}"
        request.meta["proxy"] = proxy_url

Fíjate en la llamada a urllib.parse.quote() alrededor de las credenciales. Si tu contraseña contiene @, : o / —y los generadores de contraseñas adoran meter estos caracteres—, romperá el análisis de la URL a menos que se codifique primero. Es una solución de una sola línea que te ahorra una hora bastante incómoda depurando errores de “invalid proxy URL” que no tienen nada que ver con que el proxy sea realmente inválido.

Mantén las credenciales fuera de los logs y prueba la codificación percent-encoding con valores representativos, pero falsos. El tunneling HTTPS, SOCKS5 y las credenciales no latinas tienen límites distintos según el handler; no des por hecho que un patrón de autenticación funciona igual en todos sin una prueba de integración fija.

Flujo seguro desde un archivo de entorno protegido, pasando por ajustes de proxy codificados, hasta los metadatos de petición de Scrapy

Paso 5: añade rotación de proxies

Un solo proxy —incluso uno bueno— haciendo 5.000 peticiones al mismo sitio acabará siendo detectado. Necesitas un pool.

Opción A — hacerlo tú mismo. Es realmente sencillo:

import random

class RotatingProxyMiddleware:
    def __init__(self, proxy_pool):
        self.proxy_pool = proxy_pool

    @classmethod
    def from_crawler(cls, crawler):
        return cls(proxy_pool=crawler.settings.getlist("PROXY_POOL"))

    def process_request(self, request, spider):
        request.meta["proxy"] = random.choice(self.proxy_pool)

Esto funciona para usos básicos, pero no tiene ni idea de qué proxies siguen vivos. Estás tirando los dados en cada petición.

Opción B — usar scrapy-rotating-proxies. Este paquete de terceros añade detección de baneos y backoff automático desde el principio:

pip install scrapy-rotating-proxies

Aquí conviene ser sincero: la última versión en PyPI es la 0.6.2, fechada en 2019, y el proyecto está marcado como Alpha. No significa necesariamente que esté roto con Scrapy moderno, pero “sin mantenimiento activo desde 2019” no es lo mismo que “probado para tráfico de producción en 2026”. Fija la versión, pruébalo contra tus sitios reales y no asumas que maneja endpoints de proxy autenticados: en gran medida, no lo hace.

Paso 6: construye un middleware de proxy tolerante a fallos (detección de proxies caídos)

Esta es la sección que todos los tutoriales rivales se saltan por completo, y es lo que separa una demo de algo que aguanta un rastreo de 6 horas sin supervisión.

EscenarioLo que muestran la mayoría de los tutorialesLo que añade este middleware
El proxy devuelve 407No se abordaLo trata como un fallo de autenticación del proxy
El destino devuelve 403/429A menudo se agrupanMantiene separada la retroalimentación de política/límites de la salud del proxy
El proxy agota el tiempoNo se abordaUmbral de timeout configurable, caída de puntuación de salud
Todos los proxies están caídosNo se abordaFallback elegante o pausa del rastreo con advertencia registrada
Proxy intermitenteNo se abordaPeriodo de enfriamiento antes de volver a añadirlo al pool
import time
import random
from scrapy.exceptions import IgnoreRequest

class FaultTolerantProxyMiddleware:
    MAX_FAILURES = 3
    COOLDOWN_SECONDS = 300

    def __init__(self, proxy_pool):
        self.pool = {p: {"failures": 0, "banned_until": 0} for p in proxy_pool}

    @classmethod
    def from_crawler(cls, crawler):
        return cls(proxy_pool=crawler.settings.getlist("PROXY_POOL"))

    def _healthy_proxies(self):
        now = time.time()
        return [p for p, s in self.pool.items() if s["banned_until"] < now]

    def process_request(self, request, spider):
        healthy = self._healthy_proxies()
        if not healthy:
            spider.logger.warning("Todos los proxies están en mal estado: pausando el rastreo")
            raise IgnoreRequest("No hay proxies sanos disponibles")
        request.meta["proxy"] = random.choice(healthy)

    def process_response(self, request, response, spider):
        proxy = request.meta.get("proxy")
        if proxy and response.status == 407:
            self._mark_failure(proxy)
        return response

    def process_exception(self, request, exception, spider):
        proxy = request.meta.get("proxy")
        if proxy:
            self._mark_failure(proxy)

    def _mark_failure(self, proxy):
        state = self.pool[proxy]
        state["failures"] += 1
        if state["failures"] >= self.MAX_FAILURES:
            state["banned_until"] = time.time() + self.COOLDOWN_SECONDS
            state["failures"] = 0

Un par de notas de haber construido esto de verdad: no trates cualquier 403 como prueba de que el proxy está muerto —RFC 9110 define 403 como “el servidor entendió la petición pero se niega a cumplirla”, lo que también puede significar que tus cabeceras o tu sesión parecen sospechosas, aunque el proxy no tenga la culpa. En cambio, un 407 sí significa que el proxy está rechazando específicamente tu autenticación: es una señal más fuerte y más concreta. Mezclar ambas señales en el mismo saco es la forma más rápida de quemar proxies sanos sin motivo.

Deja explícitos los retries transitorios por defecto de Scrapy en producción para que los revisores vean la política:

RETRY_HTTP_CODES = [500, 502, 503, 504, 522, 524, 408, 429]
RETRY_TIMES = 2

Esos son los valores por defecto de Scrapy 2.17. No añadas 403 o 407 a lo loco: 403 es una negativa del destino con varias causas posibles, mientras que 407 es un problema de autenticación del proxy que un reintento genérico no va a resolver. Si un contrato concreto con un destino justifica reintentar otro estado, documenta ese motivo y pruébalo por separado.

Tratamiento distinto para fallo de autenticación 407, limitación 429, reintento 503, éxito 200 y una puerta cerrada cuando no hay proxies disponibles

Paso 7: un patrón medido de proxy en reintentos

Algunos destinos autorizados pueden devolver contenido válido directamente y solo necesitar un proxy tras una respuesta transitoria documentada. Eso puede reducir los bytes que pasan por proxy, pero no existe un porcentaje universal de ahorro defendible ni una tasa portátil de éxito directo. Mide tu propia carga de trabajo antes de adoptar el patrón.

Usa el helper público get_retry_request() de Scrapy y mantén la escalada limitada a estados específicos del destino que hayas clasificado explícitamente. Este ejemplo trata 429 y 503 como señales de presión que justifican reintento; excluye de forma intencional 403 y 407.

from scrapy.downloadermiddlewares.retry import get_retry_request

class CostAwareEscalationMiddleware:
    def process_response(self, request, response, spider):
        if response.status not in {429, 503}:
            return response

        retry = get_retry_request(
            request,
            spider=spider,
            reason=f"proxy_escalation_{response.status}",
            max_retry_times=2,
        )
        if retry is None:
            return response

        current_tier = request.meta.get("proxy_tier", "direct")
        if current_tier == "direct":
            retry.meta["proxy"] = spider.settings["DATACENTER_PROXY"]
            retry.meta["proxy_tier"] = "datacenter"
        elif current_tier == "datacenter":
            retry.meta["proxy"] = spider.settings["RESIDENTIAL_PROXY"]
            retry.meta["proxy_tier"] = "residential"
        else:
            return response
        return retry

Registra la tasa de contenido válido en acceso directo, la tasa de contenido válido vía proxy, los bytes por registro satisfactorio, los reintentos por éxito y la latencia añadida. Un diseño direct-first solo es aceptable cuando el acceso directo está autorizado y el sistema falla de forma cerrada siempre que se requiera un proxy. El ahorro es la reducción medida del tráfico pasado por proxy, no un porcentaje supuesto.

Cuándo no compensa gestionar proxies por tu cuenta

Quiero ser claro con esto en vez de fingir que todo lo anterior fue inútil: todo lo de arriba es ingeniería real y útil, y para muchos proyectos —rastreos de gran volumen, pipelines personalizados, cualquier caso en el que necesites control total sobre la programación de peticiones— es la decisión correcta.

Pero si tu objetivo real es “obtener datos estructurados de esta página” y no “operar infraestructura de proxies”, una API de extracción puede ser una mejor frontera. La documentación actual de POST /extract de Thunderbit acepta una URL de página y un JSON Schema opcional; si omites el schema, el servicio puede generarlo a partir del contenido de la página. El endpoint también ofrece modos de renderizado none, basic y full, junto con controles de timeout y espera después de la carga. La extracción basada solo en prompts no forma parte del contrato de solicitud actualmente admitido, así que construye las integraciones de producción sobre el schema documentado. Esto mueve la interfaz de extracción detrás de una sola petición; no justifica una promesa universal sobre cualquier objetivo con anti-bot o CAPTCHA.

FactorScrapy + proxies por tu cuentaExtracción basada en API (por ejemplo, Thunderbit)
Esfuerzo de configuraciónAlto: middleware, rotación, lógica de reintentosBajo: una llamada API con un schema
Comportamiento de red/renderizadoTú configuras handlers, proxies, cabeceras y delaysControlado mediante opciones documentadas de la API
MantenimientoTú te encargas de selectores, salud del pool y cambios del destinoTú te encargas de la calidad del schema, validación y comportamiento de integración
Modelo de costesTarifas de proxy + computación + tiempo de ingenieríaLa documentación actual indica 20 unidades por página (verificado 2026-08-10)
ControlTotal: pipelines personalizados, cadena de middlewareLimitado a las capacidades de la API
Mejor paraRastreo complejo, gran volumen, lógica personalizadaExtracción concreta, prototipado, enriquecimiento

Si lo que haces es extraer páginas estructuradas para listas de leads, datos de producto o investigación, ejecuta una prueba piloto representativa con la extensión de Chrome de Thunderbit o con la API y compara registros válidos, latencia, unidades y tiempo de mantenimiento. Si tu proyecto necesita grafos de rastreo personalizados y control del pipeline, Scrapy sigue siendo la opción más sólida.

Saber más

Consejos y errores comunes

  • Consejo: prueba los proxies contra httpbin.org/ip antes de apuntarlos a un objetivo real. Es la forma más rápida de confirmar que el enrutamiento funciona antes de añadir complejidad encima.
  • Error: poner el proxy en request.headers en lugar de en request.meta. Es un fallo muy común por despiste: HttpProxyMiddleware solo lee meta["proxy"], y un intento basado en cabeceras fallará en silencio, sin un error obvio.
  • Error: asumir que los proxies HTTP y HTTPS se configuran igual. Una URL de proxy HTTP que enruta a un destino HTTPS normalmente funciona mediante túnel CONNECT con un handler compatible, pero usar el esquema https:// para el propio endpoint del proxy es una configuración distinta y menos soportada; no las confundas.
  • Consejo: si necesitas soporte SOCKS5, comprueba primero las capacidades del download handler de tu versión de Scrapy. El Httpx handler experimental de Scrapy 2.17 añadió soporte SOCKS5 mediante httpx[socks], pero sigue marcado como experimental: no bases una dependencia de producción en él sin probarlo tú mismo.

Métodos alternativos

Además de scrapy-rotating-proxies, algunos equipos pasan toda la lógica de proxy a través de un gateway del proveedor: una única URL de proxy donde el vendor gestiona la rotación, la persistencia de sesión y la geo-selección por detrás. Esto sacrifica algo de control a cambio de bastante menos código de middleware, y merece la pena presupuestarlo frente a un pool autogestionado antes de construir uno desde cero.

Conclusión

Configurar un proxy en Scrapy lleva una línea. Hacer que esa configuración sobreviva a un rastreo real de producción exige una política de fallo explícita, credenciales protegidas, límites de handler probados y código selector que reemplace deliberadamente los metadatos de proxy copiados en los reintentos. Si te quedas con dos hábitos, que sean estos: fallar de forma cerrada cuando se necesite un proxy y no comprometer nunca una contraseña de proxy en un archivo Python.

Preguntas frecuentes

¿Cómo configuro un proxy personalizado en Scrapy con autenticación? Usa el formato de URL protocol://username:password@host:port, pero codifica primero el nombre de usuario y la contraseña con urllib.parse.quote() si contienen caracteres especiales. En producción, lee esas credenciales mediante un método de clase from_crawler que tome los valores de variables de entorno, en lugar de escribirlas directamente en el código.

¿Qué número de prioridad debo usar para mi proxy middleware personalizado en Scrapy? 350 es una prioridad habitual para un selector porque se ejecuta antes de HttpProxyMiddleware en 750. No garantiza rotación. Un reintento recibe un proxy nuevo solo si el selector reconoce la petición copiada y sobrescribe su valor anterior de meta["proxy"].

¿Cómo gestiono automáticamente los proxies caídos en Scrapy? Crea un middleware que lleve la cuenta de fallos por proxy en process_response y process_exception, retire los proxies del pool activo tras superar un umbral de fallos y los vuelva a añadir después de un periodo de enfriamiento, en vez de banearlos permanentemente.

¿Puedo usar Scrapy con proxies SOCKS5? El HttpxDownloadHandler experimental de Scrapy 2.17 documenta soporte SOCKS5 cuando está instalado httpx[socks]. El handler HTTP/1.1 por defecto no soporta proxies SOCKS. Fija la versión del handler y prueba la integración antes de tratar esta ruta como lista para producción.

¿Cuánto puede ahorrar de verdad el patrón de proxy en reintentos? No existe un porcentaje portable. Mide la proporción de peticiones autorizadas que devuelven contenido válido directamente, los bytes enviados por cada nivel de proxy, los reintentos por cada registro exitoso y la latencia añadida. La reducción observada en bytes pasados por proxy es tu ahorro; si el acceso directo no está autorizado o no es válido, no uses este patrón.

Ke
Ke
CTO en Thunderbit | Científico de datos sénior y experto en ML Con casi una década de experiencia en aprendizaje automático y ciencia de datos, Ke Shen es exalumno de la Universidad de Columbia y antiguo científico de datos sénior en Walmart Labs. Con una sólida experiencia, reconocida por sus pares, en Python, R, Java y estadística, comparte conocimientos probados en el campo sobre cómo llevar algoritmos complejos de IA desde la teoría hasta una arquitectura lista para producción.
Topics
Scrapy proxy middlewarePython web scrapingProxy rotation
Tabla de contenidos
Thunderbit · Agente de datos web con IA

Extrae datos de cualquier página en 1 clic

Con la confianza de más de 250.000 usuarios
plan gratuito disponible
Extrae Datos Usando IA
Transfiere fácilmente datos a Google Sheets, Airtable o Notion
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week