Eine Website wechselt fast nie in einem einzigen Schritt davon, deinen Crawler normal zu bedienen, zu ihn komplett zu blockieren. Was zuerst passiert, ist leiser. Ein paar zusätzliche Requests landen auf einer Challenge-Seite. Manche Antworten kommen mit 200 OK zurück, ohne dass etwas Brauchbares drinsteckt. Die Latenz kriecht nach oben. Ein paar Datensätze fallen bei der Validierung durch. Jedes Signal für sich sieht nach Rauschen aus, und jedes lebt auf einem anderen Dashboard, sodass niemand die Zusammenhänge erkennt, bis der Datensatz ein Loch hat.
Ein Target-Health-Score ist die Lösung: eine Zahl pro Website, die angibt, ob diese Website sich noch wie ihr eigenes Normal verhält, mit den zugehörigen Gründen. Dieser Beitrag behandelt, welche Signale einfließen, wie man sie kombiniert, ohne sich selbst zu täuschen, und was der Crawler tun sollte, wenn die Zahl fällt.
Target Health ist nicht Proxy Health
Es lohnt sich, präzise zu sein, was hier gemessen wird, denn die beiden werden oft verwechselt.
Proxy Health fragt, ob eine Route funktioniert: ein Gateway, ein Land, eine Session, ein Exit. Target Health fragt, ob eine bestimmte Website noch willens und in der Lage ist, dich zu bedienen. Eine tote Proxy-Route schlägt gegen jede Website fehl. Eine Website, die sich gegen dich wendet, schlägt über jede Route hinweg fehl.
Dieser Unterschied ist die erste Diagnose. Wenn Fehler zunehmen, teile sie nach Route auf. Wenn sie sich auf ein Land, einen Pool oder ein Session-Muster konzentrieren, ist es ein Routenproblem, und der Ansatz aus monitoring residential proxy health at scale greift. Wenn sie gleichmäßig über jede Route steigen, die du an diese Website sendest, hat die Website ihre Meinung über dich geändert, und dafür ist dieser Score gedacht.
Die Signale
Gruppiere die Signale danach, was sie offenbaren. Manche sind laut, manche fast unhörbar, und die stillen sind am teuersten zu übersehen.
| Signal | Wie es aussieht | Warum es wichtig ist |
|---|---|---|
| Hard Blocks | 403, 429, Connection Resets | Explizite Ablehnung; leicht zu zählen |
| Challenges | CAPTCHA- oder Zwischenseiten | Die Website vermutet Automatisierung und testet |
| Soft Blocks | 200 OK mit Block-Seite, leeren Ergebnissen oder abgespecktem Layout | Als Erfolg getarnte Ablehnung |
| Latenz-Drift | Steigende p95-Antwortzeit gegenüber dem eigenen Normal der Website | Oft absichtliche Verzögerung, manchmal nur Last |
| Extraktionsfehler | Pflichtfelder fehlen, Schema stimmt nicht mehr | Die Seite hat sich geändert, oder dir wird etwas anderes ausgeliefert |
| Kosten-Drift | Mehr Retries, Bytes oder Credits pro gültigem Datensatz | Alles Obige, ausgedrückt in Geld |
Soft Blocks verdienen besondere Aufmerksamkeit, weil Statuscodes lügen. In einer Messung des Geo-Blockings aus Kuba im Jahr 2023 lieferten 32 Domains ihre Block-Seiten mit einem 200 OK-Status aus, wie in which countries get geo-blocked most beschrieben. Ein Crawler, der dem Statuscode vertraut, verzeichnet diese als Erfolge. Erkenne Soft Blocks über den Inhalt: bekannte Block-Page-Marker, eine Antwortgröße weit unter dem Normal des jeweiligen Seitentyps, oder eine Extraktion, die nichts zurückgibt, wo sie sonst immer etwas zurückgab.
Zwei Verantwortliche, zwei Scores
Eine Unterscheidung erspart eine Menge Verwirrung: trenne “die Website hat sich geändert” von “die Website hat sich gegen dich gewendet”.
Ein Redesign zerbricht deinen Parser. Jede Seite lädt einwandfrei, aber Pflichtfelder verschwinden. Das ist ein Extraktionsproblem mit einem Code-Fix, verantwortet von wer immer den Parser pflegt. Eine Website, die anfängt zu challengen und soft zu blocken, ist ein Beziehungsproblem, und die Lösung ist eine Änderung daran, wie, wie viel oder ob überhaupt gesammelt wird. Unterschiedliche Verantwortliche, unterschiedliche Reaktionen.
Berechne also Hostilität, das heißt Blocks, Challenges, Soft Blocks und Latenz, als den Health Score, und verfolge Extraktionsvalidität daneben als separates Parser-Health-Signal. Wenn beide gleichzeitig fallen, schau zuerst auf die Hostilität: eine Website, die Challenge-Seiten ausliefert, wird auch jeden Extraktor zerbrechen.
Bewerte gegen das eigene Normal der Website
Der häufigste Fehler ist die Verwendung globaler Schwellenwerte. Eine Challenge-Rate von 5% ist alarmierend auf einer Website, die dich noch nie gechallenged hat, und völlig normal auf einer, die jeden beim ersten Besuch challenged. Jedes Signal muss mit dem eigenen Baseline dieser Website verglichen werden, über ein Fenster, das lang genug ist, um stabil zu sein, etwa die vorherigen zwei Wochen, und ohne den jüngsten Tag, damit ein schlechter Tag nicht zum neuen Normal wird.
Dann gewichten, kappen und summieren:
from dataclasses import dataclass
@dataclass
class Window:
requests: int
hard_blocks: int # 403, 429, connection resets
challenges: int # CAPTCHA or interstitial pages
soft_blocks: int # 200 OK carrying a block page or an empty result
p95_latency_ms: float
MIN_REQUESTS = 50
WEIGHTS = {"hard_block": 35, "challenge": 25, "soft_block": 25, "latency": 15}
def signals(w):
n = max(1, w.requests)
return {
"hard_block": w.hard_blocks / n,
"challenge": w.challenges / n,
"soft_block": w.soft_blocks / n,
"latency": w.p95_latency_ms,
}
def badness(name, now, base):
if name == "latency":
# Full penalty at three times the site's own normal latency.
return min(1.0, max(0.0, (now / max(base, 1.0) - 1) / 2))
# Full penalty at 20 percentage points above the site's own normal rate.
return min(1.0, max(0.0, (now - base) / 0.20))
def health_score(current, baseline):
if current.requests < MIN_REQUESTS:
return None, ["not enough requests to judge"]
now, base = signals(current), signals(baseline)
penalty = {k: w * badness(k, now[k], base[k]) for k, w in WEIGHTS.items()}
score = round(100 - sum(penalty.values()))
reasons = [k for k, p in sorted(penalty.items(), key=lambda kv: -kv[1]) if p >= 1]
return score, reasons
Ein paar Designentscheidungen hier sind bewusst getroffen.
- Nur Überschuss über der Baseline zählt. Eine Website, die schon immer 3% der Requests gechallenged hat, verliert dafür heute keine Punkte.
- Jedes Signal ist gekappt. Ein durchgehendes Signal kann den Score nicht unter null drücken oder die anderen ertränken, und die Reasons-Liste zeigt, welches dominierte.
- Ein kleines Fenster liefert keinen Score. Fünf Requests mit einem Block sind keine 20%-Block-Rate, es sind schlicht nicht genug Daten. Ein fehlender Score ist ehrlicher als ein sicher falscher.
- Die Gewichte sind Meinungen. Beginne mit etwas Ähnlichem wie diesen und passe sie nach der Durchsicht einiger echter Vorfälle an. Hard Blocks und Soft Blocks verdienen das meiste Gewicht, weil sie Daten bedeuten, die du nicht bekommen hast.
Glätte den Score auch über die Zeit, zum Beispiel mit einem exponentiell gewichteten Durchschnitt, damit eine einzelne schlechte Minute keinen Alarm auslöst, während ein stetiger Rückgang trotzdem innerhalb der Stunde sichtbar wird.
Canaries: von dir kontrollierte Ground Truth
Jedes obige Signal ist abgeleitet. Canaries geben dir etwas, das der Wahrheit näherkommt. Wähle pro Website eine Handvoll stabiler Seiten, bei denen du weißt, wie die richtige Antwort aussieht: ein Produkt, dessen Preis du prüfen kannst, ein Listing, dessen Artikelanzahl du kennst, eine Seite, deren Struktur sich seit Monaten nicht geändert hat. Rufe sie nach einem Zeitplan über denselben Pfad wie den Produktionsverkehr ab.
Wenn ein Canary eine Seite zurückgibt, die normal aussieht, aber den falschen Wert trägt, hast du den am schwersten zu erkennenden Fehler gefunden: Inhalt, der einwandfrei parst und schlicht nicht das ist, was ein echter Besucher sehen würde. Kein Statuscode und kein Latenzgraph zeigt dir das. Canaries machen auch die Baseline vertrauenswürdig, weil du ihr korrektes Verhalten unabhängig vom Crawler kennst.
Binde Aktionen an Bänder, und behalte Menschen im Loop
Ein Score, auf den niemand reagiert, ist ein Dashboard. Gib ihm Bänder, und gib jedem Band eine Aktion, die das System selbständig ausführt:
| Band | Bedeutung | Automatische Aktion |
|---|---|---|
| 80 bis 100 | Verhält sich wie sein eigenes Normal | Keine |
| 50 bis 79 | Verschlechtert sich | Concurrency für diese Website reduzieren, Revisit-Intervalle verlängern, prüfen ob Fehler website-weit oder routenspezifisch sind |
| Unter 50 | Die Website wehrt sich deutlich | Website pausieren, nur Canaries weiterlaufen lassen, Person alarmieren |
Das Verschlechterungs-Band fließt direkt in den Rest des Crawlers ein. Niedrigere Concurrency ist wofür der Per-Host-Limiter in backpressure and flow control da ist, und ein fallender Score sollte die effektiven Kosten dieser Website in einem cost-aware scheduler erhöhen, sodass Budget zu Websites wandert, bei denen es noch Daten kauft.
Das unterste Band ist bewusst nicht über eine Pause hinaus automatisiert. Eine Website, die sich stark wehrt, sagt dir etwas, und die richtige Reaktion ist eine menschliche Entscheidung: weiter verlangsamen, prüfen ob deine Datensammlung noch zu den Nutzungsbedingungen der Website passt, nach einer offiziellen API oder einem Datenfeed suchen, oder aufhören. Automatisch zu schwereren Sammelmethoden zu eskalieren, sobald der Score fällt, verwandelt ein Signal nur in ein Wettrüsten, und genau das soll ein Health Score dir helfen zu vermeiden. Rate limiting and request throttling behandelt, wie man liest, was eine Website von dir verlangt.
Behandle es wie jeden anderen Alert
Behandle den Score als Alert mit einer False-Positive-Rate, und überprüfe ihn. Frage nach jedem Vorfall, ob sich der Score früh genug bewegt hat, ob die Gründe auf die tatsächliche Ursache hindeuteten und ob die automatische Aktion geholfen hat. Das meiste Feintuning kommt aus zwei oder drei echten Vorfällen, nicht aus dem Entwerfen von Gewichten im Voraus. Bewahre die Historie: der Score über Monate ist die beste Aufzeichnung, die du hast, wie sich die Haltung jeder Website gegenüber automatisiertem Verkehr verändert.
Fazit
Websites wenden sich allmählich und leise gegen Crawler, durch Challenges, verschleierte Ablehnungen und langsamere Antworten, lange bevor es zu einem offenen Block kommt. Jedes Signal allein ist mehrdeutig. Verglichen mit dem eigenen Normal der Website, gewichtet, gekappt und kombiniert, ergeben sie eine Zahl, die sich früh bewegt, mit angehängten Gründen.
Der Score ist am wertvollsten für das, was er dem Crawler erlaubt, ruhig zu tun: sich zurückzuziehen, bevor er blockiert wird, Budget anderswohin zu verschieben und die schwierigen Entscheidungen an eine Person mit den Beweisen vor Augen zu übergeben. Die umfassenderen Metriken rund darum finden sich in monitoring a web scraping pipeline.