Op een document waarvan de langste alinea 151 tekens telt, geeft jusText met de standaardinstellingen nul tekens terug. Niet een gedeeltelijke extractie — gewoon een lege string. Verlaag één drempel zodat precies één alinea erbovenuit komt, en hetzelfde document levert 832 tekens op. Verlaag je hem nog verder, dan blijft het 832.
Bij deze fixture is het gedrag dus een klif, geen helling. Of de standaardinstelling aan de verkeerde kant zit, hangt af van de alinalengtes en de verdeling van boilerplate in de doelcorpus.
Wat jusText is en waarom lexicale dichtheid telt
Vergeleken met de andere extractors in deze fixture-set leunt jusText opvallend zwaar op taalspecifieke stopwoorddichtheid. Een blok met een hoog aandeel functiewoorden — de, en, van, was — is waarschijnlijker lopende tekst. Dat lexicale signaal is niet de hele classifier: alinalengte, linkdichtheid, HTML-afgeleide blokgrenzen, afstand tot koppen, klassen van buurblokken en een contextgevoelige tweede pass beïnvloeden het resultaat ook.
Officiële referentie: jusText's officiële repository.

Omdat de classifier met een taalspecifieke stopwoordenlijst werkt, wordt jusText geleverd met 100 daarvan. Die expliciete, taalspecifieke lexicale basis is het duidelijkste onderscheidende punt in deze vergelijking, al is meertalige kwaliteit niet getest.
Geteste versie: 3.0.2, BSD 2-Clause, 822 GitHub-stars. Python 3.14.2.
De klif, gemeten

De classifier van jusText werkt in twee stappen. In een contextvrije pass krijgt elke alinea de klasse good, bad, short of neargood. Daarna promoot een contextgevoelige pass neargood naar good — maar alleen als het naast een blok staat dat al good is. En een alinea krijgt pas zelfstandig good als die boven length_high uitkomt, standaard 200 tekens.
Op een document waarin niets de 200 haalt, wordt er niets gezaaid voor die promotie en zakt elk neargood-blok terug naar boilerplate. De hele pagina komt leeg terug.
Ik heb de drempel uitgeprobeerd op een fixture waarvan de langste alinea 151 tekens is:
length_high | Alinea's geclassificeerd als good | Teruggegeven tekens |
|---|---|---|
| 200 (standaard) | 0 | 0 |
| 150 | 8 | 832 |
| 120 | 8 | 832 |
| 100 | 8 | 832 |
| 80 | 8 | 832 |
justext-length-threshold.json.
Op deze threshold-fixture veranderde het overschrijden van de lijn door één alinea het resultaat voor alle acht doelalinea’s, en verder versoepelen voegde niets toe. De trace past bij een contextpass die geschikte neargood-buren rond een bestaand good-blok promoot; dit betekent niet dat op willekeurige pagina’s automatisch elke buur wordt gepromoveerd.
Voordat ik de switch aan length_high toeschreef, heb ik length_low op vier waarden gesweept in combinatie met max_link_density op twee waarden: acht combinaties, allemaal nul output. Het aanpassen van een van die twee instellingen bracht op deze fixture geen output terug.
Over de volledige set van 22 fixtures blijft het patroon overeind: 2 van de 22 fixtures gaven output bij length_high=200, 9 van de 22 bij 150, 15 van de 22 bij 120.
Twee dingen zegt dit niet. Het zegt niet dat jusText slecht extraheert — op een echte natuurlijke-tekstpagina gaf het met de standaardinstellingen 1.190 tekens schone artikeltekst terug, omdat een echte nieuwsparagraaf al bij de eerste poging over de 200 tekens heen komt. En het zegt niet dat de standaard fout is; het zegt dat de standaard uitgaat van lange alinea’s, en dat je moet bepalen of jouw corpus die heeft vóór je iets draait.
De andere kant van deze fixture-set: meer lek op standaardinstellingen
Op deze gelabelde fixture-set heeft jusText met de standaardinstellingen het hoogste gemeten boilerplate-lek.
| Bibliotheek | Artikel-recall (alle 22) | Boilerplate-lek | Content-token-precisie | Verontreinigende tokens |
|---|---|---|---|---|
| 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. Eén fixture-set, één scorer, elk item getagd met een unieke sentinel zodat herstel exact substring-membership is.

47% boilerplate-lek en 74 verontreinigende tokens — twee keer zoveel lek als Readability en ruim meer dan het dubbele aan contaminatie in deze gelabelde synthetische set. Dit is een diagnostisch resultaat op standaardinstellingen, geen stabiele rangorde voor het hele product.
Het geobserveerde lek past bij dezelfde contextpass als bij de klif. Geschikte neargood-blokken kunnen worden gepromoot wanneer de omliggende blokklassen en afstandsregels dat toelaten; een proza-achtig promo- of commentblok naast artikeltekst kan daardoor de grens overgaan. Het fixture-resultaat laat zien welke gelabelde blokken zijn gelekt, terwijl het vereenvoudigde mechanisme nog steeds afhankelijk is van jusText's exacte contextregels.
De recall is 0.8378, derde van onderen, en alle verlies komt door de drempel: het herstelde niets op een enkel artikel van 129 tekens, niets op een pagina met tien korte alinea’s en niets op het bijna lege document.
De inventaris van stopwoordenlijsten per taal
Negenennegentig andere stopwoordenlijsten.
justext.get_stoplists() geeft 100 talen terug. De classifier is van ontwerp uit taalspecifiek geparametriseerd, niet via een vertaling van een Engelstalige heuristiek, en van taal wisselen is één argument:
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 en goose3 hebben ook taalgerelateerd gedrag, maar in deze review is geen enkele extractor gescoord op niet-Engelse ground truth. De 100 meegeleverde stopwoordenlijsten maken jusText juist een duidelijke kandidaat voor meertalige evaluatie; de inventaris alleen bewijst niet dat de extractiekwaliteit in die talen goed is of dat concurrenten die talen slechter afdekken.
De API bestaat uit twee functies en negen instelbare constanten — length_low 70, length_high 200, stopwords_low 0.30, stopwords_high 0.32, max_link_density 0.20, max_heading_distance 200, plus encoding-afhandeling. Klein, overzichtelijk en allemaal gedocumenteerd in de signature.
Installatie en snelheid
pip install justext haalt 3 packages binnen — het minste in deze vergelijking — en 22.4 MiB, in minder dan twee seconden.
Officiële referentie: jusText op PyPI.
| Bibliotheek | Packages | site-packages | Koude import | Extractie 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. Elke bibliotheek in een eigen lege virtualenv.
Drie packages en 22.4 MiB is in deze vergelijking een lichte dependency, en 0.56 ms mediane extractie ligt dicht bij trafilatura's 0.51 in deze testopstelling. De omgevingsmeting splitst de pakketgrootte niet uit naar bestandstype, dus ze kan niet zeggen hoeveel van de schijfruimte door stopwoordenlijsten wordt ingenomen.
De onderhoudsvraag, zorgvuldig beantwoord
De verouderde onderhoudsmaatstaven die hier zijn gebruikt, zijn de laatste repository-push en de laatste PyPI-release, beide 2025-02-25. Dat was zeventien maanden vóór de test. Acht releases in totaal, 91 forks, 9 open issues, niet gearchiveerd.
De PyPI-classifiers noemen Python-ondersteuning tot 3.9. Ik heb het gedraaid op 3.14.2 en het werd geïnstalleerd, importeerde in 0.777 s en extraheerde op 19 van 22 fixtures zonder één uitzondering.
De metadata loopt dus vijf Python-versies achter op de werkelijkheid, en de werkelijkheid is dat het werkt. Dat is het bruikbare onderscheid: een stille repository zegt iets over support, niet automatisch over functie. Voor een bibliotheek waarvan het hele algoritme een gepubliceerde methode uit 2011 is plus een set woordenlijsten, is “af” een plausibele staat — er valt niet veel meer te veranderen, en stopwoordenlijsten verouderen niet zoals een anti-bot workaround dat doet.
Wat een stille repo wel betekent: als je een bug tegenkomt, los je die zelf op of fork je de code. Zet dat af tegen negen open issues, wat niet het profiel is van een bibliotheek die verdrinkt in onbehandelde problemen.
Geheugen en wat kapotte HTML daarmee doet
Twee operationele vragen worden hier apart gemeten.
De bredere stress-testcontext staat in de vergelijking van tien bibliotheken op geheugen en foutieve HTML.
Piek resident memory, via /usr/bin/time -l, één vers proces per cel — de import-bodem is wat de bibliotheek kost geladen en idle, de pieken bevatten het document.
| Bibliotheek | Runtime | Import-bodem | 226 KB piek | 10 MB piek |
|---|---|---|---|---|
| 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- en Node-baselines zijn niet onderling vergelijkbaar; de interpreter zit in beide.
jusText's bodem is 30.3 MiB en de piek op deze 10 MB-fixture is 431.2 MiB, ongeveer 14.2 keer de import-bodem en 43.1 keer de inputgrootte in absolute RSS. Eén fixture en één proces leveren geen algemene schaalcurve op; Python- en Node-baselines blijven bovendien niet vergelijkbaar.
Kapotte HTML. Twaalf documenten die elk precies één ding breken — niet-afgesloten tags, verkeerd geneste inline-elementen, attributen zonder quotes met spaties, losse sluit-tags, helemaal geen <html>, dubbele attributen, een document afgekapt midden in een tag, foute entiteiten, een niet-afgesloten <script>, een liegende charset-declaratie, een comment met markup en 600 niveaus nesting — plus twee goed gevormde controles op dezelfde grootte, omdat “het gaf niets terug” alleen iets zegt over malformedness als de bibliotheek ook op een schoon document van dezelfde grootte stil blijft.
justext gooide op 0 van de 14 een fout en gaf op 13 niets terug, en herstelde 0/33 gescoorde sentinels over de kapotte fixtures heen (malformed-results.json). De goed gevormde korte controle gaf ook 0 tekens terug; de goed gevormde lange controle was het enige niet-lege resultaat met 1.333 tekens. De twaalf malformed fixtures bleven allemaal leeg, en het geval met de niet-afgesloten <script> is uitgesloten van sentinel-overlevingsscore. Deze batch laat dus parser-tolerantie zien — geen uitzondering — maar kan stilte niet toeschrijven aan malformedness in plaats van aan de al gemeten grootte-drempel.
Voor- en nadelen
In zijn voordeel. 100 taal-stopwoordenlijsten, en een classifier die daar ook echt rond is gebouwd in plaats van erin vertaald. Het kleinste aantal dependencies in de vergelijking met 3 packages. 0.56 ms mediane extractie. Negen gedocumenteerde, overzichtelijke tuning-constanten. BSD 2-Clause. Werkt netjes op Python 3.14 ondanks classifiers die stoppen bij 3.9.
Tegen. Het hoogste boilerplate-lek in deze synthetische test op standaardinstellingen: 47%, met 74 verontreinigende tokens. De korte-paragraaffixture gaf een lege string terug toen geen enkele alinea length_high overschreed. Recall was 0.8378 op deze set. De laatst geregistreerde repository-push en release waren zeventien maanden vóór de test, dus onderhoudseigendom verdient aandacht.
Wie het wel en niet zou moeten gebruiken
Evalueer jusText voor meertalige corpora, omdat de taalspecifieke stopwoordenlijstlaag expliciet en breed is. Deze test inventariseerde 100 stopwoordenlijsten maar mat geen meertalige kwaliteit. Het is ook een kandidaat wanneer een dependency van drie packages en expliciete drempelinstellingen passen bij de deployment.
Sla het over als je een model per token voedt, waar 74 verontreinigende tokens tegenover goose3's en newspaper4k's nul een directe kostenpost zijn. Sla het over voor pagina’s met korte alinea’s — productbeschrijvingen, listings, changelogs, FAQ-items — tenzij je length_high bewust hebt ingesteld. En sla het over als je voor compliance- of procurement-redenen een actief onderhouden dependency nodig hebt; dat is een reële eis, ook als de code werkt.
Als je het wel gebruikt, stem dan length_high af op een gelabelde validatieset in plaats van de standaard of een percentielregel te kopiëren. Sweep realistische drempels en meet zowel artikel-recall als boilerplate-precisie; het verlagen van de poort kan korte proza herstellen, maar ook ongewenste buurblokken promoten.
Waar een beheerde API past
jusText neemt HTML aan die je al hebt, net als alles in deze vergelijking. Geen van deze bibliotheken haalt zelf een pagina op, rendert JavaScript of handelt een anti-botlaag af.
Voor dezelfde fixtures over alle zes extractors heen, zie de vergelijking van zes extractors.
Een gehoste fetch/render/extract-service, inclusief onze eigen Thunderbit, dekt een ander verantwoordelijkheidsgebied. Thunderbit is hier niet gebenchmarkt. Het onderscheid is aangeleverde-HTML prozaclassificatie versus een service die een URL ophaalt en verwerkt; dit artikel geeft geen kwaliteitsvergelijking op dezelfde metric.
De eerlijke samenvatting: jusText's meertalige stopwoordenlijsten zijn een echte, gratis mogelijkheid. Als jouw probleem pagina’s ophalen in veel talen is en niet proza classificeren in die talen, dan heb je iets anders nodig.
Voor het bredere veld behandelt onze overzichtspagina van web scraping API’s gehoste opties en de open-source scraper pillar self-hosted varianten. Als de output naar een model gaat, is HTML naar Markdown omzetten in Python waar de meeste fidelity verloren gaat.
Probeer Thunderbit voor webdata-extractie
Moet je jusText gebruiken?
Het is een kandidaat als de corpus meertalig is of als de verdeling van alinalengtes baat heeft bij expliciete drempelafstemming. Valideer beide eigenschappen vóór uitrol.
De 100 meegeleverde stopwoordenlijsten zijn een echt ontwerpelement, maar meertalige nauwkeurigheid is niet getest. De drempelklif is afstembaar; of een lagere instelling acceptabel is, hangt af van recall en boilerplate-precisie op een gelabelde steekproef.
Op deze synthetische Engelstalige set met standaardinstellingen lekte newspaper4k nul gelabelde boilerplate-units en herstelde het 0.9865 van de artikel-units. Dat maakt het een vergelijkingskandidaat voor deze workload, niet een universele vervanger.
Probeer Thunderbit voor webdata-extractie Get Started Free
FAQ's
Waarom geeft jusText een lege string terug in plaats van een gedeeltelijke extractie?
De classifier werkt in twee passes. Een alinea krijgt alleen zelfstandig de klasse good als die boven length_high uitkomt (standaard 200 tekens); daarna promoot de tweede pass naburige neargood-blokken. Zonder alinea boven de drempel is er geen seed, dus zakt elke kandidaat terug naar boilerplate en blijft het resultaat leeg. Het is van meet af aan alles-of-niets, niet het falen om een gedeeltelijk antwoord te vinden.
Is jusText verlaten? De laatste repository-push en de laatste PyPI-release waren allebei op 2025-02-25 — zeventien maanden vóór de test — en de PyPI-classifiers stoppen bij Python 3.9. Maar het installeerde en draaide op Python 3.14.2 zonder uitzondering, en 9 open issues is geen enorme achterstand. Lees de data als onderhoudsrisico, niet als bewijs van kapot gedrag; het praktische risico is dat je je eigen bugs moet oplossen.
Waarom lekt het meer boilerplate dan Readability? Op deze fixture-set gingen geschikte proza-achtige buurblokken onder de standaard contextregels over de outputgrens. Promotie hangt af van blokklasse, afstand en context, niet automatisch van elke buur. Het gemeten resultaat was een boilerplate-unit-lek van 47% en 74 verontreinigende tokens op standaardinstellingen.
Hoe gebruik ik het voor een andere taal?
justext.justext(html, justext.get_stoplist("German")). get_stoplists() geeft alle 100 beschikbare lijsten terug. De stopwoordenlijst is de taalspecifieke lexicale input voor een classifier die ook alinalengte, linkdichtheid, HTML-afgeleide segmentatie, afstand tot koppen en context van buurblokken gebruikt. Dit verandert de taalinvoer; het valideert op zichzelf niet de Duitse extractiekwaliteit.
Wat is hier niet getest?
Echte webpagina’s helemaal niet — dit zijn gecontroleerde fixtures met gelabelde units. De meertalige capaciteit, die het belangrijkste verkooppunt van de bibliotheek is, is geïnventariseerd met 100 stopwoordenlijsten maar niet gescoord op niet-Engelse tekst. Encoding-hoekgevallen, ondanks de encoding, default_encoding en enc_errors-parameters van jusText. En max_heading_distance plus de twee stopwoord-ratiodrempels bleven overal op de standaardwaarden.


