Web Scraping verschafft Ihnen die Daten, aber die Speicherung und Analyse sind ebenso wichtig. Ein Ordner mit losen JSON- oder CSV-Dateien ist für einen einmaligen Abruf in Ordnung, doch sobald Sie Preise über Zeit verfolgen, Datensätze aus verschiedenen Quellen vergleichen oder eine echte Frage beantworten wollen, wird dieser flache Stapel zum Engpass. Eine SQL-Datenbank gibt gescrapten Daten ein strukturiertes Zuhause, das Sie abfragen, filtern und aggregieren können, ohne jedes Mal wegwerfbaren Parsing-Code zu schreiben.

Dieser Leitfaden baut den vollständigen Pfad von Anfang bis Ende mit Python und SQL auf. Sie scrapen einen kleinen Satz produktähnlicher Datensätze von einer neutralen Beispielseite über die Crawling API, entwerfen ein SQL-Schema, fügen die geparsten Zeilen ein und führen analytische Abfragen aus, um Erkenntnisse zu gewinnen. Er bleibt auf öffentliche, illustrative Daten und eine Platzhalter-URL beschränkt, sodass Sie ihn sicher nachvollziehen und später Ihr eigenes Ziel eintauschen können.

Was Sie bauen werden

Ein ausführbarer Python-Ablauf, der eine gerenderte Listenseite über die Crawling API abruft, jede Produktkarte mit BeautifulSoup parst, die Datensätze in eine SQLite-Tabelle schreibt und diese Tabelle dann nach Preisbändern, Durchschnittswerten und Kategorieanzahlen abfragt. Jeder gescrapte Datensatz enthält diese Felder:

  • Name der auf der Listenkarte angezeigte Produkttitel.
  • Preis der aufgeführte Preis, als Zahl gespeichert, damit Sie ihn vergleichen und aggregieren können.
  • Kategorie der Bereich oder Produkttyp, zu dem der Artikel gehört.
  • URL der Link zur eigenen Seite des Produkts.
  • Gescrapt am ein Zeitstempel, den die Datenbank automatisch ausfüllt, damit Sie verfolgen können, wann jede Zeile erfasst wurde.

Warum gescrapte Daten in SQL gespeichert werden sollten

Wo die Daten landen, entscheidet, wie nützlich sie später sind. Dateien funktionieren, bis Sie eine Frage stellen müssen, die Zeilen übergreift: Welche Artikel liegen unter einer Preisschwelle, wie hoch der Durchschnittspreis pro Kategorie ist, wie der Abruf dieser Woche mit dem der letzten Woche verglichen werden kann. SQL wurde genau dafür entwickelt, und eine relationale Datenbank bietet einige Dinge, die ein Ordner mit Dateien nicht kann.

  • Strukturierte Speicherung. Tabellen und Spalten erzwingen eine konsistente Form, sodass jeder Datensatz die gleichen Felder in den gleichen Typen hat.
  • Effizientes Abfragen. Ein einziges SELECT filtert, sortiert und aggregiert Tausende von Zeilen ohne manuelles Schleifen.
  • Datenintegrität. Primärschlüssel, Typen und Constraints halten die Daten konsistent und erkennen fehlerhafte Zeilen beim Einfügen.
  • Skalierbarkeit. Ob Sie Tausende oder Millionen von Datensätzen speichern, eine SQL-Engine bewältigt das Wachstum und bleibt mit den richtigen Indizes schnell.
  • Wiederholbare Analysen. Abfragen sind wiederverwendbar. Sobald Sie eine nützliche geschrieben haben, führen Sie sie morgen erneut auf den neuen Daten aus, ohne etwas neu aufzubauen.

Wenn Sie Speicherformate breiter abwägen, deckt der Vergleich in JSON vs. CSV ab, wann eine flache Datei noch die richtige Wahl ist, und der Datenmodellierungsleitfaden geht tiefer auf das Schema-Design ein, als wir hier Platz haben.

Warum eine einfache Anfrage auf einer modernen Listenseite versagt

Bevor die Speicherarbeit wichtig ist, benötigen Sie saubere Datensätze zum Speichern, und genau hier neigt eine naive HTTP-Anfrage zu versagen. Viele moderne Listenseiten rendern ihren Inhalt im Browser durch JavaScript: Die erste HTML-Antwort ist eine dünne Hülle, und die Produktkarten erscheinen erst, nachdem die Skripte der Seite ausgeführt wurden. Rufen Sie Daten aus dieser initialen Antwort ab, erfassen Sie nur einen Bruchteil der Liste oder gar nichts.

Das zweite Problem ist der Zugang. Websites, die kommerziell wertvolle Listen veröffentlichen, beobachten automatisierten Traffic und blockieren Anfragen von Datacenter-IPs oder allem, was nicht wie ein echter Browser aussieht. Ein zuverlässiger Scraper benötigt also zwei Dinge in einer Anfrage: einen Browser, der die Seite rendert, und eine IP, die die Website als echten Besucher liest. Sie können das mit einem Headless-Browser und einem Pool rotierender Residential-Proxies aufbauen, aber diesen Stack gesund zu halten, ist das meiste der Arbeit. Die Crawling API faltet beides in einen einzigen Aufruf und gibt fertiges HTML zurück, das Sie parsen können. Für die Parsing-Seite sind der Python-Web-Scraping-Leitfaden und der Leitfaden zur Strukturierung gescrapten Daten nützliche Begleiter.

Voraussetzungen

Einige Dinge sollten vorhanden sein, bevor Sie Code schreiben. Keines davon dauert lange.

Grundlegende Python- und SQL-Kenntnisse. Sie sollten mit dem Ausführen eines Python-Skripts und dem Lesen eines SELECT-Statements vertraut sein. Sie müssen kein Datenbankadministrator sein; dieser Leitfaden verwendet SQLite, das mit Python ausgeliefert wird, sodass kein Server installiert werden muss.

Python 3.8 oder höher. Überprüfen Sie Ihre Version mit python --version. Wenn Sie es nicht haben, installieren Sie es von python.org und stellen Sie sicher, dass Python in Ihrem PATH ist.

Ein Crawlbase-Konto und Token. Registrieren Sie sich, öffnen Sie Ihr Dashboard und kopieren Sie Ihr Token. Crawlbase enthält bis zu 20.000 kostenlose Anfragen zum Start, was mehr als genug ist, um diesen Leitfaden durchzuarbeiten. Behandeln Sie das Token wie ein Passwort und bewahren Sie es aus der Versionskontrolle heraus. Wenn Ihr Ziel Inhalte clientseitig rendert, verwenden Sie das JavaScript (JS)-Token, damit die Seite gerendert wird, bevor Sie sie erhalten.

Richten Sie das Projekt ein

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

bash
python --version

python -m venv scraper_env
source scraper_env/bin/activate

pip install crawlbase beautifulsoup4

Unter Windows aktivieren Sie die Umgebung mit scraper_env\Scripts\activate anstelle der source-Zeile. Das crawlbase-Paket ist der offizielle Client für die Crawling API, und beautifulsoup4 parst das zurückgegebene HTML, damit Sie einzelne Felder herausziehen können. Sowohl sqlite3 als auch json werden mit der Python-Standardbibliothek ausgeliefert, sodass für den Speicherschritt nichts weiter installiert werden muss.

Schritt 1: Eine gerenderte Seite abrufen

Beginnen Sie damit, eine fertige Seite zu erhalten. Importieren Sie die Klasse CrawlingAPI, initialisieren Sie sie mit Ihrem Token und fordern Sie die Listing-URL an. Wir verwenden einen Platzhalter, https://example.com/products; verweisen Sie ihn auf eine beliebige öffentliche Listenseite, zu deren Erfassung Sie berechtigt sind. Das Prüfen des Crawlbase cb_status (legacy pc_status) vor dem Parsen hält Fehler laut statt still.

python
from crawlbase import CrawlingAPI

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

LISTING_URL = "https://example.com/products"

def crawl(page_url):
    response = api.get(page_url)
    if response["headers"]["cb_status"] == "200":
        return response["body"].decode("utf-8")
    print(f"Request failed: {response['headers']['cb_status']}")
    return None

if __name__ == "__main__":
    html = crawl(LISTING_URL)
    print(html[:500] if html else "No HTML returned")

Führen Sie dies aus und Sie sollten echtes Seiten-Markup zurückgedruckt sehen, was bestätigt, dass die Anfrage funktioniert hat, bevor Sie einen einzigen Selektor schreiben. Wenn Ihr Ziel seine Karten clientseitig rendert, übergeben Sie stattdessen das JS-Token und fügen Sie {"ajax_wait": "true", "page_wait": 5000} als zweites Argument zu api.get hinzu, damit der dynamische Inhalt Zeit zum Laden hat.

Crawlbase Crawling API

Die obige crawl-Funktion verbirgt den schwierigen Teil: fertiges HTML von einer Seite zurückzubekommen, die im Browser rendert und Datacenter-Traffic blockiert. Die Crawling API führt die Seite in einem echten Browser aus, rotiert serverseitig durch Residential-IPs und liefert Ihnen das gerenderte HTML in einem Aufruf, sodass Sie keine eigene Headless-Flotte und keinen eigenen Proxy-Pool betreiben müssen. Starten Sie mit dem kostenlosen Tarif und verweisen Sie zuerst auf eine öffentliche Listenseite.

Schritt 2: Die zu speichernden Datensätze parsen

Mit fertigem HTML laden Sie es in BeautifulSoup und ziehen aus jeder Produktkarte einen Datensatz heraus. Die folgenden Selektoren gehen von einem Karten-Layout mit Titel, Preis, Kategorietag und Link aus, einer gängigen Form für Listenseiten. Jede Suche ist abgesichert, sodass ein fehlendes Feld einen sicheren Standardwert zurückgibt, anstatt den Lauf abzubrechen. Das Detail, das für die Speicherung wichtig ist, ist der Preis: Scrapen Sie ihn als Text, entfernen Sie dann das Währungssymbol und Kommas, damit er als Zahl in die Datenbank gelangt, die Sie vergleichen und mitteln können.

python
import re
from bs4 import BeautifulSoup

def parse_price(text):
    if not text:
        return None
    cleaned = re.sub(r"[^0-9.]", "", text)
    return float(cleaned) if cleaned else None

def parse_products(html):
    soup = BeautifulSoup(html, "html.parser")
    records = []
    for card in soup.select("div.product-card"):
        name = card.select_one("h2.product-title")
        price = card.select_one("span.price")
        category = card.select_one("span.category")
        link = card.select_one("a.product-link")
        records.append({
            "name": name.get_text(strip=True) if name else None,
            "price": parse_price(price.get_text() if price else None),
            "category": category.get_text(strip=True) if category else "Uncategorized",
            "url": link["href"] if link and link.get("href") else None,
        })
    return records

parse_price entfernt alles, was keine Ziffer oder Dezimalpunkt ist, sodass aus "$1,299.00" der Float 1299.0 wird. Dieser einzelne Schritt macht die späteren Preisabfragen möglich: Text sortiert alphabetisch und kann nicht gemittelt werden, aber eine Zahl kann beides korrekt. Passen Sie die Selektoren (product-card, product-title, price, category, product-link) an das Markup Ihres echten Ziels an; der Rest des Ablaufs bleibt gleich.

Schritt 3: Das SQL-Schema entwerfen

Entwerfen Sie nun die Tabelle, die diese Datensätze enthält. Ein gutes Schema spiegelt Ihre Datensatzform wider, wählt den richtigen Typ pro Spalte und fügt einen Primärschlüssel plus einen Zeitstempel hinzu, den die Datenbank für Sie ausfüllt. Beachten Sie die folgenden Entscheidungen: price ist REAL (eine Zahl, kein Text), damit es verglichen und aggregiert werden kann, und scraped_at wird standardmäßig auf die aktuelle Zeit gesetzt, sodass jede Zeile aufzeichnet, wann sie erfasst wurde.

sql
CREATE TABLE IF NOT EXISTS products (
    id        INTEGER PRIMARY KEY AUTOINCREMENT,
    name      TEXT NOT NULL,
    price     REAL,
    category  TEXT,
    url       TEXT UNIQUE,
    scraped_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Speed up the price filters and category rollups you will run later
CREATE INDEX IF NOT EXISTS idx_price ON products(price);
CREATE INDEX IF NOT EXISTS idx_category ON products(category);

Zwei Designentscheidungen sind es wert, hervorgehoben zu werden. Der UNIQUE-Constraint auf url verhindert, dass dasselbe Produkt zweimal eingefügt wird, was wichtig ist, da Scraper erneut ausgeführt werden und Sie nicht wollen, dass gestrige Zeilen heute dupliziert werden. Die Indizes halten die Preis- und Kategorieabfragen schnell, wenn die Tabelle wächst. Bei MySQL oder PostgreSQL liest sich das Schema nahezu identisch: Schreiben Sie AUTO_INCREMENT oder SERIAL anstelle von AUTOINCREMENT, und DECIMAL(10,2) ist eine strengere Wahl als REAL für Geldbeträge. Der Datenmodellierungsleitfaden deckt ab, wann jeder Typ die richtige Wahl ist.

Schritt 4: Die geparsten Datensätze einfügen

Mit der entworfenen Tabelle verbinden Sie sich von Python aus, erstellen sie bei Bedarf und fügen die geparsten Datensätze ein. Verwenden Sie immer parametrisierte Abfragen: Die ?-Platzhalter lassen den Treiber das Escaping übernehmen, was verhindert, dass fehlerhafter Text das Insert unterbricht, und schließt Injection ab. executemany schreibt jeden Datensatz in einem gebündelten Aufruf, viel schneller als eine Schleife mit einzelnen Inserts bei Hunderten von Zeilen.

python
import sqlite3

SCHEMA = """
CREATE TABLE IF NOT EXISTS products (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    price REAL,
    category TEXT,
    url TEXT UNIQUE,
    scraped_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
"""

def store_records(records, db_path="scraped_data.db"):
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()
    cursor.execute(SCHEMA)

    rows = [
        (r["name"], r["price"], r["category"], r["url"])
        for r in records if r["name"]
    ]
    cursor.executemany(
        "INSERT OR IGNORE INTO products (name, price, category, url) "
        "VALUES (?, ?, ?, ?)",
        rows,
    )

    conn.commit()
    inserted = cursor.rowcount
    conn.close()
    return inserted

INSERT OR IGNORE ergänzt den UNIQUE-Constraint auf url aus Schritt 3: Eine Zeile, deren URL bereits vorhanden ist, wird stillschweigend übersprungen, anstatt einen Fehler auszulösen, sodass das erneute Ausführen des Scrapers neue Einträge ergänzt, ohne alte zu duplizieren. Das einmalige Commit nach dem Batch hält den Schreibvorgang schnell. Bei MySQL gilt dasselbe Codemuster mit mysql.connector anstelle von sqlite3 und %s-Platzhaltern statt ?; alles Nachgelagerte ist identisch.

Warum parametrisierte Abfragen

Bauen Sie niemals ein INSERT, indem Sie gescrapten Text direkt in den SQL-String einfügen. Gescrapte Werte sind nicht vertrauenswürdige Eingaben und können Anführungszeichen oder Zeichen enthalten, die das Statement brechen oder, schlimmer, verändern. Die ?-Platzhalter übergeben diesen Text dem Treiber als Daten, niemals als Code, was sowohl sicherer als auch weniger fehleranfällig ist.

Schritt 5: Daten mit SQL-Abfragen analysieren

Die Daten sind nun in einer abfragbaren Form, was der eigentliche Punkt der Verwendung von SQL ist. Hier sind drei Arten von Analysen, die Sie ständig benötigen: Filtern und Sortieren, Aggregieren für Zusammenfassungen und Gruppieren für Einblicke pro Kategorie. Jede ist ein einfaches SELECT, das Sie aus der SQLite-Shell, einer Datenbank-GUI oder von Python aus ausführen können.

Zunächst filtern und sortieren. Dies zieht jedes Produkt unter einer Preisschwelle heraus, das Günstigste zuerst:

sql
SELECT name, price, category
FROM products
WHERE price < 500
ORDER BY price ASC;

Als nächstes aggregieren Sie die gesamte Tabelle in eine einzeilige Zusammenfassung. Funktionen wie COUNT, AVG, MIN und MAX reduzieren viele Zeilen auf die Zahlen, die Sie tatsächlich melden möchten:

sql
SELECT
    COUNT(*) AS total_products,
    ROUND(AVG(price), 2) AS average_price,
    MIN(price) AS cheapest,
    MAX(price) AS most_expensive
FROM products;

Schließlich gruppieren Sie nach Kategorie, um zu sehen, wie der Katalog aufgeteilt ist. GROUP BY führt die Aggregate einmal pro Kategorie aus, und HAVING filtert diese Gruppen nachträglich:

sql
SELECT
    category,
    COUNT(*) AS items,
    ROUND(AVG(price), 2) AS avg_price
FROM products
GROUP BY category
HAVING COUNT(*) > 1
ORDER BY avg_price DESC;

Um diese von Python aus statt aus einer Shell auszuführen, öffnen Sie dieselbe Verbindung und lesen die Zeilen zurück. Dieses Snippet führt den Kategorien-Rollup aus und druckt jede Gruppe:

python
def category_summary(db_path="scraped_data.db"):
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()
    cursor.execute("""
        SELECT category, COUNT(*), ROUND(AVG(price), 2)
        FROM products
        GROUP BY category
        ORDER BY 3 DESC
    """)
    for category, count, avg_price in cursor.fetchall():
        print(f"{category}: {count} items, avg {avg_price}")
    conn.close()

Wenn Ihre Analyse über das hinausgeht, was einfaches SQL bequem handhabt, ziehen Sie die Tabelle in einen DataFrame und machen Sie dort weiter; der pandas-Analyseleitfaden setzt genau an diesem Punkt an.

Alles in einem Ablauf verdrahten

Die vier Funktionen verketten sich zu einem einzigen ausführbaren Skript. Scrapen, parsen, speichern und dann analysieren:

python
def main():
    html = crawl(LISTING_URL)
    if not html:
        return
    records = parse_products(html)
    inserted = store_records(records)
    print(f"Parsed {len(records)} records, inserted {inserted} new rows")
    category_summary()

if __name__ == "__main__":
    main()

Jeder Lauf ruft die Seite ab, schreibt dank INSERT OR IGNORE nur neue Zeilen und gibt die Kategoriezusammenfassung aus. Planen Sie es mit einem Cron-Job und die Tabelle wird zu einer wachsenden Geschichte, die Sie im Laufe der Zeit abfragen können, was der Punkt ist, an dem SQL seinen Wert gegenüber einem Ordner mit datierten CSV-Dateien beweist.

Wie die Ausgabe aussieht

Ein gespeicherter Datensatz enthält die strukturierten Felder sowie die von der Datenbank zugewiesene ID und den Zeitstempel. Die Auswahl einiger Zeilen zurück gibt etwa Folgendes zurück:

json
[
  {
    "id": 1,
    "name": "Wireless Headphones",
    "price": 129.99,
    "category": "Audio",
    "url": "https://example.com/products/wireless-headphones",
    "scraped_at": "2026-06-11 09:42:18"
  },
  {
    "id": 2,
    "name": "Mechanical Keyboard",
    "price": 89.50,
    "category": "Accessories",
    "url": "https://example.com/products/mechanical-keyboard",
    "scraped_at": "2026-06-11 09:42:18"
  }
]

Die Kategoriezusammenfassungsabfrage gegen dieselbe Tabelle gibt einen kompakten Rollup aus, eine Zeile pro Kategorie mit Anzahl und Durchschnittspreis, was genau die Art von Einblick ist, die ein Haufen roher Dateien ohne zusätzlichen Code nicht liefern kann.

Über eine einzelne Seite hinaus skalieren

Der obige Ablauf verarbeitet eine Seite. Echte Datensätze umspannen viele, und einige Anpassungen bringen dies von einer Demo zu etwas Produktionsreifem.

  • Paginieren. Die meisten Listenseiten stellen einen Seitenparameter oder einen Nächste-Link zur Verfügung. Durchlaufen Sie die Seiten, rufen Sie crawl und parse_products für jede auf und übergeben Sie die kombinierten Datensätze in einem Batch an store_records.
  • Inserts bündeln. executemany und ein einziges commit pro Batch minimieren bereits Roundtrips. Für sehr große Jobs committen Sie alle paar Tausend Zeilen statt alle auf einmal, damit ein Fehler nicht den gesamten Lauf verliert.
  • Indizieren Sie, was Sie abfragen. Die beiden Indizes aus Schritt 3 decken Preis- und Kategoriefilter ab. Fügen Sie einen Index für jede andere Spalte hinzu, die Sie häufig filtern oder sortieren.
  • Async für Volumen. Für Tausende von Seiten reiht der Async Crawler Anfragen ein und liefert Ergebnisse an einen Webhook, sodass Sie keine offenen Verbindungen halten, während Sie crawlen. Kombinieren Sie ihn mit gebündelten Inserts und die Datenbank hält mit.

Wenn Sie das größere Collect-Parse-Store-Analyze-System entwerfen und nicht nur ein einzelnes Skript, erklärt der Leitfaden zur Datenpipeline-Architektur, wie diese Phasen im großen Maßstab zusammenpassen.

Verantwortungsvolles Scraping

Halten Sie die Erfassung in Grenzen. Scrapen Sie nur öffentliche Daten, die nicht hinter einem Login liegen, lesen und respektieren Sie die Nutzungsbedingungen der Website und ihre robots.txt, und halten Sie Ihre Anfragerate vernünftig, damit Sie die Server des Ziels nicht belasten. Wenn die Daten identifizierbare Personen betreffen, gelten Datenschutzregeln wie DSGVO und CCPA, also vermeiden Sie personenbezogene Daten, wenn Sie keine rechtliche Grundlage und einen klaren Bedarf haben. Das Beispiel hier verwendet eine Platzhalter-URL und illustrative Produktfelder genau deshalb, um diese Bedenken zu vermeiden; wenden Sie dasselbe Urteilsvermögen an, wenn Sie den Scraper auf eine echte Website richten.

Zusammenfassung

Wichtigste Erkenntnisse

  • SQL schlägt flache Dateien für Analysen. Eine strukturierte Tabelle ermöglicht es Ihnen, Tausende von Datensätzen mit einer einzigen Abfrage zu filtern, aggregieren und gruppieren, anstatt wegwerfbaren Parsing-Code zu verwenden.
  • Daten beim Eingang bereinigen. Entfernen Sie Währungssymbole und Kommas, damit der Preis als Zahl landet; eine numerische Spalte sortiert und mittelt korrekt, wo Text das nicht tut.
  • Schema bewusst entwerfen. Wählen Sie echte Typen, fügen Sie einen Primärschlüssel und eine UNIQUE-URL hinzu, um Duplikate zu blockieren, und indizieren Sie die Spalten, auf die Sie filtern.
  • Sicher und in Batches einfügen. Parametrisierte ?-Platzhalter und executemany mit einem Commit pro Batch halten Inserts sowohl sicher als auch schnell.
  • Mit einfachem SELECT analysieren. WHERE, ORDER BY, die Aggregatfunktionen und GROUP BY verwandeln gespeicherte Zeilen in Preisbänder, Durchschnittswerte und Einblicke pro Kategorie.

Häufig gestellte Fragen

Warum gescrapte Daten in SQL statt in einer CSV- oder JSON-Datei speichern?

Dateien sind für einen einmaligen Abruf in Ordnung, machen aber zeilenübergreifende Fragen mühsam. Eine SQL-Datenbank erzwingt eine konsistente Struktur, ermöglicht das Filtern, Sortieren und Aggregieren mit einer Abfrage und skaliert mit Indizes auf Millionen von Zeilen. Sie verarbeitet auch wiederholte Läufe sauber: Ein UNIQUE-Constraint verhindert Duplikate, sodass Sie im Laufe der Zeit an dieselbe Tabelle anhängen können, anstatt datierte Dateien zu jonglieren.

Welche Datenbank sollte ich verwenden, SQLite, MySQL oder PostgreSQL?

SQLite ist ideal für kleine bis mittlere Projekte und lokale Arbeit, da es mit Python ausgeliefert wird und keinen Server benötigt, weshalb dieser Leitfaden es verwendet. MySQL eignet sich für Webanwendungen und größere gemeinsame Datensätze, und PostgreSQL ist stark bei komplexen Abfragen und Analysen. Der Python-Ablauf hier ändert sich nur in der Verbindung und der Platzhaltersyntax, wenn Sie zwischen ihnen wechseln; Schema und Abfragen bleiben nahezu identisch.

Wie vermeide ich das zweimalige Einfügen desselben Datensatzes?

Setzen Sie einen UNIQUE-Constraint auf eine Spalte, die den Datensatz identifiziert, wie z.B. die Produkt-URL, und fügen Sie dann mit INSERT OR IGNORE (oder ON CONFLICT bei PostgreSQL) ein. Die Datenbank überspringt jede Zeile, deren Schlüssel bereits vorhanden ist, sodass das erneute Ausführen des Scrapers nur neue Einträge hinzufügt, anstatt die alten zu duplizieren.

Warum den Preis vor der Speicherung in eine Zahl umwandeln?

Weil ein als Text gespeicherter Preis wie "$1,299.00" nicht korrekt verglichen oder gemittelt werden kann: Er sortiert alphabetisch und bricht Aggregatfunktionen. Das Entfernen des Symbols und der Kommas zum Speichern eines numerischen price bedeutet, dass WHERE price < 500, AVG(price) und ORDER BY price alle wie erwartet funktionieren.

Benötige ich das JavaScript-Token dafür?

Nur wenn Ihr Ziel seinen Inhalt clientseitig rendert. Das normale Token gibt statisches HTML zurück, was für serverseitig gerenderte Seiten ausreicht. Wenn die Auflistung nach dem Ausführen der Skripte der Seite befüllt wird, verwenden Sie das JS-Token und fügen Sie die Optionen ajax_wait und page_wait hinzu, damit der dynamische Inhalt geladen wird, bevor das HTML erfasst wird.

Wie skaliere ich dies auf viele Seiten, ohne die Datenbank zu überlasten?

Paginieren Sie das Scraping und übergeben Sie die kombinierten Datensätze an ein gebündeltes executemany-Insert, das alle paar Tausend Zeilen committet statt nach jedem einzelnen. Für große Crawls reiht der Async Crawler Anfragen ein und postet Ergebnisse an einen Webhook, sodass Sie keine Verbindungen offen halten, und das Indizieren der abgefragten Spalten hält Lesevorgänge schnell, wenn die Tabelle wächst.

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