ReviewProof

Dieses Projekt ist ein Python-basiertes Web-Scraping-System zur Erfassung umfassender Daten ueber lokale Geschaefte in Bielefeld, Deutschland - einschliesslich Restaurants, Aerzten, Cafes, Geschaeften und mehr. Der Scraper nutzt Playwright (eine moderne Browser-Automatisierungsbibliothek), um mit Google Search zu interagieren und Geschaeftsinformationen zu extrahieren, darunter Bewertungen, Rezensionsanzahlen, Adressen, Telefonnummern und DSGVO-bezogene Loeschhinweise.

Scraper Interface

Hauptziele:

  • Erfassung von Daten von 500+ Geschaeften aus mehreren Kategorien
  • Erfassung von Bewertungen, Rezensionsanzahlen, Adressen und Loeschhinweisen
  • Datenqualitaet durch strenge Validierungsregeln gewaehrleisten
  • Eine wiederverwendbare, wartbare Scraper-Architektur aufbauen
  • Mehrere Geschaeftstypen unterstuetzen: Restaurants, Aerzte, Geschaefte, Cafes

Architektur

Systemuebersicht

Loading diagram...

Komponentenarchitektur

Loading diagram...

Daten-Pipeline

Ende-zu-Ende-Flow

Loading diagram...

Phase 1: Suche und Sammlung

Der Scraper verwendet eine Multi-Term-Suchstrategie fuer maximale Abdeckung verschiedener Geschaeftstypen:

Jeder Suchbegriff durchsucht 3 Seiten mal 10 Ergebnisse equals 30 potenzielle Eintraege pro Begriff. Mit 6 Suchbegriffen sind das bis zu 180 potenzielle Eintraege.

Search Results

Phase 2: Namensextraktion

Loading diagram...

Phase 3: Individuelles Scraping

Loading diagram...

Scraping-Methodik

Browser-Setup

Wichtige Konfigurationen:

  • headless=False: fuer visuelle Fehlersuche
  • AutomationControlled Flag: Bot-Erkennung umgehen
  • no-sandbox: fuer einige Linux-Umgebungen erforderlich

Such-URL-Muster

| Parameter | Wert | Zweck | |-----------|------|--------| | q | Suchbegriff | Google-Abfrage | | tbm=lcl | local | Lokale Geschaeftsergebnisse | | hl=de-DE | Deutsch | Deutsche Sprachergebnisse | | start | 0, 10, 20 | Seitennummerierung |

Loading diagram...

Datenextraktionsmuster

Bewertungsmuster

Adressmuster

Geloeschte Rezensionen (DSGVO)

Datenvalidierung und Bereinigung

Validierungsregeln

Loading diagram...

Filter-Mathematik

Der Namensfilter-Algorithmus verwendet praezise mathematische Beschraenkungen. Er validiert Namen zwischen 8-70 Zeichen und verwendet Schluesselwort-Mengenoperationen um sicherzustellen, dass nur gueltige Geschaeftsnamen enthalten sind. Fuzzy-Abgleich mit Levenshtein-Distanz hilft doppelte Eintraege zu erkennen und zu entfernen.

Geschaefts-Schluesselwoerter

Das Filtersystem unterstuetzt mehrere Geschaeftskategorien:

Ablehnungsmuster

Saubere Kategorien

Das System kategorisiert Geschaefte automatisch in:

Medizinisch:

  • Aerzte (Dr., Dr. med., Prof.)
  • Praxen (Praxis, Gemeinschaftspraxis)
  • Kliniken (Klinik, Krankenhaus)
  • Zahnarzte (Zahnarzt, Zahnärzte)
  • Fachärzte (Facharzt, Centrum)
  • Therapiezentren

Restaurants und Essen:

  • Restaurants (Restaurant, Gastronomie)
  • Cafes (Cafe, Konditorei)
  • Fast Food (Pizza, Doener, Grill)
  • Baeckereien (Baeckerei)

Einzelhandel und Dienstleistungen:

  • Geschaefte und Laeden
  • Elektronik (Elektro, Elektronik)
  • Mode (Mode, Boutique)
  • Maerkte (Markt)

Validation Process

Statistische Formeln

Datenqualitaet wird mit statistischen Metriken gemessen:

  • Durchschnittsbewertung: mean = SUM(x) / n

  • Standardabweichung: std = sqrt(SUM((x-mean)^2)/n)

  • Daten-Vollstaendigkeitsraten:

    • Bewertungs-Vollstaendigkeit: R = count(rating) / total * 100%
    • Adress-Vollstaendigkeit: A = count(address) / total * 100%
    • Geloeschte Rezensionen: D = count(deleted) / total * 100%
  • Bewertungs-Histogramm-Bins: | Bin | Bereich | Anzahl | |-----|---------|--------| | 1 | 4.5-5.0 | 89 | | 2 | 4.0-4.4 | 45 | | 3 | 3.5-3.9 | 18 | | 4 | unter 3.5 | 5 |

  • Kategorieverteilungs-Prozentsaetze:

    • Arzt: 62/157 = 39.5%
    • Zahnarzt: 35/157 = 22.3%
    • Klinik: 28/157 = 17.8%
    • Arztpraxis: 20/157 = 12.7%
    • Facharzt: 12/157 = 7.6%

Zeitberechnungen

Leistungszeit wird wie folgt berechnet:

  • Seitenladezeit-Schaetzungen:

    • Durchschnittliche Ladezeit: t_load = 1.8s +/- 0.5s
    • Timeout-Schwelle: t_max = 10s
  • Zufaellige Verzoegerungsverteilung: U(1.0, 2.0) Sekunden zwischen Anfragen

  • Gesamtlaufzeit-Formel: T_total = n * (t_load + t_parse + t_save) + d * (n-1) wobei: n = Anzahl der Eintraege t_load = 1.8s durchschnittliche Seitenladung t_parse = 0.3s Parsing-Zeit t_save = 0.1s Datenbank-Schreibzeit d = Zufallsverzoegerung ~ U(1.0, 2.0)

    Fuer 157 Eintraege: T = 157 * (1.8 + 0.3 + 0.1) + 156 * 1.5 = 680s = 11 Minuten

Leistungsanalyse

| Operation | Zeitkomplexitaet | Beschreibung | |-----------|----------------|-------------| | Namensfilterung | O(n) | Lineare Scan der Token-Menge | | Fuzzy-Abgleich | O(n * m) | Levenshtein auf alle Paare | | Bewertungsextraktion | O(1) | Ein einzelner Regex-Abgleich | | DB-Insert/Update | O(1) | Hash-Tabellen-Lookup | | CSV-Export | O(n) | Vollstaendiger Tabellenscan |

  • Speicherschaetzung:

    • Roher HTML-Puffer: ~5MB pro Seite
    • Namen-Menge: ~50KB fuer 1000 Namen
    • SQLite-DB: ~500KB fuer 157 Eintraege
    • Gesamt-Spitze: ~10MB
  • Durchsatz-Berechnung: throughput = entries / time = 157 / 680s = 0.23 Eintraege/Sekunde

Erweiterte Berechnungen

  • Haversine-Distanz (fuer zukuenftige Kartenvisualisierung):

  • Google Maps Koordinaten-Extraktion:

  • Qualitaetsbewertungs-Algorithmus (0-100):

Datenbankschema

SQLite-Schema

Entity-Beziehung

Loading diagram...

Feldbeschreibungen

| Feld | Typ | Beschreibung | Beispiel | |-------|------|-------------|---------| | id | INTEGER | Primaerschluessel | 1 | | name | TEXT | Geschaeftsname | "Dr. med. Hans Mueller" | | rating | TEXT | Bewertung (1.0-5.0) | "4.5" | | total_reviews | TEXT | Anzahl der Rezensionen | "103" | | deleted_reviews | TEXT | DSGVO-Loeschhinweis | "Einige Ergebnisse..." | | address | TEXT | Vollstaendige Adresse | "Adresse: Hauptstr. 1, 33602 Bielefeld" | | url | TEXT | Google Maps URL | "https://www.google.com/maps/..." | | category | TEXT | Auto-kategorisierte Kategorie | "Doctor", "Dentist", "Clinic" | | scrape_date | TEXT | Erstes Scraping-Datum | "2026-05-11" | | last_updated | TEXT | Letztes Aktualisierungsdatum | "2026-05-11" | | status | TEXT | Aktiv/Inaktiv | "active" |

Kategorie-Auto-Tagging

Datenfluss-Diagramme

Vollstaendiger Pipeline

Loading diagram...

Fehlerbehandlungsflow

Loading diagram...

Herausforderungen und Loesungen

Herausforderung 1: Dynamische Google-UI

Problem: Google aendert haeufig die HTML-Struktur und CSS-Klassennamen.

Loesung: Textbasierte Extraktion statt CSS-Selektoren verwenden:

Vorher (Selektor-basiert):

Nachher (Text-basiert):

Problem: Google zeigt Cookie-Consent-Overlay, das Inhalte blockiert.

Loesung: Automatisches Button-Klicken mit mehreren Versuchen:

Herausforderung 3: Nicht-medizinische Eintraege

Problem: Suchergebnisse enthalten Fitnessstudios, Apotheken, Optiker.

Loesung: Strenge Filterung mit Schluesselwortvalidierung:

Herausforderung 4: Doppelte Eintraege

Problem: Gleiche Klinik erscheint unter verschiedenen Namen.

Loesung: Datenbank-Level-Deduplizierung mit Namen-Abgleich:

Herausforderung 5: Fehlende Bewertungsdaten

Problem: Einige Eintraege zeigen keine Bewertungen.

Loesung: Strenge Validierung - nur Eintraege mit vollstaendigen Daten speichern:

Scraping Results

Ergebnisse und Statistiken

Aktueller Datensatz

| Metrik | Wert | |--------|-------| | Gesamteintraege | 157 | | Mit Bewertungen | 157 (100%) | | Mit Rezensionen | 157 (100%) | | Mit geloeschten Rezensionen | 58 (37%) | | Mit Adressen | 16 (10%) |

Bewertungsverteilung

Loading diagram...

Kategorieaufschluesselung

| Kategorie | Anzahl | Prozentsatz | |----------|----|-------------| | Arzt | 62 | 39% | | Zahnarzt | 35 | 22% | | Klinik | 28 | 18% | | Arztpraxis | 20 | 13% | | Facharzt | 12 | 8% |

Geloeschte Rezensionen Analyse

Loading diagram...

Results Dashboard

Technischer Stack

Abhaengigkeiten

Dateistruktur

Database Structure

Zukuenftige Verbesserungen

Geplante Verbesserungen

  1. Parallele Verarbeitung

    • Mehrere Browser-Kontexte gleichzeitig verwenden
    • Gesamt-Scraping-Zeit um 50% reduzieren
  2. Erweiterte Validierung

    • Fuzzy-Namensabgleich fuer Duplikaterkennung
    • URL-basierte Deduplizierung als Backup
  3. Adressextraktion

    • Regex-Muster fuer deutsche Adressen verbessern
    • Mehrere Adressformate parsen
  4. Rezensionsinhalt

    • Tatsaechlichen Rezensionstext erfassen (mit Consent)
    • Stimmungsanalyse auf Rezensionen
  5. Ueberwachung

    • Aenderungen ueber Zeit verfolgen (Re-Scraping-Erkennung)
    • Warnung bei Bewertungsaenderungen

Potenzielle Erweiterungen

Anhang: Code-Referenz

Hauptschleifen-Struktur

CSV-Export-Funktion


Fazit

Dieses Projekt demonstriert einen praktischen Ansatz zur automatisierten Datensammlung aus Web-Suchergebnissen:

  1. Textbasierte Extraktion ist robuster als CSS-Selektoren fuer dynamische Webseiten
  2. Strenge Validierung gewaehrleistet hohe Datenqualitaet, auch wenn es weniger Eintraege bedeutet
  3. Modulares Design ermöglicht einfache Wartung und Erweiterung
  4. Automatisierte Bereinigung erkennt schlechte Eintraege, die durch die anfängliche Filterung rutschen
  5. Mathematische Validierung liefert quantifizierbare Datenqualitaetsmetriken

Der Scraper erfasst erfolgreich validierte Geschaeftsdaten aus Bielefeld, wobei 100% der Eintraege Bewertungen und Rezensionsanzahlen enthalten. Die Architektur ist fuer Erweiterbarkeit auf andere Staedte und Datenquellen ausgelegt.


Dokumentversion: 1.1
Zuletzt aktualisiert: 11. Mai 2026
Lizenz: MIT

Created:
5/11/2026
Last Updated:
5/11/2026