Zurück zum Blog
Anleitungen & How-tos2026-03-15·12 Min. Lesezeit

Google Maps Bewertungen mit Python scrapen: Leitfaden 2025

Von Ibrahim DemolCEO IBLeadAktualisiert am 12. Juni 2026

Wenn du Google Maps Bewertungen mit Python scrapen möchtest, hast du es mit einem der schwierigeren Scraping-Ziele im Web zu tun. Google lädt Bewertungen dynamisch, ändert seine HTML-Struktur und erkennt aktiv Bots. Dieser Leitfaden behandelt zwei funktionierende Methoden – Playwright und Selenium – mit vollständigem Code, Anti-Detection-Techniken und ehrlichen Hinweisen darauf, was nicht funktioniert und warum.

Keine Floskeln. Nur funktionierender Code.


Was ist Google Bewertungen Scraping?

Google Bewertungen Scraping ist die automatisierte Extraktion von Kundenbewertungsdaten aus Google Maps und Google Business-Einträgen. Anstatt Bewertungen manuell zu kopieren, besucht ein Skript die Unternehmensseiten und zieht die Daten für dich.

Jede Bewertung enthält nützliche Felder:

  • Sternbewertung (1–5)
  • Bewertungstext
  • Name des Bewerters
  • Datum der Veröffentlichung
  • Antwort des Unternehmens (falls vorhanden)

Diese Daten haben echten Wert. Reputationsüberwachung, Wettbewerbsanalyse, Sentiment-Tracking, Lead-Qualifizierung – all das beginnt mit Rohdaten aus Bewertungen.

Warum nicht die offizielle Google API verwenden?

Die Google Places API gibt dir Bewertungen, aber mit strengen Limits. Du erhältst maximal 5 Bewertungen pro Unternehmen. Keine historischen Daten. Keine Wettbewerbsbewertungen. Die Preise steigen schnell, sobald du das kostenlose Kontingent überschreitest.

Web Scraping gibt dir Zugang zu allen öffentlichen Bewertungen, ohne künstliche Obergrenze. Der Nachteil: Du musst die Anti-Bot-Systeme von Google selbst handhaben.


Warum Python für diese Aufgabe?

Python hat das beste Ökosystem für Browserautomatisierung und Datenextraktion. Drei Bibliotheken übernehmen den Großteil der schweren Arbeit:

  • Playwright – modern, schnell, async-ready, integrierte Stealth-Funktionen
  • Selenium – bewährt, große Community, maximale Kompatibilität
  • BeautifulSoup – leichtgewichtiges HTML-Parsen, sobald du den Rohinhalt hast

Google Bewertungen laden über JavaScript. Statische Scraper (Requests + BeautifulSoup allein) funktionieren hier nicht. Du benötigst einen echten Browser, der JS ausführt, die Seite scrollt und Schaltflächen klickt – genau das tun Playwright und Selenium.


Die zentrale Herausforderung: Warum Google zurückschlägt

Bevor du eine einzige Zeile Code schreibst, solltest du verstehen, mit was du es zu tun hast.

Dynamisches Laden von Inhalten

Google zeigt nicht alle Bewertungen im ursprünglichen HTML. Der erste Seitenaufruf zeigt 10–20 Bewertungen. Weitere laden, während du scrollst. Jede Gruppe löst separate Netzwerk-Anfragen aus. Dein Scraper muss das Scrollen simulieren, um diese Ladevorgänge auszulösen.

Bot-Erkennungsschichten

Google betreibt mehrere Erkennungssysteme gleichzeitig:

  • Browser-Fingerabdruck – Bildschirmauflösung, Schriftarten, Zeitzone, Sprache
  • Verhaltensanalyse – Mausbewegungsmuster, Scrollgeschwindigkeit, Klicktiming
  • Anfrage-Mustererkennung – nicht-menschliche Anfragefrequenz
  • IP-Reputation – Kennzeichnung von IPs, die zu viele Anfragen senden

Wenn du einen dieser Auslöser triffst, siehst du CAPTCHAs, leere Ergebnisse oder eine vollständige Sperre.

Ständig wechselnde HTML-Struktur

Google aktualisiert regelmäßig sein Frontend. Ein CSS-Selektor, der heute funktioniert, kann nächste Woche null Ergebnisse zurückgeben. Robuste Scraper verwenden mehrere Fallback-Selektoren für jedes Feld.


Methode 1: Playwright (Empfohlen für 2025)

Playwright ist der bessere Ausgangspunkt für neue Projekte. Es ist 2–3x schneller als Selenium, hat integrierte Async-Unterstützung und handhabt Anti-Detection mit weniger manueller Konfiguration.

Setup

python -m venv google_scraper_env
source google_scraper_env/bin/activate  # Windows: google_scraper_env\Scripts\activate
pip install playwright pandas emoji beautifulsoup4 lxml
playwright install chromium

Vollständiger Playwright Scraper

from playwright.sync_api import sync_playwright
import pandas as pd
import re
import emoji
import logging
import time
import random

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

class GoogleReviewsScraper:
    def __init__(self, headless=True):
        self.headless = headless
        self.reviews_data = []

    def clean_text(self, text):
        text = emoji.replace_emoji(text, replace='')
        text = re.sub(r'\s+', ' ', text).strip()
        return text

    def random_delay(self, min_delay=1, max_delay=3):
        time.sleep(random.uniform(min_delay, max_delay))

    def initialize_browser(self):
        playwright = sync_playwright().start()
        browser = playwright.chromium.launch(
            headless=self.headless,
            args=[
                '--disable-blink-features=AutomationControlled',
                '--disable-extensions',
                '--no-sandbox',
                '--disable-setuid-sandbox',
                '--disable-dev-shm-usage',
                '--disable-gpu'
            ]
        )
        context = browser.new_context(
            user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
            viewport={'width': 1366, 'height': 768}
        )
        page = context.new_page()
        page.add_init_script("""
            Object.defineProperty(navigator, 'webdriver', {
                get: () => undefined,
            });
        """
)
        return playwright, browser, page

    def search_business(self, page, business_name):
        try:
            page.goto("https://www.google.com/maps", wait_until="networkidle")
            self.random_delay(2, 4)
            search_box = page.locator("input[id='searchboxinput']")
            search_box.fill(business_name)
            search_box.press("Enter")
            page.wait_for_timeout(5000)
            logger.info(f"Searched for: {business_name}")
            return True
        except Exception as e:
            logger.error(f"Error searching: {e}")
            return False

    def navigate_to_reviews(self, page):
        try:
            reviews_tab = page.get_by_role("tab", name=re.compile("Reviews|reviews", re.IGNORECASE))
            if reviews_tab.is_visible():
                reviews_tab.click()
                page.wait_for_timeout(3000)
                logger.info("Navigated to reviews section")
                return True
            logger.warning("Reviews tab not found")
            return False
        except Exception as e:
            logger.error(f"Error navigating to reviews: {e}")
            return False

    def scroll_and_load_reviews(self, page, max_reviews=100):
        loaded_reviews = 0
        scroll_attempts = 0
        max_scroll_attempts = 20

        while loaded_reviews < max_reviews and scroll_attempts < max_scroll_attempts:
            try:
                page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
                self.random_delay(2, 4)
                current_reviews = page.locator('[data-review-id]').count()
                if current_reviews > loaded_reviews:
                    loaded_reviews = current_reviews
                    logger.info(f"Loaded {loaded_reviews} reviews...")
                    scroll_attempts = 0
                else:
                    scroll_attempts += 1
                try:
                    more_button = page.locator("button", has_text=re.compile("more|More", re.IGNORECASE))
                    if more_button.is_visible():
                        more_button.click()
                        self.random_delay(2, 3)
                except:
                    pass
            except Exception as e:
                logger.error(f"Error during scrolling: {e}")
                break

        logger.info(f"Total reviews found: {loaded_reviews}")
        return loaded_reviews

    def extract_review_data(self, page):
        reviews = []
        try:
            review_elements = page.locator('[data-review-id]').all()
            for element in review_elements:
                try:
                    review_data = {}

                    name_element = element.locator('div[class*="name"] span, div[class*="Name"] span').first
                    review_data['reviewer_name'] = name_element.inner_text() if name_element.is_visible() else "Anonymous"

                    rating_element = element.locator('[role="img"][aria-label*="star"]').first
                    if rating_element.is_visible():
                        rating_text = rating_element.get_attribute('aria-label')
                        rating_match = re.search(r'(\d+)', rating_text)
                        review_data['rating'] = int(rating_match.group(1)) if rating_match else None

                    text_elements = element.locator('span[class*="review-text"], div[class*="review-text"]').all()
                    review_text = ""
                    for text_elem in text_elements:
                        if text_elem.is_visible():
                            review_text += text_elem.inner_text() + " "
                    review_data['review_text'] = self.clean_text(review_text.strip())

                    date_element = element.locator('span[class*="date"], div[class*="date"]').first
                    review_data['review_date'] = date_element.inner_text() if date_element.is_visible() else "Unknown"

                    if review_data['review_text']:
                        reviews.append(review_data)
                except Exception as e:
                    logger.warning(f"Error on individual review: {e}")
                    continue

            logger.info(f"Extracted {len(reviews)} reviews")
            return reviews
        except Exception as e:
            logger.error(f"Extraction error: {e}")
            return []

    def scrape_reviews(self, business_name, max_reviews=100):
        playwright, browser, page = self.initialize_browser()
        try:
            if not self.search_business(page, business_name):
                return []
            if not self.navigate_to_reviews(page):
                return []
            self.scroll_and_load_reviews(page, max_reviews)
            reviews = self.extract_review_data(page)
            self.reviews_data = reviews
            return reviews
        except Exception as e:
            logger.error(f"Scraping failed: {e}")
            return []
        finally:
            browser.close()
            playwright.stop()

    def save_to_csv(self, filename="google_reviews.csv"):
        if self.reviews_data:
            df = pd.DataFrame(self.reviews_data)
            df.to_csv(filename, index=False, encoding='utf-8')
            logger.info(f"Saved to {filename}")
        else:
            logger.warning("No reviews to save")

if __name__ == "__main__":
    scraper = GoogleReviewsScraper(headless=False)
    business_name = "Starbucks Times Square New York"
    reviews = scraper.scrape_reviews(business_name, max_reviews=50)
    if reviews:
        scraper.save_to_csv(f"reviews_{business_name.replace(' ', '_')}.csv")
        print(f"Scraped {len(reviews)} reviews.")
    else:
        print("No reviews scraped.")

Was dieser Code tut

  • Stealth-Flags verbergen den Automatisierungsfingerabdruck vor der Erkennungsschicht von Google
  • Zufällige Verzögerungen zwischen 1–4 Sekunden ahmen den menschlichen Browsing-Rhythmus nach
  • Scroll-Schleife lädt weiter, bis sie max_reviews erreicht oder der Inhalt erschöpft ist
  • Mehrere Fallback-Selektoren bewältigen die häufigen HTML-Änderungen von Google
  • CSV-Export liefert eine saubere Datei, die bereit für die Analyse oder den Import in jedes Tool ist

Methode 2: Selenium (Zuverlässige Alternative)

Selenium ist seit über einem Jahrzehnt der Standard für Browserautomatisierung. Es ist langsamer als Playwright, hat aber eine größere Community und mehr Dokumentation.

Wann man Selenium wählen sollte

  • Du arbeitest mit einer Legacy-Infrastruktur, die es bereits verwendet
  • Du benötigst maximale Kompatibilität über Browser-Versionen hinweg
  • Dein Team hat bestehende Selenium-Expertise

Setup

pip install selenium pandas

Du benötigst auch ChromeDriver, der mit deiner Chrome-Version übereinstimmt. Modernes Selenium (4.6+) verwaltet die Treiberverwaltung automatisch.

Vollständiger Selenium Scraper

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.action_chains import ActionChains
from selenium.common.exceptions import TimeoutException, NoSuchElementException
import pandas as pd
import time
import random
import re
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class SeleniumGoogleReviewsScraper:
    def __init__(self, headless=True):
        self.headless = headless
        self.driver = None
        self.wait = None
        self.reviews_data = []

    def setup_driver(self):
        options = Options()
        if self.headless:
            options.add_argument("--headless")
        options.add_argument("--disable-blink-features=AutomationControlled")
        options.add_experimental_option("excludeSwitches", ["enable-automation"])
        options.add_experimental_option('useAutomationExtension', False)
        options.add_argument("--no-sandbox")
        options.add_argument("--disable-dev-shm-usage")
        options.add_argument("--window-size=1366,768")
        options.add_argument("--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")

        self.driver = webdriver.Chrome(options=options)
        self.driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined,});")
        self.wait = WebDriverWait(self.driver, 20)
        logger.info("Driver initialisiert")

    def random_delay(self, min_s=1, max_s=3):
        time.sleep(random.uniform(min_s, max_s))

    def search_google_maps(self, business_name):
        try:
            self.driver.get("https://www.google.com/maps")
            self.random_delay(2, 4)
            search_box = self.wait.until(EC.presence_of_element_located((By.ID, "searchboxinput")))
            search_box.clear()
            for char in business_name:
                search_box.send_keys(char)
                time.sleep(random.uniform(0.05, 0.15))
            search_box.submit()
            self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "[data-value='Reviews']")))
            logger.info(f"Searched for: {business_name}")
            return True
        except TimeoutException:
            logger.error("Timeout bei der Suche")
            return False

    def click_reviews_tab(self):
        try:
            reviews_tab = self.wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "[data-value='Reviews']")))
            self.driver.execute_script("arguments[0].scrollIntoView(true);", reviews_tab)
            self.random_delay(1, 2)
            reviews_tab.click()
            self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "[data-review-id]")))
            logger.info("Bewertungs-Tab angeklickt")
            return True
        except TimeoutException:
            logger.error("Bewertungs-Tab nicht gefunden")
            return False

    def scroll_to_load_reviews(self, target_reviews=100):
        last_height = self.driver.execute_script("return document.body.scrollHeight")
        reviews_loaded = 0
        scroll_attempts = 0

        while reviews_loaded < target_reviews and scroll_attempts < 30:
            self.driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
            self.random_delay(2, 4)
            try:
                show_more = self.driver.find_element(By.XPATH, "//button[contains(text(), 'more') or contains(text(), 'More')]" )
                if show_more.is_displayed():
                    ActionChains(self.driver).move_to_element(show_more).click().perform()
                    self.random_delay(2, 3)
            except NoSuchElementException:
                pass

            current_count = len(self.driver.find_elements(By.CSS_SELECTOR, "[data-review-id]"))
            if current_count > reviews_loaded:
                reviews_loaded = current_count
                logger.info(f"Loaded {reviews_loaded} reviews...")
                scroll_attempts = 0
            else:
                scroll_attempts += 1

            new_height = self.driver.execute_script("return document.body.scrollHeight")
            if new_height == last_height:
                scroll_attempts += 1
            last_height = new_height

        return reviews_loaded

    def extract_reviews(self):
        reviews = []
        review_elements = self.driver.find_elements(By.CSS_SELECTOR, "[data-review-id]")
        for element in review_elements:
            try:
                review_data = {}
                try:
                    review_data['reviewer_name'] = element.find_element(By.CSS_SELECTOR, "div[class*='name'] span").text.strip()
                except NoSuchElementException:
                    review_data['reviewer_name'] = "Anonymous"
                try:
                    aria_label = element.find_element(By.CSS_SELECTOR, "[role='img'][aria-label*='star']").get_attribute('aria-label')
                    match = re.search(r'(\d+)', aria_label)
                    review_data['rating'] = int(match.group(1)) if match else None
                except NoSuchElementException:
                    review_data['rating'] = None
                try:
                    text_elems = element.find_elements(By.CSS_SELECTOR, "span[class*='review-text']")
                    review_data['review_text'] = " ".join([e.text for e in text_elems if e.text]).strip()
                except NoSuchElementException:
                    review_data['review_text'] = ""
                try:
                    review_data['review_date'] = element.find_element(By.CSS_SELECTOR, "span[class*='date']").text.strip()
                except NoSuchElementException:
                    review_data['review_date'] = "Unknown"

                if review_data['review_text']:
                    reviews.append(review_data)
            except Exception as e:
                logger.warning(f"Fehler bei der Bewertungsextraktion: {e}")
                continue

        logger.info(f"Extrahierte {len(reviews)} Bewertungen")
        return reviews

    def scrape_business_reviews(self, business_name, max_reviews=100):
        try:
            self.setup_driver()
            if not self.search_google_maps(business_name):
                return []
            if not self.click_reviews_tab():
                return []
            self.scroll_to_load_reviews(max_reviews)
            reviews = self.extract_reviews()
            self.reviews_data = reviews
            return reviews
        except Exception as e:
            logger.error(f"Scraping fehlgeschlagen: {e}")
            return []
        finally:
            if self.driver:
                self.driver.quit()

    def save_to_csv(self, filename="selenium_reviews.csv"):
        if self.reviews_data:
            pd.DataFrame(self.reviews_data).to_csv(filename, index=False, encoding='utf-8')
            logger.info(f"Gespeichert in {filename}")

if __name__ == "__main__":
    scraper = SeleniumGoogleReviewsScraper(headless=False)
    reviews = scraper.scrape_business_reviews("McDonald's Times Square", max_reviews=75)
    if reviews:
        scraper.save_to_csv("mcdonalds_times_square_reviews.csv")
        print(f"Scraped {len(reviews)} reviews.")

Anti-Detection-Techniken, die tatsächlich funktionieren

Beide Scraper oben enthalten grundlegende Stealth. Hier ist, was du hinzufügen solltest, wenn du weiter gehen musst.

Proxy-Rotation

Single-IP-Scraping wird schnell blockiert. Rotiere Proxys, um Anfragen zu verteilen:

import random

PROXY_LIST = [
    "http://user:pass@proxy1:port",
    "http://user:pass@proxy2:port",
    "http://user:pass@proxy3:port",
]

def get_random_proxy():
    return random.choice(PROXY_LIST)

# In Playwright:
context = browser.new_context(proxy={"server": get_random_proxy()})

Residential-Proxys funktionieren besser als Datacenter-Proxys speziell für Google. Datacenter-IPs werden schneller markiert.

User-Agent-Rotation

USER_AGENTS = [
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/120.0',
]

def get_random_ua():
    return random.choice(USER_AGENTS)

Menschliches Tippen

def human_type(element, text):
    for char in text:
        element.send_keys(char)
        time.sleep(random.uniform(0.05, 0.2))

Tippen mit gleichmäßiger Geschwindigkeit ist ein Botsignal. Variable Verzögerungen pro Zeichen wirken menschlich.

Session-Warm-Up

Gehe nicht direkt zu Google Maps. Besuche zuerst Google Suche, warte ein paar Sekunden und navigiere dann zu Maps. Kalte Sessions, die direkt zu Scraping-Zielen springen, werden häufiger markiert.


Umgang mit dynamischen Inhalten

Google Bewertungen verwenden unendliches Scrollen – keine Seitenzahlen, keine "nächste" Schaltfläche. Dein Scraper muss weiter scrollen, bis entweder:

  1. Es dein max_reviews Ziel erreicht, oder
  2. Nach mehreren Scrollversuchen keine neuen Bewertungen geladen werden

Der obige Code behandelt dies mit einem consecutive_failures Zähler. Nach 5 Scrolls ohne neue Bewertungen stoppt er. Das ist der richtige Ansatz – nicht ewig schleifen.

Erweiterung gekürzter Bewertungen

Lange Bewertungen werden mit einem "Mehr"-Link abgeschnitten. Um den vollständigen Text zu erhalten:

def expand_truncated_reviews(page):
    expand_buttons = page.locator("button:has-text('More'), span:has-text('...')")
    count = expand_buttons.count()
    for i in range(min(count, 100)):
        btn = expand_buttons.nth(i)
        if btn.is_visible():
            btn.click()
            page.wait_for_timeout(300)
    logger.info(f"Erweitert {count} gekürzte Bewertungen")

Führe dies nach dem Laden aller Bewertungen aus, bevor du die Extraktion durchführst.


Rechtliche und ethische Überlegungen

Das Scraping öffentlich sichtbarer Daten ist in den meisten Rechtsordnungen im Allgemeinen legal. Das Urteil HiQ v. LinkedIn von 2022 in den USA bestätigte, dass das Scraping öffentlicher Daten das Computer Fraud and Abuse Act nicht verletzt.

Das gesagt, gelten einige Regeln:

  • Überlasten Sie keine Server. Halte die Anfragen unter 10 pro Minute für gelegentliche Nutzung.
  • Respektiere robots.txt. Die robots.txt von Google schränkt einige Pfade ein – überprüfe sie.
  • Veröffentliche gescrapte Inhalte nicht wörtlich. Aggregiere und analysiere, kopiere nicht einfach.
  • Vermeide persönliche Daten. Namen von Bewertern sind öffentlich, aber baue keine Profile über Einzelpersonen auf.
  • Kommerzielle Nutzung benötigt rechtliche Überprüfung. Wenn du gescrapte Daten verkaufst, konsultiere einen Anwalt.

Der sicherste Ansatz: Scrape für interne Analysen, nicht für die Weiterverbreitung.


Wann Python Scraping nicht das richtige Werkzeug ist

Das Schreiben und Warten eines Google Maps Scrapers erfordert echten Aufwand. Google ändert regelmäßig seine HTML-Struktur. Selektoren brechen. Anti-Bot-Maßnahmen entwickeln sich weiter. Du wirst Zeit mit Debugging verbringen, nicht mit Analysen.

Wenn du Google Maps Bewertungsdaten in großem Maßstab benötigst – über Hunderte oder Tausende von Unternehmen hinweg – ist eine vorindexierte Datenbank schneller und zuverlässiger als ein DIY-Scraper.

IBLead indiziert über 50 Millionen Unternehmen in 37 Ländern, mit bis zu 500 Google Bewertungen pro Eintrag: voller Text, Sternbewertung, Datum und Name des Bewerters. Die Daten werden wöchentlich aktualisiert und sofort in CSV exportiert. Keine Scraping-Infrastruktur zu warten, keine Proxys zu verwalten, keine Selektoren zu reparieren, wenn Google sein Frontend aktualisiert.

Für einmalige Recherchen zu einer Handvoll Unternehmen funktioniert der Python-Ansatz in diesem Leitfaden gut. Für fortlaufende Lead-Generierung oder Reputationsüberwachung im großen Maßstab sind 52 $ für 10.000 Leads schwer zu schlagen.

Jetzt kostenlos starten – 200 credits inklusive


FAQ

Wie viele Bewertungen kann ich pro Tag scrapen, ohne blockiert zu werden?

Starte konservativ: 100–500 Bewertungen pro Tag, über 5–10 Unternehmen, mit 2–3 Sekunden Verzögerung zwischen den Aktionen. Mit Proxy-Rotation und ordentlichem Sitzungsmanagement kannst du auf 1.000–2.000 Bewertungen pro Tag pushen. Aggressives Scraping (5.000+ Bewertungen/Tag) erfordert Residential-Proxy-Netzwerke und mehrere Browser-Sitzungen, die parallel laufen.

Ist Playwright oder Selenium besser zum Scrapen von Google Maps Bewertungen mit Python?

Playwright ist die bessere Wahl für neue Projekte im Jahr 2025. Es ist 2–3x schneller, hat integrierte Async-Unterstützung und handhabt Anti-Detection mit weniger manueller Konfiguration. Selenium ist weiterhin gültig, wenn du bestehende Infrastruktur hast oder maximale Community-Unterstützung benötigst. Beide Methoden funktionieren – der Code in diesem Leitfaden zeigt beide.

Warum geben meine Selektoren leere Ergebnisse zurück?

Google aktualisiert regelmäßig sein Frontend. Ein Selektor, der letzten Monat funktioniert hat, kann heute nichts zurückgeben. Die Lösung: Verwende mehrere Fallback-Selektoren für jedes Feld und teste mit headless=False, damit du sehen kannst, wie die Seite tatsächlich aussieht. Das extract_with_fallbacks() Muster, das in diesem Leitfaden gezeigt wird, behandelt dies systematisch.

Kann ich Google Bewertungen für Wettbewerbsanalysen scrapen?

Ja. Öffentliche Bewertungsdaten sind öffentlich zugänglich. Die Analyse des Wettbewerbs-Sentiments, das Verfolgen von Bewertungs-Trends oder das Identifizieren von häufigen Beschwerden ist ein legitimer Anwendungsfall. Veröffentliche keine einzelnen Bewertungen wörtlich oder baue persönliche Profile über Bewerter auf. Konzentriere dich auf aggregierte Erkenntnisse.

Wie gehe ich mit CAPTCHAs um?

Prävention schlägt Lösung. Verlangsamen Sie Ihre Anfragefrequenz, verwenden Sie Residential-Proxys, fügen Sie realistische Verzögerungen hinzu und wärmen Sie Sitzungen auf, bevor Sie scrapen. Wenn ein CAPTCHA dennoch erscheint: Führen Sie in der Entwicklung mit headless=False aus und lösen Sie es manuell. In der Produktion integrieren Sie entweder einen CAPTCHA-Lösungsdienst oder implementieren Sie ein exponentielles Backoff, das 5–10 Minuten wartet, bevor es erneut versucht.

Bereit loszulegen?

Zugriff auf jedes Google Maps Unternehmen, angereichert mit E-Mails und rechtlichen Daten.

IBLead kostenlos testen