Integración

Usa Shifter con Scrapy

Conecta los proxies residenciales e ISP de Shifter a cualquier spider de Scrapy mediante un pequeño middleware de descarga. Rotación por solicitud, sesiones persistentes y geolocalización por spider, todo en 20 líneas de Python.

Inicio rápido

Instalar

pip install scrapy

Uso básico

# settings.py
DOWNLOADER_MIDDLEWARES = {
    "myproject.middlewares.ShifterProxyMiddleware": 350,
    "scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware": 360,
}

# middlewares.py
class ShifterProxyMiddleware:
    PROXY = (
        "customer-USERNAME-country-us-sid-123ABC:"
        "PASSWORD@p.shifter.io:443"
    )

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

# Run as usual:
# scrapy crawl my_spider

Características

Se conecta al pipeline estándar de middleware de descarga de Scrapy, sin forks ni runtime parcheado
Rotación por solicitud de forma predeterminada, con `sid` para sesiones persistentes y `ttl-N` para fijar IPs durante N segundos
Compatible de forma directa con scrapy-playwright, scrapy-splash y scrapy-rotating-proxies
Geolocalización en más de 195 países mediante parámetros de usuario -- país, región, ciudad, ASN
Compatible con Scrapy Cloud, Scrapyd, GitHub Actions, Airflow y cualquier capa de orquestación
Compatible con Scrapy 2.x y Python 3.7+, admite tanto callbacks síncronos como asíncronos

Ejemplos

Middleware de descarga (sesión persistente)

La forma estándar de conectar un proxy a Scrapy. Añade un `sid` al nombre de usuario y cada solicitud del spider compartirá una IP residencial. Añade `country-uk-city-london` para aplicar geolocalización.

# myproject/middlewares.py
import secrets

class ShifterProxyMiddleware:
    """Routes every Scrapy request through Shifter's residential pool."""

    def __init__(self, country="us", city=None, ttl=300):
        self.sid = secrets.token_hex(4)
        parts = [
            "customer-USERNAME",
            f"country-{country}",
        ]
        if city:
            parts.append(f"city-{city}")
        parts.append(f"sid-{self.sid}")
        parts.append(f"ttl-{ttl}")
        username = "-".join(parts)

        self.proxy_url = f"http://{username}:PASSWORD@p.shifter.io:443"

    @classmethod
    def from_crawler(cls, crawler):
        s = crawler.settings
        return cls(
            country=s.get("SHIFTER_COUNTRY", "us"),
            city=s.get("SHIFTER_CITY"),
            ttl=s.getint("SHIFTER_TTL", 300),
        )

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

# myproject/settings.py
DOWNLOADER_MIDDLEWARES = {
    "myproject.middlewares.ShifterProxyMiddleware": 350,
    "scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware": 360,
}

SHIFTER_COUNTRY = "uk"
SHIFTER_CITY    = "london"

Rotación por solicitud

No establezcas un sid: deja que la pasarela rote las IPs en cada solicitud. Útil para scraping de alto volumen en objetivos paginados donde cada página debe parecer un visitante diferente.

# myproject/middlewares.py
import secrets

class ShifterRotatingMiddleware:
    """Rotates the residential IP on every Scrapy request."""

    PROXY_HOST = "p.shifter.io:443"

    def process_request(self, request, spider):
        # Unique sid per request -> guaranteed new IP for every fetch
        unique_sid = secrets.token_hex(6)
        username   = (
            f"customer-USERNAME-country-{spider.country}"
            f"-sid-{unique_sid}"
        )
        request.meta["proxy"] = (
            f"http://{username}:PASSWORD@{self.PROXY_HOST}"
        )

# myproject/spiders/products.py
import scrapy

class ProductsSpider(scrapy.Spider):
    name    = "products"
    country = "us"  # consumed by the middleware

    custom_settings = {
        "DOWNLOADER_MIDDLEWARES": {
            "myproject.middlewares.ShifterRotatingMiddleware": 350,
        },
        "CONCURRENT_REQUESTS": 32,
    }

    start_urls = [
        f"https://example.com/products?page={i}" for i in range(1, 100)
    ]

    def parse(self, response):
        for card in response.css(".product-card"):
            yield {
                "title": card.css("h2::text").get(),
                "price": card.css(".price::text").get(),
                "url":   response.urljoin(card.css("a::attr(href)").get()),
            }

Spiders por país (geo-scraping concurrente)

Crea una clase de spider y parametriza el país en tiempo de ejecución. Ejecuta varias instancias en paralelo, cada una con su propio pool de IPs residenciales.

# scrapy crawl localized -a country=uk
# scrapy crawl localized -a country=de
# scrapy crawl localized -a country=jp

import scrapy

class LocalizedSpider(scrapy.Spider):
    name = "localized"

    def __init__(self, country="us", *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.country = country
        self.start_urls = [
            f"https://www.example.com/{country}/products",
        ]

    def start_requests(self):
        proxy = (
            f"customer-USERNAME-country-{self.country}-sid-{self.country}-batch:"
            f"PASSWORD@p.shifter.io:443"
        )
        for url in self.start_urls:
            yield scrapy.Request(url, meta={"proxy": proxy}, callback=self.parse)

    def parse(self, response):
        for product in response.css(".product"):
            yield {
                "country": self.country,
                "title":   product.css("h2::text").get(),
                "price":   product.css(".price::text").get(),
            }

Scrapy + scrapy-playwright (páginas renderizadas con JS)

Cuando el objetivo necesita JavaScript, sustituye el descargador por scrapy-playwright. Pasa el proxy en las opciones de lanzamiento: Scrapy sigue gestionando la planificación y los pipelines.

# pip install scrapy-playwright
# playwright install chromium

# settings.py
DOWNLOAD_HANDLERS = {
    "http":  "scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler",
    "https": "scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler",
}
TWISTED_REACTOR = "twisted.internet.asyncioreactor.AsyncioSelectorReactor"

PLAYWRIGHT_LAUNCH_OPTIONS = {
    "headless": True,
    "proxy": {
        "server":   "http://p.shifter.io:443",
        "username": "customer-USERNAME-country-fr-sid-789GHI",
        "password": "PASSWORD",
    },
}

# spider.py
import scrapy

class JsHeavySpider(scrapy.Spider):
    name = "js_heavy"
    start_urls = ["https://app.example.com/dashboard"]

    def start_requests(self):
        for url in self.start_urls:
            yield scrapy.Request(
                url,
                meta={"playwright": True, "playwright_include_page": True},
                callback=self.parse,
            )

    async def parse(self, response):
        page = response.meta["playwright_page"]
        await page.wait_for_selector(".widget")
        widgets = await page.query_selector_all(".widget")
        for w in widgets:
            yield {"label": await w.text_content()}
        await page.close()
Preguntas frecuentes

Preguntas frecuentes

Preguntas frecuentes sobre el uso de Shifter con Scrapy.

Escribe un pequeño middleware de descarga que establezca `request.meta['proxy']` en tu URL de Shifter, y luego regístralo en DOWNLOADER_MIDDLEWARES con una prioridad inferior a 750 (para que se ejecute antes que HttpProxyMiddleware). Veinte líneas de Python, sin SDK necesario.

Genera un sid nuevo en process_request, por ejemplo con `secrets.token_hex(6)`, e incrústalo en el nombre de usuario del proxy. Cada solicitud tendrá un sid diferente y, por tanto, una IP residencial distinta de la pasarela de Shifter. No se necesita la dependencia externa scrapy-rotating-proxies.

Usa un sid fijo para toda la ejecución del rastreo. Genéralo una vez al inicio del spider (o en el constructor del middleware) y reutilízalo en cada solicitud. Añade `ttl-N` para extender la vida útil de la IP a N segundos.

Sí. Pasa un argumento `-a country=uk` al ejecutar un spider, expónlo como ajuste en custom_settings, o léelo dentro de tu middleware. Construye la URL del proxy con `country-uk` en el nombre de usuario: cada solicitud de ese spider pasará por IPs residenciales del Reino Unido.

Sí. Configura el proxy en PLAYWRIGHT_LAUNCH_OPTIONS: `server`, `username`, `password`. scrapy-playwright los reenvía a la llamada de lanzamiento de Playwright, que gestiona el desafío de autenticación básica en modo headless sin necesidad de una extensión.

Sí. Los proyectos de Scrapy Cloud son simplemente spiders de Scrapy: tu middleware de descarga y la URL del proxy de Shifter se incluyen dentro del tarball de tu proyecto. Añade las credenciales como ajustes del proyecto en Scrapy Cloud (o como variables de entorno) para no incluirlas en el código fuente.

Comenzar

Empieza a usar Shifter con Scrapy

Integra los más de 205M de proxies residenciales y de ISP de Shifter en tus spiders de Scrapy mediante un middleware de 20 líneas. Rotación por solicitud, sesiones sticky y soporte completo para scrapy-playwright.

Prueba Shifter gratisConfiguración en minutos. Cancela cuando quieras.