Что такое ротация прокси в 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 на Cloudflare | 10–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.






