En uzun paragrafı 151 karakter olan bir belgede, jusText varsayılan ayarlarıyla sıfır karakter döndürüyor. Bu, kısmi bir çıkarım değil; dümdüz boş bir string. Eşiği biraz aşağı çekip tam bir paragrafın sınırı geçmesini sağladığınızda, aynı belge bu kez 832 karakter veriyor. Daha da indirseniz sonuç yine 832’de kalıyor.
Bu örnekte davranış, yumuşak bir eğimden çok bir uçurum gibi. Varsayılanın yanlış tarafta olup olmadığı ise hedef korpustaki paragraf uzunluklarına ve boilerplate dağılımına bağlı.
jusText nedir ve sözlük yoğunluğu neden önemlidir?
Bu örnek setindeki diğer çıkarıcılara kıyasla jusText, dile özgü stopword yoğunluğuna alışılmadık derecede fazla dayanır. the, and, of, was gibi işlev kelimelerinin oranı yüksek olan bir blok, düz yazı olma ihtimali daha yüksek diye görülür. Ancak bu sözlük sinyali sınıflandırıcının tamamı değildir: paragraf uzunluğu, bağlantı yoğunluğu, HTML’den türetilen blok sınırları, başlık mesafesi, komşu sınıflar ve bağlama duyarlı ikinci bir geçiş de sonucu etkiler.
Resmî kaynak: jusText’in resmî deposu.

Sınıflandırıcı bir dil stoplist’i kullandığı için jusText 100 farklı dil desteğiyle gelir. Bu açık ve dile özgü sözlük yüzeyi, bu karşılaştırmadaki en belirgin farktır; ancak çok dilli kalite test edilmemiştir.
Test edilen sürüm: 3.0.2, BSD 2-Clause, 822 GitHub yıldızı. Python 3.14.2.
Uçurum, ölçümle ortaya kondu

jusText’in sınıflandırıcısı iki aşamalı çalışır. Bağlamdan bağımsız ilk geçiş, her paragrafı good, bad, short veya neargood olarak etiketler. Ardından bağlama duyarlı ikinci geçiş, neargood olanları good seviyesine yükseltir — ama yalnızca zaten good olan bir bloğun yanında duruyorsa. Bir paragrafın tek başına good sayılması ise ancak varsayılanı 200 karakter olan length_high değerini aşmasıyla olur.
Hiçbir paragraf 200’ü geçmeyen bir belgede, yükseltme için başlangıç noktası oluşmaz ve her neargood blok da boilerplate’e dönüşür. Tüm sayfa boş döner.
En uzun paragrafın 151 karakter olduğu bir örnekte eşiği aşağı doğru taradım:
length_high | good olarak sınıflanan paragraflar | Dönen karakter sayısı |
|---|---|---|
| 200 (varsayılan) | 0 | 0 |
| 150 | 8 | 832 |
| 120 | 8 | 832 |
| 100 | 8 | 832 |
| 80 | 8 | 832 |
justext-length-threshold.json.
Bu eşik örneğinde, çizgiyi geçen tek bir paragraf tüm sekiz hedef paragrafın çıktısını değiştirdi; eşiği daha da gevşetmek ek bir şey kazandırmadı. İz, mevcut bir good bloğun çevresindeki uygun neargood komşularını bağlam geçişinin yükselttiği senaryoyla uyumlu; ancak bu, herhangi bir sayfada her komşunun koşulsuz yükseltildiği anlamına gelmez.
Etkisinin length_high’ten geldiğini söylemeden önce length_low için dört değer ile max_link_density için iki değeri çapraz taradım: sekiz kombinasyonun tamamı sıfır döndürdü. Bu ayarlardan herhangi birini değiştirmek bu örnekte çıktıyı geri getirmedi.
Tüm 22 örnekten oluşan set boyunca desen aynı: length_high=200 iken 22’nin 2’si, 150 iken 22’nin 9’u, 120 iken 22’nin 15’i çıktı verdi.
Bunun söylediği iki şey yok. Birincisi, jusText kötü çıkarıyor demiyor — gerçek bir doğal dil sayfasında varsayılanlarla 1.190 karakter temiz makale metni verdi; çünkü gerçek bir haber paragrafı ilk denemede 200 karakteri aşıyor. İkincisi, varsayılan yanlış demiyor; varsayılanın uzun paragraflar varsaydığını söylüyor ve herhangi bir şey çalıştırmadan önce korpusunuzda böyle paragraflar olup olmadığına siz karar vermelisiniz.
Bu örnek setinin diğer tarafı: varsayılanlarda daha yüksek sızıntı
Bu etiketli örnek setinde, varsayılan ayarlarda jusText ölçülen en yüksek boilerplate sızıntısına sahip.
| Kütüphane | Makale geri çağırma oranı (22/22) | Boilerplate sızıntısı | İçerik-token kesinliği | Kirletici token sayısı |
|---|---|---|---|---|
| Readability | 1.0000 | 0.2353 | 0.9109 | 35 |
| trafilatura | 0.9865 | 0.0588 | 0.9411 | 4 |
| newspaper4k | 0.9865 | 0.0000 | 0.9452 | 0 |
| resiliparse | 0.9054 | 0.0588 | 0.9381 | 7 |
| jusText | 0.8378 | 0.4706 | 0.8760 | 74 |
| goose3 | 0.8243 | 0.0000 | 1.0000 | 0 |
sixway-scores.json. Tek bir skorlayıcı, tek bir örnek seti; her birim benzersiz bir sentinel ile etiketlendiği için kurtarma tam olarak alt dize üyeliğiyle ölçülüyor.

%47 boilerplate sızıntısı ve 74 kirletici token — bu etiketli sentetik sette Readability’nin sızıntı oranının iki katı, kirlenmenin ise iki katından fazlası. Bu, varsayılan ayarlardaki tanısal bir sonuçtur; ürün genelinde sabit bir sıralama değildir.
Gözlenen sızıntı, uçurum örneğinde devrede olan aynı bağlam geçişiyle uyumlu. Uygun neargood bloklar, çevre blok sınıfları ve mesafe kuralları izin verdiğinde yükseltilebilir; dolayısıyla düz yazı benzeri bir tanıtım metni ya da yorum, makale metninin yanındaki sınırı aşabilir. Örnek sonucu, hangi etiketli blokların sızdığını gösterir; sade mekanizma ise jusText’in tam bağlam kurallarına bağlıdır.
Geri çağırma oranı 0.8378 ve alttan üçüncü sırada; kaybın tamamı eşiğe takılıyor: tek bir 129 karakterlik makalede hiçbir şey kurtaramadı, on kısa paragraf içeren bir sayfada hiçbir şey kurtaramadı, neredeyse boş bir belgede de hiçbir şey kurtaramadı.
Dil stoplist envanteri
Doksan dokuz başka stoplist daha.
justext.get_stoplists() 100 dili döndürür. Sınıflandırıcı, tasarım gereği dile göre parametrelenmiştir; İngilizce bir sezginin çevrilmiş hali değildir ve dili değiştirmek tek bir argümanla olur:
import justext
paragraphs = justext.justext(html, justext.get_stoplist("Czech"))
text = "\n".join(p.text for p in paragraphs if not p.is_boilerplate)
trafilatura ve goose3 de dile ilişkin davranışlar sunar; ancak bu inceleme hiçbir çıkarıcıyı İngilizce dışı gerçek veri üzerinde puanlamadı. jusText’in yerleşik 100 stoplist’i onu çok dilli değerlendirme için güçlü bir aday yapıyor; yalnızca bu envanter, o dillerdeki çıkarım kalitesini kanıtlamaz ya da rakiplerin daha zayıf çalıştığını göstermez.
API iki fonksiyon ve dokuz ayarlanabilir sabitten oluşuyor — length_low 70, length_high 200, stopwords_low 0.30, stopwords_high 0.32, max_link_density 0.20, max_heading_distance 200, ayrıca encoding işlemleri. Küçük, okunabilir ve hepsi imzada belgelenmiş.
Kurulum ve hız
pip install justext 3 paket kuruyor — karşılaştırmadaki en az sayı — ve 22.4 MiB yer kaplıyor; bu işlem iki saniyenin altında tamamlanıyor.
Resmî kaynak: PyPI üzerinde jusText.
| Kütüphane | Paket sayısı | site-packages | Soğuk import | Çıkarma p50 |
|---|---|---|---|---|
| resiliparse | 5 | 21.0 MiB | 0.015 s | 0.06 ms |
| jusText | 3 | 22.4 MiB | 0.777 s | 0.56 ms |
| goose3 | 16 | 44.3 MiB | 2.181 s | 1.85 ms |
| newspaper4k | 22 | 47.5 MiB | 2.812 s | 2.69 ms |
| trafilatura | 17 | 69.9 MiB | 1.584 s | 0.51 ms |
install-and-import.json. Her kütüphane kendi boş sanal ortamında.
Üç paket ve 22.4 MiB bu karşılaştırmada küçük bir bağımlılık, 0.56 ms medyan çıkarım da bu düzende trafilatura’nın 0.51 ms değerine oldukça yakın. Ortam ölçümü disk alanını dosya türlerine göre ayırmıyor; bu yüzden stoplist’lerin ne kadar yer tuttuğunu söyleyemez.
Bakım sorusu, dikkatli cevap
Burada kullanılan tarihli bakım ölçütleri, son depo gönderimi ve son PyPI sürümü; ikisi de 2025-02-25. Bu, testten on yedi ay öncesine denk geliyor. Toplam sekiz sürüm, 91 fork, 9 açık issue, arşivlenmiş değil.
PyPI sınıflandırıcıları Python desteğini 3.9’da bırakıyor. Ben bunu 3.14.2 üzerinde çalıştırdım; kuruldu, 0.777 s’de import edildi ve 22 örneğin 19’unda tek bir istisna olmadan çıktı verdi.
Yani meta veriler gerçekliğin beş Python sürümü gerisinde ve gerçeklik de çalıştığı yönünde. Faydalı ayrım şu: sessiz bir depo, otomatik olarak işlev bozukluğu değil, destek sinyalidir. Tüm algoritması 2011’de yayımlanmış bir yöntem ve bir dizi kelime listesinden oluşan bir kütüphane için “bitmiş” hali oldukça makul bir durumdur — değiştirilecek çok az şey vardır ve stoplist’ler, anti-bot geçici çözümleri gibi çürümez.
Sessiz bir deponun anlamı şudur: bir hataya çarparsanız, onu siz düzeltirsiniz ya da çatallarsınız. Bu da, çözülmemiş sorunlara boğulan bir kütüphane profili olmayan dokuz açık issue ile birlikte değerlendirilmelidir.
Bellek ve bozuk HTML’nin etkisi
Burada iki operasyonel soru ayrı ayrı ölçülüyor.
Daha geniş stres testi bağlamı on kütüphaneli bellek ve bozuk HTML karşılaştırmasında yer alıyor.
Tepe çalışan bellek /usr/bin/time -l ile, hücre başına yeni bir süreç üzerinden ölçüldü — import tabanı, kütüphanenin yüklenmiş ve boşta durumdayken maliyetini gösterir; tepeler ise belgeyi de içerir.
| Kütüphane | Çalışma zamanı | Import tabanı | 226 KB tepe | 10 MB tepe |
|---|---|---|---|---|
| html2text | python3.14 | 18.7 | 19.9 | 71.2 |
| pyquery | python3.14 | 30.3 | 33.9 | 172.5 |
| resiliparse | python3.14 | 20.5 | 25.1 | 225.1 |
| markdownify | python3.14 | 23.9 | 28.9 | 278.5 |
| goose3 | python3.14 | 44.1 | 52.4 | 398.5 |
| cheerio | node22 | 66.8 | 76.5 | 398.5 |
| justext | python3.14 | 30.3 | 36.6 | 431.2 |
| newspaper4k | python3.14 | 52.6 | 61.8 | 668.5 |
| trafilatura | python3.14 | 52.5 | 64.8 | 927.1 |
| turndown | node22 | 47.8 | 68.4 | 2947.1 |
memory-results.json. Python ve Node taban çizgileri birbirleriyle karşılaştırılabilir değildir; yorumlayıcı her ikisinin de içindedir.
jusText’in taban değeri 30.3 MiB ve bu 10 MB’lık örnekteki tepesi 431.2 MiB; bu da import tabanının yaklaşık 14.2 katı ve mutlak RSS cinsinden girdi boyutunun 43.1 katı. Tek bir örnek ve tek bir süreç, genel bir ölçek eğrisi oluşturmaz; Python ve Node taban çizgileri de hâlâ birbiriyle karşılaştırılamaz.
Bozuk HTML. On iki belge, her biri tam bir şeyi bozacak şekilde hazırlanmış: kapanmayan etiketler, yanlış iç içe geçmiş satır içi öğeler, boşluk içeren tırnaklanmamış öznitelikler, ortada kalan kapanışlar, hiç <html> olmaması, yinelenen öznitelikler, etikette kesilmiş belge, bozuk entity’ler, kapanmayan <script>, yanlış charset bildirimi, işaretleme içeren yorum ve 600 seviye iç içe geçme — ayrıca aynı boyutlarda iki düzgün kontrol, çünkü “hiçbir şey döndürmedi” ifadesi ancak kütüphane aynı boyuttaki temiz belgede de sessizse bozukluk hakkında anlam taşır.
justext, 14’ün 0’ında hata verdi ve 13’ünde de boş döndü; bozuk örneklerde skorlanan sentinel’ların 0/33’ünü kurtardı (malformed-results.json). Düzgün kısa kontrol de 0 karakter verdi; düzgün uzun kontrol ise 1.333 karakterle boş olmayan tek sonuç oldu. On iki bozuk örneğin tamamı boş kaldı ve kapanmayan <script> durumu sentinel hayatta kalma puanlamasına dahil edilmedi. Bu seri, ayrıştırıcı toleransını — yani istisna vermemesini — gösteriyor; ancak sessizliği, ölçülmüş boyut eşiğinden ziyade bozukluğa atfetmiyor.
Artılar ve eksiler
Artıları. 100 dil stoplist’i ve bunlara gerçekten dayanan, onları sadece çevirmeyen bir sınıflandırıcı. Karşılaştırmadaki en düşük bağımlılık sayısı: 3 paket. 0.56 ms medyan çıkarım. Belgelenmiş, okunabilir dokuz ayar sabiti. BSD 2-Clause. Sınıflandırıcılar 3.9’da kalmasına rağmen Python 3.14 üzerinde sorunsuz çalışıyor.
Eksileri. Bu sentetik testte varsayılanlarda en yüksek boilerplate sızıntısı: %47 ve 74 kirletici token. Kısa paragraf örneği, hiçbir paragraf length_high değerini aşmadığında boş string döndürdü. Bu sette geri çağırma oranı 0.8378. Son depo gönderimi ve sürüm, testten on yedi ay önce olduğu için bakım sahipliği ayrıca düşünülmeli.
Kim kullanmalı, kim kullanmamalı?
jusText’i değerlendirin; çünkü dile özgü stoplist yüzeyi açık ve geniş olduğu için çok dilli korpuslarda anlamlı olabilir. Bu test 100 stoplist’i envanterledi ama çok dilli kaliteyi ölçmedi. Ayrıca üç paketlik bağımlılık ve açık eşik kontrolleri dağıtımınıza uygunsa adaydır.
Şunlarda kullanmayın: token başına modele veri veriyorsanız, goose3 ve newspaper4k’nin sıfırına karşılık 74 kirletici token doğrudan maliyettir. Kısa paragraf ağırlıklı sayfalarda — ürün açıklamaları, listeler, changelog’lar, SSS maddeleri — length_high değerini bilinçli ayarlamadıysanız kullanmayın. Ve uyumluluk ya da satın alma gereği olarak aktif biçimde bakımı yapılan bir bağımlılığa ihtiyacınız varsa da kullanmayın; kod çalışsa bile bu gerçek bir kısıttır.
Kullanacaksanız, length_high değerini varsayılanı ya da bir yüzdelik kuralı kopyalamak yerine etiketli bir doğrulama örneği üzerinde ayarlayın. Olası eşikleri tarayın, hem makale geri çağırmasını hem de boilerplate kesinliğini ölçün; eşiği düşürmek kısa düz yazıyı kurtarabilir ama istenmeyen komşu blokları da yükseltebilir.
Yönetilen API nerede devreye girer?
jusText, bu karşılaştırmadaki her araç gibi, elinizde zaten bulunan HTML üzerinde çalışır. Bu kütüphanelerin hiçbiri sayfa çekmez, JavaScript çalıştırmaz ya da anti-bot katmanını yönetmez.
Aynı altı çıkarıcı için aynı örnek setleri görmek isterseniz altı kütüphaneli çıkarım karşılaştırmasına bakın.
Bizim kendi Thunderbit çözümümüz de dahil olmak üzere barındırılan bir çekme/render/çıkarma servisi farklı bir sorumluluk sınırını kapsar. Thunderbit burada benchmark edilmedi. Ayrım, sağlanan HTML üzerinde düz yazı sınıflandırması yapmak ile bir URL’yi alıp işleyen bir servis arasındadır; bu makale aynı ölçekte bir kalite karşılaştırması sunmuyor.
Dürüst çerçeve şu: jusText’in çok dilli stoplist’leri gerçek bir yetenek ve ücretsizdir. Sorununuz birçok dilde sayfa çekmek ise, o dillerde düz yazıyı sınıflandırmak değil, farklı bir ürüne bakıyorsunuz demektir.
Daha geniş alan için web scraping API karşılaştırmamız barındırılan seçenekleri, açık kaynak scraper rehberimiz ise kendi kendine barındırılan çözümleri ele alıyor. Çıktı bir modele gidecekse, en çok doğruluk kaybı Python’da HTML’yi Markdown’a dönüştürmede yaşanıyor.
Web Verisi Çekmek İçin Thunderbit’i Deneyin
jusText kullanmalı mısınız?
Korpus çok dilli ise veya paragraf uzunluğu dağılımı açık eşik ayarından fayda görüyorsa adaydır. Dağıtımdan önce her iki özelliği de doğrulayın.
Yerleşik 100 stoplist gerçek bir tasarım özelliğidir; ancak çok dilli doğruluk test edilmedi. Eşik uçurumu ayarlanabilir; daha düşük bir değer kabul edilebilir mi, bu da etiketli bir örnekte ölçülen geri çağırma ve boilerplate kesinliğine bağlı.
Bu İngilizce sentetik sette varsayılanlarda newspaper4k sıfır etiketli boilerplate birimi sızdırdı ve makale birimlerinin 0.9865’ini geri aldı. Bu, bu iş yükü için onu bir karşılaştırma adayı yapar; evrensel bir alternatif önerisi değildir.
Web Verisi Çekmek İçin Thunderbit’i Deneyin Get Started Free
SSS
jusText neden kısmi bir çıkarım yerine boş string döndürüyor?
Çünkü sınıflandırıcısı iki aşamalı çalışır. Bir paragrafın tek başına good sınıfını alması için length_high eşiğini aşması gerekir (varsayılan 200 karakter); ikinci aşama ise komşu neargood blokları yükseltir. Eşiğin üstünde paragraf yoksa tohum oluşmaz; bu yüzden tüm adaylar boilerplate’e düşer ve sonuç boş gelir. Bu tasarım gereği ya hep ya hiçtir; kısmi yanıt bulamama durumu değildir.
jusText terk edilmiş mi? Son depo gönderimi ve son PyPI sürümü ikisi de 2025-02-25 tarihli — testten on yedi ay önce — ve PyPI sınıflandırıcıları Python 3.9’da bitiyor. Ama Python 3.14.2 üzerinde istisnasız kuruldu ve çalıştı; ayrıca 9 açık issue büyük bir birikim sayılmaz. Tarihleri, çalışmanın bozuk olduğunun kanıtı değil bakım riski olarak okuyun; pratik risk, kendi hatalarınızı kendiniz düzeltmeniz gerekebilmesidir.
Neden Readability’den daha fazla boilerplate sızdırıyor? Bu örnek setinde, varsayılan bağlam kuralları altında uygun düz yazı benzeri komşu bloklar çıktı sınırını geçti. Yükseltme, her komşu için otomatik değil; blok sınıfına, mesafeye ve bağlama bağlı. Ölçülen sonuç, varsayılanlarda %47 boilerplate sızıntısı ve 74 kirletici token oldu.
Başka bir dil için nasıl kullanırım?
justext.justext(html, justext.get_stoplist("German")). get_stoplists() mevcut 100’ünün tamamını döndürür. Stoplist, paragraf uzunluğu, bağlantı yoğunluğu, HTML’den türetilen bölümleme, başlık mesafesi ve komşu blok bağlamını da kullanan bir sınıflandırıcının dile özgü sözlük girdisidir. Bu, dil girdisini değiştirir; tek başına Almanca çıkarım kalitesini doğrulamaz.
Burada ne test edilmedi?
Gerçek dünya sayfaları — bunların hepsi etiketli birimlerden oluşan kontrollü örnekler. Kütüphanenin ana satış noktası olan çok dilli yetenek, 100 stoplist olarak envanterlendi ama İngilizce dışı metinde puanlanmadı. encoding, default_encoding ve enc_errors parametrelerini sunmasına rağmen encoding köşe durumları. Ayrıca max_heading_distance ve iki stopword oranı eşiği tüm test boyunca varsayılan bırakıldı.


