GPT-4o ile web scraping: Güçlü ama maliyetli
(blancas.io)- OpenAI API’nin structured outputs özelliğiyle HTML tablolarını yapılandırılmış veriye dönüştüren yapay zeka destekli bir web scraper denendi; GPT-4o, bazı karmaşık tablolarda beklenenden iyi çıkarım kalitesi gösterdi
- Weather.com’un 10 günlük tahmini gibi gösterim yapısı karmaşık tablolarda gündüz/gece tahminlerini ayırdı ve ekranda görünmeyen değerleri de HTML kaynağında buldu
- Wikipedia’daki Human Development Index gibi yinelenen değerlerin birleştirilmiş satırlar olarak yer aldığı tablolarda sütun başına değer sayıları uyuşmadığı için tabloyu yeniden oluşturmak zorlaştı; yalnızca prompt’u değiştirmek sorunu çözmedi
- API çağrı maliyetini azaltmak için XPath üretimi de denendi, ancak hatalı ya da boş sonuç veren XPath’ler üretildi; önce veriyi çıkarıp ardından bu değerlere göre XPath istemek daha kararlıydı
- İki günlük deneyde 24 dolar harcandı; HTML öznitelikleri azaltılınca karakter sayısı yarıya indi ve performansta düşüş görülmedi, ancak maliyet nedeniyle ek doğrulama sınırlı kaldı
structured outputs ile HTML tablolarını çıkarma
- OpenAI API’nin structured outputs özelliğiyle yapay zeka destekli bir web scraper uygulandı
- İlk deney, HTML string’ini GPT-4o’ya verip tablo verilerini yapılandırılmış biçimde çıkarmasını isteme yöntemiydi
- Kullanılan Pydantic modeli, tablo adını ve sütun listesini içeren
ParsedTableile sütun adını ve değer listesini içerenParsedColumnyapısından oluşuyordu - Sistem prompt’unda, HTML tablolarından yapılandırılmış veri çıkaran uzman bir web scraper rolü verildi
- GPT-4o mini de denendi, ancak sonuçlar çok daha kötü olduğu için sonraki deneyler GPT-4o ile yürütüldü
Karmaşık tablolarda görülen güçlü yönler
- Basit tablolardan sonra Weather.com’un 10 günlük hava tahmini tablosu girdi olarak verildi
- Bu tabloda en üstte büyük bir satır, kalan 9 gün içinse daha küçük satırlar bulunuyordu
- GPT-4o, kalan 9 günün gündüz/gece tahmini yapısını tanıyarak
Day/Nightsütununu ekledi - Başta çıkarılan
Conditionsütunu bir halüsinasyon gibi görünüyordu, ancak HTML kaynağı kontrol edildiğinde ekranda görünmeyen etiketler olarak gerçekten mevcut olduğu anlaşıldı
Birleştirilmiş satırlarda yaşanan başarısızlık
- Wikipedia’daki Human Development Index tablosu dışarıdan basit görünse de yinelenen değerlere sahip satırlar birleştirildiği için GPT-4o bunu doğru işleyemedi
- Model, talimatlara uygun olarak tek tek sütunları çıkardı; ancak her sütundaki değer sayısı farklı olduğundan sonucu tablo olarak ifade etmek zordu
- “Birleştirilmiş satırları birden çok JSON değeri olarak çıkar ve tüm sütunların satır sayısı aynı olsun” benzeri şekilde sistem prompt’u değiştirildi, ancak işe yaramadı
- Sütunlar yerine satır bazlı çıkarım talimatı veren bir prompt henüz denenmedi
XPath üretim yönteminin sınırları
- Her seferinde OpenAI API çağrısı yapmak maliyeti artırabileceğinden, çıkarılan veri yerine XPath döndürmesi denendi
- Amaç, aynı sayfadaki güncellenmiş verileri yeniden alırken model çağrısı yapmadan XPath ile scraping yapmaktı
- Prompt, HTML içeriğini ve sütun adlarını alıp Selenium’daki
driver.find_elements(By.XPATH, xpath)içinde değerlendirilebilecek XPath string’leri döndürecek şekilde kurgulandı - Bu yöntem kararlı değildi
- GPT-4o’nun hatalı XPath döndürdüğü durumlar oldu
- Selenium’dan bahseden cümlelerle bu kısmen hafifletildi, ancak hatalı veri ya da boş sonuç döndüren XPath’ler de üretildi
Veri çıkarımı ile XPath üretimini birleştirme
- Sonraki deneme, önce GPT-4o’nun veriyi çıkarması ve bu sonucu referans değer olarak kullanarak XPath istenmesi yöntemiydi
- Bu kombinasyon, en baştan yalnızca XPath istemekten çok daha iyi çalıştı
- Üretilen XPath’in sonuç döndürmediği durumlar olduğundan, sonuç yoksa tekrar deneyen basit bir retry mantığı eklendi
- Test edilen tablolarda bu yeniden deneme yöntemi etkili oldu
- Yeni sorunlar da devam ediyor
- İlk aşamadaki veri çıkarımı bazen görselleri metne dönüştürüyordu
- Örneğin yukarı ok görseli
arrow-upwardsgibi bir metin olarak çıkarılabiliyordu - İkinci aşama, gerçek HTML’de bulunmayan bir metni aradığı için başarısız oluyordu
- Bu sorun ayrıca düzeltilmedi
Maliyet ve HTML temizleme
- GPT-4o ile web scraping yapıldığında küçük HTML tabloları bile çok sayıda karakter içerdiğinden maliyet artabiliyor
- İki gün boyunca yapılan deneylerde şimdiden 24 dolar harcandı
- Maliyeti azaltmak için modele göndermeden önce HTML string’inden gereksiz verileri kaldıran bir temizleme mantığı eklendi
- Üretilen XPath’in çoğunlukla kullandığı
class,id,data-testiddışındaki tüm öznitelikler kaldırılınca tablonun karakter sayısı yarıya düştü - Bu temizlemeden sonra performans düşüşü görülmedi; çıkarım kalitesinin gerçekten iyileşebileceği de düşünülüyor
- Mevcut XPath üretim aşaması, tablonun her sütunu için bir model çağrısı yapıyor
- Tek seferde birden fazla XPath üretme iyileştirmesi de mümkün, ancak henüz denenmedi veya performansı değerlendirilmedi
Demo ve ek deney fikirleri
- GPT-4o’nun çıkarım kalitesi etkileyiciydi, ancak OpenAI’ye ödenmesi gereken maliyet de yüksek hissediliyor
- Streamlit ile yapılmış basit demoya https://orange-resonance-9766.ploomberapp.io adresinden bakılabilir
- Kaynak kodu GitHub’da yayımlanmış; yüksek olgunlukta bir araç beklenmemesi gerektiği notu eklenmiş
- Daha fazla tablo test edilmek istendi, ancak OpenAI maliyetinin artması nedeniyle yalnızca az sayıda tabloyla deney yapıldı
- Daha fazla zaman olsaydı şunlar denenirdi
- Mevcut demo, kullanıcının URL ve başlangıç XPath’i girdiği tek seferlik bir süreç; kullanıcının çıkarılacak tabloya tıklayıp örnek satırlar sağladığı bir yaklaşım daha iyi bir kullanıcı deneyimi olabilir
- Karmaşık tablolarda tüm sütunu tek bir XPath ile çıkarmak zor olabileceğinden, LLM’in Python gibi bir program döndürmesini isteme yöntemi denenmek isteniyor
- GPT-4o kullanım maliyeti pahalı ve çok fazla gereksiz veri gönderildiği düşünüldüğünden, HTML temizleme yönteminin daha fazla denenmesi gerekiyor
1 yorum
Hacker News yorumları
HTML’i doğrudan LLM’e vermek yerine önce Markdown gibi basit bir biçime dönüştürdüğümde en iyi sonucu aldım.
Kullandığım araçlar arasında Extractus https://github.com/extractus ve dom-to-semantic-markdown https://github.com/romansky/dom-to-semantic-markdown var.
Bulutta çalışan Magic Loops https://magicloops.dev/ içinde Apify https://apify.com/ ve Firecrawl https://www.firecrawl.dev/ kullanıyoruz; Chrome Extension’da ise dom-to-semantic-markdown kullanıyoruz.
Şu anda belirli sitelere yönelik XPath’leri kullanıcı destekli bir akışla oluşturup, LLM çağrısından önce yalnızca gerekli öğeleri çıkarma yöntemini deniyoruz; problemi basitleştirince GPT-4o mini ile de oldukça iyi sonuç aldık.
Headless tarayıcıda Chrome Extension çalıştırabildiği için, veriyi dışarı almadan önce tarayıcının içinde semantik Markdown dönüşümü yapabiliyorsunuz.
Tarayıcının iFrame’e alınabilen gerçek zamanlı görünümü de var; böylece kullanıcı, oluşturulmakta olan XPath hakkında anında geri bildirim verebiliyor: https://docs.browserbase.com/features/session-live-view#give...
Benim deneyimime göre performans Markdown’a oldukça yakındı; dönüşüm ise daha kolaydı ve daha az istisna çıkarıyordu.
Bulduğum sayfa “Alpha Draft” olduğundan, Semantic Markdown içerik külliyatının çok büyük olmadığını sanıyorum; eğitim verisi eksikliği LLM’in anlamasını da zorlaştırabilir.
Yine de yeterince okunabilir bir biçim olduğu için, LLM yapılandırılmış meta veriyi parantez içi açıklama gibi ele alırsa bunu oldukça iyi işleyebilir gibi geliyor.
OpenAI kısa süre önce Batch API’yi duyurdu; böylece tüm prompt’ları hazırlayıp toplu olarak çalıştırabiliyorsunuz ve maliyet de %50’ye düşüyor: https://platform.openai.com/docs/guides/batch
Daha önce GPT-4o mini ile çok kullandım ve 3.000 öğeyi 5 dakikadan kısa sürede işleyebildim.
Gerçek zamanlı çalışması gerekmeyen uygulamalar için oldukça iyi olabilir.
vLLM, aynı biçimde “offline batch mode” desteğinin bir kısmını ekledi; ancak henüz OpenAI endpoint uygulamasına kadar gelmiş değil.
Fazlasıyla doğal bir özellik.
Yapılandırılmış içerikler, örneğin öğe listeleri veya basit tablolar için özellikle LLM’e gerek yok.
Yakın zamanda herhangi bir web sitesinde otomatik çalışan bir web scraper https://easyscraper.com geliştirdim; ilk sürümü yapay zekayla yapmıştım ama sonuçta öğe özniteliklerine ve konuma dayalı sezgiseller daha hızlı, daha ucuz ve daha doğru çıktı.
Çoğu web sitesinde yapay zeka dışı yaklaşım çok iyi çalışıyor; bu yüzden verinin yapılandırılmamış olması veya sayfa verisine dayanarak çıktı biçiminin türetilmesi gerektiği durumlar gibi, yapay zekanın gerçekten gerekli olup olmadığını önce kontrol etmek iyi olur.
Yazarın yaptığı gibi LLM’e XPath ürettirip, normalde o XPath ile klasik scraping yapabilir; bozulduğunda da LLM ile XPath’i güncelletebilirsiniz.
Yine de veri yeniden akmaya başlamazsa veya pipeline’ın ilerleyen kısmında beklenmeyen bir biçim yüzünden kırılırsa o zaman bir insana bildirim gönderilebilir.
Böyle bir aracın neden olmadığını hep merak etmişimdir.
“HTML reducer” gibi bir şeyin zaten var olup olmadığını merak ediyorum
Sayfa kaynağına olduğu gibi bakınca rastgele JavaScript, reklamlar, gereksiz öznitelikler ve render için kullanılan aşırı iç içe yapı yüzünden token’ların %90’ı çöp oluyor
DOM parser ile dolaşıp yalnızca metin içeren düğümleri, HTML yapısını ve gerekli etiket özniteliklerini (class/id gibi) bırakırsak maliyeti ciddi ölçüde düşürebiliriz; XPath yaklaşımı da daha iyi çalışabilir
Readability de kullanılıyor ama DOM yapısını kaybediyor; JavaScript’i yoğun web sitelerinde veya “continue reading” gibi metni genişleten sayfalarda kalite düşüyor
Bu amaç için standarda yakın aracın ne olduğunu merak ediyorum
İlgi varsa açık kaynak olarak yayımlayabiliriz; reducer’dan geçirdikten sonra LLM çıktısının çok daha iyi hale gelmesi şaşırtıcıydı
Herhangi bir URL’nin başına https://r.jina.ai/ eklediğinizde, o sayfanın LLM’e vermeye uygun ana içeriğinin Markdown sürümünü döndürüyor
Örnek https://r.jina.ai/https://simonwillison.net/2024/Sep/2/anato..., asıl sayfa ise https://simonwillison.net/2024/Sep/2/anatomy-of-a-textual-us...
Kod açık kaynak, kendiniz çalıştırabilirsiniz: https://github.com/jina-ai/reader
TypeScript ile yazılmış ve Puppeteer ile https://github.com/mozilla/readability kullanıyor
Ben Markdown dönüşümü olmadan yalnızca Readability kullanarak sayfa başlığını ve gövde metnini çıkardım; bunu Playwright ve shot-scraper ile çalıştıran bir tarif de var: https://shot-scraper.datasette.io/en/stable/javascript.html#...
vimium’dan alıp değiştirdiğimiz bir yaklaşım; HTML’i yalnızca önemli kısımlar kalacak şekilde damıtırken çeşitli istisna durumlarını da ele alıyor
Yazarın işin ve yazının %99’unu yapıp kalan %1 olan ollama veya llama.cpp tabanlı bir motor indirerek düzgün bir yerel LLM’i test etmemiş olması şaşırtıcı
Bu kullanım senaryosunda 7B veya 30B modeller de iyi iş çıkarabilir; çalıştırma maliyeti de yeterince düşük olduğundan GPT-4o’ya gerek olmayabilir
LLM’lerle yeni yeni uğraşmaya başladım; yerel barındırılan modelleri de inceleyeceğim
Kadoa’da https://kadoa.com yapay zeka ile otomatik web scraping yapıyorduk; ilk denemeler yazıdakine benziyordu
Pahalı ve yavaş GPT-3’ün olduğu dönemden başladık; büyük ölçekte maliyet etkin bir çözüme ihtiyacımız vardı
Sonunda çıkarım aşamasında her seferinde LLM kullanmak yerine, CSS seçicileri veya XPath çıkarım kodu üretmek için kod üretimi kullandık; sonra da web sitesindeki değişikliklere göre scraper kodunu ayarlattık
Temizleme ve dönüştürme için küçük, fine-tune edilmiş LLM’ler kullandık; doğrulamada ise ters arama gibi geleneksel yöntemlerin yanında veri kalitesini değerlendirmek için LLM-as-a-judge kullandık
Bunu birkaç basit veri kaynağına uygulamak ile binlerce web sitesinde kararlı, ölçeklenebilir ve maliyet etkin şekilde çalıştırmak tamamen farklı problemlerdi; geleneksel ETL mühendisliği ile küçük ve iyi değerlendirilmiş LLM adımlarını karıştırmak doğru yaklaşımdı
Scrape etmek istediğiniz HTML örneğini verip bir BeautifulSoup kod parçası isterseniz oldukça iyi sonuç verdi
Genellikle çekmek istediğiniz yapı aynen korunuyor; onu parse edecek karmaşık string’i elle yazmak ise sıkıcı
Asıl parsing’i LLM’e bırakmak fazla kaçıyor, ayrıca halüsinasyonların sonucu kirletme riski de var
HTML’i önce ön işlemden geçirirseniz daha ucuz ve daha iyi sonuçlar alabilirsiniz
Henüz bahsedilmemiş gibi görünüyor; şahsen trafilatura https://trafilatura.readthedocs.io/en/latest/ ile iyi sonuçlar gördüm
LLM’e yalnızca metin göndermeniz yeterli, bu yüzden maliyeti muazzam düşürebiliyorsunuz
Yakın tarihli projemde https://github.com/philippe2803/contentmap de kullandım; bu, domain XML sitemap’ini başlangıç noktası alıp rastgele bir web sitesi için vektör deposu oluşturan basit bir Python kütüphanesi
Her domain’in HTML yapısı farklı olduğu için gerçek içeriği çıkarıp HTML etiketlerini vb. kaldırmak gerekiyordu; Trafilatura bunu birkaç satır kodla neredeyse tüm URL’lerde yapıyor
Bu kadar çok turuncu etiket yapıştırılmış bir yazıyı ilk kez görüyorum denecek seviyede
NewsCatcher’da GPT-4o ile çok sayıda test yapıyoruz ve 100 binden fazla haber web sitesini crawl ettikten sonra haber içeriklerini parse etmemiz gerekiyor
Herhangi bir makaleden veri çıkaran kural tabanlı model oldukça iyi çalıştı; GPT ile bunu daha da iyileştirmenin bir yolunu bulamadık
Daha ilginç olan taraf crawling; haber makalelerinin yayımlanabileceği tüm konumları bilmek gerekiyor ve bazen 50’den fazla alt bölüm olabiliyor
Web sitesine özgü yapılar sık değişmediği için, birçok projede çıkarım kodu üretme yaklaşımının yeterli olabileceğini düşünüyorum
Bu yüzden LLM ile HTML parse etme kodu üretme tarafına bakıyoruz; ilgileniyorsanız artem [at] newscatcherapi.com adresinden iletişime geçebilirsiniz
Keşke self-servis kayıt olsaydı
Web scraping, kurucu ortağımla beni bugünkü openpipe.ai’yi kurmaya götüren gerçek çıkış noktasıydı
GPT-4 bu işi gerçekten iyi yapıyor ama çok pahalı
Ancak belirli türde siteleri scrape etme yeteneğini çok daha ucuz fine-tuned modellere distill etmek epey kolay; o tür sitelerde de istikrarlı biçimde iyi scrape ediyor
Biz de bu problem üzerinde epey uzun zamandır çalışıyoruz; nereye geldiğimizi göstermek için iletişime geçeceğim