U dokumentu, jehož nejdelší odstavec má 151 znaků, vrátí jusText se svým výchozím nastavením nula znaků. Ne částečný výstup — prázdný řetězec. Snížíte jeden práh tak, aby přes něj prošel právě jeden odstavec, a tentýž dokument najednou vrátí 832 znaků. Snížíte ho ještě víc a pořád dostanete 832.
Na tomto testovacím vzorku je chování spíš prudký zlom než pozvolný sklon. Zda je výchozí nastavení na špatné straně, záleží na délce odstavců a rozložení boilerplate v cílovém korpusu.
Co je jusText a proč záleží na lexikální hustotě
Ve srovnání s ostatními extraktory v této sadě je jusText neobvykle silně závislý na jazykově specifické hustotě stop slov. Blok s vysokým podílem funkčních slov — the, and, of, was — má větší šanci být skutečným textem. Tento lexikální signál ale není jediným kritériem: výsledek ovlivňuje i délka odstavce, hustota odkazů, hranice bloků odvozené z HTML, vzdálenost od nadpisů, třídy sousedních bloků i kontextově citlivý druhý průchod.
Oficiální zdroj: oficiální repozitář jusText.

Protože klasifikátor pracuje se seznamem stop slov pro konkrétní jazyk, dodává se jusText se 100 jazykovými sadami. Tahle explicitní jazyková lexikální vrstva je v tomto srovnání jeho nejvýraznější odlišnost, i když se kvalita pro více jazyků netestovala.
Otestovaná verze: 3.0.2, BSD 2-Clause, 822 hvězdiček na GitHubu. Python 3.14.2.
Zlomový bod v číslech

Klasifikátor jusText běží ve dvou průchodech. První, bez kontextu, přiřadí každému odstavci třídu good, bad, short nebo neargood. Druhý, kontextový, povýší neargood na good — ale jen tehdy, když sousedí s blokem, který už je good. A odstavec získá good sám od sebe pouze tehdy, když překročí length_high, které má ve výchozím nastavení 200 znaků.
Na dokumentu, kde nic nepřekročí hranici 200 znaků, se nic nestane zárodkem pro povýšení a každý blok neargood spadne zpět do boilerplate. Celá stránka se vrátí prázdná.
Prahovou hodnotu jsem prošel na testovacím vzorku, jehož nejdelší odstavec má 151 znaků:
length_high | Odstavců klasifikovaných jako good | Vrácených znaků |
|---|---|---|
| 200 (výchozí) | 0 | 0 |
| 150 | 8 | 832 |
| 120 | 8 | 832 |
| 100 | 8 | 832 |
| 80 | 8 | 832 |
justext-length-threshold.json.
Na tomto prahovém vzorku stačilo, aby přes čáru prošel jediný odstavec, a výstupem bylo všech osm cílových odstavců; další snižování už nic nepřidalo. Trace odpovídá tomu, že kontextový průchod povyšuje vhodné sousedy neargood kolem existujícího bloku good; neznamená to však, že by se na libovolné stránce automaticky povyšoval každý soused.
Než bych přisoudil změnu samotnému length_high, prošel jsem length_low ve čtyřech hodnotách zkřížených s max_link_density ve dvou: osm kombinací, všechny s nulovým výstupem. Změna kterékoli z těchto voleb na tomto vzorku výstup neobnovila.
Napříč celou sadou 22 vzorků je vzorec stejný: při length_high=200 vrátily výstup 2 z 22 vzorků, při 150 9 z 22, při 120 15 z 22.
Dvě věci z toho neplynou. Neříká to, že jusText extrahuje špatně — na skutečné stránce s přirozeným jazykem v základním nastavení vrátil 1 190 znaků čistého článku, protože skutečný novinový odstavec hranici 200 znaků poprvé bez potíží překročí. A neříká to, že je výchozí nastavení špatně; říká to, že výchozí nastavení počítá s dlouhými odstavci, a vy byste si měli před spuštěním ověřit, zda je váš korpus skutečně obsahuje.
Druhá strana téže sady: vyšší únik boilerplate při výchozím nastavení
V této označkované testovací sadě má jusText ve výchozím nastavení nejvyšší naměřený únik boilerplate.
| Knihovna | Recall článku (všech 22) | Únik boilerplate | Přesnost obsahu | Kontaminující tokeny |
|---|---|---|---|---|
| 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. Jedna sada vzorků, jeden scorer, každá jednotka označená jedinečným sentinel tagem, takže obnova je přesná a odpovídá substrátové příslušnosti.

47% únik boilerplate a 74 kontaminujících tokenů — dvojnásobek míry úniku oproti Readability a víc než dvojnásobná kontaminace v této označené syntetické sadě. Jde o diagnostický výsledek při výchozím nastavení, ne o stabilní pořadí produktu napříč vším použitím.
Pozorovaný únik odpovídá stejnému kontextovému průchodu, který stojí i za tím prudkým zlomem. Vhodné sousední bloky neargood mohou být povýšeny, pokud to dovolí třídy okolních bloků a pravidla vzdálenosti; blok podobný textu nebo komentář vedle článku tak může hranici překročit. Výsledek na vzorku ukazuje, které označené bloky unikly, zatímco zjednodušený mechanismus zůstává podmíněný přesnými kontextovými pravidly jusText.
Jeho recall je 0.8378, třetí od konce, a veškerá ztráta plyne z prahu: neobnovil nic u jediného článku o 129 znacích, nic na stránce s deseti krátkými odstavci ani nic na téměř prázdném dokumentu.
Inventář jazykových stoplistů
Devadesát devět dalších stoplistů.
justext.get_stoplists() vrací 100 jazyků. Klasifikátor je jazykově parametrizovaný záměrně, ne jako překlad jedné anglické heuristiky, a změna jazyka je otázkou jednoho argumentu:
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 i goose3 také nabízejí chování navázané na jazyk, ale tato recenze netestovala žádný extraktor na neanglické referenční pravdě. Sto přibalených stoplistů dělá z jusText jasného kandidáta pro vícejazyčné hodnocení; samotný inventář ale neprokazuje kvalitu extrakce v těchto jazycích ani to, že konkurence je pokrývá méně efektivně.
API jsou dvě funkce a devět laditelných konstant — length_low 70, length_high 200, stopwords_low 0.30, stopwords_high 0.32, max_link_density 0.20, max_heading_distance 200, plus práce s kódováním. Krátké, čitelné a všechno je zdokumentované přímo v signatuře.
Instalace a rychlost
pip install justext stáhne 3 balíčky — nejméně ze srovnávaných nástrojů — a 22,4 MiB, a to za méně než dvě sekundy.
Oficiální odkaz: jusText na PyPI.
| Knihovna | Balíčky | site-packages | Studený import | Extraction 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. Každá knihovna ve vlastním prázdném virtuálním prostředí.
Tři balíčky a 22,4 MiB jsou v tomto srovnání malá závislost a medián extrakce 0,56 ms se v tomto harnessu blíží 0,51 ms u trafilatury. Měření prostředí ale nerozkládá velikost balíčku podle typu souborů, takže neříká, kolik z místa na disku zabírají stoplisty.
Otázka údržby, opatrně zodpovězená
Zastaralá metrika údržby použitá zde vychází z posledního pushi do repozitáře a posledního vydání na PyPI, obojí 2025-02-25. To bylo sedmnáct měsíců před testováním. Celkem osm releasů, 91 forků, 9 otevřených issues, archivace neproběhla.
Klasifikátory na PyPI uvádějí podporu Pythonu jen do verze 3.9. Spustil jsem to na 3.14.2 a fungovalo to, import proběhl za 0.777 s a extrakce na 19 z 22 vzorků proběhla bez jediné výjimky.
Metadata tedy zaostávají za realitou o pět verzí Pythonu, ale realita je taková, že to funguje. To je ten podstatný rozdíl: tichý repozitář je signál o podpoře, ne automaticky o funkčnosti. U knihovny, jejíž celý algoritmus je veřejně popsaná metoda z roku 2011 plus sada slovních seznamů, je „hotovo“ docela uvěřitelný stav — už není moc co měnit a stoplisty neshnijí jako workaround proti botům.
Co tichý repozitář znamená v praxi: když narazíte na chybu, budete ji opravovat sami nebo si projekt forknete. Zvažte to proti devíti otevřeným issues, což není profil knihovny topící se v neřešených problémech.
Paměť a co s ní udělá rozbitý HTML
Dvě provozní otázky se zde měří odděleně.
Širší kontext zátěžového testu je v porovnání paměti a chybného HTML u deseti knihoven.
Špičková residentní paměť, přes /usr/bin/time -l, vždy jeden čerstvý proces na buňku — importní minimum je cena knihovny při načtení a nečinnosti, maxima zahrnují dokument.
| Knihovna | Runtime | Importní minimum | Špička 226 KB | Špička 10 MB |
|---|---|---|---|---|
| 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. Základní hodnoty Pythonu a Node nejsou mezi sebou přímo srovnatelné; interpreter je uvnitř obou.
Importní minimum jusText je 30.3 MiB a jeho špička na tomto vzorku o velikosti 10 MB je 431.2 MiB, tedy asi 14.2× importního minima a 43.1× velikosti vstupu v absolutním RSS. Jeden vzorek a jeden proces neurčují obecnou křivku škálování; baseline Pythonu a Node navíc zůstávají nesrovnatelné.
Rozbité HTML. Dvanáct dokumentů, z nichž každý má přesně jeden problém — neukončené tagy, špatně zanořené inline prvky, atributy bez uvozovek s mezerami, osamělé uzávěry, vůbec žádný <html>, duplicitní atributy, dokument uříznutý uprostřed tagu, špatné entity, neukončený <script>, nepravdivé tvrzení o kódování, komentář obsahující markup a 600 úrovní zanoření — plus dva dobře utvořené kontrolní dokumenty stejné velikosti, protože „nic nevrátil“ něco vypovídá o malformovanosti jen tehdy, když knihovna mlčí i na čistém dokumentu stejné velikosti.
justext vyhodil výjimku u 0 z 14 a nic nevrátil u 13, přičemž na rozbitých vzorcích obnovil 0/33 hodnocených sentinelů (malformed-results.json). I dobře utvořený krátký kontrolní dokument vrátil 0 znaků; jediným ne-prázdným výsledkem byl dlouhý kontrolní dokument s 1 333 znaky. Všechny dvanácti rozbité vzorky zůstaly prázdné a případ s neukončeným <script> je ze skórování přežití sentinelů vyřazen. Tato dávka tedy ukazuje toleranci parseru — žádná výjimka — ale nemůže připsat ticho malformovanosti místo již změřeného velikostního prahu.
Klady a zápory
Ve prospěch. 100 jazykových stoplistů a klasifikátor, který je skutečně na nich postavený, nikoli na jejich dodatečném překladu. Nejmenší počet závislostí ve srovnání: 3 balíčky. Medián extrakce 0.56 ms. Devět zdokumentovaných, čitelných ladicích konstant. BSD 2-Clause. Bez problémů běží na Pythonu 3.14, ačkoliv klasifikátory končí u 3.9.
Proti. Nejvyšší únik boilerplate v tomto syntetickém testu při výchozím nastavení: 47 %, se 74 kontaminujícími tokeny. Testovací vzorek s krátkými odstavci vrátil prázdný řetězec, když žádný odstavec nepřekročil length_high. Recall byl na této sadě 0.8378. Poslední zaznamenaný push do repozitáře i release byly sedmnáct měsíců před testováním, takže je třeba počítat s rizikem kolem údržby.
Kdo by jej měl používat a kdo ne
Zvažte jusText pro vícejazyčné korpusy, protože jazykově specifická vrstva stoplistů je explicitní a široká. Tento test sice inventarizoval 100 stoplistů, ale nehodnotil kvalitu pro více jazyků. Je také kandidátem tam, kde se hodí závislost na třech balíčcích a explicitní řízení prahů.
Vyhněte se mu, pokud krmíte model po tokenech, kde 74 kontaminujících tokenů proti nule u goose3 a newspaper4k představuje přímý náklad. Vyhněte se mu také u stránek s krátkými odstavci — produktové texty, výpisy, changelogy, FAQ — pokud jste length_high nenastavili záměrně. A vyhněte se mu i tehdy, když potřebujete aktivně udržovanou závislost z důvodů compliance nebo nákupu, což je reálný požadavek i tehdy, když kód funguje.
Pokud ho použijete, laděte length_high proti označené validační vzorku, ne kopií výchozí hodnoty nebo percentilem. Projděte několik rozumných prahů a měřte jak recall článku, tak přesnost vůči boilerplate; nižší práh může zachránit krátký prozaický text, ale zároveň povýšit nechtěné sousední bloky.
Kam zapadá spravované API
jusText pracuje s HTML, které už máte, stejně jako všechny nástroje v tomto srovnání. Žádná z těchto knihoven stránku nestahuje, nespouští JavaScript ani neřeší anti-bot vrstvu.
Pro stejnou sadu vzorků napříč všemi šesti extraktory viz srovnání extrakce u šesti knihoven.
Hostovaná služba pro fetch/render/extraction, včetně našeho Thunderbit, řeší jinou hranici odpovědnosti. Thunderbit zde nebyl benchmarkován. Rozdíl je mezi klasifikací textu z dodaného HTML a službou, která URL sama získá a zpracuje; tento článek neposkytuje srovnání kvality na stejných metrikách.
Poctivé shrnutí: vícejazyčné stoplisty jusText jsou reálná a zdarma dostupná schopnost. Pokud váš problém spočívá spíš ve stahování stránek v mnoha jazycích než v klasifikaci textu v nich, je to jiný nákup.
Pro širší přehled náš přehled web scraping API pokrývá hostovaná řešení a přehled open-source scraperů zase self-hosted varianty. Pokud výstup míří do modelu, převod HTML do Markdownu v Pythonu je místo, kde se ztrácí nejvíc věrnosti.
Vyzkoušet Thunderbit pro extrakci webových dat
Měli byste používat jusText?
Je kandidátem, pokud je korpus vícejazyčný nebo pokud vám jeho rozložení délek odstavců vyhovuje pro explicitní ladění prahů. Obě vlastnosti si před nasazením ověřte.
100 přibalených stoplistů je skutečná designová výhoda, ale vícejazyčná přesnost nebyla testována. Prahový zlom je laditelný; zda je nižší nastavení přijatelné, závisí na recallu a přesnosti vůči boilerplate změřených na označeném vzorku.
Na této anglické syntetické sadě při výchozím nastavení newspaper4k nepropustil žádné označené jednotky boilerplate a zachytil 0.9865 jednotky článku. To z něj dělá kandidáta pro toto zatížení, ne univerzální náhradu.
Vyzkoušet Thunderbit pro extrakci webových dat Get Started Free
Časté dotazy
Proč jusText vrací prázdný řetězec místo částečné extrakce?
Klasifikátor má dva průchody. Odstavec získá třídu good sám od sebe pouze nad hodnotou length_high (výchozí 200 znaků); druhý průchod pak povyšuje sousední bloky neargood. Když žádný odstavec hranici nepřekročí, nevznikne žádný zárodek pro povýšení, takže každý kandidát spadne zpět do boilerplate a výsledek je prázdný. Je to konstrukčně všechno-nebo-nic, ne neschopnost najít částečnou odpověď.
Je jusText opuštěný projekt? Poslední push do repozitáře i poslední vydání na PyPI byly 2025-02-25 — sedmnáct měsíců před testem — a klasifikátory na PyPI končí u Pythonu 3.9. Ale na Pythonu 3.14.2 se nainstaloval a běžel bez výjimky a 9 otevřených issues není velká fronta. Data čtěte jako riziko údržby, ne jako důkaz rozbitého chování; praktické riziko je, že si případné chyby budete muset opravit sami.
Proč uniká víc boilerplate než Readability? V této sadě vzorků prošly výstupní hranicí vhodné sousední bloky podobné textu podle výchozích kontextových pravidel. Povýšení je podmíněné třídou bloku, vzdáleností a kontextem, ne automatické pro každého souseda. Naměřený výsledek byl 47% únik jednotek boilerplate a 74 kontaminujících tokenů při výchozím nastavení.
Jak ho použiju pro jiný jazyk?
justext.justext(html, justext.get_stoplist("German")). get_stoplists() vrací všech dostupných 100. Stoplist je jazykově specifický lexikální vstup do klasifikátoru, který zároveň používá délku odstavce, hustotu odkazů, segmentaci odvozenou z HTML, vzdálenost od nadpisů a kontext sousedních bloků. Tím se změní jazykový vstup; samo o sobě to ale neověřuje kvalitu extrakce v němčině.
Co se zde netestovalo?
Skutečné webové stránky vůbec — jde o kontrolované vzorky s označenými jednotkami. Vícejazyčná schopnost, což je hlavní prodejní argument knihovny, byla inventarizována na 100 stoplistech, ale nehodnocena na neanglickém textu. Hraniční případy kódování, přestože jusText vystavuje parametry encoding, default_encoding a enc_errors. A max_heading_distance i oba prahy pro poměr stop slov zůstaly po celou dobu na výchozích hodnotách.


