Colly'de Döner Proxy Kullanımı: Go ile Üretim Seviyesinde Web Scraping

Go'nun Colly çerçevesinde döner proxy'leri idiomatik şekilde nasıl entegre edeceğinizi öğrenin. Collector modeli, RoundRobinProxySwitcher, residential IP rotasyonu ve üretim desenlerini kapsayan geliştirici odaklı rehber.

Rotating Proxies in Colly: A Framework-Idiomatic Guide for Go Developers
Bu makalede

Go ekosisteminde web scraping yapmak istediğinizde Colly, en hızlı ve en çok benimsenen çerçevelerden biridir. Ancak hedef siteler Cloudflare, PerimeterX veya Datadome gibi anti-bot duvarlarına sahip olduğunda, tek bir IP'den binlerce istek göndermek dakikalar içinde engellenmenize yol açar. İşte Colly'de döner proxy konusunun kritik olduğu nokta burasıdır: Her istekte IP değiştirmek, rate limitlerini aşmak ve engellenmeden ölçeklenmek için temel bir gerekliliktir.

Bu rehber, Colly'nin collector modelini, proxy yüzeyini ve residential IP rotasyonunu üretim seviyesinde nasıl kullanacağınızı adım adım anlatır. Ayrıca ProxyHat'ın gate.proxyhat.com:8080 gateway'i ile nasıl entegre edileceğini gösteren çalıştırılabilir Go örnekleri içerir.

Yasal Uyarı: Bu rehber yalnızca herkese açık verilerin toplanması içindir. CFAA ve GDPR kapsamında, bir sitenin Hizmet Şartları'nı ihlal eden veya kişisel verileri izinsiz toplayan scraping faaliyetleri yasa dışı olabilir. Her zaman robots.txt kurallarına ve sitenin rate limit politikalarına saygı gösterin.

Colly'de Döner Proxy: Temel Mekanizma

Colly, Go'nun net/http paketi üzerine inşa edilmiş, event-driven bir scraping çerçevesidir. Her HTTP isteği bir Collector üzerinden geçer ve proxy'ler SetProxyFunc metodu ile istek seviyesinde enjekte edilir. Bu, her istek için farklı bir çıkış IP'si kullanmanıza olanak tanır.

Colly'nin proxy sistemi iki temel bileşenden oluşur:

  • Built-in RoundRobinProxySwitcher: Verilen proxy listesinde sırayla dolaşır.
  • Custom proxy function: func(*http.Request) (*url.URL, error) imzasına sahip herhangi bir fonksiyon — kendi rotasyon mantığınızı yazmanız için tam esneklik sağlar.

Her iki yaklaşım da HTTP, HTTPS ve SOCKS5 protokollerini destekler. Residential proxy'ler ile birleştiğinde, her istek farklı bir ISP'den geldiği için hedef site IP tabanlı engellemeleri zor uygular.

Colly Collector Modeli ve Callback Mimarisi

Colly'nin çekirdeği Collector struct'ıdır. Bir collector, HTTP isteklerinin yaşam döngüsünü yönetir ve üç ana callback zincirine sahiptir:

  • OnRequest: İstek gönderilmeden önce çağrılır. Header'ları değiştirebilir, proxy'yi ayarlayabilirsiniz.
  • OnHTML: Yanıt alındıktan sonra, goquery tabanlı DOM traversali ile CSS selector'lere göre elementleri yakalar.
  • OnError: İstek başarısız olduğunda çağrılır — retry mantığı burada kurulur.

Colly varsayılan olarak asenkron modda çalışabilir. c.Async = true ayarı ile istekler goroutine'lerde paralel yürütülür. Bu, yüksek throughput gerektiren senaryolarda kritiktir, ancak paylaşılan state yönetimini zorlaştırır. Colly, bunun için sync.Mutex veya channel tabanlı desenler önerir.

goquery, jQuery benzeri bir API sunar ve Colly'nin OnHTML callback'inde *goquery.Selection olarak expose edilir. Bu sayede CSS selector'lerle DOM'da gezinmek, attribute'ları çekmek ve iç içe sorgular yazmak oldukça doğaldır.

Proxy Yüzeyi: RoundRobinProxySwitcher ve Custom Proxy Func

Colly'nin proxy paketi, hazır bir round-robin switcher sunar. Bu switcher, verilen proxy URL listesinde sırayla dolaşır ve her istekte bir sonrakini seçer.

RoundRobinProxySwitcher ile Basit Rotasyon

package main

import (
    "fmt"
    "log"
    "github.com/gocolly/colly/v2"
    "github.com/gocolly/colly/v2/proxy"
)

func main() {
    c := colly.NewCollector()

    // ProxyHat residential proxy URL'leri
    proxies := []*url.URL{
        url.Parse("http://user-country-DE-session-s1:pass@gate.proxyhat.com:8080"),
        url.Parse("http://user-country-US-session-s2:pass@gate.proxyhat.com:8080"),
        url.Parse("http://user-country-GB-session-s3:pass@gate.proxyhat.com:8080"),
    }

    switcher, err := proxy.RoundRobinProxySwitcher(proxies...)
    if err != nil {
        log.Fatal(err)
    }
    c.SetProxyFunc(switcher)

    c.OnHTML("title", func(e *colly.HTMLElement) {
        fmt.Println("Title:", e.Text)
    })

    c.Visit("https://example.com")
}

Custom Proxy Func ile Gelişmiş Rotasyon

Round-robin yeterli olmadığında — örneğin her istekte rastgele bir ülke seçmek veya başarısız proxy'leri geçici olarak devre dışı bırakmak istediğinizde — kendi func(*http.Request) (*url.URL, error) fonksiyonunuzu yazabilirsiniz.

func customProxySwitcher(proxies []*url.URL) colly.ProxyFunc {
    var idx int
    var mu sync.Mutex
    return func(r *http.Request) (*url.URL, error) {
        mu.Lock()
        defer mu.Unlock()
        p := proxies[idx%len(proxies)]
        idx++
        return p, nil
    }
}

Bu desen, IP rotasyonunu tamamen kontrol altına almanızı sağlar. Örneğin, her isteğe benzersiz bir session-ID atayarak sticky session davranışı taklit edebilir veya belirli bir ülke için IP havuzu oluşturabilirsiniz.

Neden Residential IP'ler Gerekli?

Datacenter IP'leri, ASN (Autonomous System Number) bazlı tespit sistemlerinde kolayca flag'lenir. Cloudflare ve benzeri WAF sağlayıcıları, datacenter IP bloklarını bilinen bot trafik kaynakları olarak sınıflandırır. Residential IP'ler ise gerçek ISP'lerden (Deutsche Telekom, Comcast, Vodafone vb.) tahsis edildiği için normal kullanıcı trafiğinden ayırt edilmesi çok daha zordur.

ProxyHat'ın residential proxy servisinde, kullanıcı adı içinde ülke, şehir ve session parametreleri belirtebilirsiniz:

  • user-country-DE:pass — Almanya çıkış IP'si
  • user-country-DE-city-berlin:pass — Berlin şehir seviyesinde hedefleme
  • user-session-abc123:pass — Aynı session ID ile aynı IP'yi koruyun (sticky session)

Bu parametreleri her istekte değiştirerek, coğrafi dağılımı kontrol edebilir ve aynı IP'den çok fazla istek gitmesini engelleyebilirsiniz.

Çalıştırılabilir Go Örneği: Residential Proxy ile Collector

Aşağıdaki örnek, ProxyHat residential proxy'leri ile çalışan, rate limit'li ve paralel istek yapan bir Colly collector'ıdır:

package main

import (
    "fmt"
    "log"
    "math/rand"
    "net/http"
    "net/url"
    "sync"
    "time"

    "github.com/gocolly/colly/v2"
    "github.com/gocolly/colly/v2/proxy"
)

func main() {
    c := colly.NewCollector(
        colly.MaxDepth(2),
        colly.UserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64)"),
    )

    // ProxyHat residential proxy URL listesi
    countries := []string{"DE", "US", "GB", "FR", "JP"}
    var proxies []*url.URL
    for _, cc := range countries {
        u, _ := url.Parse(fmt.Sprintf(
            "http://user-country-%s-session-%d:YOUR_PASSWORD@gate.proxyhat.com:8080",
            cc, rand.Intn(10000),
        ))
        proxies = append(proxies, u)
    }

    switcher, err := proxy.RoundRobinProxySwitcher(proxies...)
    if err != nil {
        log.Fatal(err)
    }
    c.SetProxyFunc(switcher)

    // Rate limiting: paralellik ve gecikme
    c.Limit(&colly.LimitRule{
        DomainGlob:  "*",
        Parallelism: 10,
        Delay:       2 * time.Second,
        RandomDelay: 1 * time.Second,
    })

    var mu sync.Mutex
    var results []string

    c.OnHTML("h1", func(e *colly.HTMLElement) {
        mu.Lock()
        results = append(results, e.Text)
        mu.Unlock()
    })

    c.OnError(func(r *colly.Response, err error) {
        log.Printf("Hata: %s — status: %d", err, r.StatusCode)
    })

    targets := []string{
        "https://example.com",
        "https://example.org",
        "https://example.net",
    }

    for _, t := range targets {
        c.Visit(t)
    }

    c.Wait() // Asenkron modda tüm goroutine'lerin bitmesini bekle

    for _, r := range results {
        fmt.Println("Bulundu:", r)
    }
}

Bu örnekte dikkat edilmesi gereken noktalar:

  • Parallelism: 10 — Aynı anda en fazla 10 istek yürütülür.
  • Delay + RandomDelay — Her istek arasında 2 saniye sabit + 0–1 saniye rastgele gecikme eklenir. Bu, trafiğin bot benzeri düzgünlüğünü kırar.
  • Session ID — Her ülke için rastgele bir session ID üretilir, böylece aynı IP tekrar tekrar kullanılmaz.

Üretim Desenleri: Retry, Clone, Transport ve Dağıtık Scraping

Retry Mantığı: c.Clone() ile Yeniden Deneme

Colly'de retry yapmak için OnError callback'inde c.Clone() kullanarak collector'ın bir kopyasını oluşturabilir ve aynı URL'i tekrar ziyaret edebilirsiniz. Clone, proxy ayarlarını ve callback'leri kopyalar, ancak shared state'i kopyalamaz.

retryCount := make(map[string]int)
var retryMu sync.Mutex

maxRetries := 3

c.OnError(func(r *colly.Response, err error) {
    retryMu.Lock()
    n := retryCount[r.Request.URL.String()]
    retryCount[r.Request.URL.String()] = n + 1
    retryMu.Unlock()

    if n < maxRetries {
        time.Sleep(time.Duration(n+1) * 2 * time.Second) // Exponential backoff
        r.Request.Retry()
    }
})

Custom Transport ile TLS Fingerprint Yönetimi

Bazı anti-bot sistemleri TLS handshake fingerprint'ini kontrol eder. Colly, varsayılan http.Transport'ı özelleştirmenize olanak tanır:

c.WithTransport(&http.Transport{
    TLSClientConfig: &tls.Config{
        InsecureSkipVerify: false,
        MinVersion:         tls.VersionTLS12,
        CipherSuites: []uint16{
            tls.TLS_AES_128_GCM_SHA256,
            tls.TLS_AES_256_GCM_SHA384,
            tls.TLS_CHACHA20_POLY1305_SHA256,
        },
    },
    MaxIdleConns:        100,
    IdleConnTimeout:     90 * time.Second,
    DisableCompression:  false,
})

Dağıtık Scraping: Redis Storage Backend

Tek bir makine 500–1000 RPS'i geçtiğinde bottleneck olur. Colly, ziyaret edilen URL'leri paylaşmak için Redis ve SQLite storage backend'leri sunar. Birden fazla Colly instance'ı aynı Redis'e bağlanarak URL queue'yu paylaşabilir ve duplicate ziyaretleri önleyebilir.

storage := &storage.Redis{
    Address:  "redis://localhost:6379",
    Prefix:   "colly_scraper_",
}
c.SetStorage(storage)

Bu desen, Kubernetes pod'ları veya Docker container'ları arasında yatay ölçeklenme sağlar. Her pod, Redis'ten bir URL alır, işler ve sonucu ortak bir depoya yazar. ProxyHat'ın proxy lokasyonları ile birleştiğinde, her pod farklı bir bölgeden trafik gönderebilir.

Proxy Tipleri Karşılaştırması

Özellik Datacenter Proxy Residential Proxy Mobile Proxy
Tespit Zorluğu Düşük (ASN tespiti kolay) Yüksek (gerçek ISP) Çok Yüksek
Hız / Latency ~50ms ~200–500ms ~300–800ms
Fiyat (yaklaşık) $0.50/GB $2–5/GB $5–15/GB
Anti-bot Bypass Düşük başarı oranı %90+ başarı %95+ başarı
Uygun Senaryo API scraping, basit siteler SERP, e-ticaret, sosyal medya Sosyal medya, sıkı anti-bot

Colly Ne Zaman Kullanılmamalı?

Colly, HTTP istek-yanıt modeline dayanır. Eğer hedef site bir JavaScript SPA'sı ise (React, Vue, Angular) ve içerik client-side rendering ile geliyorsa, Colly'nin OnHTML callback'i boş bir DOM görecektir. Bu durumda chromedp veya Playwright gibi headless browser çözümleri daha uygundur.

Yine de Colly, headless browser fleet'leri ile birlikte kullanılabilir: Colly URL keşfi ve queue yönetimi için, chromedp ise rendering için. Bu hibrit yaklaşım, hem hız hem de rendering kapasitesi sağlar.

Etik ve Yasal Hususlar

  • Yalnızca herkese açık verileri toplayın. Login arkasındaki verilere erişmek CFAA ihlali olabilir.
  • robots.txt dosyasını kontrol edin ve Disallow kurallarına uyun.
  • GDPR kapsamında, AB vatandaşlarına ait kişisel verileri izinsiz toplamak ağır para cezalarına yol açabilir (en fazla €20 milyon veya global cironın %4'ü).
  • Rate limitlere saygı gösterin — saniyede 100 istek göndermek bir siteyi DoS'a uğratabilir.

Key Takeaways

  • Colly'de döner proxy, SetProxyFunc ile istek seviyesinde uygulanır; RoundRobinProxySwitcher veya custom func(*http.Request) (*url.URL, error) kullanılabilir.
  • Residential proxy'ler, datacenter IP'lerine göre %90+ daha yüksek başarı oranı sunar ve anti-bot sistemlerinde tespit edilmesi çok daha zordur.
  • ProxyHat kullanıcı adında -country-DE-city-berlin ve -session-abc123 parametreleri ile her isteği coğrafi olarak yönlendirebilirsiniz.
  • Limit() kuralları ile Parallelism ve RandomDelay ayarlamak, bot tespitini zorlaştırır.
  • Dağıtık scraping için Redis storage backend kullanın ve birden fazla pod/container arasında URL queue paylaşın.
  • JS-heavy SPA'ler için Colly tek başına yeterli değildir; chromedp ile hibrit bir yaklaşım düşünün.

ProxyHat'ın residential proxy servisi ile Colly entegrasyonu hakkında daha fazla bilgi için fiyatlandırma sayfamızı inceleyin veya web scraping kullanım senaryolarımıza göz atın. SERP takibi için özel çözümlerimizi SERP tracking sayfamızda bulabilirsiniz. Teknik dokümantasyon için ProxyHat Docs adresini ziyaret edin.

Sık sorulan sorular

Colly'de döner proxy nedir?

Colly'de döner proxy, her HTTP isteğinin farklı bir çıkış IP'sinden gönderilmesini sağlayan bir tekniktir. Colly'nin SetProxyFunc metodu ile bir proxy switcher fonksiyonu kaydedilir ve her istekte bu fonksiyon çağrılarak yeni bir proxy URL döndürülür. RoundRobinProxySwitcher hazır bir çözüm sunarken, custom func(*http.Request) (*url.URL, error) ile kendi rotasyon mantığınızı yazabilirsiniz. Bu, tek IP'den binlerce istek göndererek IP tabanlı engellemeye takılmayı önler.

Colly'de döner proxy neden önemlidir?

Colly'de döner proxy, hedef sitenin anti-bot sistemleri tarafından IP tabanlı engellenmeyi önlemek için kritiktir. Tek bir IP'den saniyede yüzlerce istek göndermek, Cloudflare veya Datadome gibi WAF'ler tarafından dakikalar içinde tespit edilir. Her istekte IP değiştirmek, trafiğin normal kullanıcı dağılımına benzemesini sağlar ve başarı oranını datacenter proxy'lere göre %90+ artırabilir. Özellikle SERP scraping ve e-ticaret fiyat monitoring gibi yüksek hacimli senaryolarda zorunludur.

Colly'de döner proxy için hangi proxy tipi en iyisidir?

Colly'de döner proxy için residential proxy'ler en iyi sonucu verir. Datacenter IP'leri ASN bazlı tespit sistemlerinde kolayca flag'lendiği için anti-bot duvarları tarafından hızla engellenir. Residential IP'ler ise Deutsche Telekom, Comcast gibi gerçek ISP'lerden tahsis edildiği için normal kullanıcı trafiğinden ayırt edilmesi çok daha zordur. Mobile proxy'ler de çok yüksek başarı oranı sunar ancak maliyetleri daha yüksektir. ProxyHat'ın residential servisinde kullanıcı adında ülke ve session parametreleri ile her isteği ayrı bir IP'den gönderebilirsiniz.

Colly ile scraping yaparken engellenmemek için ne yapmalı?

Colly ile engellenmemek için birkaç önlem alın: Her istekte residential proxy ile IP değiştirin, Parallelism'i 10–20 civarında tutun, Delay ve RandomDelay ile istekler arasına 1–3 saniye gecikme ekleyin, gerçekçi User-Agent header'ları kullanın, ve retry mantığını exponential backoff ile kurun. Ayrıca robots.txt kurallarına uyun ve tek siteden saniyede 50'den fazla istek göndermekten kaçının. ProxyHat'ın session parametresi ile sticky session kullanarak aynı domain için tutarlı IP kullanabilirsiniz.

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