Modell / Datensatz
mishushakov/llm-scraper avatar
mishushakov/llm-scraper

llm-scraper: Webseiten mit Zod-Schema und Playwright in Objekte verwandeln

Turn any webpage into structured data using LLMs

6.927 Sterne453 ForksTypeScriptMIT
GitHub

Auf einen Blick

Was ist das?
llm-scraper verbindet Playwright mit dem Vercel AI SDK und lässt ein Sprachmodell Daten aus einer Seite in ein Zod-Schema schreiben. Der Ansatz ist elegant für unregelmäßige Seiten, aber er kostet Tokens, Bandbreite und hängt an der Qualität des Modells.
Für wen ist es gedacht?
llm-scraper passt zu Teams, die viele unterschiedlich aufgebaute Seiten auswerten müssen und dafür bereits ein LLM im Einsatz haben. Wer stabile, hochfrequente Extraktionen aus einer Handvoll bekannter Domains braucht, sollte bei selektorbasierten Scrapern bleiben.
Darf ich es kommerziell nutzen?
Ja. MIT ist eine freizügige Lizenz: Sie dürfen darauf aufbauende Software nutzen, verändern und verkaufen, solange Sie die Urheberrechts- und Lizenzhinweise beibehalten.
Wird es noch gepflegt?
Ja. Die letzten Commits kamen vor 6 Tagen.
In welcher Sprache ist es geschrieben?
Hauptsächlich TypeScript, laut der Sprachstatistik von GitHub.

Die Antworten beruhen auf den GitHub-Daten des Projekts (zuletzt abgeglichen am 15. September 2026) und auf unserer Analyse. Sie sind keine Rechtsberatung.

TIEFGEHENDE OPEN-SOURCE-ANALYSE

Das Problem: Schema statt Selektor

Klassisches Scraping setzt voraus, dass man die Struktur einer Seite kennt. Man schreibt einen CSS-Selektor, wartet auf das passende Element und parst den Text. Sobald das Markup wechselt oder die Seite ihre Inhalte unterschiedlich rendert, bricht der Selektor. llm-scraper dreht das um: Statt zu beschreiben, wo ein Wert steht, beschreibt man mit Zod, welche Form die Ausgabe haben soll. Das Modell liest den Seiteninhalt und füllt das Schema. Die Bibliothek positioniert sich laut README als Werkzeug, das strukturierte Daten aus jeder Webseite extrahiert, und die Beispiele im Repository zeigen genau diesen Ablauf. Die Zielgruppe sind TypeScript-Entwickler, die bereits mit Playwright arbeiten und ein LLM anbinden können. Wer nur eine Tabelle von einer festen URL ziehen will, für den ist der Ansatz überdimensioniert.

Wie der Ablauf zwischen Browser, Schema und Modell aussieht

Der Datenfluss ist im README-Beispiel klar erkennbar: Zuerst startet Playwright einen Chromium-Browser und öffnet eine Seite. Danach wird ein LLM-Provider initialisiert, hier über openai('gpt-4o'). Mit new LLMScraper(llm) entsteht die Scraper-Instanz. Der Aufruf scraper.run(page, Output.object({ schema }), { format: 'html' }) übergibt die Seite, das gewünschte Ausgabeobjekt und ein Format. Die Bibliothek bereitet den Seiteninhalt gemäß diesem Format auf und schickt ihn zusammen mit dem Schema an das Modell. Zurück kommt ein Objekt, das dem Zod-Schema entspricht, im Beispiel die fünf Top-Stories von Hacker News mit Titel, Punkten, Autor und Kommentar-URL. Sechs Formate stehen zur Wahl: html für vorverarbeitetes HTML, raw_html ohne Verarbeitung, markdown, text über Readability.js, image für Screenshots im multimodalen Betrieb und custom für eine eigene Funktion. Die Wahl des Formats ist der eigentliche Hebel, denn sie bestimmt, wie viele Tokens das Modell sieht und wie viel Kontext verloren geht.

Installation und Provider-Anbindung

Die Installation folgt dem README: npm i zod playwright llm-scraper. Für das Modell kommt ein Provider-Paket des Vercel AI SDK dazu, etwa @ai-sdk/openai, @ai-sdk/anthropic oder @ai-sdk/google. Der Modellname wird direkt übergeben, beispielsweise anthropic('claude-3-5-sonnet-20240620') oder google('gemini-1.5-flash'). Für Groq zeigt das README den Umweg über createOpenAI mit baseURL 'https://api.groq.com/openai/v1' und apiKey aus process.env.GROQ_API_KEY. Für lokale Modelle ist ollama-ai-provider-v2 dokumentiert, mit ollama('llama3'). Das sind die einzigen Anbindungen, die das Material belegt. Die Version 2.0 hat laut README auf Vercel AI SDK 6 umgestellt und die Beispiele aktualisiert. Wer von einer älteren Version kommt, sollte die Beispiele im examples-Ordner als Referenz nehmen, denn die Importpfade und die Output.object-Signatur stammen aus dem neuen SDK.

Streaming und Code-Generierung als zwei Auswege

Zwei Funktionen verdienen eigene Betrachtung. Erstens stream: Statt run aufzurufen, liefert scraper.stream(page, Output.object({ schema })) ein Objekt mit einem stream-Feld, über das man mit for await (const data of stream) partielle Ergebnisse erhält. Das ist nützlich, wenn die Extraktion lange dauert und man Zwischenstände anzeigen will. Zweitens generate: Der Aufruf scraper.generate(page, Output.object({ schema })) erzeugt laut README ein wiederverwendbares Playwright-Skript, das die Inhalte gemäß Schema ausliest. Das Ergebnis wird mit page.evaluate(code) ausgeführt und anschließend mit schema.parse(result) validiert. Das ist der interessanteste Teil des Projekts, weil er das LLM aus der Laufzeit entfernt: Man zahlt das Modell einmal für die Code-Erzeugung und führt danach deterministischen Code aus. Ob der generierte Code auf einer strukturell veränderten Seite noch greift, hängt davon ab, was das Modell geschrieben hat, und dazu macht das README keine Zusagen.

Grenzen: Tokens, Formatwahl und fehlende Fehlerbehandlung

Der offensichtlichste Nachteil ist der Preis. Jede Extraktion schickt Seiteninhalt an ein Modell. Bei format: 'raw_html' kann das bei großen Seiten erheblich werden, und das README nennt keine Obergrenze oder Kürzungsstrategie. Die Formatwahl ist deshalb keine Geschmacksfrage, sondern eine Kostenentscheidung: text über Readability.js reduziert den Umfang, entfernt aber möglicherweise genau die Attribute, die man braucht. Ein zweiter Punkt ist die Zuverlässigkeit. Das Modell füllt ein Schema, aber die Bibliothek validiert das Ergebnis nicht selbst gegen Zod, jedenfalls zeigt das README keine automatische Prüfung nach run. Das Beispiel ruft schema.parse erst nach generate auf. Wer auf korrekte Typen angewiesen ist, muss also selbst parsen. Drittens: Das Projekt hat laut den vorliegenden Angaben keine Releases. Es gibt keine Versionsnummern, keine Changelogs, keine Migrationshinweise außer dem Hinweis auf 2.0. Für ein Werkzeug, das in eine Pipeline eingebaut wird, ist das ein reales Risiko, unabhängig davon, wie aktiv das Repository wirkt.

Wann ein selektorbasierter Scraper die bessere Wahl bleibt

Die naheliegende Alternative ist ein klassischer Scraper auf Playwright-Basis, etwa mit page.locator und einem CSS- oder XPath-Selektor, ohne Modellaufruf. Der Unterschied liegt nicht in der Geschwindigkeit, sondern in der Fehlerart. Ein Selektor bricht sichtbar: Entweder das Element existiert oder nicht, und man bekommt eine Exception. Ein LLM liefert dagegen plausibel aussehende Werte auch dann, wenn die Seite anders aussieht als erwartet. Es gibt keinen Fehler, nur ein falsches Ergebnis. Für Seiten mit stabiler Struktur, für hohe Frequenzen oder für Anwendungen, in denen ein stiller Datenfehler teuer ist, ist der selektorbasierte Weg die solidere Wahl. llm-scraper spielt seine Stärke dort aus, wo sich die Struktur ständig ändert oder wo man viele verschiedene Domains mit einem einzigen Schema abdecken will. Der generate-Aufruf ist in diesem Vergleich der interessante Mittelweg: Er nutzt das Modell einmalig und überführt das Ergebnis zurück in deterministischen Code.

Wartung, Lizenz und was das für den Betrieb bedeutet

llm-scraper steht unter der MIT-Lizenz. Das erlaubt kommerzielle Nutzung und Modifikation, solange der Lizenztext erhalten bleibt. Das ist eine bewusst permissive Wahl und für den Einbau in eigene Produkte unkompliziert. Rechtlich relevant ist eher die andere Seite: Die Bibliothek lädt Webseiten mit Playwright und schickt deren Inhalt an einen Modellanbieter. Ob das mit den Nutzungsbedingungen der Zielseite und mit den Datenvereinbarungen des Anbieters zusammenpasst, ist eine Frage, die jedes Team für sich klären muss. Zur Wartung lässt sich aus dem Material wenig ableiten außer dem letzten Push und dem Hinweis auf Version 2.0 mit Vercel AI SDK 6. Da das AI SDK selbst schnelllebig ist, ist die Provider-Schicht der wahrscheinlichste Ort für Breaking Changes. Wer llm-scraper einsetzt, sollte die Importe aus @ai-sdk/* und die Output.object-Signatur als die Stellen behandeln, die bei einem Upgrade zuerst geprüft werden müssen.

Redaktionelles Fazit

llm-scraper passt zu Teams, die viele unterschiedlich aufgebaute Seiten auswerten müssen und dafür bereits ein LLM im Einsatz haben. Wer stabile, hochfrequente Extraktionen aus einer Handvoll bekannter Domains braucht, sollte bei selektorbasierten Scrapern bleiben. Vor dem ersten produktiven Einsatz ist zu klären, wie das Modell mit dem Format raw_html oder text auf einer echten Zielseite umgeht und ob die Token-Kosten pro Lauf in das Budget passen. Ein erster Test mit dem generate-Aufruf zeigt, ob sich der LLM-Schritt durch einen festen Playwright-Selektor ersetzen lässt.

Offizielle Quellen

  1. Issues
  2. License: MIT
  3. mishushakov/llm-scraper on GitHub
  4. README
Community-Notizen

Community-Notizen