Rotierende Proxies in Colly: Ein Go-Entwickler-Leitfaden für Proxy-Rotation

Praktischer Leitfaden zur Integration rotierender Proxys in Colly mit ProxyHat: RoundRobinProxySwitcher, benutzerdefinierte Proxy-Funktionen, Residential IPs, Retries und Produktionsmuster für verteiltes Scraping.

Rotating Proxies in Colly: A Framework-Idiomatic Guide for Go Developers
In diesem Artikel

Rotierende Proxys in Colly: Warum und wie Go-Entwickler sie einsetzen

Wenn Sie mit Colly, dem beliebten Go-Web-Scraping-Framework, hochvolumige Datenextraktion betreiben, stoßen Sie unweigerlich auf IP-basierte Ratenlimits und Anti-Bot-Systeme. Rotierende Proxys in Colly sind die idiomatische Antwort: Anstatt Tausende Requests von einer einzigen IP zu senden, verteilen Sie die Last über ein Pool von Residential- oder Datacenter-IPs. Dieser Leitfaden zeigt, wie Sie Collys Erweiterungspunkte — SetProxyFunc, RoundRobinProxySwitcher, Limit() und Storage-Backends — korrekt nutzen, um einen produktionsreifen Scraper mit ProxyHat-Residential-Proxys zu bauen.

Bevor wir in den Code einsteigen, ein rechtlicher Hinweis: Scraping öffentlich zugänglicher Daten ist in vielen Jurisdiktionen zulässig, aber Sie müssen robots.txt respektieren, die Nutzungsbedingungen (ToS) der Zielseite prüfen und bei personenbezogenen Daten die DSGVO beachten. In den USA kann unbefugter Zugriff nach dem Computer Fraud and Abuse Act (CFAA) strafbar sein. Dieser Artikel behandelt ausschließlich öffentlich verfügbare Daten und ethisches Scraping-Verhalten.

Collys Collector-Modell: Callbacks, Async und goquery

Colly basiert auf einem Collector-Objekt, das HTTP-Requests ausführt und über Callbacks DOM-Elemente an Handler weitergibt. Die Kern-Callbacks sind:

  • OnRequest(func(*colly.Request)) — wird vor jedem Request aufgerufen; ideal zum Setzen von Headern oder zur Proxy-Auswahl.
  • OnHTML(goquerySelector, func(*colly.HTMLElement)) — feuert, wenn ein CSS-Selektor matcht; das HTMLElement wrappt goquery für DOM-Traversierung.
  • OnError(func(*colly.Response, error)) — wird bei HTTP-Fehlern oder Parse-Fehlern aufgerufen; hier setzen Sie Retry-Logik an.
  • OnResponse(func(*colly.Response)) — feuert nach jeder erfolgreichen Response, vor OnHTML.

Im asynchronen Modus (c.Async = true) führt Colly Requests parallel aus, was den Durchsatz drastisch erhöht — aber nur, wenn Ihr Proxy-Pool groß genug ist. Mit c.Limit() steuern Sie Parallelität und Verzögerung, was für Proxy-Rotation essenziell ist.

Grundlegendes Collector-Setup

package main

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

func main() {
    c := colly.NewCollector(
        colly.UserAgent("Mozilla/5.0 (compatible; ResearchBot/1.0)"),
        colly.MaxDepth(2),
    )

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

    c.OnError(func(r *colly.Response, err error) {
        log.Printf("Fehler bei %s: %v", r.Request.URL, err)
    })

    c.OnRequest(func(r *colly.Request) {
        log.Println("Visiting:", r.URL.String())
    })

    if err := c.Visit("https://example.com"); err != nil {
        log.Fatal(err)
    }
}

Die idiomatische Proxy-Schnittstelle: SetProxyFunc und RoundRobinProxySwitcher

Colly bietet zwei Wege, Proxys zu konfigurieren. Der einfache Weg ist c.SetProxy(urlString) für einen statischen Proxy. Für Rotation nutzen Sie c.SetProxyFunc(func(*http.Request) (*url.URL, error)) — eine Funktion, die für jeden Request dynamisch eine Proxy-URL zurückgibt. Colly liefert mit proxy.RoundRobinProxySwitcher eine fertige Implementierung, die Round-Robin über eine Liste von Proxy-URLs macht.

RoundRobinProxySwitcher mit ProxyHat

Die einfachste Form der Rotation: Sie übergeben mehrere ProxyHat-URLs mit verschiedenen Session-IDs an den Switcher. Jeder Request nutzt automatisch die nächste URL.

package main

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

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

    // ProxyHat Residential Proxys mit verschiedenen Sessions
    proxies := []*url.URL{
        // Format: http://user-session-abc123:pass@gate.proxyhat.com:8080
        mustParse("http://user-session-sess01:pass@gate.proxyhat.com:8080"),
        mustParse("http://user-session-sess02:pass@gate.proxyhat.com:8080"),
        mustParse("http://user-session-sess03:pass@gate.proxyhat.com:8080"),
        mustParse("http://user-session-sess04:pass@gate.proxyhat.com:8080"),
        mustParse("http://user-session-sess05:pass@gate.proxyhat.com:8080"),
    }

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

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

    c.Visit("https://httpbin.org/ip")
}

func mustParse(raw string) *url.URL {
    u, err := url.Parse(raw)
    if err != nil {
        panic(err)
    }
    return u
}

Benutzerdefinierte Proxy-Funktion: Geo-Targeting pro Request

Für fortgeschrittene Szenarien — etwa Geo-Targeting pro Request oder Sticky Sessions mit deterministischer Zuordnung — schreiben Sie eine eigene func(*http.Request) (*url.URL, error). Hier rotieren wir Land und Stadt im Benutzernamen:

package main

import (
    "math/rand"
    "net/http"
    "net/url"
    "sync"
    "github.com/gocolly/colly/v2"
)

var (
    countries = []string{"DE", "US", "GB", "FR", "IT"}
    cities    = map[string][]string{
        "DE": {"berlin", "munchen", "hamburg"},
        "US": {"new-york", "chicago", "los-angeles"},
        "GB": {"london", "manchester", "birmingham"},
        "FR": {"paris", "lyon", "marseille"},
        "IT": {"rome", "milan", "naples"},
    }
    counter int
    mu      sync.Mutex
)

func geoProxyFunc(r *http.Request) (*url.URL, error) {
    mu.Lock()
    country := countries[counter%len(countries)]
    citySlice := cities[country]
    city := citySlice[counter%len(citySlice)]
    sessionID := fmt.Sprintf("sess-%d", counter)
    counter++
    mu.Unlock()

    // Username-Format: user-country-DE-city-berlin-session-sess-42
    raw := fmt.Sprintf(
        "http://user-country-%s-city-%s-session-%s:pass@gate.proxyhat.com:8080",
        country, city, sessionID,
    )
    return url.Parse(raw)
}

func main() {
    c := colly.NewCollector(
        colly.MaxDepth(3),
    )
    c.SetProxyFunc(geoProxyFunc)

    c.Limit(&colly.LimitRule{
        DomainGlob:  "*",
        Parallelism: 20,
        Delay:       500 * time.Millisecond,
    })

    c.OnHTML("h1", func(e *colly.HTMLElement) {
        log.Printf("[%s] %s", e.Request.Ctx.Get("proxy_country"), e.Text)
    })

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

Warum Residential IPs für harte Ziele nötig sind

Datacenter-IPs sind leicht zu erkennen: Cloud-Provider wie AWS, Google Cloud und Hetzner veröffentlichen ihre IP-Blöcke in öffentlichen Datenbanken. Anti-Bot-Dienste wie Cloudflare, PerimeterX und Akamai blockieren Datacenter-IPs oft bereits auf Netzwerkebene, bevor überhaupt ein HTTP-Statuscode zurückkommt. Residential Proxys verwenden IPs, die echten ISPs zugewiesen sind — sie erscheinen als normale Haushaltsverbindungen und haben eine deutlich höhere Success-Rate bei harten Zielen.

Typische Erfolgsraten bei stark geschützten Seiten liegen bei Datacenter-Proxys unter 10%, während Residential Proxys 80–95% erreichen, abhängig von Rotationsstrategie und Request-Kadenz. ProxyHat bietet Residential Proxys mit Geo-Targeting auf Länder- und Stadtebene über Username-Flags:

  • user-country-DE:pass — beliebige deutsche IP
  • user-country-DE-city-berlin:pass — IP aus Berlin
  • user-session-abc123:pass — Sticky Session, gleiche IP für die Lebensdauer der Session

Kombinieren Sie Geo-Targeting und Sessions: user-country-DE-city-berlin-session-abc123:pass hält eine Berliner IP für alle Requests derselben Session stabil. Das ist wichtig für Login-Flows oder mehrstufige Formulare.

SOCKS5 als Alternative

Für Ziele, die HTTP-Proxy-Header inspizieren oder SOCKS5 bevorzugen, nutzt ProxyHat Port 1080:

proxies := []*url.URL{
    mustParse("socks5://user-session-s1:pass@gate.proxyhat.com:1080"),
    mustParse("socks5://user-session-s2:pass@gate.proxyhat.com:1080"),
    mustParse("socks5://user-session-s3:pass@gate.proxyhat.com:1080"),
}
rp, _ := proxy.RoundRobinProxySwitcher(proxies...)
c.SetProxyFunc(rp)

Beachten Sie, dass SOCKS5 einen leicht höheren Overhead hat als HTTP-CONNECT — typischerweise 10–30 ms zusätzliche Latenz pro Request. Messen Sie beide Varianten gegen Ihr Ziel.

Produktionsmuster: Retries, Delay, TLS und verteiltes Scraping

Ein produktiver Scraper muss mit transienten Fehlern umgehen, Rate-Limits respektieren und über mehrere Instanzen skalieren. Hier sind die wichtigsten Muster.

Retries mit c.Clone()

Collys OnError-Callback ist der richtige Ort für Retry-Logik. Verwenden Sie c.Clone(), um einen unabhängigen Sub-Collector zu erzeugen, der denselben Proxy und dieselben Callbacks erbt, aber eigene Zähler führt:

c.OnError(func(r *colly.Response, err error) {
    if r.StatusCode == 429 || r.StatusCode == 503 {
        retry := r.Request.Ctx.GetInt("retry")
        if retry < 3 {
            r.Request.Ctx.Put("retry", retry+1)
            time.Sleep(time.Duration(retry+1) * 2 * time.Second)
            r.Request.Retry()
        }
    }
})

Die exponentielle Backoff-Strategie (2s, 4s, 6s) verhindert, dass Sie bei einem temporären Block noch aggressiver werden und die IP dauerhaft sperren.

Limit-Regeln: Parallelism und RandomDelay

Collys Limit() akzeptiert mehrere Regeln pro Domain. Kombinieren Sie Parallelism mit RandomDelay, um natürliches Verkehrsverhalten zu simulieren:

c.Limit(&colly.LimitRule{
    DomainGlob:  "*.example.com",
    Parallelism: 10,
    Delay:       1 * time.Second,
    RandomDelay: 500 * time.Millisecond,
})

Mit RandomDelay wird jeder Request zusätzlich um 0–500 ms zufällig verzögert. Für harte Ziele sollten Sie nicht mehr als 5–10 gleichzeitige Requests pro Domain senden.

Custom Transport: TLS-Fingerprint und Timeouts

Colly erlaubt den Zugriff auf den zugrundeliegenden http.Transport über c.WithTransport(t). Das ist nützlich für Custom-TLS-Konfiguration und aggressive Timeouts:

c.WithTransport(&http.Transport{
    TLSClientConfig: &tls.Config{
        InsecureSkipVerify: false,
        MinVersion:         tls.VersionTLS12,
    },
    DialContext: (&net.Dialer{
        Timeout:   10 * time.Second,
        KeepAlive: 30 * time.Second,
    }).DialContext,
    MaxIdleConns:        100,
    IdleConnTimeout:     90 * time.Second,
    TLSHandshakeTimeout: 10 * time.Second,
})

Verteiltes Scraping mit Redis-Storage

Für Multi-Instance-Setups nutzt Colly Storage-Backends. Der Redis-Storage teilt besuchte URLs und Cookies über mehrere Prozesse hinweg — ideal für Container-Fleets:

import "github.com/gocolly/redisstorage"

storage := &redisstorage.Storage{
    Address:  "redis:6379",
    Password: "",
    DB:       0,
    Prefix:   "scraper",
}
c.SetStorage(storage)
defer storage.Client.Close()

Mit Redis als Storage können Sie 5–20 Colly-Instanzen parallel betreiben, ohne URLs doppelt zu besuchen. Die visited-URL-Set wird atomar über SETNX verwaltet.

Vergleich: Proxy-Typen für Colly

Eigenschaft Datacenter Residential Mobile
Success-Rate bei harten Zielen 10–30% 80–95% 90–99%
Latenz 50–200 ms 200–800 ms 500–2000 ms
Preis (pro GB) ~$0,50–1 ~$3–8 ~$15–30
Erkennungsrisiko Hoch Niedrig Sehr niedrig
Einsatz in Colly Einfache Ziele, Tests Produktion, SERP-Scraping Mobile-App-APIs, hartnäckige Blocks

Wann Colly NICHT die richtige Wahl ist

Colly ist ein HTTP-Client-Scraper — er führt kein JavaScript aus. Wenn Ihr Ziel eine Single-Page-Application (React, Vue, Angular) ist, die Inhalte erst clientseitig rendert, sehen Sie nur eine leere HTML-Hülle. In diesem Fall benötigen Sie einen Headless-Browser wie chromedp oder Playwright für Go. Kombinieren Sie dann den Browser mit ProxyHat über Chrome's --proxy-server-Flag:

chromedp.Run(ctx,
    chromedp.Navigate("about:blank"),
    // Proxy wird beim Browser-Kontext gesetzt
)
// --proxy-server=http://user-country-DE:pass@gate.proxyhat.com:8080

Für reine HTML-Seiten, APIs und JSON-Endpoints ist Colly jedoch die schnellere und ressourceneffizientere Wahl — ein Colly-Prozess verbraucht typischerweise unter 50 MB RAM und kann 500–1000 Requests pro Sekunde verarbeiten.

ProxyHat-spezifisches Setup

ProxyHat-Residential-Proxys sind über einen einzigen Gateway-Endpunkt erreichbar. Alle Konfiguration — Geo-Targeting, Sessions, Rotation — erfolgt über den Benutzernamen. Hier die wichtigsten Formate:

  • HTTP (Standard): http://USERNAME:PASSWORD@gate.proxyhat.com:8080
  • SOCKS5: socks5://USERNAME:PASSWORD@gate.proxyhat.com:1080
  • Geo-Targeting: user-country-DE-city-berlin:pass@gate.proxyhat.com:8080
  • Sticky Session: user-session-abc123:pass@gate.proxyhat.com:8080

Weitere Details finden Sie in der ProxyHat-Dokumentation. Aktuelle Preise und verfügbare Standorte finden Sie auf der ProxyHat-Preisseite und der Locations-Seite.

Praktische Use Cases

Rotierende Proxys in Colly eignen sich besonders für:

  • SERP-Tracking — Google-Ergebnisse über mehrere Länder hinweg erfassen, ohne CAPTCHAs auszulösen.
  • Web-Scraping im großen Maßstab — E-Commerce-Preisüberwachung über Tausende Produktseiten.
  • Social-Media-Recherche — öffentliche Posts und Metadaten sammeln, ohne Account-Sperren zu riskieren.
  • KI-Trainingsdaten-Sammlung — große Korpora aus öffentlichen Quellen aggregieren.

Key Takeaways

  • SetProxyFunc ist der idiomatische Weg — nutzen Sie proxy.RoundRobinProxySwitcher für einfache Rotation oder eine eigene func(*http.Request) (*url.URL, error) für Geo-Targeting pro Request.
  • Residential Proxys sind Pflicht für harte Ziele — Datacenter-IPs werden von Cloudflare & Co. oft direkt blockiert. ProxyHat-Residential-IPs erreichen 80–95% Success-Rate.
  • Geo-Targeting über Username-Flags-country-DE-city-berlin und -session-abc123 in der Username-Zeile steuern Standort und Sticky-Sessions.
  • Limit-Regeln setzenParallelism auf 5–20, RandomDelay 200–500 ms, um natürliches Verhalten zu simulieren.
  • Redis-Storage für verteiltes Scraping — mehrere Colly-Instanzen teilen sich besuchte URLs über Redis, doppelte Requests werden vermieden.
  • Colly ist kein Browser — für JS-Heavy-SPAs nutzen Sie chromedp oder Playwright mit ProxyHat als --proxy-server.

Häufig gestellte Fragen (FAQ)

Was sind rotierende Proxys in Colly?

Rotierende Proxys in Colly bedeuten, dass jeder HTTP-Request über eine andere Proxy-IP gesendet wird. Colly bietet dafür SetProxyFunc und den vorgefertigten RoundRobinProxySwitcher, der Round-Robin über eine Liste von Proxy-URLs macht. Mit ProxyHat können Sie Rotation über verschiedene Session-IDs im Benutzernamen steuern.

Warum sind rotierende Proxys in Colly wichtig?

Ohne Rotation senden Sie alle Requests von einer IP und erreichen schnell Ratenlimits oder werden geblockt. Mit rotierenden Residential-Proxys verteilen Sie die Last auf hunderte IPs, was die Success-Rate bei geschützten Zielen von unter 30% auf über 80% erhöht. Das ist besonders wichtig für SERP-Scraping und Preisüberwachung.

Welcher Proxy-Typ funktioniert am besten für rotierende Proxys in Colly?

Residential Proxys sind die beste Wahl für harte Ziele, da sie echte ISP-IPs verwenden und von Anti-Bot-Systemen schwerer zu erkennen sind. Datacenter-Proxys sind günstiger, werden aber häufig blockiert. Mobile Proxys bieten die höchste Success-Rate, sind jedoch teurer und langsamer. Für die meisten Colly-Anwendungen sind Residential Proxys der beste Kompromiss.

Wie vermeide ich Blocks bei der Implementierung rotierender Proxys in Colly?

Nutzen Sie Residential Proxys mit Geo-Targeting, setzen Sie Limit()-Regeln mit Parallelism von 5–20 und RandomDelay von 200–500 ms. Implementieren Sie Retry-Logik mit exponentiellem Backoff in OnError. Rotieren Sie Session-IDs pro Request, um IP-Wiederholungen zu vermeiden, und respektieren Sie robots.txt und die Rate-Limits der Zielseite.

Kann ich SOCKS5-Proxys in Colly verwenden?

Ja, Colly unterstützt SOCKS5-Proxys über das socks5://-URL-Schema. Bei ProxyHat verwenden Sie Port 1080 statt 8080: socks5://user-session-abc123:pass@gate.proxyhat.com:1080. Beachten Sie, dass SOCKS5 typischerweise 10–30 ms zusätzliche Latenz pro Request verursacht.

Häufig gestellte Fragen

Was sind rotierende Proxys in Colly?

Rotierende Proxys in Colly bedeuten, dass jeder HTTP-Request über eine andere Proxy-IP gesendet wird. Colly bietet dafür SetProxyFunc und den vorgefertigten RoundRobinProxySwitcher, der Round-Robin über eine Liste von Proxy-URLs macht. Mit ProxyHat können Sie Rotation über verschiedene Session-IDs im Benutzernamen steuern.

Warum sind rotierende Proxys in Colly wichtig?

Ohne Rotation senden Sie alle Requests von einer IP und erreichen schnell Ratenlimits oder werden geblockt. Mit rotierenden Residential-Proxys verteilen Sie die Last auf hunderte IPs, was die Success-Rate bei geschützten Zielen von unter 30% auf über 80% erhöht. Das ist besonders wichtig für SERP-Scraping und Preisüberwachung.

Welcher Proxy-Typ funktioniert am besten für rotierende Proxys in Colly?

Residential Proxys sind die beste Wahl für harte Ziele, da sie echte ISP-IPs verwenden und von Anti-Bot-Systemen schwerer zu erkennen sind. Datacenter-Proxys sind günstiger, werden aber häufig blockiert. Mobile Proxys bieten die höchste Success-Rate, sind jedoch teurer und langsamer. Für die meisten Colly-Anwendungen sind Residential Proxys der beste Kompromiss.

Wie vermeide ich Blocks bei der Implementierung rotierender Proxys in Colly?

Nutzen Sie Residential Proxys mit Geo-Targeting, setzen Sie Limit()-Regeln mit Parallelism von 5–20 und RandomDelay von 200–500 ms. Implementieren Sie Retry-Logik mit exponentiellem Backoff in OnError. Rotieren Sie Session-IDs pro Request, um IP-Wiederholungen zu vermeiden, und respektieren Sie robots.txt und die Rate-Limits der Zielseite.

Kann ich SOCKS5-Proxys in Colly verwenden?

Ja, Colly unterstützt SOCKS5-Proxys über das socks5://-URL-Schema. Bei ProxyHat verwenden Sie Port 1080 statt 8080: socks5://user-session-abc123:pass@gate.proxyhat.com:1080. Beachten Sie, dass SOCKS5 typischerweise 10–30 ms zusätzliche Latenz pro Request verursacht.

Bereit loszulegen?

Residential-, ISP- und Mobile-Proxys in über 148 Ländern. Erstelle ein kostenloses Konto.

Kostenloses Konto erstellen
← Zurück zum Blog