Scraping

Änderungserkennung im großen Maßstab: Webseiten vergleichen, ohne im Rauschen zu ertrinken

Seiten ändern sich bei jedem Laden: Werbung, Zeitstempel, Tokens. Wie man echte Änderungen vom Rauschen unterscheidet, mit Normalisierung, feldbasierten Diffs und Simhash, inklusive getestetem Code.

Chris Collins

Chris Collins

27. September 2026 · 9 Min. Lesezeit

Jeder Monitoring-Job stellt irgendwann dieselbe Frage: Hat sich diese Seite geändert? Das klingt nach einem Hash-Vergleich. Ist es aber nicht. Moderne Seiten ändern sich bei jedem Laden, mit rotierenden Anzeigen, Zeitstempeln, Empfehlungsblöcken, Session-Tokens und Live-Zählern, sodass ein naiver Vergleich jedes Mal eine Änderung meldet und der Alarm-Kanal sich mit Rauschen füllt, bis ihn jeder stummschaltet. Der gegenteilige Fehler ist leiser und schlimmer: eine Pipeline, die so sehr auf das Ignorieren von Rauschen getrimmt ist, dass sie die Preissenkung oder das entfernte Zertifikat übersieht, die sie eigentlich erfassen sollte.

Dieser Leitfaden behandelt, wie man echte Änderungen im großen Maßstab erkennt: Felder statt Seiten vergleichen, das normalisieren, was man nicht vermeiden kann zu vergleichen, messen, wie stark sich eine Seite geändert hat statt ob sie sich überhaupt geändert hat, und jede Art von Änderung an den richtigen Ort weiterleiten.

Die wichtigsten Erkenntnisse

  • Roher Byte-Vergleich ist für die meisten Websites nutzlos. Wir haben eine Nachrichten-Startseite zweimal abgerufen, 45 Sekunden auseinander: Die Bytes unterschieden sich, und selbst der bereinigte Text unterschied sich.
  • Vergleichen Sie Felder, nicht Seiten, wo immer es möglich ist. Ein Preis, ein Titel oder ein Lagerstatus hat sich entweder geändert oder nicht.
  • Wo Sie ganze Seiten vergleichen müssen, normalisieren Sie zuerst und messen Sie dann die Ähnlichkeit. Simhash, die Fingerprinting-Technik, die Google zur Near-Duplicate-Erkennung über 8 Milliarden Seiten beschrieben hat, verwandelt „Hat es sich geändert?” in „Wie stark hat es sich geändert?”
  • Klassifizieren Sie jede Änderung: Feldänderung, Inhaltsänderung oder Rauschen. Jede verdient eine andere Reaktion.
  • Passen Sie die Einstellungen pro Website und pro Seitentyp an. Ein Schwellenwert, der für eine Produktseite richtig ist, ist für eine Nachrichten-Startseite falsch.

Warum naives Diffing scheitert

Um das Problem konkret zu sehen, haben wir die internationale Startseite einer großen Nachrichtenseite zweimal abgerufen, 45 Sekunden auseinander. Das rohe HTML unterschied sich, wie erwartet. Interessanter: Nach dem Entfernen von Skripten, Stilen und Markup sowie Zeitstempeln und Tokens unterschied sich der sichtbare Text immer noch. Live-Seiten aktualisieren sich fortlaufend. Ein Monitor, der bei jedem Unterschied Alarm schlägt, hätte bei dieser Seite bei jedem einzelnen Durchlauf Alarm geschlagen.

Die Quellen des Rauschens sind vorhersehbar:

RauschenBeispielTypische Lösung
Eingebettete Skripte und DatenAnalytics-Payloads, JSON-State, CSRF-TokensSkript- und Stilblöcke vor dem Vergleich entfernen
Zeitbasierter Text„Vor 3 Minuten aktualisiert”, Uhrzeiten, DatenMit Mustern entfernen oder Felder vergleichen, die diese ausschließen
Rotierende ModuleAnzeigen, „gerade im Trend”, EmpfehlungenNur den Bereich oder die Felder vergleichen, die Sie interessieren
Personalisierung und ExperimenteA/B-Test-Varianten, standortspezifische BlöckeVon einem festen Standpunkt mit konsistenten Einstellungen erfassen
ReihenfolgeListen, die bei jedem Laden durchmischt werdenVor dem Vergleich sortieren

Manches Rauschen ist eigentlich ein Unterschied darin, wer gefragt hat. Eine Seite, die aus Deutschland geladen wurde, kann sich von derselben Seite unterscheiden, die aus den Vereinigten Staaten geladen wurde, aus Gründen, die nichts mit einer Änderung zu tun haben. Halten Sie den Standpunkt für jede überwachte Seite fest, sodass sich zwischen den Durchläufen nur die Zeit ändert. Bei einem Residential-Gateway bedeutet das, das Land für jeden Durchlauf dieses Jobs festzulegen, zum Beispiel customer-USERNAME-country-de.

Prinzip 1: Felder vergleichen, nicht Seiten

Der zuverlässigste Änderungsdetektor vergleicht überhaupt keine Seiten. Er extrahiert die Felder, die wichtig sind, wie Preis, Verfügbarkeit, Titel, eine Zertifikatsliste oder eine Adresse, und vergleicht diese. Ein Feld hat sich geändert oder nicht, und Rauschen an anderer Stelle der Seite ist irrelevant.

Strukturierte Daten machen das einfacher, als es klingt. Viele Seiten veröffentlichen ihre Schlüsselfelder als JSON-LD, das weitaus stabiler ist als das Layout drumherum; das Extrahieren wird in Hören Sie auf, HTML zu parsen behandelt. Wo Felder stattdessen von Selektoren stammen, vergleichen Sie die extrahierten Werte, niemals das HTML drumherum.

Der Feldvergleich macht auch Alarme nützlich. „Preis änderte sich von 89.00 auf 79.00” ist umsetzbar. „Die Seite hat sich geändert” ist es nicht.

Prinzip 2: Normalisieren, was Sie vergleichen müssen

Manches Monitoring betrifft tatsächlich ganze Seiten: Nutzungsbedingungen, die „Über uns”-Seite eines Lieferanten, eine Nachhaltigkeitserklärung, eine Richtlinienseite. Entfernen Sie dafür, was nie wichtig ist, bevor Sie vergleichen:

  • Nicht-Inhalts-Blöcke entfernen: Skripte, Stile, Templates, Inline-SVG.
  • Nur sichtbaren Text behalten, mit zusammengefasstem Leerraum und vereinheitlichter Groß-/Kleinschreibung.
  • Volatile Fragmente entfernen: Uhrzeiten, ISO-Daten, relative Zeiten, Tokens und lange hexadezimale Identifikatoren.
  • Auf einen Bereich beschränken, wenn eine Seite einen stabilen Hauptinhaltsbereich hat, wie den Artikeltext oder das Hauptelement.

Normalisierung entfernt einen großen Teil des Rauschens. Sie entfernt nicht alles, weshalb der nächste Schritt wichtig ist.

Prinzip 3: Messen, wie viel, nicht ob

Statt zu fragen, ob normalisierter Text identisch ist, fragen Sie, wie ähnlich er ist. Simhash ist dafür ein gutes Werkzeug. Es reduziert ein Dokument auf einen 64-Bit-Fingerabdruck mit einer nützlichen Eigenschaft: ähnliche Dokumente erhalten Fingerabdrücke, die sich nur in wenigen Bit-Positionen unterscheiden. Google beschrieb die Verwendung dafür zur Near-Duplicate-Erkennung in „Detecting Near-Duplicates for Web Crawling” (WWW 2007), wo die Autoren bestätigten, dass „für ein Repository von 8 Milliarden Web-Seiten 64-Bit-Simhash-Fingerabdrücke und k = 3 vernünftig sind”, was bedeutet, dass Seiten, deren Fingerabdrücke sich in höchstens drei Bits unterscheiden, als Near-Duplicates behandelt werden können.

Das macht Änderungserkennung zu einer Frage der Distanz. In unserem Test lagen die beiden Abrufe der Nachrichten-Startseite, 45 Sekunden auseinander, 2 Bits auseinander: unterhalb des Schwellenwerts, also Rauschen. Dieselbe Startseite verglichen mit einem unabhängigen Artikel lag 34 Bits auseinander: eindeutig anderer Inhalt.

import hashlib
import re

VOLATILE = [
    r"\b\d{1,2}:\d{2}(?::\d{2})?\s?(?:am|pm|AM|PM)?\b",          # clock times
    r"\b\d{4}-\d{2}-\d{2}(?:T[\d:.]+Z?)?\b",                      # ISO dates
    r"\b\d+\s+(?:second|minute|hour|day)s?\s+ago\b",              # relative times
    r"\b(?:csrf|nonce|token|session|sid)[\w-]*[=:]\s*[\w-]+",      # tokens
    r"\b[0-9a-f]{24,}\b",                                         # long hex ids
]


def normalise(html):
    """Visible text only, with volatile fragments removed."""
    html = re.sub(r"(?is)<(script|style|noscript|svg|template)\b.*?</\1>", " ", html)
    text = re.sub(r"(?s)<[^>]+>", " ", html)
    for pattern in VOLATILE:
        text = re.sub(pattern, " ", text, flags=re.I)
    return re.sub(r"\s+", " ", text).strip().lower()


def simhash(text, bits=64):
    """Charikar-style simhash over word 3-grams."""
    words = text.split()
    grams = [" ".join(words[i:i + 3]) for i in range(max(1, len(words) - 2))]
    weights = [0] * bits
    for gram in grams:
        h = int.from_bytes(hashlib.blake2b(gram.encode(), digest_size=8).digest(), "big")
        for i in range(bits):
            weights[i] += 1 if h >> i & 1 else -1
    return sum(1 << i for i in range(bits) if weights[i] > 0)


def distance(a, b):
    return bin(a ^ b).count("1")


def compare(old_html, new_html, old_fields=None, new_fields=None, threshold=3):
    """Classify a change as none, noise, content or field-level."""
    old_fields, new_fields = old_fields or {}, new_fields or {}
    field_changes = {k: (old_fields.get(k), new_fields.get(k))
                     for k in set(old_fields) | set(new_fields)
                     if old_fields.get(k) != new_fields.get(k)}
    if field_changes:
        return {"kind": "field", "changes": field_changes}
    if old_html == new_html:
        return {"kind": "none"}
    d = distance(simhash(normalise(old_html)), simhash(normalise(new_html)))
    return {"kind": "content" if d > threshold else "noise", "distance": d}

Behandeln Sie den Schwellenwert als Ausgangspunkt, nicht als Konstante. Der Wert aus WWW 2007 wurde gewählt, um Duplikate unter Milliarden von Seiten zu finden, nicht um eine einzelne Seite über die Zeit zu überwachen. Kalibrieren Sie ihn pro Seitentyp: Rufen Sie jede überwachte Seite mehrfach kurz hintereinander ab, wobei sich nichts Wesentliches ändern sollte, und setzen Sie den Schwellenwert knapp über den beobachteten Distanzen. Kurze Seiten erfordern mehr Sorgfalt, da ein paar geänderte Wörter den Fingerabdruck eines kleinen Dokuments weiter verschieben als bei einem langen.

Prinzip 4: Klassifizieren, dann weiterleiten

Ein Detektor, der nur „geändert” zurückgibt, schiebt die eigentliche Arbeit auf denjenigen ab, der den Alarm liest. Geben Sie eine Art zurück und leiten Sie danach weiter:

ArtBedeutungWohin es geht
fieldEin Wert, den Sie verfolgen, hat sich geändertDirekt in den Datensatz und, falls wichtig, ein Alarm
contentDie Substanz der Seite hat sich über das Rauschen hinaus geändertEine menschliche Überprüfungswarteschlange, mit angehängtem Text-Diff
noiseDie Seite hat sich bewegt, aber innerhalb der normalen SchwankungFür die Kalibrierung protokolliert, niemals alarmiert
noneByte-identischNichts

Zwei Verfeinerungen zahlen sich aus. Bewahren Sie den vorherigen Snapshot und ein lesbares Text-Diff zusammen mit jeder content-Änderung auf, damit ein Prüfer sie in Sekunden beurteilen kann. Und erfassen Sie die Rate jeder Art pro Website: Eine Website, deren Rausch-Distanz über Wochen zunimmt, ändert ihre Templates, und eine Website, die plötzlich überhaupt keine Änderungen mehr produziert, liefert Ihnen möglicherweise eine veraltete oder blockierte Seite, ein Fehlermodus, der in die stille Fehlerrate behandelt wird.

Skalierung

Änderungserkennung im großen Maßstab ist größtenteils ein Speicher- und Planungsproblem.

  • Speichern Sie Fingerabdrücke und Felder, nicht ganze Seiten, für die meisten Durchläufe. Ein 64-Bit-Fingerabdruck und eine Handvoll Felder sind winzig. Bewahren Sie vollständige Snapshots nur auf, wenn eine Änderung erkannt wird, oder nach einem langsameren Zeitplan für Audits.
  • Besuchen Sie nach erwarteter Änderung erneut. Seiten, die sich selten ändern, brauchen keine stündlichen Prüfungen. Kostenbewusste Crawl-Planung legt dar, wie man ein Abruf-Budget dort ausgibt, wo Änderungen wahrscheinlich sind, und jedes none- oder noise-Ergebnis ist ein Beleg für dieses Modell.
  • Nutzen Sie zuerst günstige Signale. Wo eine Website zuverlässige ETag- oder Last-Modified-Header sendet, beantwortet eine bedingte Anfrage, die 304 Not Modified zurückgibt, die Frage bei fast keiner Bandbreite.
  • Beobachten Sie den Beobachter. Canary-Seiten mit bekannten Änderungsmustern sagen Ihnen, ob der Detektor selbst noch funktioniert.

Wo dies eingesetzt wird

Dieselbe Maschinerie steckt hinter sehr unterschiedlichen Aufgaben: Preis- und Bestandsüberwachung, wo Feldänderungen das ganze Ziel sind, wie in Aufbau eines Echtzeit-Wettbewerbspreis-Feeds; Lieferanten- und Compliance-Überwachung, wo Änderungen des gesamten Seiteninhalts wichtig sind, wie in Überwachung der öffentlichen Präsenz Ihrer Lieferanten und Überprüfung von ESG-Angaben; und die Bewahrung von Beweisen, wenn eine Änderung rechtlich bedeutsam ist.

Fazit

„Hat sich diese Seite geändert?” ist die falsche Frage für das moderne Web, weil die Antwort fast immer Ja lautet. Die nützlichen Fragen sind „Hat sich ein Feld geändert, das mich interessiert?” und, wo Sie ganze Seiten vergleichen müssen, „Hat sich die Substanz über die normale Schwankung dieser Seite hinaus geändert?”

Vergleichen Sie Felder, wo immer möglich. Normalisieren Sie, was Sie nicht vermeiden können zu vergleichen, messen Sie Ähnlichkeit statt Gleichheit, kalibrieren Sie Schwellenwerte pro Seitentyp und leiten Sie jede Art von Änderung an den Ort, der darauf reagieren kann. Das Ergebnis ist ein Änderungs-Feed, dem Menschen vertrauen, und das ist die einzige Art, die gelesen wird.

Quellen und Referenzen

Bereit, loszulegen?

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

Jetzt starten