brainstorming
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or planning anything new, in software or out of it (a talk, a business, a renovation).
rotate-scraping-proxiesBlockierte Scraping-Kampagnen durch anbieterneutrale Proxy-Rotation eskalieren — zwischen Rechenzentrums-, Residential- und Mobile-Pools entscheiden, Rotation in scrapling integrieren, Sitzungs-Stickiness für zustandsbehaftete Abläufe konfigurieren, Kosten und Zustand überwachen und innerhalb rechtlicher und ethischer Grenzen bleiben. Als nächster Schritt e…
Independent GitHub snapshot · Automated classification · Original documentation governs
headless-web-scraping
(StealthyFetcher, Ratenbegrenzung, robots.txt) nicht ausreicht und der
Datenverkehr legitim ist.
license: MIT
allowed-tools: Bash Read Write Grep Glob
metadata:
author: Philipp Thoss
version: "1.0"
domain: web-scraping
complexity: intermediate
language: Python
tags: web-scraping, proxies, rotation, residential, scrapling, networking
locale: de
source_locale: en
source_commit: 75ded7a1
translator: "Claude + human review"
translation_date: "2026-04-14"Eskalation auf Netzwerkebene für Scraping-Kampagnen, bei denen die clientseitige Tarnung bereits ausgeschöpft ist. Proxy-Rotation ist ein letztes Mittel, keine Standardlösung — sie ist teuer, ethisch aufgeladen und leicht missbrauchbar. Dieser Skill lehrt ebenso, wann er nicht einzusetzen ist, wie er richtig anzuwenden ist.
headless-web-scraping (Fetcher → StealthyFetcher → DynamicFetcher) wurde
bereits versucht und das Ziel liefert weiterhin 403/429/Geo-Blocksrobots.txt erlaubt den Pfadpython-requests)Nicht verwenden, wenn: eine öffentliche API existiert (dann diese nutzen), die AGB der Website automatisierten Zugriff verbieten, Sie Geo-Lizenzierung umgehen würden oder das Ziel Betrug / Credential Stuffing / Sneaker-Bots / Content-Piraterie ist.
Machen Sie den gesamten Arbeitsablauf von einer dokumentierten rechtlichen und ethischen Prüfung abhängig. Das Überspringen dieses Schritts ist die mit Abstand größte Schadensquelle.
Vor dem Schreiben jeglichen Codes zu bestätigende Eingaben:
Expected: Jede Frage hat eine verteidigungsfähige schriftliche Antwort. Das erste „Nein" oder „Unbekannt" stoppt das Vorgehen, bis es geklärt ist.
On failure:
Unterschiedliche Pool-Typen haben unterschiedliche Kosten-, Erkennbarkeits- und Ethikprofile. Wählen Sie die günstigste Stufe, die Ihre Blockade tatsächlich löst.
| Pool-Typ | Erkennbarkeit | Kosten | Geeignet für |
|---|---|---|---|
| Datacenter | Hoch (leicht durch Cloudflare/Akamai blockiert) | $ | Websites ohne echten Anti-Bot-Schutz, nur für Geo-Verlagerung |
| Residential | Niedrig (echte ISP-IPs) | $$ | Websites, die Rechenzentrums-ASNs blockieren |
| Mobile | Sehr niedrig (Carrier-Grade NAT, mit Tausenden geteilt) | $$ | Websites, die sogar Residential blockieren (selten) |
Ethischer Vorbehalt für Residential und Mobile: Diese Pools leiten Ihren Datenverkehr durch echte Privatanschlüsse. Das Einwilligungsmodell der Pool-Betreiber variiert — einige bezahlen Nutzer, andere bündeln die Exit-Node-Zustimmung in AGB von „kostenlosen VPNs", die Nutzer nicht lesen. Bevorzugen Sie Anbieter mit auditierter, explizit erteilter Einwilligung (Opt-in). Wenn Sie selbst nicht möchten, dass ein Fremder Scraping-Traffic durch Ihren Heimrouter schickt, dann schicken Sie Ihren auch nicht durch deren.
Expected: Eine dokumentierte Auswahl der günstigsten tragfähigen Stufe mit einer kurzen Begründung, warum höhere Stufen abgelehnt wurden (oder warum eine höhere Stufe nötig ist).
On failure:
Verdrahten Sie den Proxy mit den scrapling-Fetchern. Lesen Sie Zugangsdaten
aus Umgebungsvariablen — niemals fest einkodieren, niemals eine .env in
Git einchecken.
import os
import random
from scrapling import Fetcher, StealthyFetcher
# Pattern A: provider-managed rotating endpoint (one URL, provider rotates per request)
PROXY_URL = os.environ["SCRAPING_PROXY_URL"] # http://user:pass@gateway.example:7777
fetcher = StealthyFetcher()
fetcher.configure(
headless=True,
timeout=60,
network_idle=True,
proxy=PROXY_URL,
)
# Pattern B: explicit pool, rotate yourself
POOL = os.environ["SCRAPING_PROXY_POOL"].split(",") # comma-separated URLs
def fetch_with_rotation(url):
proxy = random.choice(POOL)
fetcher = StealthyFetcher()
fetcher.configure(headless=True, timeout=60, proxy=proxy)
return fetcher.get(url)
Expected: Anfragen gelingen und die Ausgangs-IP variiert zwischen den
Aufrufen. Bestätigen Sie dies, indem Sie vor dem eigentlichen Scrape einen
IP-Echo-Endpoint (z. B. https://api.ipify.org) aufrufen.
On failure:
407 Proxy Authentication Required — Zugangsdaten sind falsch oder die
URL-Kodierung des Passworts ist defekt (Sonderzeichen neu kodieren)-rotating- oder Pro-Anfrage-
Flag prüfenEntscheiden Sie die Rotations-Granularität je nach Arbeitslast und halten Sie den Pool dann gesund.
# Sticky session for stateful flows (login, multi-page checkout-like crawls)
# Most providers expose a session ID via the username:
# user-session-abc123:pass@gateway.example:7777
# All requests with the same session ID exit through the same IP for ~10 min.
# Per-request rotation for anonymous bulk scraping (default)
# Pool health check — call before bulk run
def check_pool(pool, sample_size=5):
sample = random.sample(pool, min(sample_size, len(pool)))
alive = []
for proxy in sample:
try:
r = StealthyFetcher().configure(proxy=proxy, timeout=10).get(
"https://api.ipify.org"
)
if r.status == 200:
alive.append(proxy)
except Exception:
pass
return alive
# Backoff on transient proxy failures
def fetch_with_backoff(url, max_attempts=3):
for attempt in range(max_attempts):
try:
r = fetch_with_rotation(url)
if r.status not in (407, 502, 503):
return r
except Exception:
pass
time.sleep(2 ** attempt)
return None
Expected: Zustandsbehaftete Abläufe behalten Cookies über Anfragen hinweg; anonymes Massen-Scraping zeigt IP-Varianz zwischen den Anfragen; tote Proxys werden übersprungen statt in Schleifen zu laufen.
On failure:
Proxy-Datenverkehr hat Kosten pro GB und Kosten pro Anfrage. Außer Kontrolle geratene Scraper erzeugen außer Kontrolle geratene Rechnungen. Bauen Sie stets Limits und einen Abbruch ein.
import time
class ScrapeBudget:
def __init__(self, max_requests, max_duration_seconds, max_failures):
self.max_requests = max_requests
self.max_duration = max_duration_seconds
self.max_failures = max_failures
self.requests = 0
self.failures = 0
self.start = time.monotonic()
def allow(self):
if self.requests >= self.max_requests:
return False, "request cap reached"
if time.monotonic() - self.start >= self.max_duration:
return False, "time cap reached"
if self.failures >= self.max_failures:
return False, "failure cap reached (circuit breaker)"
return True, None
def record(self, success):
self.requests += 1
if not success:
self.failures += 1
budget = ScrapeBudget(max_requests=1000, max_duration_seconds=3600, max_failures=20)
for url in target_urls:
ok, reason = budget.allow()
if not ok:
print(f"Aborting: {reason}")
break
response = fetch_with_backoff(url)
budget.record(success=response is not None)
time.sleep(1) # rate limiting still applies even with rotation
Expected: Budget-Obergrenzen greifen, bevor Kosten außer Kontrolle geraten. Logs zeigen Erfolgsraten pro Proxy, sodass eine schlechte Ausgangs-IP identifiziert und ausgeschlossen werden kann.
On failure:
gateway., proxy=, dem
Anbieter-Hostnamen suchen).env (oder Äquivalent) steht in .gitignorerobots.txt wird weiterhin respektiert — Rotation setzt es nicht
außer KraftStealthyFetcher und Ratenbegrenzung; Rotation ist teuer und unnötig
einzusetzen ist unethisch.robots.txt ignorieren, weil „wir haben ja jetzt Rotation": Rotation
erteilt keine Erlaubnis. Die Direktive ist die Direktive.