Uwaga prawna: Scraping danych publicznych podlega regulacjom takim jak Computer Fraud and Abuse Act (CFAA) w USA oraz RODO/GDPR w Unii Europejskiej. Zbieraj wyłącznie dane publiczne, honoruj pliki robots.txt, limity częstotliwości oraz regulaminy serwisów (ToS), a tam gdzie to możliwe — preferuj oficjalne API. Ten artykuł ma charakter edukacyjny i nie stanowi porady prawnej.
Rotacja proxy w Crawlee dla Pythona to kluczowa umiejętność dla każdego programisty budującego produkcyjne crawlery. Crawlee — framework stworzony przez zespół Apify — oferuje wbudowane mechanizmy zarządzania sesjami i proxy, które znacznie przewyższają ręczne rozwiązania typu „lista proxy w pętli”. W tym przewodniku pokażemy, jak idiomatycznie zintegrować crawlee python proxy z infrastrukturą ProxyHat, wykorzystując klasę ProxyConfiguration, SessionPool oraz wzorce produkcyjne takie jak session.retire().
Architektura Crawlee: Request Queue, Autoscaling i SessionPool
Crawlee dla Pythona dzieli rdzeń architektoniczny z odpowiednikiem w TypeScript. Trzy komponenty są kluczowe dla zrozumienia proxy rotation:
- Request Queue — centralna, deduplikująca kolejka żądań, współdzielona przez wszystkie crawlery (BeautifulSoupCrawler, PlaywrightCrawler). Żądania można dodawać dynamicznie z poziomu
request_handler. - Autoscaled Pool — pula workerów, która automatycznie dostosowuje współbieżność na podstawie wydajności i limitów. Domyślnie startuje ostrożnie i zwiększa liczbę jednoczesnych żądań, gdy system radzi sobie bez błędów.
- SessionPool — zarządza sesjami HTTP, z których każda może mieć powiązany adres IP, ciasteczka i odcisk palca przeglądarki. To właśnie tutaj proxy rotation spotyka się z zarządzaniem stanem.
SessionPool to fundament idiomatycznej rotacji proxy. Zamiast traktować proxy jako listę URL-i do losowego wybierania, Crawlee wiąże każdy adres IP z sesją, która przechowuje ciasteczka i nagłówki. Dzięki temu kolejne żądania w tej samej sesji trafiają na ten sam adres IP — co jest kluczowe dla stron wymagających logowania lub utrzymania koszyka.
Więcej o architekturze Crawlee można przeczytać w oficjalnej dokumentacji Crawlee.
ProxyConfiguration: idiomatyczna rotacja proxy w Crawlee
Klasa ProxyConfiguration jest idiomatycznym sposobem konfiguracji proxy w Crawlee. Zamiast ręcznie przekazywać URL proxy do każdego żądania, definiujesz konfigurację raz, a Crawlee automatycznie aplikuje ją do wszystkich sesji i crawlerów.
Dwa główne wzorce rotacji to:
- Round-robin — każde żądanie otrzymuje nowy adres IP. Odpowiednie dla prostego scrapingu SERP lub monitoringu cen, gdzie nie potrzebujesz utrzymania stanu.
- Session-bound (sticky) — adres IP jest przypisany do sesji na cały jej cykl życia. Użyj
proxy_configuration.new_url(session_id=...), aby przypiąć residential IP do konkretnej sesji.
Oto jak wygląda podstawowa konfiguracja crawlee proxyconfiguration z ProxyHat:
from crawlee.proxy_configuration import ProxyConfiguration
# Round-robin: Crawlee wywoła new_url() bez session_id
proxy_config = ProxyConfiguration(
proxy_urls=[
'http://user-country-US:PASSWORD@gate.proxyhat.com:8080',
'http://user-country-DE:PASSWORD@gate.proxyhat.com:8080',
'http://user-country-GB:PASSWORD@gate.proxyhat.com:8080',
]
)
Dla sesji przypiętej do konkretnego IP (sticky session), używamy flagi session w nazwie użytkownika ProxyHat:
from crawlee.proxy_configuration import ProxyConfiguration
import uuid
def make_proxy_url(session_id: str, country: str = 'US') -> str:
username = f'user-country-{country}-session-{session_id}'
return f'http://{username}:PASSWORD@gate.proxyhat.com:8080'
# ProxyConfiguration z generatorem URL-i per sesja
proxy_config = ProxyConfiguration(
new_url_function=lambda session_id=None: make_proxy_url(
session_id or str(uuid.uuid4())
)
)
W tym wzorcu crawlee proxy rotation odbywa się automatycznie — Crawlee wywołuje new_url(session_id=...) dla każdej nowej sesji w SessionPool, a ProxyHat utrzymuje ten sam residential IP tak długo, jak sesja jest aktywna.
Dlaczego residential proxy biją datacenter na Cloudflare i DataDome
Systemy ochrony typu Cloudflare Bot Management i DataDome klasyfikują ruch na podstawie reputacji adresu IP. Adresy z puli datacenter (AWS, DigitalOcean, OVH) są natychmiast oznaczane jako podejrzane, ponieważ nie pochodzą od dostawców internetu (ISP). Residential proxy korzystają z adresów IP przydzielonych przez prawdziwych ISP zwykłym gospodarstwom domowym — co sprawia, że dla systemu antybotowego wyglądają jak organiczny ruch.
Według raportu Cloudflare Radar, ponad 30% ruchu internetowego jest filtrowane jako automatyczne, a systemy bot management coraz częściej stosują analizę reputacji IP w czasie rzeczywistym. Adresy datacenter mają wskaźnik blokady często przekraczający 50% na chronionych celach, podczas gdy residential proxy mogą utrzymywać wskaźnik sukcesu powyżej 90% przy odpowiedniej rotacji.
Strategia proxy warstwowych (tiered proxies) polega na hierarchii:
- Zacznij od residential proxy dla pierwszej warstwy żądań.
- Jeśli sesja otrzyma blokadę (status 403, challenge CAPTCHA), wycofaj ją (
session.retire()). - Utwórz nową sesję z nowym residential IP.
- Rezerwuj mobile proxy dla najtrudniejszych celów — mają najwyższą reputację IP, ale są najdroższe.
| Cecha | Datacenter Proxy | Residential Proxy | Mobile Proxy |
|---|---|---|---|
| Reputacja IP | Niska — oznaczane jako hosting | Wysoka — prawdziwy ISP | Bardzo wysoka — sieć komórkowa |
| Wskaźnik blokad (Cloudflare/Datadome) | 40–60% | 5–15% | <5% |
| Latencja | ~50–100ms | ~200–500ms | ~300–800ms |
| Koszt | Niski (~$1/GB) | Średni (~$5–15/GB) | Wysoki (~$20–50/GB) |
| Idiomy Crawlee | Round-robin | Session-bound rotation | Session-bound, długie sesje |
Sprawdź dostępne lokalizacje ProxyHat na stronie /pl/locations, aby dobrać geo-targetowanie do swojego przypadku użycia.
Przykład: BeautifulSoupCrawler z ProxyConfiguration i ProxyHat
Poniżej znajduje się kompletny, uruchamialny przykład crawlee session pool z proxy residential. Crawler pobiera strony e-commerce, używając sesji przypiętych do residential IP w USA.
import asyncio
import uuid
from crawlee.beautifulsoup_crawler import BeautifulSoupCrawler
from crawlee.proxy_configuration import ProxyConfiguration
from crawlee.sessions import SessionPool
PROXYHAT_USER = 'user'
PROXYHAT_PASS = 'PASSWORD'
def make_proxy_url(session_id: str, country: str = 'US') -> str:
"""Generuje URL proxy ProxyHat dla danej sesji i kraju."""
username = f'{PROXYHAT_USER}-country-{country}-session-{session_id}'
return f'http://{username}:{PROXYHAT_PASS}@gate.proxyhat.com:8080'
async def main():
# ProxyConfiguration z funkcją generującą URL per sesja
proxy_config = ProxyConfiguration(
new_url_function=lambda session_id=None: make_proxy_url(
session_id or str(uuid.uuid4())[:8]
)
)
crawler = BeautifulSoupCrawler(
proxy_configuration=proxy_config,
max_request_retries=3,
request_handler_timeout=60,
max_requests_per_crawl=500,
# Autoscaling: Crawlee sam dostosuje współbieżność
min_concurrency=2,
max_concurrency=10,
)
@crawler.router.default_handler
async def handler(request, session, request_handler_data):
response = await request_handler_data.http_client.send_request(
str(request.url)
)
# Wykrywanie blokad
if response.status_code == 403:
session.retire()
raise RuntimeError(f'Zablokowano na {request.url} — wycofuję sesję')
# Parsowanie danych
soup = request_handler_data.soup
title = soup.find('h1')
price = soup.find('span', class_='price')
await request_handler_data.push_data({
'url': str(request.url),
'title': title.text.strip() if title else None,
'price': price.text.strip() if price else None,
'session_id': session.id,
})
# Dodawanie kolejnych linków
for link in soup.select('a.product-link'):
await request_handler_data.enqueue_links(
selector='a.product-link',
label='PRODUCT'
)
await crawler.run(['https://example-store.com/products'])
if __name__ == '__main__':
asyncio.run(main())
Kluczowe elementy tego przykładu:
ProxyConfigurationznew_url_functiongeneruje unikalny URL proxy dla każdej sesji, używając flagi-session-{id}w nazwie użytkownika ProxyHat.session.retire()wycofuje sesję po blokadzie — Crawlee automatycznie tworzy nową sesję z nowym IP.max_request_retries=3zapewnia, że zablokowane żądanie zostanie ponowione z nową sesją.- Autoscaling (
min_concurrency,max_concurrency) kontroluje przepustowość — Crawlee zwiększa współbieżność, gdy wskaźnik sukcesu jest wysoki.
Wzorce produkcyjne: session.retire(), retry i error handling
Wycofywanie sesji po blokadzie
Najważniejszy wzorzec produkcyjny to session.retire(). Kiedy wykryjesz blokadę — status 403, 429, redirect do strony CAPTCHA, lub nieoczekiwany HTML z challenge — wycofujesz sesję. Crawlee automatycznie utworzy nową sesję z nowym proxy URL.
@crawler.router.default_handler
async def handler(request, session, request_handler_data):
response = await request_handler_data.http_client.send_request(
str(request.url)
)
# Wzorce detekcji blokad
blocked_signals = [
response.status_code == 403,
response.status_code == 429,
'cf-challenge' in response.headers.get('server', ''),
'captcha' in response.text.lower()[:2000],
]
if any(blocked_signals):
session.retire()
# Rzucenie wyjątku powoduje retry z nową sesją
raise RuntimeError(f'Zablokowano: {response.status_code} na {request.url}')
# Normalna obsługa...
Tiered proxy fallback
Dla najtrudniejszych celów warto zaimplementować fallback: zacznij od residential, a po N blokadach przełącz się na mobile proxy. Możesz to osiągnąć, nadpisując new_url_function na podstawie licznika blokad sesji:
block_counter = {'count': 0}
def tiered_proxy_url(session_id=None):
if block_counter['count'] > 5:
# Przełącz na mobile proxy
username = f'{PROXYHAT_USER}-country-US-session-{session_id}-mobile'
else:
username = f'{PROXYHAT_USER}-country-US-session-{session_id}'
return f'http://{username}:{PROXYHAT_PASS}@gate.proxyhat.com:8080'
Zarządzanie współbieżnością
Autoscaled Pool w Crawlee automatycznie dostosowuje współbieżność, ale warto ustawić limity. Dla residential proxy rozsądna konfiguracja to max_concurrency=10–20 — zbyt agresywne współbieżne żądania z tej samej puli IP mogą wywołać blokady. Pełną dokumentację parametrów znajdziesz na docs.proxyhat.com.
Kiedy NIE używać PlaywrightCrawler
PlaywrightCrawler uruchamia pełną przeglądarkę headless — jest 10–50x wolniejszy i zużywa znacznie więcej zasobów niż BeautifulSoupCrawler. Używaj go tylko gdy:
- Strona renderuje treść w JavaScript (SPA, React, Vue).
- Musisz wykonać interakcje (kliknięcia, scrollowanie, wypełnianie formularzy).
- System antybotowy wymaga pełnego odcisku palca przeglądarki (Canvas, WebGL, WebRTC).
W pozostałych przypadkach — statyczne HTML, API endpoints, JSON — BeautifulSoupCrawler z proxy residential jest znacznie wydajniejszy i tańszy. Monitorowanie cen SERP najlepiej realizować przez HTTP-only crawling. Zobacz nasze przypadki użycia na /pl/use-cases/serp-tracking.
Etyka i zgodność z prawem
Web scraping jest legalny dla danych publicznych, ale podlega ograniczeniom:
- CFAA (USA) — Computer Fraud and Abuse Act zabrania „nieautoryzowanego dostępu” do systemów komputerowych. Scraping za zaporami logowania lub z naruszeniem ToS może naruszać CFAA.
- GDPR/RODO (UE) — dane osobowe podlegają ochronie. Scraping danych osobowych (nazwiska, e-maile, adresy) wymaga podstawy prawnej.
- robots.txt — choć nie jest prawnie wiążący, jego ignorowanie może być argumentem przeciwko Tobie w sporze.
- Limity częstotliwości — agresywny scraping może zakłócać działanie serwisu i naruszać ToS.
Zawsze preferuj oficjalne API, gdy są dostępne. Więcej o przypadkach użycia scraping znajdziesz na /pl/use-cases/web-scraping, a cennik proxy residential na /pl/pricing.
Kluczowe wnioski: Rotacja proxy w Crawlee dla Pythona jest idiomatycznie realizowana przezProxyConfigurationznew_url_function, który generuje URL proxy per sesja.SessionPoolwiąże IP z ciasteczkami i nagłówkami. Residential proxy z ProxyHat (gate.proxyhat.com:8080) oferują wskaźnik sukcesu >90% na celach chronionych przez Cloudflare.session.retire()jest kluczowym wzorcem obsługi blokad. BeautifulSoupCrawler jest wystarczający dla większości zadań — PlaywrightCrawler używaj tylko dla JS-heavy stron.
Często zadawane pytania
Czym jest rotacja proxy w Crawlee dla Pythona?
Rotacja proxy w Crawlee dla Pythona to mechanizm zarządzania adresami IP poprzez klasę ProxyConfiguration i SessionPool. Crawlee automatycznie przypisuje proxy do sesji, utrzymując ten sam IP dla sticky sessions lub rotując IP per żądanie w trybie round-robin. Konfiguracja odbywa się raz na poziomie crawlera, a Crawlee aplikuje ją do wszystkich żądań.
Dlaczego rotacja proxy w Crawlee dla Pythona ma znaczenie dla użytkowników proxy?
Bez rotacji proxy pojedynczy adres IP zostanie szybko zablokowany przez systemy antybotowe. Crawlee integruje rotację z SessionPool, co oznacza, że ciasteczka i nagłówki są spójne z adresem IP — to zapobiega anomaliom, które systemy ochrony wykrywają jako boty. Residential proxy z rotacją sesyjną utrzymują wskaźnik sukcesu powyżej 90% na chronionych celach.
Który typ proxy najlepiej działa z rotacją w Crawlee dla Pythona?
Residential proxy są optymalne dla większości przypadków użycia w Crawlee — oferują wysoką reputację IP (prawdziwy ISP), wskaźnik blokad 5–15% na Cloudflare/DataDome i rozsądną latencję 200–500ms. Mobile proxy mają najwyższą reputację, ale są droższe ($20–50/GB). Datacenter proxy są najtańsze, ale na chronionych celach wskaźnik blokad sięga 40–60%.
Jak unikać blokad implementując rotację proxy w Crawlee dla Pythona?
Kluczowe wzorce: (1) używaj session.retire() po wykryciu blokady (403, 429, CAPTCHA); (2) ustaw max_request_retries=3, aby Crawlee ponowił żądanie z nową sesją; (3) ogranicz współbieżność do 10–20 dla residential proxy; (4) implementuj tiered fallback — residential → mobile; (5) używaj geo-targetowania dopasowanego do celu (np. -country-US dla amerykańskich serwisów).
Czy Crawlee dla Pythona obsługuje SOCKS5 proxy?
Tak, Crawlee obsługuje SOCKS5 przez ProxyConfiguration. Wystarczy użyć formatu socks5://USERNAME:PASSWORD@gate.proxyhat.com:1080 w proxy_urls lub new_url_function. SOCKS5 jest przydatny, gdy HTTP proxy jest blokowane przez sieć docelową lub gdy potrzebujesz tunelowania UDP.






