Zurück zum Blog
Anleitungen
Mihai MaximLast updated on May 7, 202610 min read

Web Scraping mit Regex: Ein praktischer Leitfaden

Web Scraping mit Regex: Ein praktischer Leitfaden
Kurz gesagt: Web-Scraping mit regulären Ausdrücken ist besonders dann sinnvoll, wenn Sie kurze, vorhersehbare Textmuster (Preise, Artikelnummern, E-Mail-Adressen, Datumsangaben) aus HTML-Code extrahieren möchten, dem Sie bereits vertrauen. Kombinieren Sie das Python-Modul re mit Beautiful Soup, beschränken Sie Ihre Muster auf einen geparsten Knoten statt auf rohen Markup-Code und halten Sie Regex vom vollständigen Parsen des HTML-Baums fern. Dieser Leitfaden führt Sie durch einen funktionierenden Titel- und Preisscraper, fortgeschrittene Regex-Funktionen und die Fallstricke, die echte Scraper in der Produktion zu Fall bringen.

Einleitung

Die meisten Python-Scraper stoßen irgendwann an einen Punkt, an dem CSS-Selektoren und XPath nicht mehr ausreichen. Du hast zwar das richtige <div>, aber darin befindet sich eine Zeichenkette wie "$1,299.00 USD (incl. VAT)" und Sie benötigen nur die Zahl. Hier kommt das Web-Scraping mit regulären Ausdrücken ins Spiel: Es handelt sich um eine musterbasierte Text-Extraktionstechnik, die auf bestimmte Strukturen im rohen HTML-Code oder im sichtbaren Text einer Seite abzielt, anstatt durch den DOM-Baum zu navigieren.

Dieser Leitfaden richtet sich an fortgeschrittene Python-Entwickler, die bereits wissen, wie man eine Seite mit requests abrufen und mit Beautiful Soup parsen können und nun reguläre Ausdrücke in dieses Toolkit integrieren möchten, ohne den Scraper instabil zu machen. Wir behandeln, wann Web-Scraping mit regulären Ausdrücken die richtige Wahl ist (und wann definitiv nicht), ein auf Scraping ausgerichtetes Token-Spickzettel, einen funktionierenden Titel- und Preisscraper, der strukturierte CSV-Dateien schreibt, sowie die fortgeschrittenen re Funktionen (benannte Gruppen, Lookarounds, Flags, re.compile), die die Lesbarkeit der Muster auch bei wachsendem Projektumfang gewährleisten. Wir werden auch ehrlich über die Grenzen von Regex bei dynamischem und fehlerhaftem HTML sprechen und darüber, wann Sie stattdessen auf Selektoren oder eine verwaltete Scraping-API zurückgreifen sollten.

Wann Regex das richtige Werkzeug für das Scraping ist (und wann nicht)

Regex eignet sich hervorragend für kurze, klar definierte Textmuster: Preise, Datumsangaben, ISBNs, Telefonnummern, Hashes, Abfrageparameter in URLs. Es ist jedoch eine schlechte Wahl für die Navigation durch beliebige HTML-Bäume mit verschachtelten Tags, optionalen Attributen und inkonsistenten Leerzeichen.

Eine einfache Entscheidungshilfe für das Web-Scraping mit Regex:

  • Verwenden Sie Regex, wenn das Feld eine stabile Struktur hat (\d+\.\d{2}, eine E-Mail, eine UUID), die Seite aus servergerendertem HTML besteht und Sie den umgebenden Knoten bereits mit einem Parser isolieren können.
  • Verzichte auf Regex, wenn die Daten in tief verschachtelten Tags verborgen sind, sich die Klassennamen im Markup bei jedem Deploy ändern oder die Seite JavaScript-gerendert ist und die gewünschten Werte erst erscheinen, nachdem der Browser Skripte ausgeführt hat.

Spickzettel für Regex-Token beim Scraping

Für fast jeden Web-Scraping-Auftrag mit Regex benötigen Sie nur einen kleinen Kern an Tokens. Die folgende Tabelle ist auf das Scraping ausgerichtet: Jedes Beispiel ist etwas, das Sie tatsächlich aus HTML extrahieren könnten.

Token

Was es findet

Scraping-Beispiel

\d

Beliebige Ziffer (0–9)

\d+ für einen Preis wie 1299

\w

Wortzeichen (Buchstaben, Ziffern, _)

\w+ für einen Slug oder eine SKU

\s

Beliebige Leerzeichen

Toleranz gegenüber unregelmäßiger HTML-Formatierung

.

Beliebiges Zeichen außer Zeilenumbruch

(.*?) innerhalb eines Tags, mit re.DOTALL für mehrzeilig

^ / $

Anfang / Ende einer Zeichenkette (oder Zeile)

Verankerung eines sauberen Textknotens

* + ?

0+, 1+, 0–1 Wiederholungen (gierig)

\s* zwischen Tags

*? +?

Nicht-gierige Varianten

(.*?)</h2> bis zum ersten schließenden Tag

[...]

Zeichenklasse

[A-Z]{2,3} für einen Währungscode

(...)

Erfassungsgruppe

Nur den Preis extrahieren aus "$1,299.00 USD"

(?P<name>...)

Benannte Erfassungsgruppe

(?P<price>\d+\.\d{2})

(?=...) / (?<=...)

Vorausschau / Rückblick

\d+(?= USD) um Ziffern vor USD

\\

Escape

Ein Literal abgleichen . oder $ in HTML

Für alles, was darüber hinausgeht, stütze dich lieber auf die Dokumentation des Python-Moduls „re und das offizielle „Regular Expression HOWTO“, anstatt Inhalte aus beliebigen Blogs zu kopieren und einzufügen.

Schritt für Schritt: Produkttitel und Preise mit Python scrapen

Um dies zu veranschaulichen, werden wir eine statische Produktlistenseite scrapen und zwei Felder extrahieren: den Produkttitel und den Preis. Wähle eine beliebige Sandbox oder einen Demo-Shop, für den du Scraping-Berechtigung hast; das unten stehende Muster geht von servergerenderten HTML-Seiten mit einer Karte pro Produkt aus. Die vier Teilschritte umfassen die Einrichtung der Umgebung, das Abrufen und Isolieren von Karten, das Schreiben von Mustern und das Speichern der strukturierten Ausgabe.

Python, requests und Beautiful Soup einrichten

Eine saubere virtuelle Umgebung hält Abhängigkeiten unter Kontrolle und sorgt für einen übersichtlichen Shell-Verlauf. Pythons re Modul ist in der Standardbibliothek enthalten, sodass nur der HTTP-Client und der Parser von Drittanbietern installiert werden müssen. Wenn Sie verschiedene Fetcher evaluieren, ist unsere Übersicht über Python-HTTP-Clients eine gute Lektüre.

python -m venv .venv
source .venv/bin/activate     # Windows: .venv\Scripts\activate
pip install requests beautifulsoup4
import csv
import re
import requests
from bs4 import BeautifulSoup

Seite abrufen und Produktkarten isolieren

Schränken Sie den Umfang immer ein, bevor Sie reguläre Ausdrücke verwenden. Wenn Sie Muster auf ein gesamtes HTML-Dokument anwenden, kann es passieren, dass Sie versehentlich auf das falsche Tag 2000 Zeilen weiter unten treffen. Verwenden Sie Beautiful Soup, um die Produktkarten zu extrahieren, und bearbeiten Sie dann den HTML-Code jeder Karte isoliert. Wenn requests.get ein fast leeres <body> und die Daten in einem <script> Tag oder erst nach der Ausführung von JS geladen werden, hilft Ihnen ein Regex-Ausdruck auf die rohe Antwort nicht weiter; Sie benötigen einen Headless-Browser oder eine Rendering-API.

URL = "https://example.com/products"  # replace with a target you are allowed to scrape
html = requests.get(URL, timeout=15).text
soup = BeautifulSoup(html, "html.parser")
cards = soup.find_all("div", attrs={"data-testid": "product-card"})

Schreibe Regex-Muster für Titel und Preise

Verankern Sie Ihre Muster an stabilen Attributen, nicht an gehashten CSS-Klassennamen wie css-7u5e79. Diese Klassen-Hashes werden bei jedem Frontend-Deployment neu generiert, und Ihr Scraper wird stillschweigend ausfallen. Bevorzugen Sie data-* Attribute, semantische Tags (<h4>, <h2>) oder itemprop Markup, wenn die Website dies bereitstellt.

TITLE_RE = re.compile(r'<h4[^>]*itemprop="name"[^>]*>(.*?)</h4>', re.DOTALL)
PRICE_RE = re.compile(r'<span[^>]*itemprop="price"[^>]*>\s*\$?([\d,]+\.\d{2})\s*</span>')

Drei Dinge, die es zu beachten gilt, wenn du auf dieser Ebene Web-Scraping mit regulären Ausdrücken verwendest:

  • (.*?) ist nicht-greedy; ohne das ? würde Ihre Titelübereinstimmung problemlos über mehrere Karten hinweg greifen.
  • [^>]* erlaubt dem Tag beliebige andere Attribute (class, id, Analytics-Hooks), ohne dass der Abgleich unterbrochen wird.
  • re.DOTALL erlaubt . Zeilenumbrüche abgleichen, sodass ein Titel, der in eine neue Zeile umbricht, dennoch erfasst wird.

Durchlaufe die Ergebnisse und speichere sie in einer strukturierten Datei

Reiner Text ist für die Fehlersuche in Ordnung, aber für die weitere Verarbeitung benötigen Sie fast immer CSV oder JSON. CSV mit expliziten Kopfzeilen macht die Ausgabe selbsterklärend und lässt sich leicht in Pandas oder eine Tabellenkalkulation laden. Speichern Sie rohes HTML, geparstes CSV und Ausführungsprotokolle in separaten Ordnern, damit sich bei erneuten Ausführungen die Daten nicht gegenseitig überschreiben.

rows = []
for card in cards:
    html_chunk = str(card)
    t = TITLE_RE.search(html_chunk)
    p = PRICE_RE.search(html_chunk)
    rows.append({
        "title": t.group(1).strip() if t else "",
        "price_usd": p.group(1) if p else "",
    })

with open("data/products.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=["title", "price_usd"])
    writer.writeheader()
    writer.writerows(rows)

Wechseln Sie bei verschachtelten Feldern (Varianten, Spezifikationen) zu JSON.

Kombiniere Regex mit Beautiful Soup für eine sauberere Extraktion

Regex und ein echter HTML-Parser sind keine Konkurrenten, sondern ergänzen sich. Beautiful Soup durchläuft den Baum und liefert dir einen fokussierten String, und die Verwendung von Regex mit Beautiful Soup wandelt diesen String in genau das gewünschte Feld um. Dies ist viel sicherer, als Web-Scraping mit Regex auf der rohen Antwort durchzuführen.

Zwei Muster, die es sich zu merken lohnt. Erstens: Übergeben Sie einen kompilierten Regex direkt an find_all oder find , um Tags nach Attributwerten zu filtern:

price_tags = soup.find_all("span", class_=re.compile(r"^price"))

Zweitens: Suche nach Elementen, deren sichtbarer Text einem Muster entspricht:

in_stock = soup.find_all(string=re.compile(r"\bIn stock\b", re.IGNORECASE))

Wenn Sie einen tieferen Einblick in die Parser-Seite wünschen, behandelt unser Beautiful-Soup-Leitfaden Selektoren, Navigation und Randfälle.

Fortgeschrittene Regex-Muster, die Scraper-Entwickler kennen sollten

Sobald Sie die Grundlagen hinter sich haben, machen eine Handvoll re Funktionen das Web-Scraping mit regulären Ausdrücken wesentlich wartungsfreundlicher.

  • Benannte Gruppen ((?P<name>...)) ersetzen die anfällige Positionsindexierung. m.group("price") ist selbsterklärend und bleibt auch bei einer Neuanordnung des Musters erhalten.
  • Mit Lookaheads und Lookbehinds kannst du Muster abgleichen, ohne sie zu verbrauchen. \d+(?= USD) erfasst eine Zahl nur, wenn USD darauf folgt; (?<=Price:\s)\$\d+ erfasst $199 erst nach dem literalen Label.
  • Flags sorgen für kurze Muster. re.IGNORECASE für In Stock vs in stock, re.DOTALL so . überschreitet Zeilenumbrüche, re.VERBOSE sodass du mehrzeilige Muster mit Kommentaren schreiben kannst.
  • re.compile Das zahlt sich aus, wenn du Tausende von Seiten scratest: einmal kompilieren, in der Schleife wiederverwenden und eine kleine, aber echte Beschleunigung erzielen.
  • re.finditer verarbeitet Übereinstimmungen verzögert, was speicherfreundlicher ist als findall bei riesigen Dokumenten.
PRICE = re.compile(r"\$(?P<amount>[\d,]+\.\d{2})(?=\s*USD)", re.IGNORECASE)
for m in PRICE.finditer(page_text):
    print(m.group("amount"))

Häufige Fallstricke und Grenzen des Web-Scrapings mit Regex

Eine ehrliche Liste von Dingen, die dir Probleme bereiten werden:

  • Hash-Klassenamen (css-7u5e79 eag3qlw7) ändern sich bei jedem Deploy. Verwenden Sie stattdessen Anker data-*, itempropoder semantischen Tags.
  • Verschachtelte Tags führen dazu, dass einfache (.*?) Übereinstimmungen, wenn der innere HTML-Code denselben Tag enthält, den du schließen möchtest.
  • Fehlerhaftes HTML (nicht geschlossene Tags, falsch gepaarte Anführungszeichen) macht Regex anfällig; ein echter Parser toleriert dies.
  • Von JavaScript gerenderte Inhalte befinden sich einfach nicht im Antworttext. Regex kann keine Daten zaubern, die der Server nie gesendet hat.
  • Kodierungsprobleme schleichen sich über &amp;, &#x27;und Smart Quotes; normalisiere den Text vor dem Abgleich.

Wenn zwei dieser Probleme gleichzeitig auftreten, wechsle zu Selektoren oder einer Rendering-API, die Post-JS-HTML zurückgibt.

Regex vs. XPath und CSS-Selektoren: Was soll man wählen?

Verwenden Sie Selektoren für die Struktur, Regex für den Text innerhalb dieser Struktur. CSS-Selektoren sind prägnant und schnell für klassen- und tagbasierte Suchvorgänge; XPath ist ausdrucksstärker, wenn Sie Achsen, Positionen oder Textprädikate benötigen. Regex kommt ins Spiel, sobald Sie den richtigen Knoten haben und dessen Zeichenfolge analysieren müssen. Unser XPath-Leitfaden und der Vergleich zwischen XPath und CSS-Selektoren gehen tiefer, wenn Sie sich zwischen den beiden entscheiden müssen.

Wichtige Erkenntnisse

  • Behandeln Sie Web-Scraping mit regulären Ausdrücken als Präzisionswerkzeug für kurze, vorhersehbare Textmuster; behalten Sie die vollständige HTML-Baumnavigation in Beautiful Soup oder lxml bei.
  • Verankern Sie Muster immer an stabilen Attributen (data-*, itemprop, semantische Tags), nicht an gehashten CSS-Klassennamen, die sich bei jedem Deploy ändern.
  • Kombinieren find/find_all mit re.compile , damit Muster auf isolierten Knoten statt auf dem gesamten Antworttext ausgeführt werden.
  • Nutzen Sie benannte Gruppen, Lookaheads re.DOTALL, re.IGNORECASEund re.compile sobald Ihr Scraper über eine einzelne Seite hinauswächst.
  • Speichern Sie die Ausgabe als CSV (oder JSON für verschachtelte Daten) mit expliziten Kopfzeilen und einer übersichtlichen Ordnerstruktur, um die Reproduzierbarkeit zu gewährleisten.

FAQ

Kann ich JavaScript-gerenderte Seiten allein mit Regex scrapen?

Nein. Regex findet Zeichen, die bereits in der Antwort enthalten sind. Wenn die benötigten Werte durch clientseitiges JavaScript in das DOM eingefügt werden, enthält der von requests einfach nicht enthalten. Du benötigst einen Headless-Browser (Playwright, Puppeteer, Selenium) oder eine Rendering-API, die das HTML nach der JS-Verarbeitung zurückgibt; dann kannst du Regex auf diese Ausgabe anwenden.

Wie teste ich Regex-Muster, bevor ich sie in Produktion nehme?

Verwenden Sie einen interaktiven Tester wie regex101 oder pythex, um Muster anhand repräsentativer HTML-Schnipsel zu validieren, wobei Sie die Python-Variante auswählen sollten. Fügen Sie anschließend kleine Unit-Tests hinzu, die jedes Muster anhand einer gespeicherten Fixture-Datei ausführen und die erfassten Gruppen überprüfen. Fixtures schützen Sie, wenn sich die Website ändert, da ein fehlgeschlagener Test genau auf das Muster hinweist, das nicht mehr funktioniert.

Sollte ich re.compile() verwenden, wenn ich viele Seiten scrape?

Ja. re.compile() parst das Muster einmal und verwendet das kompilierte Objekt über mehrere Aufrufe hinweg wieder, wodurch wiederholte Parsing-Kosten innerhalb von Hot Loops vermieden werden. Der Leistungsgewinn bei einer einzelnen Übereinstimmung ist gering, summiert sich aber über Tausende von Seiten hinweg. Der größere Vorteil ist die Lesbarkeit: Kompilierte Muster können auf der obersten Ebene des Moduls mit eindeutigen Namen statt als Inline-String-Literale stehen.

Was ist der Unterschied zwischen „greedy“ und „non-greedy“ Matching beim Scrapen von HTML?

Greedy-Quantifizierer (*, +) passen so viel Text wie möglich an, was Inhalte über mehrere Datensätze hinweg verschlingen kann. Non-greedy-Varianten (*?, +?) finden so wenig Text wie möglich und hören beim ersten gültigen Abschlusszeichen auf. Bei der HTML-Extraktion (.*?)</h4> erfasst korrekt einen Titel; (.*)</h4> würde das gesamte Dokument bis zum letzten </h4>.

Wie gehe ich mit mehrzeiligen Übereinstimmungen und ungewöhnlichen Leerzeichen in gescraptem HTML um?

Pass re.DOTALL so . erfasst Zeilenumbrüche, und re.MULTILINE wenn du mit ^ oder $ pro Zeile. Verwenden Sie für ungleichmäßige Leerzeichen innerhalb von Tags \s* (null oder mehr Leerzeichen, einschließlich Zeilenumbrüche) zwischen erwarteten Tokens anstelle von literalen Leerzeichen. Normalisieren Sie Entitäten (&amp;, &nbsp;) und Unicode-Anführungszeichen vor dem Abgleich, damit sie nicht unbemerkt ansonsten korrekte Muster unterbrechen.

Zusammenfassung und nächste Schritte

Web-Scraping mit Regex ist ein scharfes Werkzeug, aber kein Allzweckwerkzeug. Setzen Sie es dort ein, wo es sich bewährt: beim Zerlegen kurzer, vorhersehbarer Zeichenfolgen innerhalb von HTML, die Sie bereits mit einem Parser isoliert haben. Halten Sie Ihre Muster an stabilen Attributen fest, bevorzugen Sie benannte Gruppen und kompilierte Muster, und wechseln Sie zu Selektoren oder einer Rendering-Schicht, sobald die Seite JavaScript-lastig wird oder das Markup verschachtelt ist. Die meisten Scraper in der Produktion nutzen letztendlich eine Kombination aus Regex, Beautiful Soup und HTTP-Clients; wählen Sie die Ebene, die zu dem Feld passt, das Sie extrahieren, und belassen Sie es dabei.

Wenn Sie sich lieber nicht um Proxys, Wiederholungsversuche und CAPTCHAs kümmern möchten, während Sie sich auf Muster konzentrieren, liefert die WebScrapingAPI unseres Teams gerenderte HTML-Daten und strukturiertes JSON über einen einzigen Endpunkt, sodass Ihr re und Ihr Beautiful-Soup-Code weiter funktioniert, während die Anfrageebene für Sie abgewickelt wird. Als nächste Lektüre empfehlen wir unseren umfassenden Python-Web-Scraping-Leitfaden und das Daten-Parsing-Handbuch, um extrahierte Felder in saubere Datensätze umzuwandeln.

Über den Autor
Mihai Maxim, Full-Stack-Entwickler @ WebScrapingAPI
Mihai MaximFull-Stack-Entwickler

Mihai Maxim ist Full-Stack-Entwickler bei WebScrapingAPI, wo er in verschiedenen Bereichen des Produkts mitwirkt und an der Entwicklung zuverlässiger Tools und Funktionen für die Plattform mitarbeitet.

Los geht’s

Sind Sie bereit, Ihre Datenerfassung zu erweitern?

Schließen Sie sich den über 2.000 Unternehmen an, die WebScrapingAPI nutzen, um Webdaten im Unternehmensmaßstab ohne zusätzlichen Infrastrukturaufwand zu extrahieren.