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

Практическое руководство по настройке ротации прокси в Crawlee для Python: ProxyConfiguration, SessionPool, привязка residential IP к сессиям и продакшн-паттерны для обхода антибот-защиты.

Proxy Rotation in Crawlee for Python: A Developer's Guide to Residential Proxies
В этой статье

Что такое ротация прокси в Crawlee для Python и зачем она нужна

Ротация прокси в Crawlee для Python — это механизм, через который фреймворк управляет пулом прокси-серверов и привязывает каждый IP к логической сессии. Crawlee (порт Python популярного JavaScript-фреймворка Apify) предоставляет класс ProxyConfiguration и интегрированный SessionPool, которые работают поверх единой очереди запросов и автомасштабируемого пула. Если вы скрейпите сайты под Cloudflare или DataDome, простая round-robin ротация datacenter-IP почти гарантированно заканчивается банами за 100–500 запросов. Правильный подход — residential-прокси, привязанные к сессиям, с резервным переключением при блокировках.

В этом руководстве мы разберём архитектуру Crawlee, идиоматическое использование ProxyConfiguration, сравнение residential и datacenter-прокси, runnable-примеры с ProxyHat и продакшн-паттерны для масштабирования.

Архитектура Crawlee для Python: очередь запросов, автомасштабирование и SessionPool

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

  • Request Queue — единая очередь запросов (RequestManager), которую разделяют все краулеры. Запросы могут поступать из start_urls, enqueue_links или вручную.
  • Autoscaled Pool — пул воркеров, который динамически масштабирует параллелизм в зависимости от производительности системы и целевого сайта. Crawlee сам регулирует количество одновременных запросов.
  • SessionPool — пул сессий, каждая из которых хранит cookies, fingerprint браузера и привязанный прокси-URL. Сессия — это логический «пользователь», который последовательно запрашивает страницы.
  • ProxyConfiguration — класс, который генерирует прокси-URL для каждой сессии или запроса. Может работать в режимах round-robin или session-pinned.

Ключевая идея: SessionPool и ProxyConfiguration связаны. Когда Crawlee создаёт новую сессию, он вызывает proxy_configuration.new_url(session_id=session.id), чтобы получить прокси-URL. Этот URL остаётся закреплённым за сессией до тех пор, пока сессия жива или пока не будет retired при блокировке. Это означает, что cookies, fingerprint и IP-адрес формируют единый «цифровой отпечаток», который выглядит как реальный пользователь, последовательно просматривающий страницы.

BeautifulSoupCrawler против PlaywrightCrawler

Crawlee предлагает два основных типа краулеров. BeautifulSoupCrawler использует httpx для HTTP-запросов и парсит HTML через BeautifulSoup — это быстро и легко, но не выполняет JavaScript. PlaywrightCrawler запускает реальный браузер через Playwright, что позволяет рендерить SPA и обходить часть антибот-проверок, но стоит дороже по ресурсам (порядка 200–400 МБ RAM на одну вкладку).

Выбор краулера напрямую влияет на стратегию прокси. Для статичных HTML-сайтов достаточно BeautifulSoupCrawler + residential-прокси. Для сайтов с JS-челленджами (Cloudflare Turnstile, DataDome) чаще нужен PlaywrightCrawler с residential-прокси и аккуратным управлением сессиями.

ProxyConfiguration: идиоматический способ управления прокси в Crawlee

Класс ProxyConfiguration — это центральная точка управления прокси в Crawlee. Он принимает список прокси-URL или функцию-генератор и предоставляет метод new_url(session_id), который вызывается краулером при создании или восстановлении сессии.

Round-robin ротация

В простейшем случае вы передаёте список прокси-URL, и Crawlee поочерёдно раздаёт их запросам:

from crawlee.proxy_configuration import ProxyConfiguration

proxy_urls = [
    'http://user-country-US:pass@gate.proxyhat.com:8080',
    'http://user-country-DE:pass@gate.proxyhat.com:8080',
    'http://user-country-GB:pass@gate.proxyhat.com:8080',
]

proxy_config = ProxyConfiguration(proxy_urls=proxy_urls)

Проблема round-robin в том, что каждый запрос получает «новый» IP, но cookies и fingerprint браузера остаются теми же. Антибот-системы быстро замечают несоответствие: один fingerprint, но десятки разных IP за минуту — классический сигнал бота.

Session-pinned ротация: правильный паттерн

Идиоматический подход — привязать residential IP к сессии через session_id. Crawlee передаёт session.id в new_url(), и вы можете использовать это значение для генерации детерминированного прокси-URL:

from crawlee.proxy_configuration import ProxyConfiguration

def proxy_url_generator(session_id=None):
    if session_id:
        # Закрепляем IP за сессией
        username = f'user-country-US-session-{session_id}'
    else:
        # Без сессии — новая страна каждый раз
        username = 'user-country-US'
    return f'http://{username}:pass@gate.proxyhat.com:8080'

proxy_config = ProxyConfiguration(proxy_urls=[proxy_url_generator])

При использовании session_id ProxyHat выдаёт один и тот же residential IP для всех запросов в рамках сессии. Это позволяет Crawlee поддерживать целостность cookies и fingerprint — каждый «пользователь» имеет стабильный IP, что выглядит естественно для целевого сайта.

Почему residential-прокси превосходят datacenter на Cloudflare и DataDome

Антибот-системы вроде Cloudflare Bot Management и DataDome используют многоуровневую эвристику: IP-репутацию, TLS fingerprinting, поведенческий анализ и JS-челленджи. Datacenter-IP-адреса (например, AWS, DigitalOcean, Hetzner) помечены как хостинг-провайдеры почти во всех публичных базах ASN. Запрос с datacenter-IP к защищённому сайту часто получает CAPTCHA или 403 ещё до рендеринга страницы.

Residential-прокси используют IP-адреса, зарегистрированные на реальных ISP. Они не попадают в списки дата-центров и имеют высокую репутацию. По данным документации Crawlee, правильное сочетание residential-прокси со стабильными сессиями и браузерным fingerprinting значительно повышает success rate на защищённых сайтах.

ХарактеристикаDatacenter-проксиResidential-прокси
IP-репутацияНизкая (ASN хостинга)Высокая (реальный ISP)
Скорость50–100 мс200–800 мс
Success rate на Cloudflare10–30%70–95%
Цена$1–3 / GB$5–15 / GB
Стабильность IPВысокаяЗависит от сессии

Tiered proxies: стратегия резервного переключения

В продакшене полезно использовать многоуровневую стратегию: основная масса запросов идёт через residential-прокси, а при блокировке сессия переводится на другой geo или retiring с последующим пересозданием. Crawlee поддерживает это через session.retire() — после чего SessionPool создаёт новую сессию с новым прокси-URL.

Runnable-пример: BeautifulSoupCrawler с ProxyConfiguration и ProxyHat

Ниже — полный runnable-пример, который скрейпит заголовки страниц, используя residential-прокси ProxyHat с привязкой к сессиям. Каждая сессия получает уникальный session_id, который передаётся в username прокси для закрепления IP.

import asyncio
from crawlee.beautifulsoup_crawler import BeautifulSoupCrawler, BeautifulSoupCrawlerOptions
from crawlee.proxy_configuration import ProxyConfiguration
from crawlee.sessions import SessionPool

PROXYHAT_GATEWAY = 'gate.proxyhat.com'
PROXYHAT_PORT = 8080
PROXYHAT_USER = 'your_username'
PROXYHAT_PASS = 'your_password'

def make_proxy_url(session_id=None):
    """Генерирует URL прокси ProxyHat с закреплением IP за сессией."""
    if session_id:
        username = f'{PROXYHAT_USER}-country-US-session-{session_id}'
    else:
        username = f'{PROXYHAT_USER}-country-US'
    return f'http://{username}:{PROXYHAT_PASS}@{PROXYHAT_GATEWAY}:{PROXYHAT_PORT}'

async def main():
    # Создаём ProxyConfiguration с функцией-генератором
    proxy_config = ProxyConfiguration(
        proxy_urls=[make_proxy_url],
    )

    # Конфигурируем краулер с прокси и пулом сессий
    crawler = BeautifulSoupCrawler(
        proxy_configuration=proxy_config,
        max_request_retries=3,
        max_requests_per_crawl=100,
        request_handler_timeout=30,
    )

    @crawler.router.default_handler
    async def handler(request):
        session = request.session
        if session:
            print(f'Сессия {session.id} | Прокси: {session.proxy_url}')

        title = request.soup.find('title')
        text = title.get_text(strip=True) if title else 'Нет заголовка'
        print(f'URL: {request.url} | Title: {text}')

        # Если видим признаки блокировки — уводим сессию
        if 'captcha' in text.lower() or 'access denied' in text.lower():
            if session:
                session.retire()
            raise RuntimeError(f'Блокировка на {request.url}')

        await crawler.enqueue_links()

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

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

В этом примере функция make_proxy_url принимает session_id и формирует username вида your_username-country-US-session-abc123. ProxyHat интерпретирует session-abc123 как идентификатор сессии и выдаёт один и тот же residential IP для всех запросов с этим ID. Когда Crawlee вызывает session.retire(), старая сессия уничтожается, создаётся новая с новым session_id, и ProxyConfiguration генерирует новый прокси-URL с новым IP.

Per-session username через ProxyHat SDK

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

import uuid

def make_proxy_url(session_id=None):
    sid = session_id if session_id else uuid.uuid4().hex[:12]
    username = f'{PROXYHAT_USER}-country-US-session-{sid}'
    return f'http://{username}:{PROXYHAT_PASS}@{PROXYHAT_GATEWAY}:{PROXYHAT_PORT}'

Это особенно полезно при горизонтальном масштабировании: каждый воркер генерирует уникальные session_id, и ProxyHat равномерно распределяет запросы по residential-пулу. Подробности о доступных локациях и параметрах — на странице локаций ProxyHat.

Продакшн-паттерны: session.retire(), ретраи, параллелизм и обработка ошибок

1. Retire сессии при блокировке

Когда краулер сталкивается с 403, CAPTCHA или редиректом на страницу блокировки, нужно немедленно retire сессию. Crawlee автоматически создаст новую, но старый IP больше не будет загрязнять пул:

@crawler.router.default_handler
async def handler(request):
    response = request.http_response
    session = request.session

    if response and response.status_code in (403, 429):
        if session:
            session.retire()
        raise RuntimeError(f'Заблокирован: {request.url} (HTTP {response.status_code})')

    # Нормальная обработка
    soup = request.soup
    title = soup.find('title')
    if title and 'captcha' in title.get_text().lower():
        if session:
            session.retire()
        raise RuntimeError(f'CAPTCHA на {request.url}')

    await crawler.enqueue_links()

2. max_request_retries и exponential backoff

Параметр max_request_retries определяет, сколько раз Crawlee повторит запрос перед тем, как пометить его как failed. Рекомендуется 3–5 ретраев. Crawlee автоматически добавляет задержку между попытками. При превышении ретраев запрос попадает в failed_requests и логируется.

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

Crawlee автоматически масштабирует количество одновременных запросов на основе метрик производительности. Вы можете задать ограничения:

  • max_concurrency — верхний предел параллелизма (например, 50 для residential-прокси).
  • min_concurrency — минимальный уровень (обычно 1–5).
  • autoscaled_pool_options — тонкая настройка порогов масштабирования.

Для residential-прокси рекомендуется max_concurrency в диапазоне 20–50, поскольку каждый запрос создаёт новую TCP-сессию через residential-шлюз. Слишком высокий параллелизм может привести к rate-limiting на стороне ProxyHat или целевого сайта.

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

Любое необработанное исключение в request_handler приводит к ретраю запроса. Но не все ошибки стоит ретраить — например, 404 не имеет смысла повторять. Используйте request.label для категоризации и условную логику:

@crawler.router.handler('product')
async def product_handler(request):
    response = request.http_response
    if response and response.status_code == 404:
        # Не ретраим — страница реально не существует
        return
    if response and response.status_code == 403:
        session = request.session
        if session:
            session.retire()
        raise RuntimeError('Заблокирован')

    # Извлекаем данные товара
    soup = request.soup
    price = soup.select_one('.price')
    if price:
        await request.push_data({
            'url': request.url,
            'price': price.get_text(strip=True),
        })

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

Не каждый проект требует PlaywrightCrawler. Если целевой сайт отдаёт полный HTML в ответ на HTTP-запрос (без JS-рендеринга), BeautifulSoupCrawler работает в 5–10 раз быстрее и потребляет на порядок меньше памяти. Проверьте: откройте URL в curl и посмотрите, есть ли нужные данные в исходном HTML. Если да — не запускайте браузер.

Playwright нужен, когда:

  • Сайт использует JS-челленджи (Cloudflare Turnstile, DataDome interstitial).
  • Контент загружается через XHR/fetch после загрузки страницы.
  • Нужно взаимодействие с UI (клики, скролл, заполнение форм).

В остальных случаях — BeautifulSoupCrawler с residential-прокси через ProxyHat — это оптимальный баланс скорости, стоимости и надёжности. Подробнее о вариантах использования — в разделе web-scraping use case.

Этика, право и ограничения

Важно: Эта статья предназначена для сбора публично доступных данных в законных целях. Сбор данных за аутентификацией или в нарушение Terms of Service может нарушать Computer Fraud and Abuse Act (CFAA) в США и аналогичные законы в других юрисдикциях. Обработка персональных данных подпадает под GDPR в ЕС. Проконсультируйтесь с юристом перед запуском продакшн-краулера.

Практические принципы ответственного скрейпинга:

  • Соблюдайте robots.txt. Согласно RFC 9309, robots.txt — это стандарт, который определяет, какие пути доступны для автоматических обходов. Crawlee не соблюдает robots.txt автоматически — добавьте проверку вручную.
  • Уважайте rate limits. Не отправляйте сотни запросов в секунду на один домен. Residential-прокси не дают carte blanche на DDoS.
  • Предпочитайте официальные API. Если у сайта есть публичный API — используйте его. Это дешевле, надёжнее и законнее.
  • Собирайте только публичные данные. Не пытайтесь обходить аутентификацию или paywall.

Настройка ProxyHat в Crawlee

ProxyHat предоставляет residential, mobile и datacenter-прокси с HTTP-шлюзом на gate.proxyhat.com:8080 и SOCKS5 на :1080. Все параметры гео-таргетинга и сессий передаются в username — это означает, что вам не нужно менять URL-шаблон для разных стран или сессий, достаточно модифицировать username.

Примеры username-паттернов:

  • user-country-US — любой residential IP из США.
  • user-country-US-session-abc123 — закреплённый IP для сессии abc123.
  • user-country-DE-city-berlin-session-xyz789 — закреплённый IP из Берлина.

Для SOCKS5 используйте порт 1080:

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

Тарифы и объёмы трафика — на странице цен ProxyHat. Для SERP-трекинга и поискового мониторинга также см. use case SERP tracking. Полную техническую документацию по параметрам прокси можно найти в официальной документации ProxyHat.

Ключевые выводы

Key Takeaways:

  • Используйте ProxyConfiguration с функцией-генератором и session_id для привязки residential IP к сессии — это идиоматический паттерн Crawlee.
  • Residential-прокси превосходят datacenter на Cloudflare и DataDome: success rate 70–95% против 10–30%.
  • Вызывайте session.retire() при 403/429/CAPTCHA — Crawlee автоматически создаст новую сессию с новым IP.
  • Не запускайте PlaywrightCrawler без необходимости — BeautifulSoupCrawler в 5–10 раз быстрее для статичных сайтов.
  • Соблюдайте robots.txt, rate limits и предпочитайте официальные API. Проконсультируйтесь с юристом по CFAA/GDPR.
  • ProxyHat username-паттерн: user-country-US-session-{session_id} на gate.proxyhat.com:8080.

FAQ

Что такое ротация прокси в Crawlee для Python?

Ротация прокси в Crawlee для Python — это механизм управления пулом прокси-серверов через класс ProxyConfiguration. Crawlee привязывает прокси-URL к логической сессии из SessionPool, что позволяет поддерживать cookies, fingerprint и IP-адрес как единый цифровой отпечаток. Метод new_url(session_id) генерирует прокси-URL для каждой сессии — либо через round-robin, либо через функцию-генератор с закреплением IP.

Почему ротация прокси важна для пользователей прокси в Crawlee?

Без ротации прокси все запросы идут с одного IP, что быстро приводит к блокировкам на защищённых сайтах. С другой стороны, случайная round-robin ротация без привязки к сессиям создаёт подозрительный паттерн: один fingerprint, но десятки разных IP. Правильная ротация — residential-прокси, закреплённые за сессией, — обеспечивает естественный видимый паттерн и высокий success rate на антибот-защите.

Какой тип прокси лучше всего подходит для Crawlee?

Для сайтов под Cloudflare или DataDome — residential-прокси с привязкой к сессиям. Они имеют репутацию реальных ISP и не попадают в списки дата-центров. Datacenter-прокси подходят для простых сайтов без антибот-защиты или для API-эндпоинтов, где IP-репутация не критична. Mobile-прокси — премиум-вариант для самых защищённых целей. ProxyHat поддерживает все три типа на одном шлюзе gate.proxyhat.com:8080.

Как избежать блокировок при ротации прокси в Crawlee?

Используйте session.retire() при обнаружении 403, 429 или CAPTCHA — Crawlee создаст новую сессию с новым IP. Установите max_request_retries 3–5. Ограничьте max_concurrency до 20–50 для residential-прокси. Проверяйте заголовки и содержимое ответа на признаки блокировки. Используйте PlaywrightCrawler только когда действительно нужен JS-рендеринг. Соблюдайте robots.txt и не превышайте разумные rate limits.

Часто задаваемые вопросы

Что такое ротация прокси в Crawlee для Python?

Ротация прокси в Crawlee для Python — это механизм управления пулом прокси-серверов через класс ProxyConfiguration. Crawlee привязывает прокси-URL к логической сессии из SessionPool, что позволяет поддерживать cookies, fingerprint и IP-адрес как единый цифровой отпечаток. Метод new_url(session_id) генерирует прокси-URL для каждой сессии — либо через round-robin, либо через функцию-генератор с закреплением IP.

Почему ротация прокси важна для пользователей прокси в Crawlee?

Без ротации прокси все запросы идут с одного IP, что быстро приводит к блокировкам на защищённых сайтах. Случайная round-robin ротация без привязки к сессиям создаёт подозрительный паттерн: один fingerprint, но десятки разных IP. Правильная ротация — residential-прокси, закреплённые за сессией — обеспечивает естественный видимый паттерн и высокий success rate на антибот-защите.

Какой тип прокси лучше всего подходит для Crawlee?

Для сайтов под Cloudflare или DataDome — residential-прокси с привязкой к сессиям. Они имеют репутацию реальных ISP и не попадают в списки дата-центров. Datacenter-прокси подходят для простых сайтов без антибот-защиты. Mobile-прокси — премиум-вариант для самых защищённых целей. ProxyHat поддерживает все три типа на одном шлюзе gate.proxyhat.com:8080.

Как избежать блокировок при ротации прокси в Crawlee?

Используйте session.retire() при обнаружении 403, 429 или CAPTCHA — Crawlee создаст новую сессию с новым IP. Установите max_request_retries 3–5. Ограничьте max_concurrency до 20–50 для residential-прокси. Проверяйте заголовки и содержимое ответа на признаки блокировки. Используйте PlaywrightCrawler только когда действительно нужен JS-рендеринг. Соблюдайте robots.txt и не превышайте разумные rate limits.

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

Резидентные, ISP и мобильные прокси в 148+ странах. Создайте бесплатный аккаунт.

Создать бесплатный аккаунт
← Вернуться в Блог