7 Punkte von GN⁺ 2024-09-03 | 1 Kommentare | Auf WhatsApp teilen
  • Es wurde ein KI-gestützter Web Scraper erprobt, der mit den structured outputs der OpenAI API HTML-Tabellen als strukturierte Daten extrahiert; GPT-4o zeigte bei einigen komplexen Tabellen eine bessere Extraktionsqualität als erwartet
  • Bei Tabellen mit komplexer Darstellungsstruktur, etwa der 10-Tage-Vorhersage von Weather.com, unterschied GPT-4o zwischen Tages- und Nachtvorhersagen und fand auch Werte im HTML-Quelltext, die auf dem Bildschirm nicht sichtbar waren
  • Bei Tabellen wie dem Human Development Index auf Wikipedia, in denen wiederholte Werte in zusammengeführten Zeilen stehen, geriet die Anzahl der Werte pro Spalte auseinander, wodurch sich die Tabelle nur schwer rekonstruieren ließ; allein durch Prompt-Anpassungen ließ sich das nicht lösen
  • Um API-Aufrufkosten zu senken, wurde auch die XPath-Erzeugung ausprobiert, doch dabei entstanden falsche XPaths oder solche mit leeren Ergebnissen; stabiler war es, zuerst die Daten zu extrahieren und anschließend anhand dieser Werte XPaths anzufordern
  • Für zwei Tage Experimente wurden 24 $ ausgegeben; durch das Reduzieren von HTML-Attributen halbierte sich die Zeichenanzahl, ohne sichtbaren Leistungsabfall, doch wegen der Kosten blieb die weitere Validierung begrenzt

HTML-Tabellen mit structured outputs extrahieren

  • Mit der Funktion structured outputs der OpenAI API wurde ein KI-gestützter Web Scraper implementiert
  • Im ersten Experiment wurde ein HTML-String an GPT-4o übergeben und das Modell gebeten, Tabellendaten in strukturierter Form zu extrahieren
  • Das verwendete Pydantic-Modell bestand aus ParsedTable, das den Tabellennamen und eine Spaltenliste enthält, sowie ParsedColumn, das Spaltenname und Werteliste enthält
  • Im System-Prompt erhielt das Modell die Rolle eines spezialisierten Web Scrapers, der strukturierte Daten aus HTML-Tabellen extrahiert
  • GPT-4o mini wurde ebenfalls ausprobiert, lieferte aber deutlich schlechtere Ergebnisse; die weiteren Experimente wurden daher mit GPT-4o durchgeführt

Stärken bei komplexen Tabellen

  • Nach einer einfachen Tabelle wurde die Tabelle der 10-Tage-Wettervorhersage von Weather.com eingegeben
  • Diese Tabelle hat oben eine große Zeile, während die übrigen 9 Tage aus kleineren Zeilen bestehen
  • GPT-4o erkannte die Struktur aus Tages- und Nachtvorhersagen für die übrigen 9 Tage und fügte eine Day/Night-Spalte hinzu
  • Die zunächst extrahierte Spalte Condition wirkte wie eine Halluzination, existierte nach Prüfung des HTML-Quelltexts aber tatsächlich als nicht sichtbarer Tag

Fehler bei zusammengeführten Zeilen

  • Die Tabelle zum Human Development Index auf Wikipedia wirkt äußerlich einfach, enthält aber Zeilen mit wiederholten Werten, die zusammengeführt sind, was GPT-4o nicht korrekt verarbeiten konnte
  • Das Modell extrahierte wie angewiesen einzelne Spalten, doch jede Spalte hatte eine unterschiedliche Anzahl von Werten, sodass sich das Ergebnis nur schwer als Tabelle darstellen ließ
  • Der System-Prompt wurde in etwa zu „Extrahiere zusammengeführte Zeilen als mehrere JSON-Werte, damit alle Spalten die gleiche Zeilenanzahl haben“ geändert, doch das funktionierte nicht
  • Ein Prompt, der statt Spalten eine zeilenweise Extraktion anweist, wurde noch nicht ausprobiert

Grenzen der XPath-Erzeugung

  • Da wiederholte Aufrufe der OpenAI API teuer werden können, wurde versucht, statt der extrahierten Daten XPath zurückzugeben
  • Ziel war es, aktualisierte Daten von derselben Seite erneut per XPath zu scrapen, ohne das Modell aufzurufen
  • Der Prompt war so aufgebaut, dass er HTML-Inhalt und Spaltennamen erhält und einen XPath-String zurückgibt, der in Seleniums driver.find_elements(By.XPATH, xpath) ausgewertet werden kann
  • Dieser Ansatz war nicht stabil
    • GPT-4o gab mitunter falsche XPaths zurück
    • Die Erwähnung von Selenium in der Formulierung entschärfte das teilweise, dennoch entstanden auch XPaths, die falsche Daten oder leere Ergebnisse zurückgaben

Datenextraktion und XPath-Erzeugung kombinieren

  • Der nächste Versuch bestand darin, GPT-4o zuerst Daten extrahieren zu lassen und diese Ergebnisse als Referenzwerte für die XPath-Anfrage zu verwenden
  • Diese Kombination funktionierte deutlich besser als der Ansatz, von Anfang an nur XPath anzufordern
  • Da erzeugte XPaths gelegentlich keine Ergebnisse lieferten, wurde eine einfache Retry-Logik ergänzt, die bei ausbleibenden Ergebnissen erneut versucht
  • Bei den getesteten Tabellen war diese Retry-Methode wirksam
  • Es bleiben aber neue Probleme
    • Die Datenextraktion im ersten Schritt wandelte Bilder gelegentlich in Text um
    • Beispielsweise konnte ein Pfeil-nach-oben-Bild als Text wie arrow-upwards extrahiert werden
    • Im zweiten Schritt wurde dann nach Text gesucht, der im tatsächlichen HTML nicht vorkommt, was zum Scheitern führte
    • Dieses Problem wurde nicht gesondert behoben

Kosten und HTML-Bereinigung

  • Web Scraping mit GPT-4o kann teuer werden, da selbst kleine HTML-Tabellen viele Zeichen enthalten können und damit Kosten verursachen
  • In zwei Tagen Experimentieren wurden bereits 24 $ ausgegeben
  • Um die Kosten zu senken, wurde eine Bereinigungslogik ergänzt, die vor der Übergabe an das Modell unnötige Daten aus dem HTML-String entfernt
  • Nachdem alle Attribute außer den von den erzeugten XPaths hauptsächlich verwendeten class, id und data-testid entfernt wurden, halbierte sich die Zeichenanzahl der Tabelle
  • Nach dieser Bereinigung war kein Leistungsabfall zu erkennen; möglicherweise verbessert sich die Extraktionsqualität dadurch sogar tatsächlich
  • Der aktuelle Schritt zur XPath-Erzeugung führt pro Tabellenspalte jeweils einen Modellaufruf aus
  • Eine Verbesserung, bei der mehrere XPaths auf einmal erzeugt werden, wäre möglich, wurde aber noch nicht ausprobiert oder hinsichtlich der Leistung bewertet

Demo und Ideen für weitere Experimente

  • Die Extraktionsqualität von GPT-4o war beeindruckend, zugleich fühlten sich die an OpenAI zu zahlenden Kosten hoch an
  • Eine einfache mit Streamlit erstellte Demo ist unter https://orange-resonance-9766.ploomberapp.io verfügbar
  • Der Quellcode ist auf GitHub veröffentlicht, mit dem Hinweis, kein ausgereiftes Tool zu erwarten
  • Es sollten eigentlich mehr Tabellen getestet werden, doch wegen steigender OpenAI-Kosten wurden nur wenige Tabellen ausprobiert
  • Wenn mehr Zeit verfügbar wäre, wären folgende Versuche geplant
    • Die aktuelle Demo ist ein einmaliger Prozess, bei dem Nutzer URL und initiales XPath eingeben; eine bessere User Experience könnte darin bestehen, dass Nutzer die zu extrahierende Tabelle anklicken und Beispielzeilen bereitstellen
    • Bei komplexen Tabellen kann es schwierig sein, eine ganze Spalte mit nur einem XPath zu extrahieren; daher wäre es interessant, zu testen, ob das LLM ein Programm etwa in Python zurückgeben kann
    • Da die Nutzung von GPT-4o teuer ist und offenbar viele unnötige Daten übergeben werden, sollten weitere Ansätze zur HTML-Bereinigung ausprobiert werden

1 Kommentare

 
GN⁺ 2024-09-03
Meinungen auf Hacker News
  • Am besten funktionierte es, HTML nicht direkt in ein LLM zu geben, sondern es zuerst in ein einfacheres Format wie Markdown umzuwandeln.
    Als Tools habe ich unter anderem Extractus https://github.com/extractus und dom-to-semantic-markdown https://github.com/romansky/dom-to-semantic-markdown ausprobiert.
    In Magic Loops https://magicloops.dev/, das in der Cloud läuft, verwenden wir intern Apify https://apify.com/ und Firecrawl https://www.firecrawl.dev/; in der Chrome Extension nutzen wir dom-to-semantic-markdown.
    Derzeit experimentieren wir damit, in einem nutzerunterstützten Flow XPaths für bestimmte Sites zu erzeugen und vor dem LLM-Aufruf nur die benötigten Elemente herauszuziehen; durch die Vereinfachung des Problems war selbst GPT-4o mini ziemlich brauchbar.

    • Es wäre schön, wenn ihr euch auch https://browserbase.com/ ansehen würdet, das wir entwickeln.
      Dort kann man Chrome Extensions in einem Headless Browser ausführen, sodass die semantische Markdown-Umwandlung im Browser stattfinden kann, bevor die Daten nach außen gegeben werden.
      Außerdem gibt es eine iFrame-fähige Live-Ansicht des Browsers, sodass Nutzer sofort Feedback zum gerade erzeugten XPath geben können: https://docs.browserbase.com/features/session-live-view#give...
    • Mich würde interessieren, ob ihr die Umwandlung in Markdown mit einem Ansatz verglichen habt, bei dem man aus dem HTML nur Tag-Attribute entfernt, Links auflöst und nicht sichtbare Elemente entfernt.
      Meiner Erfahrung nach war die Performance ziemlich ähnlich wie bei Markdown, die Umwandlung war aber einfacher und hatte weniger Sonderfälle.
    • Von Semantic Markdown https://hackmd.io/@sparna/semantic-markdown-draft hatte ich bisher noch nicht gehört; es sieht so aus, als würden dabei RDF-Daten in ein Markdown-Dokument eingebettet.
      Die gefundene Seite ist ein „Alpha Draft“, daher dürfte es nicht besonders viele Semantic-Markdown-Inhaltskorpora geben, und der Mangel an Trainingsdaten könnte das Verständnis durch LLMs eher behindern.
      Trotzdem ist es ein gut lesbares Format, und wenn ein LLM die strukturierten Metadaten wie erläuternde Klammerzusätze behandelt, könnte es damit ziemlich gut umgehen.
    • Ich habe etwas Ähnliches in einem anderen Kontext gemacht: komplexes JSON, das einen Ausführungsgraphen beschreibt, zunächst in das einfachere Graphviz-dot-Format umgewandelt und dann an ein LLM gegeben; das funktionierte ziemlich gut.
  • OpenAI hat kürzlich die Batch API angekündigt, mit der man alle Prompts vorbereiten und dann gesammelt ausführen kann; die Kosten sinken dabei ebenfalls auf 50 %: https://platform.openai.com/docs/guides/batch
    Ich habe sie früher viel mit GPT-4o mini genutzt und konnte 3.000 Elemente in unter 5 Minuten verarbeiten.
    Für Anwendungen, die keine Echtzeitverarbeitung brauchen, kann das ziemlich gut sein.

    • Ich hoffe, dass Open-Source-Inferenzserver diesen Endpunkt bald ebenfalls unterstützen.
      vLLM hat teilweise Unterstützung für einen „offline batch mode“ im selben Format hinzugefügt, ist aber noch nicht bei einer OpenAI-Endpunkt-Implementierung angekommen.
    • OpenAIs Angebot ist gut, aber verglichen mit traditionellen Textextraktionsmethoden, die eine ähnliche Precision und Recall liefern, ist es meiner Ansicht nach immer noch um ein bis zwei Größenordnungen teurer.
    • Das war eine wirklich gute Entscheidung von OpenAI, und ich hoffe, dass andere Cloud-Tools wie Azure dieselbe Funktion anbieten.
      Es ist eine sehr naheliegende Funktion.
  • Für strukturierte Inhalte, etwa Listen von Einträgen oder einfache Tabellen, braucht man nicht unbedingt ein LLM.
    Ich habe kürzlich einen Web Scraper gebaut, der automatisch auf jeder Website funktioniert: https://easyscraper.com. Die frühe Version war mit AI gebaut, aber am Ende waren Heuristiken auf Basis von Elementattributen und Positionen schneller, günstiger und genauer.
    Auf den meisten Websites funktionieren Nicht-AI-Ansätze sehr gut; daher sollte man zuerst prüfen, ob AI wirklich nötig ist, etwa wenn die Daten unstrukturiert sind oder das Ausgabeformat aus den Seitendaten abgeleitet werden muss.

    • LLMs sind robuster gegenüber Website-Updates, die gewöhnliches Scraping kaputtmachen können.
      Wie der Autor kann man ein LLM XPaths erzeugen lassen, im Normalfall mit diesen XPaths klassisch scrapen und bei einem Bruch das LLM die XPaths aktualisieren lassen.
      Wenn die Daten dann trotzdem nicht wieder fließen oder die Pipeline weiter hinten wegen eines unerwarteten Formats bricht, kann man immer noch einen Menschen benachrichtigen.
    • Ein Tool, bei dem man direkt auswählen und festlegen kann, was gescrapt werden soll, sehe ich zum ersten Mal.
      Ich habe mich immer gefragt, warum es so ein Tool nicht gibt.
  • Ich frage mich, ob es so etwas wie einen „HTML reducer“ bereits gibt
    Wenn man sich den Seitenquelltext unverändert ansieht, bestehen 90 % der Tokens aus Müll: zufälligem JavaScript, Werbung, unnötigen Attributen und übermäßiger Verschachtelung fürs Rendering
    Wenn man mit einem DOM-Parser hindurchläuft und nur Knoten mit Text, die HTML-Struktur und benötigte Tag-Attribute (etwa class/id) übrig lässt, ließen sich die Kosten wohl stark senken, und auch XPath-Ansätze könnten besser funktionieren
    Readability wird zwar ebenfalls genutzt, verliert aber die DOM-Struktur, und bei Websites mit viel JavaScript oder Seiten, die Text per „continue reading“ erweitern, sinkt die Qualität
    Ich frage mich, welches Tool für diesen Zweck quasi als Standard gilt

  • Es überrascht mich, dass der Autor 99 % der Arbeit und des Schreibens erledigt hat, aber nicht das letzte 1 %: eine ollama- oder llama.cpp-basierte Engine herunterzuladen und ein ordentliches lokales LLM zu testen
    Für diesen Anwendungsfall könnten auch 7B- oder 30B-Modelle gut funktionieren, und die Ausführungskosten wären niedrig genug, sodass GPT-4o möglicherweise gar nicht nötig ist

    • Guter Vorschlag
      Ich fange gerade erst an, mit LLMs herumzuspielen, und werde mir auch lokal gehostete Modelle ansehen
  • Bei Kadoa https://kadoa.com haben wir automatisches Web-Scraping mit KI betrieben, und die frühen Experimente ähnelten dem Artikel
    Wir haben angefangen, als es nur das teure und langsame GPT-3 gab, und brauchten eine kosteneffiziente Lösung im großen Maßstab
    Am Ende haben wir in der Extraktionsphase nicht jedes Mal ein LLM eingesetzt, sondern per Codegenerierung CSS-Selektoren oder XPath-Extraktionscode erzeugt und den Scraper-Code anschließend an Website-Änderungen anpassen lassen
    Für Bereinigung und Transformation nutzten wir ein kleines feinabgestimmtes LLM, und für die Validierung bewerteten wir die Datenqualität mit LLM-as-a-judge zusammen mit traditionellen Methoden wie Reverse Search
    Das auf ein paar einfache Datenquellen anzuwenden und es zuverlässig, skalierbar und kosteneffizient über Tausende Websites hinweg zu betreiben, waren völlig verschiedene Probleme; die richtige Lösung war eine Mischung aus traditionellem ETL-Engineering und kleinen, gut evaluierten LLM-Schritten

  • Wenn man ein Beispiel des HTML gibt, das man scrapen möchte, und nach einem BeautifulSoup-Codefragment fragt, funktioniert das ziemlich gut
    Meist bleibt die Struktur, die man auslesen will, unverändert; den kniffligen String zum Parsen dafür selbst zu schreiben, ist aber mühsam
    Das eigentliche Parsen einem LLM zu überlassen, ist übertrieben und birgt zudem das Risiko, dass Halluzinationen die Ergebnisse verunreinigen

  • Wenn man HTML zuerst vorverarbeitet, bekommt man günstigere und bessere Ergebnisse
    Ich glaube, es wurde noch nicht erwähnt, aber persönlich habe ich mit trafilatura https://trafilatura.readthedocs.io/en/latest/ gute Ergebnisse erzielt

    • Große Zustimmung zu trafilatura
      Man muss dem LLM nur den Text schicken und kann die Kosten dadurch enorm senken
      Ich habe es auch in einem aktuellen Projekt verwendet: https://github.com/philippe2803/contentmap. Das ist eine einfache Python-Bibliothek, die ausgehend von der Domain-XML-Sitemap einen Vektorspeicher für beliebige Websites erstellt
      Da die HTML-Struktur je nach Domain unterschiedlich ist, mussten nur die eigentlichen Inhalte extrahiert und HTML-Tags usw. entfernt werden; Trafilatura erledigt das mit wenigen Codezeilen für fast jede URL
  • Das ist wohl der erste Beitrag, den ich sehe, der so viele orangefarbene Tags hat.
    Bei NewsCatcher führen wir viele Tests mit GPT-4o durch; wir crawlen mehr als 100.000 News-Websites und müssen anschließend die News-Inhalte parsen.
    Ein regelbasiertes Modell, das aus beliebigen Artikeln Daten extrahiert, funktionierte ziemlich gut, und wir haben keinen Weg gefunden, es mit GPT weiter zu verbessern.
    Spannender ist der Bereich Crawling: Man muss alle Stellen kennen, an denen News-Artikel veröffentlicht werden können, und manchmal gibt es mehr als 50 Unterbereiche.
    Da sich die Struktur einzelner Websites nicht häufig ändert, denke ich, dass es für viele Projekte ausreichen kann, Extraktionscode generieren zu lassen.
    Deshalb schauen wir uns an, mit LLMs HTML-Parsing-Code zu generieren; wer Interesse hat, kann sich unter artem [at] newscatcherapi.com melden.

    • Ich würde das gern in einem Hobbyprojekt ausprobieren.
      Es wäre schön, wenn es eine Self-Service-Registrierung gäbe.
  • Web Scraping war tatsächlich der Anlass, aus dem mein Mitgründer und ich das heutige openpipe.ai gebaut haben.
    GPT-4 ist wirklich sehr gut darin, aber viel zu teuer.
    Allerdings lässt sich die Fähigkeit, bestimmte Arten von Websites zu scrapen, ziemlich leicht in ein deutlich günstigeres Fine-Tuning-Modell distillieren, und für diese Art von Websites scraped es zuverlässig gut.

    • Kyle, ich hätte dir das früher sagen sollen.
      Wir beschäftigen uns auch schon ziemlich lange mit diesem Problem und ich melde mich, um zu zeigen, wie weit wir gekommen sind.