Ротация прокси в 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 принадлежат настоящим интернет-провайдерам и неотличимы от обычного трафика.
| Характеристика | Residential | Datacenter | Mobile |
|---|---|---|---|
| Проходимость Cloudflare | 85–95% | 10–30% | 90–98% |
| Средняя задержка | 200–800ms | 50–200ms | 500–2000ms |
| Цена за GB | Средняя | Низкая | Высокая |
| Стабильность sticky IP | Высокая | Средняя | Низкая |
| Идеально для | SERP, e-commerce, соцсети | Простые API, внутренние системы | Мобильные приложения, соцсети |
Tiered-стратегия: fallback между типами прокси
В продакшене не полагайтесь на один тип прокси. Tiered-подход работает так:
- Residential — основной слой для защищённых сайтов.
- Datacenter — fallback для простых endpoint или когда residential-пул исчерпан.
- 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 и потребляет значительно больше ресурсов. Прежде чем запускать браузер, попробуйте:
- Обычный HTTP-запрос через BeautifulSoupCrawler — часто достаточно для статичных страниц.
- API эндпоинт — многие сайты имеют JSON API, который не требует рендеринга.
- 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, или перейдите к тарифам.






