Crawlee for Python'da Proxy Rotation: Üretim Düzeyinde Rehber

Crawlee for Python'da ProxyConfiguration ve SessionPool ile residential proxy rotasyonu nasıl yapılır? Cloudflare/DataDome aşma, otomatik ölçeklendirme ve üretim desenlerini içeren eksiksiz geliştirici rehberi.

Proxy Rotation in Crawlee for Python: A Developer's Guide to Residential Proxies
Bu makalede

Yasal uyarı: Bu rehber yalnızca halka açık verilerin toplanması içindir. Web scraping; ABD'de CFAA, Avrupa'da GDPR ve benzeri düzenlemeler kapsamında yasal sonuçlar doğurabilir. Her zaman robots.txt dosyasını kontrol edin, hedef sitenin Hizmet Şartları'nı okuyun ve resmi API'leri tercih edin. Bu içerik yasal tavsiye değildir.

Crawlee for Python'da proxy rotation, modern web scraping'in en kritik teknik gereksinimlerinden biridir. Cloudflare, DataDome ve PerimeterX gibi bot koruma sistemleri yaygınlaştıkça, tek bir IP'den yüzlerce istek göndermek artık sürdürülebilir bir strateji değildir. Crawlee'nin ProxyConfiguration ve SessionPool mimarisi, proxy rotasyonunu bir afterthought değil, crawler'ın merkez bir parçası olarak ele alır.

Bu rehberde, Crawlee for Python'da proxy rotation'ı sıfırdan üretim düzeyine kadar inşa edeceğiz: BeautifulSoupCrawler ve PlaywrightCrawler üzerinden SessionPool entegrasyonuna, ProxyHat residential proxy'leri ile session-bağlı rotasyona ve blok yönetiminden ölçeklendirmeye kadar her adımı kod örnekleriyle göstereceğiz.

Crawlee for Python'da Proxy Rotation: Mimari ve Sorunun Kökeni

Crawlee for Python, Apify ekibinin geliştirdiği açık kaynak bir web scraping ve browser automation framework'üdür. Temel bileşenleri şunlardır:

  • Request Queue: Tüm crawler tipleri (BeautifulSoupCrawler, PlaywrightCrawler) ortak bir istek kuyruğu paylaşır. Bu, karma crawling stratejilerini mümkün kılar.
  • Autoscaled Pool: Eşzamanlılık otomatik olarak ayarlanır. Sistem, hata oranını ve yanıt sürelerini izleyerek concurrent request sayısını dinamik olarak artırır veya azaltır.
  • SessionPool: Her session, bir proxy IP'sine, cookie setine ve tarayıcı parmak izine bağlıdır. Bu, hedef siteye "tutarlı bir kullanıcı" gibi görünmenizi sağlar.
  • ProxyConfiguration: Proxy rotasyon stratejisini tanımlayan merkezi sınıf. Round-robin veya session-bağlı rotasyon destekler.

Sorunun kökeni basittir: Hedef siteler, tek bir IP adresinden gelen aşırı istekleri bot trafiği olarak sınıflandırır. Crawlee'nin resmi dokümantasyonu, proxy kullanımını bir opsiyon değil, üretim crawling'inin temel bir gereksinimi olarak konumlandırır. Bir IP'den dakikada 100+ istek gönderdiğinizde, çoğu modern web sitesi sizi dakikalar içinde engeller.

Crawlee'nin SessionPool mekanizması, proxy rotasyonunun kalbidir. Her Session nesnesi şunları içerir:

  • Bir proxy URL'si (ProxyConfiguration'dan atanır)
  • Cookie jar (oturum boyunca korunur)
  • Tarayıcı parmak izi (PlaywrightCrawler için)
  • Durum bilgisi (aktif, engellenmiş, retired)

Bu bağlama kritik öneme sahiptir. Örneğin, bir e-ticaret sitesinde login olduktan sonra sepete ürün eklerseniz, cookie'ler ve IP adresi aynı kalmalıdır. Her istekte IP değiştirirse, hedef site oturumu hemen sonlandırır. Crawlee'nin proxy_configuration.new_url(session_id=session.id) metodu, aynı session ID için aynı proxy'yi döndürerek bu tutarlılığı garanti eder.

ProxyConfiguration: Crawlee'de İdiomatik Proxy Yönetimi

Crawlee'nin ProxyConfiguration sınıfı, proxy yönetimini idiomatik bir şekilde ele alır. İki ana kullanım pattern'i vardır:

1. Round-Robin Rotasyon

Her istek için farklı bir proxy URL'si döndürülür. Bu, basit scraping görevleri için uygundur ancak oturum tutarlılığı gerektirmeyen durumlarda kullanılmalıdır.

from crawlee.proxy_configuration import ProxyConfiguration

# ProxyHat gateway ile round-robin rotasyon
proxy_configuration = 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',
    ]
)

# new_url() her çağrıda bir sonraki proxy'yi döndürür
proxy_url = await proxy_configuration.new_url()

2. Session-Bağlı Rotasyon (Sticky Sessions)

Aynı session_id için her zaman aynı proxy URL'si döndürülür. Bu, login gerektiren siteler, çok adımlı formlar ve sayfalama içeren görevler için kritiktir.

from crawlee.proxy_configuration import ProxyConfiguration

# ProxyHat ile session-bağlı rotasyon
proxy_configuration = ProxyConfiguration(
    proxy_urls=[
        'http://user-country-US-session-abc123:pass@gate.proxyhat.com:8080',
        'http://user-country-US-session-def456:pass@gate.proxyhat.com:8080',
        'http://user-country-US-session-ghi789:pass@gate.proxyhat.com:8080',
    ]
)

# Aynı session_id her zaman aynı proxy'yi döndürür
proxy_url_1 = await proxy_configuration.new_url(session_id='abc123')
proxy_url_2 = await proxy_configuration.new_url(session_id='abc123')
# proxy_url_1 == proxy_url_2 (aynı proxy)

ProxyHat'ın username formatı, session ID'yi doğrudan proxy URL'ine gömer: user-country-US-session-{session_id}:pass. Bu, ProxyConfiguration'a URL listesi sağlamanın ötesinde, dinamik olarak per-session username üretmenize olanak tanır. Daha fazla bilgi için ProxyHat dokümantasyonunu inceleyebilirsiniz.

Residential vs Datacenter: Cloudflare ve DataDome Hedefleri

Proxy tipi seçimi, hedef sitenin bot koruma seviyesine bağlıdır. İşte üç ana proxy tipinin karşılaştırması:

Özellik Residential Datacenter Mobile
IP Kaynağı Gerçek ISP IP'leri Veri merkezi IP blokları Mobil operatör IP'leri
Tespit Zorluğu Yüksek Düşük Çok Yüksek
Hız Ortalama (200-500ms) Hızlı (50-100ms) Değişken (300-800ms)
Fiyat Orta Düşük Yüksek
Cloudflare Geçme Oranı %85-95 %20-40 %90-98

Cloudflare ve DataDome, IP adreslerini ASN (Autonomous System Number) düzeyinde sınıflandırır. Bir IP'nin ASN'si bir veri merkezi sağlayıcısına (örneğin AWS, DigitalOcean, Hetzner) aitse, bu IP'den gelen istekler otomatik olarak daha yüksek bir risk skoru alır. Cloudflare'nin bot yönetim dokümantasyonu, IP itibarının bot sınıflandırmasında temel bir sinyal olduğunu doğrular.

Residential proxy'ler, gerçek ISP'lere (AT&T, Comcast, Vodafone) ait IP bloklarını kullandığı için, hedef site bu IP'leri normal kullanıcı trafiği olarak değerlendirir. Bu, Cloudflare challenge'larını atlama oranını dramatik olarak artırır.

Tiered Proxy Stratejisi

Üretim sistemlerinde, tiered (katmanlı) proxy stratejisi kullanmak etkili bir yaklaşımdır:

  1. Tier 1: Datacenter proxy'ler ile hızlı, ucuz istekler (korunmasız hedefler için)
  2. Tier 2: Residential proxy'ler ile orta seviye korumalı hedefler
  3. Tier 3: Mobile proxy'ler ile en yüksek korumalı hedefler (sadece blok durumunda fallback)

Crawlee'de bu, SessionPool ile yönetilebilir. Bir session bloklandığında, session.retire() çağrılır ve bir sonraki istek yeni bir session (ve potansiyel olarak daha yüksek bir tier'dan proxy) ile yeniden denenebilir. ProxyHat'ın fiyatlandırması, bu katmanlı yaklaşımı maliyet-etkin hale getirir.

Çalışan Örnek: BeautifulSoupCrawler + ProxyConfiguration + ProxyHat

Aşağıdaki örnek, ProxyHat residential proxy'leri ile çalışan tam bir BeautifulSoupCrawler kurulumunu gösterir. Her session için benzersiz bir username üretilir ve ProxyConfiguration'a iletilir.

import asyncio
import uuid
from crawlee.beautifulsoup_crawler import BeautifulSoupCrawler
from crawlee.proxy_configuration import ProxyConfiguration
from crawlee import Request

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

def generate_proxy_url(session_id: str, country: str = 'US') -> str:
    """ProxyHat için per-session proxy URL üretir."""
    username = f'{PROXYHAT_USER}-country-{country}-session-{session_id}'
    return f'http://{username}:{PROXYHAT_PASS}@{PROXYHAT_GATEWAY}:{PROXYHAT_PORT}'

async def main():
    # 50 session için proxy URL listesi oluştur
    session_ids = [str(uuid.uuid4())[:8] for _ in range(50)]
    proxy_urls = [generate_proxy_url(sid) for sid in session_ids]
    
    proxy_configuration = ProxyConfiguration(proxy_urls=proxy_urls)
    
    crawler = BeautifulSoupCrawler(
        proxy_configuration=proxy_configuration,
        max_request_retries=3,
        max_requests_per_minute=200,
        request_handler_timeout=30,
    )
    
    @crawler.router.default_handler
    async def handler(request: Request, request_context):
        url = request.url
        title = request_context.soup.find('title').text
        print(f'[{url}] Title: {title}')
        
        # Sayfalama linklerini kuyruğa ekle
        next_page = request_context.soup.select_one('a.next-page')
        if next_page:
            await request_context.add_requests([next_page['href']])
    
    await crawler.run(['https://example.com/page/1'])

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

Bu örnekte dikkat edilmesi gereken birkaç nokta:

  • max_requests_per_minute=200: Dakikada 200 istek, hedef siteyi aşırı yüklemeden makul bir hızdır.
  • max_request_retries=3: Her istek en fazla 3 kez yeniden denenebilir. Bu, geçici ağ hatalarını tolere eder.
  • Her session ID, ProxyHat username'ine gömülür ve aynı session her zaman aynı residential IP'ye yönlendirilir.

Özel ProxyConfiguration ile Dinamik Username Üretimi

Daha büyük ölçekli operasyonlarda, proxy URL listesini statik olarak oluşturmak yerine, her session için dinamik olarak proxy URL'si üretebilirsiniz:

import uuid
from crawlee.proxy_configuration import ProxyConfiguration

class ProxyHatProxyConfiguration(ProxyConfiguration):
    """ProxyHat için özel ProxyConfiguration."""
    
    def __init__(self, username: str, password: str, 
                 country: str = 'US', **kwargs):
        self._username = username
        self._password = password
        self._country = country
        super().__init__(proxy_urls=[], **kwargs)
    
    async def new_url(self, session_id: str | None = None) -> str:
        if session_id is None:
            session_id = str(uuid.uuid4())[:8]
        
        username = f'{self._username}-country-{self._country}-session-{session_id}'
        return f'http://{username}:{self._password}@gate.proxyhat.com:8080'

# Kullanım
proxy_config = ProxyHatProxyConfiguration(
    username='your_username',
    password='your_password',
    country='US',
)

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

Bu pattern, ProxyConfiguration'ı ProxyHat'ın username formatına uygun şekilde özelleştirir. new_url(session_id=...) her çağrıldığında, session ID'ye göre dinamik bir proxy URL'si üretilir. Crawlee session pool, bu URL'yi ilgili session'a bağlar ve aynı session ID ile gelecek istekler aynı proxy'yi kullanır.

Üretim Desenleri: Blokları Yönetme ve Ölçeklendirme

1. session.retire() ile Blok Yönetimi

Bir session bloklandığında (HTTP 403, 429, veya CAPTCHA challenge), o session'ı derhal kapatmanız gerekir. Crawlee bunu session.retire() ile yapar:

@crawler.router.default_handler
async def handler(request: Request, request_context):
    response = request_context.http_response
    
    # Blok tespiti
    if response.status_code in (403, 429):
        print(f'Block detected: {response.status_code} on {request.url}')
        request_context.session.retire()
        # İstek kuyruğa geri eklenir ve yeni session ile yeniden denenecek
        raise RuntimeError(f'Blocked: {response.status_code}')
    
    # CAPTCHA tespiti
    soup = request_context.soup
    if soup.find(id='cf-challenge-running'):
        print(f'Cloudflare challenge detected on {request.url}')
        request_context.session.retire()
        raise RuntimeError('Cloudflare challenge encountered')
    
    # Normal işleme
    title = soup.find('title').text
    print(f'[{request.url}] {title}')

2. max_request_retries ve Hata Toleransı

max_request_retries, bir isteğin kaç kez yeniden deneneceğini kontrol eder. Her yeniden denemede, Crawlee otomatik olarak yeni bir session (ve dolayısıyla yeni bir proxy IP) atar. Bu, geçici blokların otomatik olarak aşılmasını sağlar.

Üretimde tipik değerler:

  • Korumasız siteler: max_request_retries=1 (hata varsa hızlıca geç)
  • Orta korumalı siteler: max_request_retries=3 (denge)
  • Yüksek korumalı siteler: max_request_retries=5 (ama dikkat: her deneme proxy maliyeti)

3. Eşzamanlılık ve Autoscaled Pool

Crawlee'nin autoscaled pool'u, eşzamanlılığı otomatik olarak ayarlar. Ancak, proxy sağlayıcınızın limitlerini aşmamak için üst sınır belirlemek önemlidir:

crawler = BeautifulSoupCrawler(
    proxy_configuration=proxy_config,
    max_request_retries=3,
    max_requests_per_minute=200,
    # Autoscaling limitleri
    max_concurrency=50,  # Aynı anda en fazla 50 istek
    min_concurrency=5,   # En az 5 eşzamanlı istek
)

ProxyHat, 100+ eşzamanlı session destekler. Ancak hedef sitenin toleransını da göz önünde bulundurun: 50 eşzamanlı istek, çoğu site için güvenli bir üst sınırdır. Daha agresif hedefler için farklı coğrafi konumlardan IP dağıtımı yaparak tek bir bölgeye yüklenmeyi önleyebilirsiniz.

4. Request Handler Hata Yönetimi

Üretimde, request handler içindeki hataların crawler'ı çökertmemesi gerekir. Crawlee, handler hatalarını otomatik olarak yakalar ve isteği yeniden kuyruğa ekler, ancak belirli hata tiplerini farklı şekilde ele almak isteyebilirsiniz:

@crawler.router.default_handler
async def handler(request: Request, request_context):
    try:
        soup = request_context.soup
        data = extract_data(soup)
        await request_context.push_data(data)
    except AttributeError as e:
        # Sayfa yapısı değişti - yeniden deneme faydasız
        print(f'Structure change: {e} on {request.url}')
        request_context.skip_navigation()
    except Exception as e:
        # Beklenmeyen hata - session'ı retire et ve yeniden dene
        print(f'Unexpected error: {e} on {request.url}')
        if request_context.session:
            request_context.session.retire()
        raise  # Crawlee yeniden deneyecek

Tarayıcı Tırmanmasına Ne Zaman Başvurmamalı ve Etik

PlaywrightCrawler vs BeautifulSoupCrawler

PlaywrightCrawler, JavaScript rendering gerektiren siteler için gereklidir. Ancak her site için browser kullanmak aşırıdır. İşte karar verme rehberi:

  • BeautifulSoupCrawler kullanın: Statik HTML, API endpoint'leri, JSON response'lar, SERP tracking, fiyat karşılaştırma sitelerinin API'leri.
  • PlaywrightCrawler kullanın: JavaScript-rendered SPA'lar, login gerektiren siteler, Cloudflare JS challenge'ları, infinite scroll.
  • API kullanın (en iyi seçenek): Hedef sitenin resmi API'si varsa, her zaman API'yi tercih edin. Daha hızlı, daha güvenilir ve yasal olarak daha güvenli.

Browser crawling, proxy bant genişimini 5-10 kat artırır. PlaywrightCrawler ile her sayfa 2-5 MB veri transfer ederken, BeautifulSoupCrawler ile bu 100-500 KB'dir. Bu fark ölçekte önemli bir maliyet etkisi yaratır. Web scraping use case rehberimizde bu konuyu daha detaylı ele aldık.

Etik Scraping İlkeleri

  1. robots.txt'i kontrol edin: /robots.txt dosyası, sitenin hangi bölümlerinin taranabilir olduğunu belirtir. Crawlee, robots.txt kontrolü için yerleşik destek sunar.
  2. Hız limitlerine saygı gösterin: Dakikada 200 istek, çoğu site için makul bir üst sınırdır. max_requests_per_minute ile bunu zorlayın.
  3. Veri minimizasyonu: İhtiyacınız olmayan veriyi toplamayın. GDPR kapsamında kişisel veri toplamak yasal yükümlülükler doğurur.
  4. Resmi API'leri tercih edin: Birçok site (Reddit, Stack Overflow, GitHub) resmi API'ler sunar. Bunlar her zaman scraping'den üstündür.
  5. Halka açık veri: Yalnızca halka açık, erişilebilir verileri toplayın. Login arkasındaki veriler CFAA kapsamında sorunlu olabilir.

SERP tracking için özel use case'leri SERP tracking sayfamızda bulabilirsiniz. ProxyHat'ın sunduğu tüm coğrafi konumları kontrol ederek hedef bölgenize en yakın residential IP'leri seçebilirsiniz.

Önemli Çıkarımlar

Key Takeaways:

  • Crawlee'nin ProxyConfiguration sınıfı, proxy rotasyonunu idiomatik bir şekilde ele alır — new_url(session_id=...) ile sticky sessions, basit liste ile round-robin.
  • SessionPool, proxy IP'lerini cookie'ler ve tarayıcı parmak izleri ile bağlar. Bu, tutarlı bir "kullanıcı" görünümü sağlar.
  • Residential proxy'ler, Cloudflare ve DataDome gibi sistemlerde %85-95 geçme oranı sunarken, datacenter proxy'ler %20-40'da kalır.
  • session.retire() ile bloklanan oturumları kapatın. max_request_retries=3 ile geçici hataları otomatik aşın.
  • BeautifulSoupCrawler'ı statik HTML için, PlaywrightCrawler'ı JS-rendered siteler için kullanın. Mümkünse resmi API'leri tercih edin.
  • ProxyHat'ın username formatı (user-country-US-session-abc123) Crawlee'nin session-bağlı rotasyonu ile doğal olarak uyumludur.

Sıkça Sorulan Sorular

Crawlee for Python'da Proxy Rotation nedir?

Crawlee for Python'da proxy rotation, ProxyConfiguration sınıfı kullanılarak her istek veya oturum için farklı bir proxy IP'si atanması işlemidir. Bu, hedef sitelerin IP tabanlı rate limiting ve bot tespit sistemlerini aşmanıza olanak tanır. Crawlee'nin SessionPool mekanizması ile proxy'leri oturumlara bağlayarak tutarlılık sağlayabilirsiniz — aynı session ID her zaman aynı proxy'yi kullanır.

Crawlee for Python'da proxy rotation neden önemlidir?

Proxy rotation, özellikle Cloudflare ve DataDome gibi gelişmiş bot koruma sistemlerine sahip sitelerde gereklidir. Tek bir IP'den çok sayıda istek göndermek hızlıca engellenmeye yol açar. Residential proxy rotasyonu, gerçek kullanıcı IP'leri üzerinden istek dağıtarak tespit riskini en aza indirir ve uzun süreli scraping operasyonlarını mümkün kılar.

Crawlee for Python'da hangi proxy tipi en iyisidir?

Cloudflare veya DataDome korumalı hedefler için residential proxy'ler en iyi seçenektir çünkü gerçek ISP IP'leri kullanırlar ve tespit edilmesi zordur. Datacenter proxy'ler daha hızlı ve ucuzdur ancak bot tespit sistemleri tarafından kolayca tanınırlar. Hibrit yaklaşımlarda datacenter proxy'ler ilk denemede, residential proxy'ler yedek olarak kullanılabilir.

Crawlee'de blokları nasıl önlersiniz?

Blokları önlemek için session.retire() ile engellenen oturumları kapatın, max_request_retries ile yeniden deneme limitleri koyun, ProxyConfiguration ile residential proxy rotasyonu kullanın ve eşzamanlılık limitlerini hedef sitenin kapasitesine göre ayarlayın. Ayrıca robots.txt dosyalarını saygı ile takip edin ve resmi API'leri tercih edin.

Sık sorulan sorular

Crawlee for Python'da Proxy Rotation nedir?

Crawlee for Python'da proxy rotation, ProxyConfiguration sınıfı kullanılarak her istek veya oturum için farklı bir proxy IP'si atanması işlemidir. Bu, hedef sitelerin IP tabanlı rate limiting ve bot tespit sistemlerini aşmanıza olanak tanır. Crawlee'nin SessionPool mekanizması ile proxy'leri oturumlara bağlayarak tutarlılık sağlayabilirsiniz.

Crawlee for Python'da proxy rotation neden önemlidir?

Proxy rotation, özellikle Cloudflare ve DataDome gibi gelişmiş bot koruma sistemlerine sahip sitelerde gereklidir. Tek bir IP'den çok sayıda istek göndermek hızlıca engellenmeye yol açar. Residential proxy rotasyonu, gerçek kullanıcı IP'leri üzerinden istek dağıtarak tespit riskini en aza indirir ve uzun süreli scraping operasyonlarını mümkün kılar.

Crawlee for Python'da hangi proxy tipi en iyisidir?

Cloudflare veya DataDome korumalı hedefler için residential proxy'ler en iyi seçenektir çünkü gerçek ISP IP'leri kullanırlar ve tespit edilmesi zordur. Datacenter proxy'ler daha hızlı ve ucuzdur ancak bot tespit sistemleri tarafından kolayca tanınırlar. Hibrit yaklaşımlarda datacenter proxy'ler ilk denemede, residential proxy'ler yedek olarak kullanılabilir.

Crawlee'de blokları nasıl önlersiniz?

Blokları önlemek için session.retire() ile engellenen oturumları kapatın, max_request_retries ile yeniden deneme limitleri koyun, ProxyConfiguration ile residential proxy rotasyonu kullanın ve eşzamanlılık limitlerini hedef sitenin kapasitesine göre ayarlayın. Ayrıca robots.txt dosyalarını saygı ile takip edin ve resmi API'leri tercih edin.

Başlamaya hazır mısınız?

148'den fazla ülkede residential, ISP ve mobil proxy'ler. Ücretsiz hesap oluşturun.

Ücretsiz hesap oluştur
← Bloga Dön