Scraping liefert dir Zeilen, aber keine Antworten. Die Daten, die ein Crawler ausgibt, sind fast immer unsauber: Preise als Zeichenketten mit Währungssymbolen gespeichert, Datumsangaben in drei verschiedenen Formaten, halb gefüllte Spalten und dasselbe Produkt doppelt aufgeführt, weil zwei Seiten darauf verlinkt haben. Bevor irgendetwas davon nützlich wird, musst du es bereinigen, und das Standardwerkzeug für diese Aufgabe in Python ist pandas.

Diese Anleitung nimmt einen realistischen gescrapten Datensatz, eine CSV mit Produktlistings, und führt ihn vollständig von rohen Zeilen bis zur Erkenntnis mit pandas. Du lädst sie in einen DataFrame, inspizierst ihn, behandelst fehlende Werte und Duplikate, korrigierst die Spaltentypen, parst Preise und Datumsangaben in echte Zahlen und Zeitstempel, dann filterst, gruppierst, aggregierst, sortierst und exportierst du das Ergebnis. Jeder Codeausschnitt ist echt und zum Kopieren und Einfügen geeignet. Die einzige Annahme ist, dass die Eingabe von Anfang an verantwortungsvoll aus öffentlichen Quellen erhoben wurde.

Was du erstellen wirst

Eine kurze, wiederholbare Bereinigungs- und Analyse-Pipeline, die einen rohen Scrape in einen aufgeräumten Datensatz und ein paar Zusammenfassungstabellen verwandelt. Am Ende hast du jedes Feld einer typischen Produktzeile angefasst:

  • product_name: Freitext, oft mit unsauberer Groß- und Kleinschreibung und Leerzeichen.
  • category: die Gruppierungsspalte, nach der du aggregieren wirst.
  • price: als Zeichenkette wie "$1,299.00" gescrapt, die zu einem Float werden muss.
  • rating: eine numerische Spalte mit fehlenden Werten, die behandelt werden müssen.
  • in_stock: ein boolean-artiges Flag, das inkonsistent als Text gespeichert ist.
  • scraped_at: eine Datumszeichenkette, die in einen echten Zeitstempel geparst werden muss.

Derselbe Workflow gilt für jeden tabellarischen Scrape, ob Listings, Bewertungen, Stellenanzeigen oder Immobilienzeilen. Wenn dein Crawler bereits sauberes JSON oder CSV schreibt, springst du direkt zur Analysehälfte. Für einen tieferen Blick auf die beiden Formate und wann du welches wählen solltest, siehe JSON vs CSV: die wichtigsten Unterschiede.

Warum gescrapte Daten zuerst bereinigt werden müssen

Rohe gescrapte Daten sind selten analysebereit. Die Extraktionsschicht zieht jeglichen Text heraus, der in einem Selektor sitzt, sodass ein Preis als "$1,299.00" zurückkommt statt als die Zahl 1299.0, eine Bewertungszelle leer sein kann, wenn die Seite sie nie gerendert hat, und dasselbe Listing zweimal erscheinen kann, wenn sich die Paginierung überschneidet. Speist du das direkt in eine Berechnung ein, bekommst du Fehler oder, schlimmer noch, stillschweigend falsche Antworten.

Die Bereinigung behebt drei Problemklassen, bevor irgendeine Analyse läuft: fehlende Werte durch unvollständige Extraktion, doppelte Zeilen durch sich überschneidende Crawls und inkonsistente Formate über Preis-, Datums- und Textspalten hinweg. Macht man diese richtig, wird der Rest von pandas, also Sortieren, Gruppieren, Aggregieren, zu ein paar Einzeilern. Wenn du diese Disziplin in eine größere Pipeline einbaust, lassen sich die Muster in Strukturieren und Bereinigen von Web-Scraping-Daten für AI und ML gut über eine einzelne CSV hinaus verallgemeinern.

Voraussetzungen

Du brauchst nicht viel, um mitzumachen.

Grundlegendes Python. Du solltest in der Lage sein, ein Skript auszuführen und ein paar Zeilen Code zu lesen. Zu wissen, was eine Liste und ein Dictionary sind, reicht aus; pandas erledigt die Schwerstarbeit.

Python 3.8 oder neuer. Prüfe deine Version mit python --version. Falls du es nicht hast, installiere es von python.org.

Eine gescrapte CSV- oder JSON-Datei. Jeder tabellarische Export reicht. Die Beispiele unten gehen von einer Datei namens products.csv mit den oben aufgeführten Spalten aus, aber die Methoden sind dieselben, egal wie deine Spalten heißen.

Das Projekt einrichten

Erstelle eine virtuelle Umgebung, damit das Projekt isoliert bleibt, und installiere dann pandas. Das ist die einzige erforderliche Abhängigkeit; matplotlib ist optional und wird nur für den schnellen Plot am Ende benötigt.

bash
python --version

python -m venv pandas_env
source pandas_env/bin/activate

pip install pandas matplotlib

Unter Windows aktivierst du die Umgebung mit pandas_env\Scripts\activate statt mit der source-Zeile. pandas liefert dir den DataFrame und jede Bereinigungsmethode unten; matplotlib ist das, worüber pandas plottet, wenn du am Ende .plot() aufrufst.

Schritt 1: Die Daten in einen DataFrame laden

Alles in pandas beginnt mit einem DataFrame, einer tabellenartigen Struktur aus Zeilen und Spalten, ganz ähnlich einer Tabellenkalkulation. Eine einzelne Spalte davon ist eine Series. Eine gescrapte CSV in einen DataFrame einzulesen, ist ein einziger Aufruf, und JSON ist mit read_json genauso einfach.

python
import pandas as pd

# Load the scraped product listings
df = pd.read_csv("products.csv")

# JSON works the same way:
# df = pd.read_json("products.json")

# Show the first five rows
print(df.head())

Die Methode head() gibt die ersten fünf Zeilen aus, deine erste Bestätigung, dass die Datei geladen wurde und die Spalten dort landeten, wo du sie erwartest. Wenn dein Scrape ein JSON-Objekt pro Zeile erzeugt hat, übergib lines=True an read_json. Von hier an arbeitet jede Operation auf dem df-Objekt im Speicher; nichts berührt die Originaldatei, bis du am Ende exportierst.

Crawlbase Crawling API

Je sauberer deine products.csv ist, bevor sie pandas erreicht, desto weniger brauchst du von dieser Anleitung tatsächlich. Die Crawling API parst unterstützte Seiten automatisch in strukturierte JSON-Felder, wobei Preise, Titel, Bewertungen und Bestand bereits in typisierte Werte aufgeteilt sind, sodass die Zeilen, die du lädst, nahezu analysebereit sind statt einer Wand aus rohen Zeichenketten. Weniger Zeit für das Reparieren von Dtypes, mehr Zeit zum Finden von Erkenntnissen.

Schritt 2: Den Datensatz inspizieren

Bevor du irgendetwas änderst, sieh dir an, was du hast. Drei Methoden verraten dir fast alles: head() zeigt Beispielzeilen, info() meldet Spaltentypen und wie viele Nicht-Null-Werte jede enthält, und describe() liefert zusammenfassende Statistiken für die numerischen Spalten.

python
# Shape: (rows, columns)
print(df.shape)

# Column names, dtypes, and non-null counts
df.info()

# Summary stats for numeric columns
print(df.describe())

Lies info() aufmerksam: Hier erkennst du Probleme früh. Wenn price als object statt als Zahl auftaucht, ist es immer noch eine Zeichenkette, und Arithmetik darauf wird scheitern. Wenn rating weniger Nicht-Null-Werte als die Zeilenanzahl hat, hast du fehlende Daten zu behandeln. Dieser eine Aufruf sagt dir, welche der nächsten Schritte du tatsächlich brauchst.

Schritt 3: Fehlende Werte behandeln

Fehlende Zellen entstehen durch unvollständige Extraktion, ein Feld, das nicht gerendert wurde, ein Selektor, der auf einer Seite nichts traf. Zähle sie zunächst pro Spalte, entscheide dann, ob du die betroffenen Zeilen verwirfst oder mit einem sinnvollen Standardwert füllst.

python
# Count missing values per column
print(df.isnull().sum())

# Drop rows missing a product name or price (can't analyse those)
df = df.dropna(subset=["product_name", "price"])

# Fill missing ratings with the column average instead of dropping
df["rating"] = df["rating"].fillna(df["rating"].mean())

Die Wahl zwischen Verwerfen und Füllen ist eine Ermessensfrage, keine Regel. Verwirf Zeilen, wenn das fehlende Feld essenziell ist und nicht erraten werden kann; ein Listing ohne Preis ist für eine Preisanalyse nutzlos. Fülle, wenn die Spalte zweitrangig ist und ein vernünftiger Ersatz besser ist, als die ganze Zeile zu verlieren; hier wird ein fehlendes rating zum Spaltenmittelwert, sodass diese Produkte in Kategorie-Aggregaten weiterhin zählen. subset bei dropna zu verwenden hält das Löschen gezielt, statt jede Zeile mit einer einzigen leeren Zelle wegzuwerfen.

Schritt 4: Doppelte Zeilen entfernen

Sich überschneidende Crawls und erneute Durchläufe hinterlassen doppelte Zeilen, und sie blähen Zählungen und Durchschnittswerte stillschweigend auf. Finde sie, verwirf sie dann und behalte das erste Vorkommen.

python
# How many fully duplicated rows are there?
print(df.duplicated().sum())

# Drop exact duplicate rows, keep the first
df = df.drop_duplicates(keep="first")

# Or de-duplicate on a unique key, like a product URL or ID
df = df.drop_duplicates(subset=["product_name", "category"])

Ein bloßes drop_duplicates() entfernt nur Zeilen, die über jede Spalte hinweg identisch sind, wodurch Beinahe-Duplikate, bei denen sich ein Feld unterscheidet, übersehen werden. Wenn dein Scrape einen natürlichen Schlüssel hat, eine Produkt-ID oder eine kanonische URL, dedupliziere darauf mit subset, sodass zwei Erfassungen desselben Artikels zu einem zusammenfallen, selbst wenn sich der gescrapte Zeitstempel unterscheidet. Führe das vor jeder Zählung aus, damit deine Summen eindeutige Produkte widerspiegeln und keine Crawl-Artefakte.

Schritt 5: Datentypen korrigieren und Preise parsen

Das ist der Schritt, der gescrapte Zeichenketten in Werte verwandelt, mit denen du rechnen kannst. Ein gescrapter price kommt als Text wie "$1,299.00" an; du entfernst das Währungssymbol und den Tausendertrennzeichen, dann castest du zu Float. Dieselbe Idee standardisiert das Bestands-Flag und räumt Textspalten auf.

python
# "$1,299.00" -> 1299.0
df["price"] = (
    df["price"]
    .str.replace(r"[$,]", "", regex=True)
    .astype("float")
)

# Tidy text: strip whitespace and normalise case
df["product_name"] = df["product_name"].str.strip()
df["category"] = df["category"].str.lower()

# "Yes"/"No" text flag -> real booleans
df["in_stock"] = df["in_stock"].str.lower().map({"yes": True, "no": False})

Der .str-Accessor lässt dich Zeichenkettenoperationen über eine ganze Spalte auf einmal ausführen, sodass die Regex [$,] sowohl das Dollarzeichen als auch das Komma aus jedem Preis entfernt, bevor astype("float") die Spalte numerisch macht. Das Kleinschreiben von category ist wichtiger, als es aussieht: Wenn die Hälfte deiner Zeilen "Phones" sagt und die andere Hälfte "phones", behandelt das Gruppieren sie als zwei Kategorien, bis du sie normalisierst. Das Bestands-Flag auf echte Booleans abzubilden, lässt dich im nächsten Schritt sauber danach filtern.

Achte auf deine Dtypes

Führe nach jeder Typumwandlung erneut df.info() aus und bestätige, dass die Spalte als float64, bool oder datetime64 gelesen wird statt als object. Ein object-Dtype auf einer Spalte, die du für numerisch hältst, ist der mit Abstand häufigste Grund, warum eine spätere Berechnung einen Fehler wirft oder stillschweigend Müll zurückgibt.

Schritt 6: Datumsangaben parsen

Datumszeichenketten sind für zeitbasierte Analysen nutzlos, bis pandas sie als Zeitstempel versteht. to_datetime konvertiert die Spalte, und sobald es ein echtes Datetime ist, kannst du danach sortieren, Bereiche filtern und Teile wie den Monat herausziehen.

python
# Parse the scraped timestamp into a real datetime
df["scraped_at"] = pd.to_datetime(df["scraped_at"], errors="coerce")

# Now date parts are available
df["scrape_month"] = df["scraped_at"].dt.to_period("M")

Das Übergeben von errors="coerce" ist der sichere Standard bei gescrapten Daten: Jeder Wert, den pandas nicht parsen kann, wird zu NaT (dem Datetime-Äquivalent von null), statt zu fehlern und das gesamte Skript anzuhalten. Wenn jede Zeile ein bekanntes Format teilt, kannst du format="%Y-%m-%d" übergeben, um das Parsen schneller und strenger zu machen. Mit einer echten Datetime-Spalte stellt der .dt-Accessor year, month, day sowie Helfer wie to_period für monatliches Bucketing bereit.

Schritt 7: Filtern und auswählen

Mit sauberen und typisierten Daten kannst du Fragen an sie stellen. Boolesche Indizierung filtert Zeilen nach Bedingung, und du kannst Bedingungen kombinieren, um weiter einzugrenzen.

python
# Only in-stock products over $100
premium = df[(df["in_stock"]) & (df["price"] > 100)]

# Just the columns you care about
premium = premium[["product_name", "category", "price", "rating"]]

print(premium.head())

Jede Bedingung innerhalb der Klammern erzeugt eine boolesche Series, und & kombiniert sie Zeile für Zeile, also umschließe jede Bedingung mit Klammern, um die Operatorrangfolge richtig zu halten. Eine Liste von Spalten mit doppelten Klammern auszuwählen, gibt einen schmaleren DataFrame zurück, praktisch, wenn ein Scrape dreißig Spalten hat und du für eine bestimmte Frage nur vier möchtest.

Schritt 8: Gruppieren, aggregieren und sortieren

Der eigentliche Lohn ist das Zusammenfassen. groupby teilt die Zeilen nach einem Schlüssel auf, dann aggregierst du jede Gruppe, Durchschnittspreis pro Kategorie, Produktanzahl pro Kategorie, die höchste Bewertung in jeder, und sortierst das Ergebnis, um es auf einen Blick zu lesen.

python
# Average price per category, highest first
avg_price = (
    df.groupby("category")["price"]
    .mean()
    .sort_values(ascending=False)
)

# Several aggregates at once
summary = df.groupby("category").agg(
    product_count=("product_name", "count"),
    avg_price=("price", "mean"),
    max_price=("price", "max"),
    avg_rating=("rating", "mean"),
)

print(avg_price)
print(summary)

Die Einzelmetrik-Form, groupby("category")["price"].mean(), gibt eine Zahl pro Kategorie zurück und liest sich fast wie Englisch. Wenn du mehrere Metriken in einer Tabelle möchtest, ist benannte Aggregation mit .agg() sauberer: Jedes Schlüsselwort wird zu einer Ausgabespalte, und das Tupel (column, function) sagt, welches Feld wie zusammengefasst werden soll. Das Anhängen von sort_values am Ende ordnet das Ergebnis so, dass die teuersten und günstigsten Kategorien oben und unten stehen.

Schritt 9: Statistiken anwenden

Für eine schnelle numerische Einschätzung einer einzelnen Spalte decken die eingebauten statistischen Methoden das meiste ab, was du brauchst, ohne pandas zu verlassen.

python
# Full statistical summary of the price column
print(df["price"].describe())

# Individual measures
median_price = df["price"].median()
std_price = df["price"].std()

print(f"Median price: {median_price:.2f}")
print(f"Std deviation: {std_price:.2f}")

Der Aufruf describe() auf einer einzelnen Spalte gibt dir Anzahl, Mittelwert, Standardabweichung, Min, Max und die Quartile in einem Durchgang, eine schnelle Methode, um Ausreißer zu erkennen, etwa einen Scraping-Fehler, der einen Preis auf null oder in die Millionen gesetzt hat. median() ist bei Preisdaten oft ehrlicher als der Mittelwert, weil ein paar sehr teure Artikel den Durchschnitt nach oben verzerren, und der Vergleich der beiden verrät dir, wie schief die Verteilung ist.

Schritt 10: Visualisieren und exportieren

Ein Diagramm macht eine Verteilung offensichtlich, und pandas plottet direkt über matplotlib. Wenn die Analyse fertig ist, schreibe die bereinigten Daten wieder hinaus, damit die nächste Stufe, ein Notebook, ein Dashboard, ein Teamkollege, sie aufgreifen kann.

python
import matplotlib.pyplot as plt

# Average price per category as a bar chart
avg_price.plot(kind="bar", title="Average price per category")
plt.ylabel("Price")
plt.tight_layout()
plt.show()

# Export the cleaned dataset
df.to_csv("products_clean.csv", index=False)
summary.to_csv("category_summary.csv")

# JSON export works the same way
df.to_json("products_clean.json", orient="records", indent=2)

Das Übergeben von index=False an to_csv hält pandas davon ab, die Zeilennummern als störende erste Spalte zu schreiben, was bei einem sauberen Export fast immer gewünscht ist. Für JSON erzeugt orient="records" eine Liste mit einem Objekt pro Zeile, die Form, die die meisten anderen Werkzeuge erwarten. Damit ist aus dem rohen Scrape eine aufgeräumte Datei und eine Zusammenfassungstabelle geworden, die du übergeben oder als Diagramm darstellen kannst.

Wie die Ausgabe aussieht

Nach dem Durchlauf der Pipeline liest sich die Zusammenfassung pro Kategorie als kleine, saubere Tabelle. Nach JSON exportiert mit orient="records", sieht jede Zeile so aus:

json
[
  {
    "category": "laptops",
    "product_count": 128,
    "avg_price": 942.55,
    "max_price": 2499.00,
    "avg_rating": 4.31
  },
  {
    "category": "phones",
    "product_count": 204,
    "avg_price": 611.20,
    "max_price": 1399.00,
    "avg_rating": 4.12
  }
]

Diese Zahlen sind illustrativ, aber die Form ist genau das, was der Code erzeugt: ein Datensatz pro Kategorie, der jeweils die Zählungen und Aggregate trägt, die du in .agg() definiert hast. Diese strukturierte Ausgabe ist es, die die nächste Stufe speist, sei es ein Preis-Tracking-Dashboard, ein Notebook oder ein Modell.

Über eine Datei hinaus skalieren

Eine einzelne CSV ist der Ausgangspunkt, nicht das Ziel. Wenn deine Scrapes wachsen, halten ein paar Gewohnheiten dieselbe Pipeline auch im großen Maßstab am Laufen.

  • Viele Dateien kombinieren. Wenn ein Crawl eine CSV pro Durchlauf schreibt, lies sie alle ein und stapele sie mit pd.concat([...]) zu einem einzelnen DataFrame vor der Bereinigung, dann dedupliziere, damit sich überschneidende Durchläufe nicht doppelt zählen.
  • Große Dateien in Chunks verarbeiten. Wenn eine Datei zu groß für den Speicher ist, übergib chunksize an read_csv und iteriere, bereinige und aggregiere jeden Chunk, sodass du nie den gesamten Datensatz auf einmal hältst.
  • Mach aus der Bereinigung eine Funktion. Verpacke die Schritte 3 bis 6 in eine einzige clean(df)-Funktion, sodass jeder neue Batch dieselbe Behandlung erhält und deine Pipeline reproduzierbar bleibt statt ein Haufen einmaliger Zellen.
  • Wähle das richtige Eingabeformat. Verschachtelte Daten, Bewertungen mit Antworten, Produkte mit Variantenlisten, passen oft besser zu JSON als zu CSV. Die richtige Wahl hängt von deiner Datenform ab, behandelt in JSON vs CSV.

Wenn pandas bei einer Spalte, die du oft scrapst, einschränkend zu wirken beginnt, deckt das breitere Ökosystem der Python-Scraping- und Datenbibliotheken die Werkzeuge ab, die da ansetzen, wo ein einzelner DataFrame aufhört.

Zusammenfassung

Wichtigste Erkenntnisse

  • Bereinige, bevor du analysierst. Gescrapte Daten kommen mit fehlenden Zellen, doppelten Zeilen und als Zeichenketten typisierten Zahlen an; behebe diese zuerst, sonst ist jede spätere Berechnung fragwürdig.
  • Inspiziere mit head, info und describe. Diese drei Methoden verraten dir die Form, die Dtypes und die Anzahl fehlender Werte, sodass du genau weißt, welche Bereinigungsschritte du brauchst.
  • Parse Preise und Datumsangaben in echte Typen. Entferne Währungssymbole und caste zu Float, konvertiere Datumszeichenketten mit to_datetime und bestätige mit info(), dass keine numerische Spalte noch object ist.
  • groupby plus agg ist, wo die Erkenntnis steckt. Teile nach einem Schlüssel auf, aggregiere mehrere Metriken auf einmal mit benannter Aggregation und sortiere das Ergebnis, um es auf einen Blick zu lesen.
  • Sauberere Eingabe bedeutet weniger Bereinigung. Je strukturierter deine Daten sind, wenn sie pandas erreichen, desto kürzer wird diese gesamte Pipeline.

Häufig gestellte Fragen

Wie installiere ich pandas in Python?

Führe pip install pandas von deinem Terminal aus, idealerweise innerhalb einer virtuellen Umgebung, damit es nicht mit anderen Projekten kollidiert. Importiere es dann in deinem Skript mit import pandas as pd, dem üblichen Alias, der in nahezu allem pandas-Code verwendet wird. Wenn du auch die hier gezeigten schnellen Diagramme möchtest, installiere matplotlib daneben mit pip install pandas matplotlib.

Was ist der Unterschied zwischen einem DataFrame und einer Series in pandas?

Ein DataFrame ist die gesamte Tabelle, Zeilen und Spalten zusammen, ganz ähnlich einer Tabellenkalkulation oder einer Datenbanktabelle. Eine Series ist eine einzelne Spalte dieser Tabelle, ein eindimensionales, beschriftetes Array. Wenn du eine Spalte mit df["price"] auswählst, erhältst du eine Series; die meisten Bereinigungsmethoden wie fillna und str.replace arbeiten auf einer Series, und du weist das Ergebnis wieder der Spalte zu.

Wie wandle ich eine gescrapte Preiszeichenkette in eine Zahl um?

Verwende den .str-Accessor, um die nicht-numerischen Zeichen zu entfernen, dann caste die Spalte. Für einen Wert wie "$1,299.00" lautet der Aufruf df["price"].str.replace(r"[$,]", "", regex=True).astype("float"), was das Dollarzeichen und das Komma entfernt und die Spalte in einen Float verwandelt, mit dem du rechnen kannst. Prüfe danach immer erneut mit df.info(), dass die Spalte kein object-Dtype mehr ist.

Sollte ich fehlende Werte in gescrapten Daten verwerfen oder füllen?

Das hängt davon ab, wie essenziell die Spalte ist. Verwirf die Zeile, wenn das fehlende Feld kritisch ist und nicht vernünftig erraten werden kann; ein Listing ohne Preis ist für eine Preisanalyse nutzlos. Fülle den Wert, wenn die Spalte zweitrangig ist und ein Ersatz besser ist, als die ganze Zeile zu verlieren, etwa wenn du eine fehlende Bewertung durch den Spaltenmittelwert ersetzt, sodass das Produkt in Kategorie-Aggregaten weiterhin zählt. Verwende dropna(subset=[...]), um bestimmte Spalten gezielt anzusprechen, statt jede Zeile mit einer einzigen Leerstelle zu löschen.

Wie fasse ich gescrapte Daten nach Kategorie zusammen?

Verwende groupby gefolgt von einer Aggregation. Für eine Metrik liefert df.groupby("category")["price"].mean() den Durchschnittspreis pro Kategorie. Für mehrere auf einmal verwende benannte Aggregation, df.groupby("category").agg(count=("product_name", "count"), avg_price=("price", "mean")), wobei jedes Schlüsselwort zu einer Ausgabespalte wird. Hänge sort_values am Ende an, um das Ergebnis zu ordnen.

Kann ich gescrapte Daten automatisch bereinigen und analysieren?

Ja. Verpacke deine Bereinigungsschritte in eine Funktion und rufe sie bei jedem neuen Batch auf, führe dann das gesamte Skript nach einem Zeitplan aus, sodass jeder frische Scrape auf dieselbe Weise verarbeitet wird. Die Logik in einer reproduzierbaren Funktion zu halten, statt über Notebook-Zellen verstreut, ist es, was die Pipeline zuverlässig macht, während deine Daten wachsen.

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