Ротация прокси в Crawlee для Python: руководство разработчика

Полное руководство по ProxyConfiguration, SessionPool и residential-прокси в Crawlee для Python: от базовой настройки до production-паттернов с session.retire(), autoscaling и обходом Cloudflare.

Proxy Rotation in Crawlee for Python: A Developer's Guide to Residential IPs

Ротация прокси в Crawlee для Python: как это работает

Если вы пишете продакшен-краулер на Crawlee для Python, рано или поздно вы упрётесь в блокировки по IP. Ротация прокси в Crawlee для Python — это не просто смена адресов каждые N запросов. Это интеграция прокси-инфраструктуры с SessionPool, который связывает cookies, отпечатки браузера и IP-адреса в единые сессии. Правильная настройка ProxyConfiguration определяет, пройдёт ли ваш краулер защиту Cloudflare или DataDome, или получит 403 на первом же запросе.

В этом руководстве мы разберём архитектуру Crawlee, идиоматичный способ подключения residential-прокси через ProxyConfiguration, production-паттерны обработки блокировок, масштабирование и этические границы веб-скрейпинга.

Правовая оговорка: скрейпинг публичных данных может подпадать под действие CFAA в США или GDPR в ЕС. Собирайте только общедоступные данные, уважайте robots.txt и правила платформ. Если есть официальный API — используйте его.

Архитектура Crawlee: очереди, краулеры и SessionPool

Crawlee для Python построен вокруг нескольких ключевых компонентов, каждый из которых влияет на то, как вы настраиваете прокси.

Единая очередь запросов

Все краулеры — BeautifulSoupCrawler и PlaywrightCrawler — работают с единой Request Queue. Очередь обеспечивает дедупликацию, хранение состояния и восстановление после сбоев. Когда запрос не проходит, Crawlee помещает его обратно в очередь с увеличенным счётчиком ретраев.

Autoscaled Pool

AutoscaledPool автоматически масштабирует количество параллельных воркеров. Он анализирует производительность: если запросы выполняются быстро и без ошибок, пул увеличивает параллелизм. Если ошибки растут — уменьшает. Вы можете задать жёсткие лимиты через max_concurrency и min_concurrency.

SessionPool: связка cookies, отпечатков и IP

SessionPool — это сердце Crawlee для работы с прокси. Каждая сессия хранит:

  • Cookies, полученные от целевого сайта.
  • Отпечатки браузера (User-Agent, заголовки).
  • Прокси-адрес, привязанный через ProxyConfiguration.
  • Счётчик ошибок и статус (активна / заблокирована / истекла).

Когда Crawlee создаёт новую сессию, он вызывает proxy_configuration.new_url(session_id=...), чтобы получить прокси-URL. Если сессия завершается через session.retire(), Crawlee создаёт новую — с новым IP, новыми cookies и новым отпечатком.

Эта связка критична: если вы меняете IP, но сохраняете cookies от старого IP, антибот-система видит несоответствие и блокирует запрос. Crawlee решает это автоматически, но только если вы используете ProxyConfiguration идиоматично — а не подставляете прокси вручную в каждый запрос.

ProxyConfiguration: идиоматичная ротация прокси

Класс ProxyConfiguration — канонический способ управления прокси в Crawlee. Он предоставляет два режима работы, и выбор режима зависит от вашей задачи.

Round-robin ротация

При передаче списка URL в proxy_urls, Crawlee раздаёт их по round-robin. Каждый новый запрос получает следующий прокси из списка. Это полезно для простых задач — например, парсинг API без привязки к сессии.

Sticky sessions через session_id

При передаче session_id в new_url(), Crawlee закрепляет конкретный прокси за конкретной сессией. Это критично для сайтов, которые проверяют соответствие IP и cookies — например, при авторизации, многошаговых формах или пагинации.

С ProxyHat вы кодируете session_id прямо в username:

http://user-session-abc123:PASSWORD@gate.proxyhat.com:8080

Каждая сессия получает свой residential IP, который остаётся стабильным, пока вы не завершите сессию. Это даёт два преимущества: антибот-системы видят «пользователя», который приходит с одного IP (как настоящий человек), а вы можете точечно «убивать» заблокированные IP без затрагивания остальных.

new_url_function для динамической генерации

Для максимальной гибкости передайте функцию в new_url_function. Crawlee вызывает её с session_id, и вы генерируете URL на лету:

from crawlee.proxy_configuration import ProxyConfiguration

proxy_config = ProxyConfiguration(
    new_url_function=lambda session_id: (
        f'http://user-session-{session_id}:PASSWORD@gate.proxyhat.com:8080'
    )
)

Это позволяет генерировать уникальные session_id (например, uuid4().hex[:8]) и получать новый residential IP для каждой сессии без заранее заданного списка.

Residential vs Datacenter: почему residential побеждает

Защитные системы вроде Cloudflare Bot Management и DataDome анализируют не только IP-адрес, но и репутацию. Datacenter-IP принадлежат облакам — AWS, Google Cloud, DigitalOcean, OVH. Для антибот-фильтра это мгновенный «красный флаг»: реальный пользователь не сидит на IP дата-центра. Residential-IP принадлежат настоящим интернет-провайдерам и неотличимы от обычного трафика.

ХарактеристикаResidentialDatacenterMobile
Проходимость Cloudflare85–95%10–30%90–98%
Средняя задержка200–800ms50–200ms500–2000ms
Цена за GBСредняяНизкаяВысокая
Стабильность sticky IPВысокаяСредняяНизкая
Идеально дляSERP, e-commerce, соцсетиПростые API, внутренние системыМобильные приложения, соцсети

Tiered-стратегия: fallback между типами прокси

В продакшене не полагайтесь на один тип прокси. Tiered-подход работает так:

  1. Residential — основной слой для защищённых сайтов.
  2. Datacenter — fallback для простых endpoint или когда residential-пул исчерпан.
  3. Mobile — для максимально защищённых целей (соцсети, мобильные API).

В Crawlee это можно реализовать через обработчик ошибок: при блокировке на residential переключайтесь на mobile, при таймауте — на datacenter для менее защищённых URL.

Runnable пример: BeautifulSoupCrawler с ProxyHat

Ниже — рабочий пример краулера на BeautifulSoupCrawler с ProxyHat residential-прокси, привязкой к стране и session_id:

import asyncio
from crawlee import Request
from crawlee.beautifulsoup import BeautifulSoupCrawler
from crawlee.proxy_configuration import ProxyConfiguration

def make_proxy_url(session_id: str, country: str = 'US') -> str:
    '''Генерирует URL прокси ProxyHat для конкретной сессии.'''
    username = f'user-country-{country}-session-{session_id}'
    password = 'YOUR_PASSWORD'
    return f'http://{username}:{password}@gate.proxyhat.com:8080'

async def main():
    proxy_config = ProxyConfiguration(
        proxy_urls=[
            make_proxy_url('abc123', 'US'),
            make_proxy_url('def456', 'US'),
            make_proxy_url('ghi789', 'US'),
        ]
    )

    crawler = BeautifulSoupCrawler(
        proxy_configuration=proxy_config,
        max_request_retries=3,
        max_requests_per_crawl=100,
    )

    @crawler.router.default_handler
    async def handler(request: Request, session) -> None:
        response = await session.get(request.url)
        
        if response.status_code in (403, 429):
            session.retire()
            raise RuntimeError(f'Blocked: {response.status_code}')
        
        soup = await response.parse()
        title = soup.find('title')
        print(f'[{session.id}] {request.url} - {title.text if title else "N/A"}')

    await crawler.run(['https://example.com'])

if __name__ == '__main__':
    asyncio.run(main())

Здесь каждая сессия получает свой residential IP через ProxyHat. При блокировке (403 или 429) вызывается session.retire() — Crawlee создаёт новую сессию с новым IP и повторяет запрос.

Генерация per-session username через SDK

Для динамического создания сессий используйте UUID и кодируйте его в username:

import uuid
from crawlee.proxy_configuration import ProxyConfiguration

def generate_session_username(country: str = 'US') -> str:
    '''Генерирует уникальный username для ProxyHat residential-прокси.'''
    session_id = uuid.uuid4().hex[:8]
    return f'user-country-{country}-session-{session_id}'

proxy_config = ProxyConfiguration(
    new_url_function=lambda session_id: (
        f'http://{generate_session_username()}:PASSWORD@gate.proxyhat.com:8080'
    )
)

Каждый вызов new_url() создаёт уникальную сессию с новым residential IP. Это идеально для распределённого скрейпинга, где каждый воркер должен выглядеть независимым пользователем.

PlaywrightCrawler с прокси: когда нужен браузер

PlaywrightCrawler поддерживает прокси через ту же ProxyConfiguration. Crawlee автоматически передаёт прокси-URL в Playwright при запуске контекста браузера:

from crawlee.playwright import PlaywrightCrawler

crawler = PlaywrightCrawler(
    proxy_configuration=proxy_config,
    max_request_retries=3,
    browser_type='chromium',
    headless=True,
)

@crawler.router.default_handler
async def handler(request, page, session) -> None:
    await page.goto(request.url)
    
    if 'challenge' in page.url:
        session.retire()
        raise RuntimeError('Cloudflare challenge detected')
    
    title = await page.title()
    print(f'[{session.id}] {request.url} - {title}')

PlaywrightCrawler автоматически связывает прокси с контекстом браузера, поэтому cookies и отпечатки остаются консистентными с IP. Это критично для обхода Cloudflare Turnstile и DataDome, которые проверяют соответствие TLS-отпечатка и IP.

Production-паттерны: надёжность в продакшене

1. session.retire() при блокировках

Не просто ретрайте заблокированные запросы — завершайте сессию. Crawlee создаст новую с новым IP, новыми cookies и новым отпечатком:

@crawler.router.default_handler
async def handler(request: Request, session) -> None:
    response = await session.get(request.url)
    
    if response.status_code in (403, 429):
        session.retire()
        raise RuntimeError(f'Blocked: {response.status_code}')
    
    # Проверка на CAPTCHA-редирект
    if 'challenge' in str(response.url):
        session.retire()
        raise RuntimeError('CAPTCHA challenge detected')
    
    # Проверка на пустой ответ (DataDome)
    content = await response.text()
    if len(content) < 200 and 'datadome' in content.lower():
        session.retire()
        raise RuntimeError('DataDome block detected')

2. max_request_retries и экспоненциальная задержка

Crawlee поддерживает автоматические ретраи через max_request_retries. При каждом ретрае создаётся новая сессия с новым прокси. Рекомендуемое значение — 3 для большинства задач. Больше — рискуете получить rate limit, меньше — потеряете данные.

3. Параллелизм через AutoscaledPool

Для residential-прокси держите concurrency в диапазоне 20–50 параллельных запросов. Выше — рискуете исчерпать пул доступных IP и получить блокировку за «нетипичную» активность:

crawler = BeautifulSoupCrawler(
    proxy_configuration=proxy_config,
    max_request_retries=3,
    autoscaled_pool_options={
        'max_concurrency': 50,
        'min_concurrency': 5,
    },
)

4. Обработка ошибок в request_handler

Классифицируйте ошибки и принимайте решения по каждой:

  • Timeout — ретрай с новым прокси, увеличить timeout.
  • 403/429 — retire сессии, ретрай.
  • CAPTCHA — retire, пометить URL для ручного ревью или переключиться на PlaywrightCrawler.
  • 5xx — ретрай с экспоненциальной задержкой, не retire.

5. Контейнеризация и масштабирование

Для распределённого скрейпинга запускайте несколько контейнеров с Crawlee, каждый со своим набором session_id. Docker Compose или Kubernetes позволяют масштабировать горизонтально:

  • Каждый контейнер — независимый краулер со своим SessionPool.
  • Используйте Redis в качестве общего хранилища очереди запросов (StorageClient в Crawlee).
  • Мониторьте success rate через логирование: если падает ниже 80% — уменьшите concurrency.
  • Лимитируйте общее количество запросов в минуту на домен, чтобы не получить бан на уровне ISP.

Когда НЕ нужен браузерный краулинг

PlaywrightCrawler в 10–20 раз медленнее BeautifulSoupCrawler и потребляет значительно больше ресурсов. Прежде чем запускать браузер, попробуйте:

  1. Обычный HTTP-запрос через BeautifulSoupCrawler — часто достаточно для статичных страниц.
  2. API эндпоинт — многие сайты имеют JSON API, который не требует рендеринга.
  3. HTTP с правильными заголовками — иногда достаточно добавить Accept, Referer и реалистичный User-Agent.

Используйте PlaywrightCrawler только когда сайт требует JS-рендеринга для контента, или есть Cloudflare Turnstile / DataDome CAPTCHA, или нужно взаимодействие с DOM (клики, скролл, заполнение форм).

Этика и правовые границы

Веб-скрейпинг — мощный инструмент, но он требует ответственности:

  • Собирайте только публичные данные. Не пытайтесь обойти paywall или авторизацию.
  • Уважайте robots.txt. Crawlee поддерживает проверку через RobotsTxtFile — не отключайте её без причины.
  • Соблюдайте rate limits. Если сайт отвечает 429 — замедлитесь, не ускоряйтесь.
  • Предпочитайте официальные API. Если у сайта есть API — используйте его.
  • GDPR и персональные данные. Сбор персональных данных граждан ЕС регулируется GDPR. Не храните PII без законного основания.

Согласно официальной документации Crawlee, краулер должен уважать robots.txt по умолчанию. CFAA в США может применяться к несанкционированному доступу к компьютерным системам, а GDPR в ЕС регулирует обработку персональных данных.

Настройка ProxyHat: подключение

ProxyHat предоставляет residential, mobile и datacenter прокси с geo-таргетингом по странам и городам. Подключение к Crawlee занимает несколько строк:

HTTP-прокси (порт 8080):

http://user-country-US-session-abc123:PASSWORD@gate.proxyhat.com:8080

SOCKS5-прокси (порт 1080):

socks5://user-country-US-session-abc123:PASSWORD@gate.proxyhat.com:1080

Доступные параметры в username:

  • country-{XX} — двухбуквенный код страны (US, DE, GB, JP).
  • city-{name} — город (berlin, london, tokyo).
  • session-{id} — идентификатор сессии для sticky IP.

Полная документация доступна на docs.proxyhat.com. Тарифы — на странице /pricing. Доступные локации — на /locations. Примеры использования — в разделах веб-скрейпинг и SERP-трекинг.

Key Takeaways

  • ProxyConfiguration — единственный идиоматичный способ управления прокси в Crawlee для Python. Не подставляйте прокси вручную в каждый запрос.
  • Sticky sessions через session_id в username ProxyHat — ключ к обходу Cloudflare и DataDome.
  • Residential-прокси обеспечивают 85–95% проходимость против 10–30% у datacenter на защищённых сайтах.
  • session.retire() при блокировке — Crawlee автоматически создаст новую сессию с новым IP.
  • Держите concurrency 20–50 для residential-прокси, чтобы не исчерпать пул IP.
  • Используйте BeautifulSoupCrawler по умолчанию, PlaywrightCrawler — только для JS-рендеринга и CAPTCHA.
  • Этика прежде всего — публичные данные, robots.txt, официальные API, GDPR-комплаенс.

Готовы начать? Изучите use-case веб-скрейпинга и SERP-трекинга с ProxyHat, или перейдите к тарифам.

Готовы начать?

Доступ к более чем 50 млн резидентных IP в 148+ странах с AI-фильтрацией.

Смотреть ценыРезидентные прокси
← Вернуться в Блог