Ein Machine-Learning-Modell ist nur so gut wie die Daten dahinter, und die meisten Daten, von denen es sich zu lernen lohnt, liegen im öffentlichen Web statt in einer ordentlichen CSV-Datei, die jemand überreicht. Produktlisten, Preise, Bewertungen, Stellenanzeigen, Nachrichten und Social-Media-Aktivitäten werden kontinuierlich und in großem Volumen erzeugt, was genau die Art frischer, praxisnaher Signale ist, die ein Modell benötigt. Dieser Leitfaden zeigt, wie man Web Scraping für maschinelles Lernen einsetzt: warum Webdaten ML antreiben, wie man sie zuverlässig im großen Maßstab erfasst, wie man sie kennzeichnet und strukturiert und wie man sie in eine Trainings-Pipeline einspeist, mit ausführbarem Python bei jedem Schritt.
Der Walkthrough beschränkt sich auf öffentliche Daten: Seiten, die jeder ohne Login anzeigen kann. Das Python erfasst HTML über die Crawlbase Crawling API, wandelt es in einen Pandas-Dataframe um, bereinigt und beschriftet die Zeilen und führt einen grundlegenden Feature-Vorbereitungsschritt durch, sodass das Ergebnis bereit für ein Modell ist. Das Ziel ist ein wiederholbarer Erfassungsschritt, den man nach einem Zeitplan erneut ausführen kann, denn ein veralteter Datensatz ist ein Modell, das still schlechter wird.
Warum Webdaten maschinelles Lernen antreiben
Überwachte Modelle lernen aus Beispielen, und das Web ist die größte Quelle von Beispielen, die es gibt. Drei Eigenschaften machen es für ML besonders wertvoll. Es ist vielfältig: Das Scrapen vieler Sites gibt einem Modell die Vielfalt, die es braucht, um zu verallgemeinern, anstatt die Eigenheiten einer Quelle auswendig zu lernen. Es ist aktuell: Das erneute Ausführen eines Collectors hält den Trainingssatz darauf ausgerichtet, wie die Welt jetzt aussieht, was in schnelllebigen Bereichen wie Preisgestaltung, Nachfrage und Stimmung am wichtigsten ist. Und es ist reichhaltig: Wo ein handgekennzeichneter Satz auf einige Tausend Zeilen kommen könnte, kann ein Scraper Hunderttausende öffentlicher Datensätze zusammenstellen.
Der Haken ist die Zuverlässigkeit. Ein einmaliges Skript, das heute auf Ihrem Laptop funktioniert, ist keine Datenquelle, auf der Sie ein Modell aufbauen können. Sites rendern Inhalte Client-seitig, rotieren ihr Markup und blockieren automatisierten Traffic, sodass die Erfassungsschicht robust sein muss, bevor irgendetwas nachgelagertes zählt. Das ist der Teil, an dem ML-Projekte in der Praxis scheitern, und wo dieser Leitfaden den Großteil seiner Zeit verbringt.
Wo gescrapte Daten in eine ML-Pipeline passen
Gescrapte Webdaten tauchen an verschiedenen Punkten in einem Projekt auf, und es hilft, klar zu sein, welchen davon man löst.
- Trainingsdaten. Die gescrapten Zeilen werden zum Datensatz, von dem Ihr Modell direkt lernt, ob überwacht, unüberwacht oder semi-überwacht.
- Feature-Engineering. Felder, die man extrahiert (Textlänge, Stimmung, Preisdeltas, Kategorieanzahlen), werden zu Eingabe-Features, die die Vorhersagekraft eines mit anderen Daten trainierten Modells steigern.
- Datenanreicherung. Wenn ein handgekennzeichneter Satz zu klein ist, erweitern gescrapte Datensätze seine Größe und Vielfalt, damit das Modell mehr vom Raum sieht.
- Evaluierung. Ein frisch gescrapter Slice, der vom Training zurückgehalten wird, ist ein realistischer Testsatz, um zu prüfen, wie sich ein Modell bei aktuellen, praxisnahen Daten verhält.
Der Rest dieses Leitfadens baut eine kleine, aber vollständige Collect-to-Features-Pipeline, die man für jeden dieser Verwendungszwecke anpassen kann. Dafür, wie das Training selbst funktioniert, sobald die Daten bereit sind, ist KI-Modelltraining erklärt eine gute Ergänzung.
Warum ein einfacher Abruf im großen Maßstab nicht ausreicht
Eine Seite mit requests zu erfassen ist einfach. Hunderttausend Seiten zuverlässig von Sites zu erfassen, die sich gegen Bots verteidigen, ist der Punkt, an dem die meisten selbst erstellten Collectors zusammenbrechen. Zwei Probleme tauchen schnell auf. Erstens rendern viele Seiten ihren Inhalt im Browser mit JavaScript, sodass das abgerufene rohe HTML eine leere Hülle ist. Zweitens markieren kommerzielle Sites automatisierten Traffic schnell: Datacenter-IPs und maschinenähnliche Anfragemuster werden blockiert, lange bevor man genug Zeilen zum Trainieren hat.
Man kann beides selbst mit einem Headless-Browser plus einem Pool rotierender Residential-Proxies lösen, aber diese Flotte gesund zu halten ist der Großteil des Engineerings. Die Crawling API fasst das in einem Aufruf zusammen: Man sendet eine URL, sie rendert die Seite hinter einer vertrauenswürdigen IP, rotiert Adressen serverseitig und gibt fertiges HTML zurück. Wenn ein Ziel sauberes statisches Markup liefert und man nur geparste Felder will, gibt die Crawling API strukturiertes JSON direkt zurück; für rohen Transport mit Rotation, die man kontrolliert, ist der Smart AI Proxy die niedrigschwelligere Option. Dieser Leitfaden verwendet die Crawling API, weil Dataset-Collection üblicherweise gemischte, gesicherte Sites umfasst.
Crawlbase bietet zwei Token-Typen. Das normale Token ruft statisches HTML ab; das JavaScript-Token (JS) rendert die Seite zuerst in einem echten Browser. Wenn Ihr Ziel Client-seitig gerendert ist, das JS-Token verwenden, andernfalls ist das normale Token schneller und günstiger. Pro Quelle wählen, nicht einmal für den gesamten Job.
Das Projekt einrichten
Sie benötigen Python 3 und pip installiert. Beides bestätigen, dann ein Projekt erstellen und die Bibliotheken installieren, die die Pipeline verwendet.
python --version pip --version mkdir ml-dataset && cd ml-dataset python -m venv .venv && source .venv/bin/activate pip install crawlbase beautifulsoup4 pandas scikit-learn
Vier Abhängigkeiten erledigen die Arbeit: crawlbase ist der Client für die Crawling API, beautifulsoup4 parst das zurückgegebene HTML, pandas hält den Datensatz als Dataframe, und scikit-learn handhabt die Feature-Vorbereitung am Ende. Man braucht außerdem ein Crawlbase-Konto und ein Token, das man nach der Anmeldung über das Dashboard erhält. In einer Umgebungsvariable statt in hartkodiertem Code aufbewahren.
Schritt 1: Seiten über die Crawling API erfassen
Mit der Erfassungsschicht beginnen, weil alles Nachgelagerte davon abhängt, dass sie sauberes HTML zurückgibt. Der Python-Client umschließt die API in einem get-Aufruf. Zwei Optionen sind für gesicherte, Client-seitig gerenderte Sites wichtig: ajax_wait weist die API an, auf asynchronen Inhalt zu warten, und page_wait hält für eine feste Anzahl von Millisekunden nach dem Laden, damit spät gerenderter Inhalt erscheint. Der Collector prüft den Statuscode, damit eine blockierte Seite nie still zu einer leeren Zeile in Ihrem Datensatz wird.
import os import time from crawlbase import CrawlingAPI # JS token renders the page in a real browser before returning HTML api = CrawlingAPI({"token": os.environ["CRAWLBASE_JS_TOKEN"]}) options = { "ajax_wait": "true", "page_wait": 5000, } def fetch_html(url): response = api.get(url, options) if response["status_code"] != 200: raise RuntimeError(f"fetch failed: {response['status_code']}") return response["body"].decode("utf-8") def collect(urls): pages = [] for url in urls: try: pages.append({"url": url, "html": fetch_html(url)}) except RuntimeError as err: print(f"skipping {url}: {err}") time.sleep(1) # pace requests so you stay unblocked return pages
Die Crawling API rotiert IPs und rendert die Seite für Sie, sodass der Collector klein bleibt. Das time.sleep zwischen Anfragen ist bewusst: Dosierung hält einen langen Durchlauf gesund. Für einen Datensatz jeder echten Größe werden Tausende von URLs, Wiederholungslogik und Nebenläufigkeit benötigt, was ein eigenes Thema ist, das im Leitfaden zu großmaßstäblichem Web Scraping behandelt wird.
Das Aufbauen eines ML-Datensatzes bedeutet Tausende von Seitenabrufen über gesicherte Sites. Die Crawling API nimmt ein Token, rendert die Seite in einem echten Browser, rotiert durch Residential-IPs serverseitig und übergibt fertiges HTML, sodass man das Betreiben einer Headless-Flotte und eines Proxy-Pools selbst überspringt. Zuerst auf eine öffentliche Quelle im kostenlosen Tarif richten.
Schritt 2: Seiten in strukturierte Datensätze parsen
Rohes HTML ist kein Datensatz. Der nächste Schritt wandelt jede Seite in einen flachen Datensatz mit den Feldern um, von denen man lernen möchte. Dieses Beispiel behandelt eine Produktlisten-Seite als Quelle und zieht Name, Preis, Bewertung und Bewertungstext heraus, aber die Form gilt überall: die Felder wählen, jedes einem Selektor zuordnen, ein Dictionary zurückgeben. Ein kleiner Helfer macht ein fehlendes Element zu einem leeren String statt zu einem Absturz.
from bs4 import BeautifulSoup def text_or_empty(node, selector): el = node.select_one(selector) return el.get_text(strip=True) if el else "" def parse_products(page): soup = BeautifulSoup(page["html"], "html.parser") rows = [] for card in soup.select(".product-card"): rows.append({ "name": text_or_empty(card, ".title"), "price": text_or_empty(card, ".price"), "rating": text_or_empty(card, ".rating"), "review": text_or_empty(card, ".review-snippet"), "source": page["url"], }) return rows
Die Selektoren oben als Startvorlage behandeln, nicht als Vertrag: Klassennamen und Datenattribute ändern sich ohne Vorankündigung, also wenn die Extraktion leere Felder zurückgibt, die Live-Seite in den Dev-Tools des Browsers erneut inspizieren und sie aktualisieren. Das ist normale Wartung für jeden Produktions-Scraper.
Schritt 3: Einen Pandas-Dataframe aufbauen
Mit einer Liste von Datensätzen gibt Pandas in einer Zeile einen Dataframe und ein Toolkit für alles danach. Alle Zeilen erfassen, parsen und laden, dann ansehen, was man hat, bevor man ihm vertraut. Die Dedup- und dropna-Schritte sind wichtiger als sie aussehen: Ein Datensatz voller doppelter oder halb leerer Zeilen bringt einem Modell das Falsche bei.
import pandas as pd urls = [ "https://www.example.com/category/page/1", "https://www.example.com/category/page/2", ] records = [] for page in collect(urls): records.extend(parse_products(page)) df = pd.DataFrame(records) df = df.drop_duplicates(subset=["name", "source"]) df = df.dropna(subset=["name"]) print(df.shape) print(df.head()) df.to_csv("dataset_raw.csv", index=False)
Das Schreiben von dataset_raw.csv zu diesem Zeitpunkt gibt einen Checkpoint: Die Erfassung ist langsam und rate-begrenzt, sodass man nie nur wegen eines Bugs in einem späteren Bereinigungsschritt erneut scrapen will. Die CSV für den Rest der Pipeline laden und den Collector als separaten, gelegentlichen Job behalten.
Schritt 4: Die Zeilen bereinigen und kennzeichnen
Gescrapte Felder kommen als unordentliche Strings an: Ein Preis ist "$118", eine Bewertung ist "4.5 out of 5", eine Rezension ist Freitext. Ein Modell braucht Zahlen und eine Zielspalte, also normalisiert dieser Schritt die rohen Felder und leitet ein Label ab. Hier ist das Label ein einfacher Stimmungs-Proxy aus der Bewertung, was eine unbezeichnete Scrape in einen überwachten Klassifikationsdatensatz verwandelt.
import re import pandas as pd df = pd.read_csv("dataset_raw.csv") def to_float(value): match = re.search(r"(\d+(?:\.\d+)?)", str(value)) return float(match.group(1)) if match else None df["price"] = df["price"].apply(to_float) df["rating"] = df["rating"].apply(to_float) df["review"] = df["review"].fillna("").str.strip() # derive a supervised label from the rating df = df.dropna(subset=["rating"]) df["label"] = (df["rating"] >= 4.0).astype(int) print(df["label"].value_counts()) df.to_csv("dataset_clean.csv", index=False)
Das Prüfen von value_counts auf dem Label ist nicht optional. Gescrapte Daten sind selten ausgewogen, und ein Ziel, das zu 95 Prozent aus einer Klasse besteht, erzeugt ein Modell, das genau aussieht, während es nichts lernt. Wenn die Aufteilung einseitig ist, vor dem Training neu ausbalancieren, durch Resampling oder durch Gewichtung der Klassen. Für eine tiefere Behandlung der Normalisierung gescrapter Felder für ML, siehe gescrapte Webdaten für KI und ML strukturieren und bereinigen.
Schritt 5: Features für ein Modell vorbereiten
Der letzte Schritt verwandelt den sauberen Dataframe in die numerische Matrix, auf der ein Modell trainiert. Text muss vektorisiert werden und numerische Spalten profitieren von Skalierung, also wendet ein scikit-learn ColumnTransformer die richtige Transformation auf jede Spalte in einem Durchgang an. Das Ergebnis ist eine Feature-Matrix X und ein Label-Vektor y, aufgeteilt in Trainings- und Test-Sets, bereit, einem beliebigen Estimator übergeben zu werden.
import pandas as pd from sklearn.model_selection import train_test_split from sklearn.compose import ColumnTransformer from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.preprocessing import StandardScaler df = pd.read_csv("dataset_clean.csv").fillna({"review": ""}) features = df[["review", "price"]] y = df["label"] pre = ColumnTransformer([ ("text", TfidfVectorizer(max_features=5000), "review"), ("num", StandardScaler(), ["price"]), ]) X = pre.fit_transform(features) X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42, stratify=y ) print(f"train: {X_train.shape}, test: {X_test.shape}")
Von hier fallen X_train und y_train direkt in die fit-Methode jedes scikit-learn-Estimators, und der zurückgehaltene Test-Split gibt eine ehrliche Genauigkeitsablesung. Das stratify=y-Argument hält die Klassenbalance über den Split hinweg konsistent, was am wichtigsten ist, wenn das Label schief ist. Die Collect-to-Features-Kette ist der wiederverwendbare Teil: Die Selektoren und die Kennzeichnungsregel tauschen und dieselben fünf Schritte bauen einen Datensatz für ein anderes Problem.
Die Erfassungsschicht gesund halten
Ein Datensatz, den man auf Abruf neu aufbauen kann, ist weit mehr wert als ein einmaliger Dump, also muss der Collector weiterarbeiten, wenn sich Ziele ändern. Einige Gewohnheiten halten einen langen Durchlauf gesund.
- Dosieren und rotieren. Anfragen verteilen und durch rotierende Residential-IPs leiten, damit keine einzelne Adresse ein Rate-Limit auslöst. Die Crawling API handhabt Rotation für Sie; wenn man einen eigenen Stack aufbaut, ist das der Teil, den man richtig machen muss.
- Statuscodes lesen. Ein Durchlauf, der beginnt, Challenges zurückzugeben, sagt einem, dass die aktuelle Rate oder IP-Stufe nicht mehr ausreicht. Das als Signal behandeln und zurückweichen, anstatt in eine Sperre hinein zu wiederholen.
- Rohes HTML als Checkpoint speichern. Das Abgerufene vor dem Parsen speichern, damit ein Parser-Bug nie eine erneute Scrape kostet.
Für das vollständige Playbook, siehe wie man Websites scrapt, ohne blockiert zu werden. Und sobald der Datensatz existiert, behandelt KI-Datenextraktion und wie sie funktioniert das automatischere Umwandeln unordentlicher Seiten in strukturierte Felder.
Der ehrliche Teil: Ethik und Legalität
Das Aufbauen eines ML-Datensatzes trägt dieselben Verantwortlichkeiten wie jede Scrape, und ob es erlaubt ist, hängt von den Nutzungsbedingungen jeder Site, Ihrer Zuständigkeit und dem ab, was Sie mit den Daten tun. Nur öffentliche Daten erfassen, das robots.txt und die angegebenen Rateerwartungen jeder Site respektieren, und das Anfragevolumen niedrig genug halten, dass man niemandes Server belastet.
Zwei Punkte sind spezifisch für ML wichtiger. Niemals personenbezogene Daten oder etwas erfassen, das an identifizierbare Personen gebunden ist, und darauf achten, dass ein abgeleitetes Label oder Feature diese nicht rekonstruiert. Und bedenken: Ein Modell erbt die Verzerrungen seiner Trainingsdaten; ein aus einer Region, Sprache oder Plattform gescrapter Satz erzeugt ein Modell, das außerhalb davon schlecht verallgemeinert. Für kommerzielle Wiederverwendung eine Genehmigung oder einen offiziellen Datenvertrag einholen, statt Schweigen als Zustimmung zu betrachten.
Wichtigste Erkenntnisse
- Webdaten sind vielfältig, aktuell und reichhaltig. Diese drei Eigenschaften sind genau das, was ein Modell zum Verallgemeinern braucht, weshalb Scraping so viele ML-Datensätze antreibt.
- Zuverlässigkeit ist der schwierige Teil, nicht das Parsen. Client-seitige Seiten rendern, IPs rotieren und Anfragen dosieren, sonst bricht der Collector, bevor man genug Zeilen hat.
- Die Crawling API fasst Rendering und Rotation in einem Aufruf zusammen. Das JS-Token für Client-seitige Seiten und das normale Token für statische verwenden, pro Quelle gewählt.
- Vor dem Training bereinigen und kennzeichnen. Unordentliche Strings in Zahlen normalisieren, eine Zielspalte ableiten und immer die Klassenbalance prüfen.
- Feature-Vorbereitung macht den Datensatz modellbereit. Text vektorisieren, Numeriken skalieren und mit einem einzigen scikit-learn-Transformer in Trainings- und Test-Sets aufteilen.
- Auf öffentlichen Daten bleiben. Nutzungsbedingungen und robots.txt respektieren, personenbezogene Daten vermeiden und auf Verzerrungen achten, die der Trainingssatz einbettet.
Häufig gestellte Fragen
Wird Web Scraping im maschinellen Lernen eingesetzt?
Ja, in großem Umfang. Die Fähigkeit, große Mengen öffentlicher Daten aus vielen Quellen zu erfassen, ermöglicht das Aufbauen von Trainingssätzen, die größer und vielfältiger sind als handgekennzeichnete Daten allein, was genau das ist, was einem Modell hilft zu verallgemeinern. Scraping hält einen Datensatz auch aktuell, sodass Modelle in schnelllebigen Bereichen wie Preisgestaltung oder Stimmung mit den aktuellen Bedingungen ausgerichtet bleiben statt aus veralteten Schnappschüssen zu lernen.
Wie erfasse ich Webdaten für einen ML-Datensatz im großen Maßstab?
Der Engpass ist Zuverlässigkeit, nicht Parsen. Viele Seiten rendern Client-seitig und die meisten kommerziellen Sites blockieren automatisierten Traffic, sodass man Rendering und einen vertrauenswürdigen, rotierenden IP-Pool benötigt, um Tausende von Seiten abzurufen, ohne abgeschnitten zu werden. Die Crawling API handhabt beides in einem Aufruf: Eine URL senden, fertiges HTML zurückbekommen und in Datensätze parsen. Anfragen dosieren, das rohe HTML als Checkpoint speichern und den Collector als separaten Job vom Rest der Pipeline halten.
Brauche ich das normale Token oder das JS-Token?
Das hängt von der Quelle ab. Das normale Token ruft statisches HTML ab und ist schneller und günstiger, also es verwenden, wenn die Seite bereits die gewünschten Daten enthält. Das JS-Token rendert die Seite zuerst in einem echten Browser, was man für Client-seitig gerenderte Sites benötigt, bei denen ein einfacher Abruf eine leere Hülle zurückgibt. Pro Quelle wählen statt eines für den gesamten Job.
Wie verwandelt man gescrapte Seiten in einen gekennzeichneten Datensatz?
Jede Seite in flache Datensätze parsen, in einen Pandas-Dataframe laden, dann bereinigen und kennzeichnen. Unordentliche Felder zu Zahlen normalisieren (Währungssymbole entfernen, Bewertungen extrahieren), Duplikate und leere Zeilen verwerfen und eine Zielspalte aus einem vertrauenswürdigen Feld ableiten, zum Beispiel eine hohe Bewertung einem positiven Label zuordnen. Immer die Klassenbalance vor dem Training prüfen, weil gescrapte Daten selten ausgewogen sind.
Wie bereitet man gescrapte Daten als Features für ein Modell vor?
Jede Spalte in eine numerische Form umwandeln, die das Modell lesen kann. Textfelder mit etwas wie TF-IDF vektorisieren, numerische Spalten skalieren, damit kein einzelnes Feature dominiert, und beides in einem Durchgang mit einem scikit-learn ColumnTransformer anwenden. Das Ergebnis in Trainings- und Test-Sets aufteilen, auf dem Label stratifizierend, damit die Klassenbalance erhalten bleibt, und die Feature-Matrix ist bereit, jedem Estimator zu passen.
Ist das Scrapen von Daten für maschinelles Lernen legal?
Das hängt von den Nutzungsbedingungen jeder Site, Ihrer Zuständigkeit und Ihrem Zweck ab. Streng auf öffentliche Daten beschränken, robots.txt und Rateerwartungen respektieren und niemals personenbezogene Daten oder etwas an identifizierbare Personen Gebundenes erfassen. Beachten, dass ein Modell die Verzerrungen seines Trainingssatzes erbt. Für kommerzielle Wiederverwendung eine Genehmigung oder einen offiziellen Datenvertrag einholen statt auf einen Scraper zu vertrauen.
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.
