Lokale Unternehmensverzeichnisse gehören zu den nützlichsten öffentlichen Datensätzen im Web. Eine Verzeichnissuche wie "Klempner in Austin" oder "Restaurants in Denver" liefert ein strukturiertes Raster von Unternehmen, jedes mit Name, Adresse, Telefonnummer, Kategorie und einer Sternebewertung mit Rezensionsanzahl. Vertriebs-, Marketing- und Forschungsteams ziehen diese Daten heran, um Interessentenlisten nach Stadt aufzubauen, CRM-Datensätze mit verifizierten Kontaktdaten anzureichern und die Wettbewerberdichte in verschiedenen Märkten zu kartieren. Manuell lässt sich das nicht über ein paar Ergebnisse hinaus skalieren, daher gehört die Arbeit in ein Skript.

Diese Anleitung zeigt Ihnen, wie Sie mit Python lokale Unternehmensangebote scrapen auf zuverlässige Weise. Sie erstellen einen kleinen, lauffähigen Scraper, der eine gerenderte Verzeichnisseite über die Crawling API abruft, jede Angebotskarte mit BeautifulSoup parst und pro Unternehmen einen sauberen Datensatz liefert: Name, Adresse, Telefon, Kategorie, Bewertung, Rezensionsanzahl und Website. Die gesamte Anleitung beschränkt sich auf öffentliche Unternehmensinformationen, und der Abschnitt zur Rechtslage am Ende ist kein Boilerplate. Lesen Sie ihn daher, bevor Sie den Scraper auf größere Mengen ansetzen.

Was Sie bauen werden

Ein Python-Skript, das eine Kategorie und eine Stadt entgegennimmt, die gerenderte Angebots-Seite über die Crawling API abruft und pro Unternehmen einen strukturierten Datensatz extrahiert. Als durchgängiges Beispiel verwenden wir eine Yellow-Pages-Suche und lesen diese Felder aus jeder Ergebniskarte:

  • Name der Unternehmensname, zum Beispiel "Austin Plumbing Co".
  • Adresse die auf der Karte angezeigte Straßenadresse.
  • Telefon die öffentlich aufgeführte Geschäftstelefonnummer.
  • Kategorie die primäre Kategorie, unter der das Verzeichnis das Unternehmen führt.
  • Bewertung die durchschnittliche Sternebewertung, sofern das Unternehmen eine hat.
  • Rezensionen die Anzahl der hinter dieser Bewertung stehenden Rezensionen.
  • Website der Link zur eigenen Website des Unternehmens, sofern aufgeführt.

Warum ein einfacher Request bei Verzeichnisseiten scheitert

Das Sammeln von Angeboten in großem Maßstab ist aus zwei Gründen, die sich bei steigendem Volumen potenzieren, nicht so einfach wie Requests senden und HTML parsen.

Erstens sind Ergebnisse geo-abhängig. Eine einfache Abfrage wie "Klempner" liefert je nachdem, ob die Anfrage aus Austin, Denver oder Phoenix zu kommen scheint, völlig unterschiedliche Unternehmen. Um einen konsistenten Datensatz zu erhalten, müssen Sie sowohl die Abfrage (Stadt einschließen) als auch den Anfrage-Standort (Geo-Targeting) kontrollieren, sonst variieren die Ergebnisse von Durchlauf zu Durchlauf unvorhersehbar.

Zweitens schützen moderne Verzeichnisse sich gegen automatisierten Traffic und rendern Angebote zunehmend clientseitig. Viele Plattformen liefern eine dünne HTML-Hülle und injizieren die eigentlichen Unternehmenskarten nachträglich mit JavaScript, sodass ein Standard-HTTP-Request eine Seite ohne Angebote liefert. Sobald Sie über ein paar Anfragen hinausgehen, beginnt die Plattform auch, IP-Sperren, CAPTCHA-Challenges und Request-Drosselung anzuwenden. Ein funktionierender Scraper benötigt daher zwei Dinge in einer einzigen Anfrage: einen Browser, der die Seite rendert, und eine IP-Adresse, die die Plattform als echten Besucher einordnet. Das lässt sich selbst mit einem Headless-Browser plus einem Pool rotierender Residential-Proxys zusammensetzen, aber das Zusammenführen und Pflegen dieser Komponenten ist der aufwändigste Teil. Die Crawling API fasst beides in einem einzigen Aufruf zusammen: Sie übergeben ihr die URL, sie rendert die Seite hinter einer vertrauenswürdigen Residential-IP und liefert fertiges HTML zur Weiterverarbeitung zurück.

Normales Token vs. JS-Token

Crawlbase bietet zwei Token-Typen. Das normale Token ruft statisches HTML ab; das JavaScript-Token (JS-Token) rendert die Seite zunächst in einem echten Browser. Statische Verzeichnisseiten lassen sich problemlos mit dem normalen Token parsen, aber Plattformen, die Angebote clientseitig injizieren (Google Maps, Yelp), benötigen das JS-Token. Passen Sie das Token an die Seite an: verwenden Sie das normale Token für einfache Seiten und das JS-Token für dynamische.

Voraussetzungen

Sie benötigen einige Dinge, bevor Sie Code schreiben. Keines davon nimmt viel Zeit in Anspruch.

Grundlegendes Python-Wissen. Sie sollten in der Lage sein, ein Python-Skript zu schreiben und auszuführen sowie Pakete mit pip zu installieren. Wenn Sie neu bei BeautifulSoup sind, behandelt die Einführung in die Verwendung von BeautifulSoup in Python die Selector-Grundlagen, auf die dieses Tutorial aufbaut.

Python 3.8 oder höher. Prüfen Sie Ihre Version mit python --version. Falls Sie es nicht haben, installieren Sie es von python.org oder über eine Distribution wie Anaconda.

Ein Crawlbase-Konto und Token. Registrieren Sie sich, öffnen Sie Ihr Dashboard und kopieren Sie Ihr Token von der Account-Docs-Seite. Behandeln Sie das Token wie ein Passwort: Es authentifiziert Ihre Anfragen, halten Sie es also aus der Versionskontrolle heraus.

Projekt einrichten

Erstellen Sie eine virtuelle Umgebung, damit die Projektabhängigkeiten isoliert bleiben, und installieren Sie dann die zwei Bibliotheken, die der Scraper benötigt.

bash
python --version

python -m venv listings_env
source listings_env/bin/activate

pip install crawlbase beautifulsoup4

Unter Windows aktivieren Sie die Umgebung mit listings_env\Scripts\activate statt der source-Zeile. Zwei Abhängigkeiten erledigen die Arbeit: crawlbase ist der offizielle Client für die Crawling API, und beautifulsoup4 parst das zurückgegebene HTML, sodass Sie jedes Feld aus einer Angebotskarte per CSS-Selector extrahieren können.

Die Angebotsseite verstehen

Eine Verzeichnis-Ergebnisseite zeigt eine Spalte von Angebotskarten, eine pro Unternehmen. Jede Karte enthält dieselbe Handvoll Felder: einen Unternehmensnamen, eine Straßenadresse, eine Telefonnummer, die Kategorie, unter der es geführt wird, und eine Bewertung mit Rezensionsanzahl. Ein "Website besuchen"-Link befindet sich auf der Karte, wenn das Unternehmen eine angegeben hat. Unterhalb der Spalte befinden sich Pagination-Steuerelemente, mit denen Sie weitere Ergebnisseiten für dieselbe Abfrage durchlaufen können.

Bevor Sie Selektoren schreiben, öffnen Sie eine Ergebnisseite in Ihrem Browser, klicken Sie mit der rechten Maustaste auf eine Angebotskarte und wählen Sie "Untersuchen". Bei Yellow Pages ist jedes Ergebnis in einem div.result-Container eingebettet, mit dem Namen in a.business-name, der Adresse in div.street-address und div.locality, dem Telefon in div.phones, der primären Kategorie in div.categories, der Bewertung durch die Klasse auf div.result-rating, der Rezensionsanzahl in span.count und der Website in a.track-visit-website. Das sind die Selektoren, die Sie anvisieren.

Schritt 1: Die gerenderte Angebotsseite abrufen

Beginnen Sie damit, die fertig gerenderte Seite zu holen. Importieren Sie die CrawlingAPI-Klasse, initialisieren Sie sie mit Ihrem Token, erstellen Sie die Such-URL aus einer Kategorie und einer Stadt und fordern Sie sie an. Die Statuscode-Prüfung vor dem Parsen macht Fehler sofort sichtbar, anstatt sie zu verschleiern.

python
from urllib.parse import quote_plus
from crawlbase import CrawlingAPI

api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"})

def build_url(category, city):
    terms = quote_plus(category)
    geo = quote_plus(city)
    return f"https://www.yellowpages.com/search?search_terms={terms}&geo_location_terms={geo}"

def crawl(page_url):
    options = {"country": "US"}
    response = api.get(page_url, options)
    if response["status_code"] == 200:
        return response["body"].decode("latin1")
    print(f"Request failed: {response['status_code']}")
    return None

if __name__ == "__main__":
    url = build_url("plumbers", "Austin, TX")
    html = crawl(url)
    print(html[:500] if html else "No HTML returned")

Der build_url-Helper setzt die Such-URL aus zwei Query-Parametern zusammen: search_terms für die Kategorie und geo_location_terms für die Stadt, beide URL-kodiert, damit Leerzeichen und Kommas die Übertragung überstehen. Die Option country pinnt die Anfrage auf eine US-IP, was die Geo-Targeting-Komponente ist: Eine Abfrage nach "plumbers in Austin" liefert nur dann sinnvolle Ergebnisse, wenn die Anfrage auch aus dem richtigen Markt zu stammen scheint. Der Body wird als latin1 dekodiert, da Verzeichnisseiten Zeichen enthalten können, bei denen strikte UTF-8-Dekodierung fehlschlägt. Führen Sie das Skript aus, und Sie sollten echtes Angebots-Markup sehen, keine leere Hülle oder eine Blockseite. Das bestätigt, dass der Abruf funktioniert, bevor Sie einen einzigen Selector schreiben.

Crawlbase Crawling API

Dieser einzelne api.get-Aufruf erledigte den Teil, der normalerweise eine Woche kostet: Er rief die Angebotsseite hinter einer vertrauenswürdigen Residential-IP an, die auf das richtige Land gepiont war, sodass das Verzeichnis echte Karten statt einer Blockseite zurückgab. Die Crawling API übernimmt Rendering, IP-Rotation und Geo-Targeting für Sie, sodass Sie keinen Headless-Browser-Fleet und keinen Proxy-Pool selbst betreiben müssen. Testen Sie es zunächst mit einer Stadt im kostenlosen Tarif.

Schritt 2: Die Angebotskarten mit BeautifulSoup parsen

Mit dem HTML laden Sie es in BeautifulSoup, finden jede Angebotskarte und extrahieren jedes Feld per Selector. Jedes Unternehmen ist in einem div.result-Container eingebettet, wobei Name, Adresse, Telefon, Kategorie, Bewertung, Rezensionsanzahl und Website jeweils durch ihre eigene Klasse zugänglich sind. Umhüllen Sie jede Karte mit einem try/except, damit eine fehlerhafte Angebotskarte den Durchlauf nicht abbricht.

python
from bs4 import BeautifulSoup

def text_of(card, selector):
    el = card.select_one(selector)
    return el.get_text(strip=True) if el else None

def parse_rating(card):
    el = card.select_one("div.result-rating")
    if not el:
        return None
    words = {"one": 1, "two": 2, "three": 3, "four": 4, "five": 5}
    rating = None
    for cls in el.get("class", []):
        base = cls.replace("-half", "")
        if base in words:
            rating = words[base] + (0.5 if "-half" in cls else 0)
    return rating

def scrape_results(html):
    soup = BeautifulSoup(html, "html.parser")
    cards = soup.select("div.result")
    results = []
    for card in cards:
        try:
            website = card.select_one("a.track-visit-website")
            results.append({
                "name": text_of(card, "a.business-name"),
                "address": text_of(card, "div.street-address"),
                "locality": text_of(card, "div.locality"),
                "phone": text_of(card, "div.phones"),
                "category": text_of(card, "div.categories"),
                "rating": parse_rating(card),
                "reviews": text_of(card, "span.count"),
                "website": website["href"] if website else None,
            })
        except Exception as e:
            print(f"Skipped a card: {e}")
    return results

Der text_of-Helper fragt ein einzelnes Element innerhalb einer Karte ab und gibt None zurück, wenn es fehlt, statt bei einem .get_text()-Aufruf auf nichts einen Fehler zu werfen. Das hält die Extraktion robust, wenn ein Feld fehlt, was häufig vorkommt, da nicht jedes Angebot eine Website oder eine Bewertung hat. Der parse_rating-Helper liest die Sternebewertung aus der Klassenliste von div.result-rating, wo das Verzeichnis den Score als Wörter wie four oder four half schreibt, und wandelt ihn in eine Zahl um. Die Rezensionsanzahl stammt aus span.count, und die Website wird aus dem href-Attribut des Ankers statt aus seinem Text gelesen. Namen, Adressen, Telefonnummern und Kategorien sind jeweils ihrem eigenen Selector zugeordnet.

Selektoren können sich ändern

Verzeichnis-Klassennamen ändern sich ohne Vorankündigung. Betrachten Sie die obigen Selektoren als Startvorlage, nicht als Vertrag. Wenn ein Feld bei jeder Karte als None zurückkommt, untersuchen Sie eine Live-Ergebnisseite in den Entwicklertools Ihres Browsers und aktualisieren Sie den Selector. Regelmäßige Selektor-Wartung ist für jeden produktiven Scraper normal, kein Zeichen für einen Fehler.

Schritt 3: Zusammensetzen und exportieren

Verbinden Sie nun Fetch und Parse zu einem lauffähigen Skript und schreiben Sie die Datensätze als JSON und CSV, sodass sie direkt in eine Tabelle oder eine Datenbank passen. Rufen Sie die gerenderte Seite ab, übergeben Sie sie an den Parser und schreiben Sie dann die strukturierten Datensätze.

python
import csv
import json
from urllib.parse import quote_plus
from crawlbase import CrawlingAPI
from bs4 import BeautifulSoup

api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"})

def build_url(category, city):
    terms = quote_plus(category)
    geo = quote_plus(city)
    return f"https://www.yellowpages.com/search?search_terms={terms}&geo_location_terms={geo}"

def crawl(page_url):
    response = api.get(page_url, {"country": "US"})
    if response["status_code"] == 200:
        return response["body"].decode("latin1")
    print(f"Request failed: {response['status_code']}")
    return None

def text_of(card, selector):
    el = card.select_one(selector)
    return el.get_text(strip=True) if el else None

def parse_rating(card):
    el = card.select_one("div.result-rating")
    if not el:
        return None
    words = {"one": 1, "two": 2, "three": 3, "four": 4, "five": 5}
    rating = None
    for cls in el.get("class", []):
        base = cls.replace("-half", "")
        if base in words:
            rating = words[base] + (0.5 if "-half" in cls else 0)
    return rating

def scrape_results(html):
    soup = BeautifulSoup(html, "html.parser")
    results = []
    for card in soup.select("div.result"):
        try:
            website = card.select_one("a.track-visit-website")
            results.append({
                "name": text_of(card, "a.business-name"),
                "address": text_of(card, "div.street-address"),
                "locality": text_of(card, "div.locality"),
                "phone": text_of(card, "div.phones"),
                "category": text_of(card, "div.categories"),
                "rating": parse_rating(card),
                "reviews": text_of(card, "span.count"),
                "website": website["href"] if website else None,
            })
        except Exception as e:
            print(f"Skipped a card: {e}")
    return results

def save(rows, name):
    with open(f"{name}.json", "w") as f:
        json.dump(rows, f, indent=2)
    if rows:
        with open(f"{name}.csv", "w", newline="") as f:
            writer = csv.DictWriter(f, fieldnames=rows[0].keys())
            writer.writeheader()
            writer.writerows(rows)

def main():
    url = build_url("plumbers", "Austin, TX")
    html = crawl(url)
    if not html:
        return
    data = scrape_results(html)
    save(data, "listings")
    print(json.dumps(data, indent=2))

if __name__ == "__main__":
    main()

Wie die Ausgabe aussieht

Führen Sie das vollständige Skript mit python scraper.py aus und erhalten Sie eine saubere Liste von Datensätzen, einen pro Unternehmen, geschrieben nach listings.json und listings.csv und auf der Konsole ausgegeben.

json
[
  {
    "name": "Austin Plumbing Co",
    "address": "1200 W 5th St",
    "locality": "Austin, TX 78703",
    "phone": "(512) 555-0142",
    "category": "Plumbers, Water Heaters",
    "rating": 4.5,
    "reviews": "(38)",
    "website": "https://www.austinplumbingco.example"
  },
  {
    "name": "Lone Star Drain & Sewer",
    "address": "904 E Cesar Chavez St",
    "locality": "Austin, TX 78702",
    "phone": "(512) 555-0188",
    "category": "Plumbers",
    "rating": null,
    "reviews": null,
    "website": null
  }
]

Der zweite Datensatz zeigt die Resilienz in der Praxis: Dieses Unternehmen hat keine Bewertung, keine Rezensionsanzahl und keine Website angegeben, sodass diese Felder als null zurückkommen, statt den Durchlauf abzubrechen. Die CSV-Version enthält dieselben Spalten in derselben Reihenfolge und lässt sich in einer Tabelle öffnen oder in eine Datenbank laden. Wenn Sie eine Auffrischung zum Abflachen verschachtelter Datensätze in Zeilen möchten, behandelt die Anleitung zum Scrapen von Tabellen von einer Website dieselbe Exportform.

Über Städte und Seiten skalieren

Eine Abfrage in einer Stadt ist eine Demo. Der eigentliche Wert von Angebotsdaten entsteht durch die Ausführung derselben Kategorie über viele Märkte, was auch der Bereich ist, in dem Konsistenz am meisten zählt. Durchlaufen Sie eine Liste von Städten, paginieren Sie jede mit dem &page=-Parameter, bis eine Seite keine Karten zurückgibt, und sammeln Sie alles in einem einzigen Datensatz.

python
import time

def scrape_city(category, city, max_pages=5):
    base = build_url(category, city)
    collected = []
    for page in range(1, max_pages + 1):
        html = crawl(f"{base}&page={page}")
        if not html:
            break
        rows = scrape_results(html)
        if not rows:
            break
        for row in rows:
            row["city"] = city
        collected.extend(rows)
        print(f"{city} page {page}: {len(rows)} listings")
        time.sleep(2)
    return collected

def scrape_cities(category, cities):
    all_rows = []
    for city in cities:
        all_rows.extend(scrape_city(category, city))
    return all_rows

data = scrape_cities("restaurants", ["Austin, TX", "Denver, CO", "Phoenix, AZ"])
save(data, "multi_city")

Die max_pages-Begrenzung hält jede Stadt begrenzt, damit eine breite Abfrage nicht endlos läuft, und der Leer-Ergebnisse-Break stoppt frühzeitig, wenn das Verzeichnis keine Seiten mehr hat. Das Stempeln jeder Zeile mit ihrer city hält die Märkte trennbar, sobald alles in einer Datei landet. Das time.sleep(2) zwischen Seiten drosselt Anfragen, damit Sie das Verzeichnis nicht in einer engen Schleife hämmern, was der schnellste Weg zur Drosselung ist. Diese Multi-City-Schleife ist dasselbe Muster wie bei einem Preisvergleichs-Tool: eine Abfrage, viele Quellen, in einen Datensatz normalisiert.

Nicht blockiert werden

Auch wenn der Abruf bereits gehandhabt wird, beobachten Verzeichnisse weiterhin Scraper-typischen Traffic. Einige Gewohnheiten halten einen Durchlauf gesund, und sie gelten für jedes kommerzielle Ziel.

  • Anfragen drosseln. Verteilen Sie Anfragen mit einer Verzögerung zwischen Seiten und variieren Sie Ihre Abfragen, statt einen Begriff mit voller Geschwindigkeit zu crawlen. Das time.sleep in der Schleife ist der Mindestabstand, nicht die Obergrenze.
  • Rotation nutzen. Ein Pool von Residential-IPs verteilt Anfragen über viele echte Nutzeradressen, sodass keine einzelne davon ein Rate-Limit auslöst. Die Crawling API erledigt das für Sie; wenn Sie einen eigenen Stack aufbauen, ist das der Teil, den Sie richtig hinbekommen müssen.
  • Geo anpassen. Pinnen Sie das Anfrage-Land auf den Markt, den Sie abfragen, damit Ergebnisse konsistent bleiben und der Traffic lokal statt fehl am Platz aussieht.
  • Statuscodes lesen. Ein Durchlauf, der beginnt, Challenges oder Fehler zurückzugeben, signalisiert Ihnen, dass die aktuelle Rate oder IP-Stufe nicht mehr ausreicht. Behandeln Sie das als Signal zum Zurückrudern, nicht als Rauschen, das Sie ignorieren können.

Das umfassendere Playbook zur Aufrechterhaltung eines gesunden Scrapers finden Sie unter how to scrape websites without getting blocked. Wenn Sie On-Demand-Anfragen überwachsen haben und Tausende von Stadt-und-Kategorie-URLs auf einmal pushen müssen, verarbeitet der asynchrone Crawler große Batches im Hintergrund und liefert Ergebnisse an einen Webhook oder Cloud Storage, sodass Sie diesen Parser wiederverwenden können, ohne selbst eine Request-Queue zu verwalten.

Ob das Scrapen eines Angebotsverzeichnisses erlaubt ist, hängt von den Nutzungsbedingungen der Plattform, Ihrer Rechtsprechung und dem ab, was Sie mit den Daten tun. Die meisten Verzeichnisse schränken den automatisierten Zugriff in ihren Bedingungen ein, sodass das Scrapen gegen diese Bedingungen verstoßen kann, unabhängig davon, wie sorgfältig Ihre Tools sind. Keiner der Codes hier ändert daran etwas; er macht nur den technischen Teil funktionsfähig. Lesen Sie die Nutzungsbedingungen der Plattform und deren robots.txt und behandeln Sie beides als Grenze für das, was Sie sammeln und wie schnell Sie es sammeln.

Einige Grundsätze sind es wert, eingehalten zu werden. Sammeln Sie nur öffentliche Unternehmensinformationen: Namen, Adressen, Telefonnummern, Kategorien, Bewertungen, Rezensionsanzahlen und Website-Links, die jeder auf einer Ergebnisseite ohne Konto sehen kann. Die aufgeführten Kontaktdaten eines Unternehmens sind öffentliche Geschäftsdaten, aber sammeln Sie keine personenbezogenen Daten über Einzelpersonen, einschließlich privater Kontaktinformationen, Rezensenten-Identitäten oder allem, was mit einer namentlich genannten Person zusammenhängt, über das hinaus, was das Unternehmen selbst veröffentlicht. Halten Sie Ihr Anfragevolumen niedrig genug, um die Server der Plattform nicht zu belasten, und respektieren Sie alle angegebenen Rate-Erwartungen. Wenn Sie die Daten kommerziell nutzen wollen, holen Sie eine Genehmigung oder ein offizielles Abkommen ein, anstatt davon auszugehen, dass Schweigen Zustimmung bedeutet.

Diese Anleitung beschränkt sich bewusst auf öffentliche Angebotsseiten, weil das die Grenze ist, die die Arbeit vertretbar hält. Sie umfasst nichts hinter einem Login, keine Kontodaten und kein Scrapen personenbezogener Daten über echte Personen. Wo eine Plattform einen offiziellen Weg bietet, bevorzugen Sie ihn: Karten- und Orte-Anbieter veröffentlichen offizielle APIs, die dieselben Angebotsfelder unter klaren Bedingungen zurückgeben, und das ist das richtige Werkzeug, wenn Sie große Mengen, garantierte Struktur oder kommerzielle Rechte benötigen. Wenn Ihr Projekt mehr als öffentliche Angebote benötigt, ist eine offizielle API oder ein Datenabkommen der richtige Weg, kein ausgefeilterer Scraper.

Zusammenfassung

Wichtigste Erkenntnisse

  • Angebote sind geo-abhängig. Schließen Sie die Stadt in die Abfrage ein und pinnen Sie das Anfrage-Land, sonst liefert dieselbe Kategorie von Durchlauf zu Durchlauf inkonsistente Unternehmen.
  • Der Abruf ist der schwierige Teil. Die Crawling API ruft die Seite hinter einer vertrauenswürdigen Residential-IP ab und rendert sie bei Bedarf, sodass Sie echte Karten statt einer Blockseite oder einer leeren Hülle erhalten.
  • BeautifulSoup übernimmt die Extraktion. Durchlaufen Sie die div.result-Karten und ordnen Sie Name, Adresse, Telefon, Kategorie, Bewertung, Rezensionen und Website aktuellen Selektoren zu, und rechnen Sie damit, dass sich diese Selektoren ändern.
  • Über Städte und Seiten skalieren. Durchlaufen Sie eine Stadtliste, paginieren Sie mit &page= bis eine Seite leer ist, stempeln Sie jede Zeile mit ihrer Stadt und drosseln Sie Anfragen mit einer Verzögerung.
  • Auf öffentliche Daten beschränken. Respektieren Sie die AGB und robots.txt der Plattform, bevorzugen Sie eine offizielle Karten- oder Orte-API für lizenzierte oder Massendaten, und sammeln Sie niemals personenbezogene Daten über Einzelpersonen.

Häufig gestellte Fragen

Benötige ich das normale Token oder das JS-Token für Angebote?

Das hängt vom Verzeichnis ab. Statische Ergebnisseiten wie Yellow Pages lassen sich problemlos mit dem normalen Token parsen. Plattformen, die Angebote clientseitig injizieren, wie Google Maps und Yelp, benötigen das JS-Token, damit die Seite in einem echten Browser gerendert wird, bevor das HTML zurückgegeben wird. Passen Sie das Token an die Seite an: Beginnen Sie mit dem normalen Token und wechseln Sie zum JS-Token, wenn die Karten im Body fehlen.

Wie erhalte ich genaue Ergebnisse für eine bestimmte Stadt?

Zwei Dinge zusammen. Fügen Sie die Stadt in die Abfrage selbst über den geo_location_terms-Parameter ein und pinnen Sie die Anfrage auf den richtigen Markt mit der country-Option der Crawling API. Lokale Suche ist standortgebunden, sodass eine Abfrage ohne beide Teile Ergebnisse liefert, die je nachdem, von wo die Anfrage zu stammen scheint, unvorhersehbar variieren.

Kann ich mehrere Städte in einem Durchlauf scrapen?

Ja. Übergeben Sie eine Liste von Städten und schleifen Sie dieselbe Kategorie über jede davon, wobei Sie die Ergebnisse in einem einzigen Datensatz zusammenführen. Stempeln Sie jeden Datensatz mit seiner Stadt, bevor Sie zusammenführen, damit die Märkte trennbar bleiben, und fügen Sie eine kurze Verzögerung zwischen Anfragen ein, um den Durchlauf zu drosseln.

Meine Selektoren geben None zurück. Was hat sich geändert?

Höchstwahrscheinlich das Markup des Verzeichnisses. Klassennamen wie a.business-name für den Namen oder div.result-rating für die Bewertung ändern sich ohne Vorankündigung. Untersuchen Sie eine Live-Ergebnisseite in den Entwicklertools Ihres Browsers, aktualisieren Sie den Selector entsprechend und führen Sie das Skript erneut aus. Regelmäßige Selektor-Wartung ist für jeden produktiven Scraper normal.

Kann ich persönliche Kontaktdaten aus Angeboten scrapen?

Nein, und diese Anleitung behandelt das nicht. Halten Sie sich an öffentliche Unternehmensinformationen: Unternehmensname, Adresse, aufgeführtes Telefon, Kategorie, Bewertung, Rezensionsanzahl und Website. Personenbezogene Daten über Einzelpersonen, private Kontaktdaten oder Rezensenten-Identitäten liegen außerhalb des Rahmens und verstoßen gegen die Bedingungen der meisten Plattformen. Für umfangreichere oder lizenzierte Daten ist der richtige Weg eine offizielle Karten- oder Orte-API.

Wie gehe ich mit sehr großen Jobs über Hunderte von Städten vor?

Für On-Demand-Arbeit reicht die Crawling API aus, aber wenn Sie Tausende von Stadt-und-Kategorie-URLs auf einmal pushen, wechseln Sie zum asynchronen Crawler. Sie pushen die URLs und empfangen Ergebnisse über einen Webhook oder Cloud Storage, anstatt auf jede Anfrage zu warten, was den Durchsatz verbessert und Engpässe vermeidet. Der Parser in dieser Anleitung verarbeitet das zurückgegebene HTML unverändert.

Jetzt loslegen

Crawlen Sie jede Website im großen Maßstab, ohne gegen die Infrastruktur zu kämpfen.

Crawlbase übernimmt Proxys, Fingerprints und CAPTCHAs, damit Ihr Team Datenpipelines ausliefert, statt Crawl-Infrastruktur zu pflegen. 1.000 Anfragen kostenlos, keine Karte erforderlich.

Self-Service · Kein Verkaufsgespräch erforderlich · Enterprise-Crawl-Volumen verfügbar