Scraping

Wie du erkennst, dass eine Seite dir gefälschte oder blockierte Inhalte liefert

Der gefährliche Scraping-Fehler ist nicht das sichtbare 403, sondern das 200 OK voller Müll. Wie man Soft-Blocks, Honeypots und vergiftete Daten erkennt.

Chris Collins

Chris Collins

31. Juli 2026 · 7 Min. Lesezeit

Der Scraping-Fehler, mit dem jeder rechnet, ist der offensichtliche: ein 403, ein 429, eine Verbindung, die in Timeout läuft. Du kannst ihn sehen, zählen und erneut versuchen. Der Fehler, der dein Dataset wirklich vergiftet, ist das Gegenteil: ein 200 OK, das völlig erfolgreich aussieht und nichts von dem enthält, was du wolltest. Eine Block-Seite als normale Antwort verkleidet. Ein Challenge-Screen. Eine leere Hülle. Eine Datenseite, die eigens fabriziert wurde, um einem Bot falsche Informationen zu füttern.

Ein Scraper, der Fehler wirft, ist lästig. Ein Scraper, der mit Müll “Erfolg hat”, ist gefährlich, denn du merkst es erst, wenn die schlechten Daten schon in deinem Warehouse, in einem Report oder in einem Modell sind. Das ist die andere Hälfte davon, warum Scraper geblockt werden: moderne Anti-Bot-Systeme ziehen es zunehmend vor, still zu täuschen statt laut abzulehnen, gerade weil ein stiller Fehler ihnen mehr wert ist als ein sichtbarer. So fängst du ihn ab.

Der Statuscode ist nicht die Wahrheit

Die erste Gewohnheit, die man ablegen muss, ist, HTTP-Statuscodes als Erfolgssignal zu vertrauen. Ein 200 bedeutet, dass der Server eine Antwort gesendet hat, nicht dass er die Antwort gesendet hat, um die du gebeten hast. Seiten liefern routinemäßig Block-Seiten, CAPTCHAs und Consent-Walls mit einem 200, denn das hält naive Scraper zufrieden und still, während es ihnen nichts liefert. Behandle den Statuscode als ein schwaches Signal und validiere den Body bei jeder einzelnen Anfrage.

Die Kategorien des täuschenden 200 sind es wert, benannt zu werden, denn jede hat ein anderes Anzeichen:

  • Soft-Blocks und Interstitials. Eine Challenge- oder “verify you are human”-Seite mit einem 200 zurückgegeben, oft viel kleiner als eine echte Seite.
  • Challenge- und CAPTCHA-Screens. Inline dort geliefert, wo der Inhalt sein sollte. Verwandt mit wie sich Anti-Bot-Abwehr entwickelt hat.
  • Degradierter oder gestrippter Inhalt. Eine Login-Wall, ein “enable JavaScript”-Stub, oder ein leeres Skelett dort, wo die Daten hätten rendern sollen.
  • Rate-Limit-Soft-Fails. Veraltete, gecachte oder leere Ergebnisse statt eines Fehlers geliefert, sobald du eine Schwelle überschreitest.
  • Falsche Geo oder Personalisierung. Die richtige Seite für das falsche Land, die falsche Währung oder den ausgeloggten Zustand, technisch gültig, still nutzlos.
  • Honeypots und vergiftete Daten. Inhalt, der Bots absichtlich geliefert wird: falsche Preise, Fallen-Links, oder plausibel aussehende Datensätze mit unmöglichen Werten.

Validiere den Inhalt, nicht nur die Zustellung

Die wirksamste Verteidigung ist eine Inhalts-Assertion bei jeder Antwort: eine billige Prüfung, dass die Seite enthält, was eine echte Seite enthalten muss. Wähle eine Invariante, die ein echtes Ergebnis immer hat und eine Block-Seite nie: ein bestimmtes Element, ein Pflichtfeld, eine minimale plausible Länge, und lasse die Anfrage fehlschlagen, wenn sie fehlt.

def is_valid_product_page(html, parsed):
# Eine echte Produktseite hat das immer. Eine Block-Seite keines davon.
if len(html) < 2000: # Block-Seiten sind meist winzig
return False
if parsed.select_one("h1.product-title") is None:
return False # das Anker-Element ist weg
if parsed.select_one('[data-price]') is None:
return False # das Feld, für das wir kamen, fehlt
return True

Der entscheidende Wandel ist, dass ein fehlendes Anker-Element ein Fehler ist, kein leeres Ergebnis. Wenn der Selektor, auf den du dich verlässt, fehlt, notiere keine leere Zeile und mache weiter, behandle die Antwort als Soft-Block und versuche sie mit einer frischen Identität erneut, genau wie du es bei einem 403 tätest. Leere zu notieren ist die Art, wie ein Block still zu Tausenden leeren Zeilen wird, die niemand bemerkt, bis es viel später ist.

Beobachte die Form deiner Antworten, nicht nur die einzelnen

Einzelprüfungen fangen offensichtlichen Müll ab. Verteilungsprüfungen fangen die subtile Drift ab, und sie sind es, die eine robuste Pipeline von einer fragilen trennen.

  • Antwortgröße. Block- und Challenge-Seiten neigen dazu, klein und uniform zu sein. Ein plötzlicher Einbruch der durchschnittlichen Seitengröße über einen Batch, oder eine Häufung von Antworten mit exakt einer Byte-Zahl, ist eine Block-Signatur, selbst wenn jede 200 zurückgibt.
  • Antwort-Hashing. Hashe eine normalisierte Version jedes Antwort-Bodys. Wenn derselbe Hash plötzlich über viele verschiedene URLs auftaucht, wird dir immer wieder eine Block-Seite geliefert, kein echter, variierter Inhalt.
  • Feld-Füllrate. Verfolge den Prozentsatz der Datensätze, bei denen jedes Feld tatsächlich befüllt wurde. Ein Feld, das gestern zu 98 Prozent und heute zu 4 Prozent gefüllt war, wurde nicht seltener, du begannst gestrippte Seiten zu bekommen.
  • Erfolgsrate pro Host. Ein Abfall bei einem bestimmten Ziel, während andere stabil bleiben, ist dieses Ziel, das seine Haltung dir gegenüber ändert, wert abgefangen zu werden, bevor es einen ganzen Lauf verschwendet. Das ist dasselbe Pro-Ziel-Signal, das beim Monitoring einer Scraping-Pipeline im großen Maßstab zählt.

Nichts davon braucht Machine Learning. Es sind Zähler und einfache Baselines, und sie sind der Unterschied zwischen einen Block in den ersten hundert Anfragen zu bemerken und ihn nach einer Million zu bemerken.

Bekannte Block-Seiten-Signaturen

Führe eine kleine Bibliothek von Phrasen und Markern, die nur je auf Block-, Challenge- oder Fehlerseiten erscheinen, und markiere jede Antwort, die sie enthält, unabhängig vom Statuscode.

BLOCK_MARKERS = (
"verify you are human",
"unusual traffic",
"access denied",
"enable javascript to continue",
"request blocked",
)
def looks_blocked(text):
low = text.lower()
return any(marker in low for marker in BLOCK_MARKERS)

Halte sie kurz und spezifisch, damit sie nicht bei echtem Inhalt, der zufällig diese Themen behandelt, falsch anschlägt, und lass sie wachsen, während du neue Abwehrmechanismen triffst. Eine Challenge-Seite, die du erkennen kannst, ist eine Challenge, durch die du erneut versuchen kannst, statt sie zu speichern.

Honeypots und vergiftete Daten

Die übelste Kategorie ist Inhalt, der darauf ausgelegt ist, echt auszusehen. Hier zählen zwei Verteidigungen.

Erstens, folge keinen Fallen-Links. Honeypot-Links sind üblicherweise vor Menschen versteckt mit display:none, visibility:hidden, Größe null, Off-Screen-Positionierung oder aria-hidden, und existieren nur, um einen Bot zu fangen, der jedem Anker folgt. Ein Crawler, der Sichtbarkeit respektiert und Links ignoriert, die ein Mensch nie klicken könnte, umgeht die meisten davon.

Zweitens, mache einen Plausibilitäts-Check der Daten selbst. Vergiftete Datensätze sind gebaut, um einen naiven Parser zu bestehen, neigen aber dazu, grundlegende Domänenregeln zu verletzen: Preise, die null oder absurd hoch sind, Daten in der Zukunft, Mengen, die nicht existieren können, Werte außerhalb jedes plausiblen Bereichs. Validiere gegen die Bereiche, die deine Domäne tatsächlich erlaubt, und stelle Datensätze, die sie verletzen, unter Quarantäne, statt ihnen zu vertrauen, weil das HTML sauber geparst hat.

Canary-Anfragen

Die zuverlässigste Frühwarnung ist ein Canary: hole periodisch eine Seite, deren korrekten Inhalt du bereits kennst, und stelle sicher, dass er noch übereinstimmt. Wenn dein Canary anfängt, eine Block-Seite oder die falschen Daten zurückzugeben, weißt du, dass das Ziel sich gegen dich gewendet hat, sofort und unzweideutig, ohne es aus einem langsamen Rückgang der Datenqualität schließen zu müssen. Fahre Canaries pro Ziel und pro Geo, da eine Seite die Exit-IPs eines Landes blockieren kann, während sie ein anderes unberührt lässt.

Wo Proxies hineinpassen

Saubere IPs reduzieren, wie oft du überhaupt soft-geblockt wirst, ein Pool mit guter Reputation kommt dort durch, wo markierte Adressen still eine Challenge-Seite gefüttert bekommen. Das senkt die Rate täuschender Antworten, die du abfangen musst, aber es beseitigt nicht die Notwendigkeit, sie abzufangen, denn Blocks sind zunehmend unsichtbar by design und keine IP ist immun. Die beiden arbeiten zusammen: Erkennung sagt dir, dass eine Antwort ein Soft-Block war, und ein rotierender Residential-Pool gibt dir eine frische Identität, um sie erneut zu versuchen, genau wie du einen harten Fehler behandeln würdest. Speise jeden erkannten Soft-Block zurück in deine Retry- und Rotationslogik (Sticky vs. rotierend), und behandle einen anhaltenden Pro-Ziel-Block-Raten-Spike als Signal zum Zurückfahren statt zum Hämmern (Blockaden vermeiden und verantwortungsvoll scrapen gelten beide).

Das Fazit

Nimm an, dass die Antwort lügt, bis sie das Gegenteil beweist. Validiere den Inhalt bei jeder Anfrage gegen eine Invariante, die eine echte Seite immer hat, und behandle einen fehlenden Anker als Fehler zum erneuten Versuchen, nicht als leere Zeile zum Speichern. Beobachte die Verteilung von Antwortgrößen, Hashes und Füllraten, damit ein Block, der 200 zurückgibt, trotzdem als Anomalie auftaucht. Führe eine kurze Signaturliste für bekannte Block-Seiten, weigere dich, versteckten Fallen-Links zu folgen, mache Plausibilitäts-Checks der Daten gegen Domänenregeln, und fahre Canaries, damit du in dem Moment erfährst, in dem ein Ziel sich gegen dich wendet.

Mach das, und der stille Fehler, der eine Dataset wochenlang still korrumpiert, hört auf, still zu sein. Kopple es mit einem sauberen Residential-Pool, damit du von vornherein seltener soft-geblockt wirst, und die Pro-GB-Tarife lassen dich das gegen deine eigenen Ziele validieren, ohne dich im Voraus zu binden.

Bereit, loszulegen?

Testen Sie Shifters Residential-Proxys, 205M+ IPs, 195+ Länder, ab $0.75/GB.

Jetzt starten