La soglia a picco di jusText su un test con paragrafi brevi

Ultimo aggiornamento il August 17, 2026
La soglia a picco di jusText su un test con paragrafi brevi
Riepilogo AI
In un documento in cui il paragrafo più lungo misura 151 caratteri, jusText con le impostazioni predefinite restituisce zero caratteri. Non un’estrazione parziale: una stringa vuota. Abbassa una soglia in modo che un solo paragrafo la superi, e lo stesso documento restituisce 832 caratteri. Abbassala ancora e restano 832. Su questo test, il comportamento è un salto netto, non una progressione graduale. Se il valore di default sia dalla parte sbagliata dipende dalla lunghezza dei paragrafi e dalla distribuzione del boilerplate nel corpus di destinazione. Valuta jusText per corpus multilingue perché la superficie delle stoplist specifiche per lingua è esplicita e ampia.

In un documento in cui il paragrafo più lungo misura 151 caratteri, jusText con le impostazioni predefinite restituisce zero caratteri. Non un’estrazione parziale: una stringa vuota. Abbassa una soglia in modo che un solo paragrafo la superi, e lo stesso documento restituisce 832 caratteri. Abbassala ancora e restano 832.

Su questo test, il comportamento è un salto secco, non una progressione graduale. Se il valore di default stia dalla parte sbagliata dipende dalla lunghezza dei paragrafi e da come il boilerplate è distribuito nel corpus di destinazione.

Cos’è jusText e perché conta la densità lessicale

Rispetto agli altri estrattori di questo set di test, jusText dipende in modo insolitamente forte dalla densità di stopword specifiche della lingua. Un blocco con un’alta presenza di parole funzionali — the, and, of, was — ha più probabilità di essere testo discorsivo. Questo segnale lessicale però non è tutto il classificatore: anche la lunghezza del paragrafo, la densità dei link, i confini dei blocchi derivati dall’HTML, la distanza dagli heading, le classi dei blocchi vicini e una seconda passata sensibile al contesto influenzano il risultato.

Riferimento ufficiale: repository ufficiale di jusText.

System diagram: Two-Pass Paragraph Classification

Poiché il classificatore usa una stoplist per lingua, jusText ne include 100. Questa superficie lessicale esplicitamente legata alla lingua è il suo elemento distintivo più chiaro in questo confronto, anche se la qualità multilingue non è stata testata.

Versione testata: 3.0.2, BSD 2-Clause, 822 stelle GitHub. Python 3.14.2.

Il salto netto, misurato

Measured results chart: Characters returned as length_high changes

Il classificatore di jusText lavora in due passaggi. Una prima passata indipendente dal contesto assegna a ogni paragrafo le etichette good, bad, short o neargood. Poi una seconda passata sensibile al contesto promuove neargood a good — ma solo quando si trova accanto a un blocco già good. Un paragrafo ottiene good da solo solo quando supera length_high, che di default è 200 caratteri.

In un documento in cui nessun paragrafo supera i 200 caratteri, non c’è nessun blocco che faccia da seme per la promozione, e ogni blocco neargood degrada a boilerplate. L’intera pagina torna vuota.

Ho variato la soglia su un test il cui paragrafo più lungo è 151 caratteri:

length_highParagraphs classified goodCharacters returned
200 (default)00
1508832
1208832
1008832
808832

justext-length-threshold.json.

Su questo test di soglia, il fatto che un solo paragrafo superi il limite cambia l’output di tutti e otto i paragrafi target, mentre abbassare ancora non aggiunge nulla. La traccia è coerente con la seconda passata che promuove i vicini neargood eleggibili attorno a un blocco good esistente; non implica però una promozione automatica di ogni vicino su pagine arbitrarie.

Prima di attribuire il cambio a length_high, ho variato length_low su quattro valori incrociandolo con max_link_density su due: otto combinazioni, tutte con risultato zero. Modificare uno di questi due parametri non ha recuperato output su questo test.

Su l’intero set di 22 fixture, il pattern regge: 2 su 22 fixture producono output con length_high=200, 9 su 22 con 150, 15 su 22 con 120.

Due cose che questo non significa. Non significa che jusText estragga male — su una pagina reale in linguaggio naturale, con le impostazioni predefinite, ha restituito 1.190 caratteri di testo pulito, perché un vero paragrafo di news supera i 200 caratteri al primo colpo. E non significa che il default sia sbagliato; significa che il default presume paragrafi lunghi, e devi decidere se il tuo corpus li contiene prima di partire.

L’altro lato di questo set: più leakage ai valori predefiniti

Su questo set di fixture etichettate, con le impostazioni predefinite, jusText mostra la più alta perdita di boilerplate misurata.

LibraryArticle recall (all 22)Boilerplate leakContent-token precisionContaminating tokens
Readability1.00000.23530.910935
trafilatura0.98650.05880.94114
newspaper4k0.98650.00000.94520
resiliparse0.90540.05880.93817
jusText0.83780.47060.876074
goose30.82430.00001.00000

sixway-scores.json. Un set di fixture, un solo scorer, ogni unità marcata con un sentinel univoco così il recupero è un’esatta appartenenza per sottostringa.

System diagram: Leakage and Silence Share a Boundary

47% di leak di boilerplate e 74 token contaminanti — il doppio del tasso di leak di Readability e più del doppio della sua contaminazione in questo set sintetico etichettato. È un risultato diagnostico ai valori di default, non una classifica stabile del prodotto in assoluto.

Il leak osservato è coerente con la stessa passata sensibile al contesto coinvolta nel salto secco. I blocchi vicini neargood eleggibili possono essere promossi quando le regole di classe e distanza del contesto lo permettono; un promo o un commento con aspetto discorsivo accanto al testo dell’articolo può quindi oltrepassare il confine. Il risultato della fixture mostra quali blocchi etichettati hanno “trascinato dentro” contenuto indesiderato, mentre il meccanismo semplificato resta comunque condizionato dalle regole di contesto precise di jusText.

Il suo recall è 0.8378, terzultimo, e tutta la perdita dipende dalla soglia: non ha recuperato nulla su un singolo articolo da 129 caratteri, nulla su una pagina con dieci paragrafi brevi e nulla sul documento quasi vuoto.

L’inventario delle stoplist linguistiche

Novantanove altre stoplist.

justext.get_stoplists() restituisce 100 lingue. Il classificatore è parametrizzato per lingua per progettazione, non tramite traduzione di una heuristic in inglese, e cambiare lingua richiede un solo argomento:

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 e goose3 espongono anche comportamenti legati alla lingua, ma questa review non ha valutato nessun estrattore su ground truth non inglese. Le 100 stoplist incluse in jusText lo rendono un candidato evidente per una valutazione multilingue; l’inventario da solo non dimostra la qualità di estrazione in quelle lingue né prova che i competitor le coprano in modo meno efficace.

L’API è composta da due funzioni e nove costanti regolabili — length_low 70, length_high 200, stopwords_low 0.30, stopwords_high 0.32, max_link_density 0.20, max_heading_distance 200, più la gestione della codifica. Poche, leggibili e tutte documentate nella firma.

Installazione e velocità

pip install justext scarica 3 pacchetti — il numero più basso nel confronto — e 22,4 MiB, in meno di due secondi.

Riferimento ufficiale: jusText su PyPI.

LibraryPackagessite-packagesCold importExtraction p50
resiliparse521.0 MiB0.015 s0.06 ms
jusText322.4 MiB0.777 s0.56 ms
goose31644.3 MiB2.181 s1.85 ms
newspaper4k2247.5 MiB2.812 s2.69 ms
trafilatura1769.9 MiB1.584 s0.51 ms

install-and-import.json. Ogni libreria in un proprio virtualenv vuoto.

Tre pacchetti e 22,4 MiB sono un peso ridotto in questo confronto, e una mediana di estrazione di 0,56 ms è vicina allo 0,51 di trafilatura in questo harness. La misurazione dell’ambiente non distingue la dimensione dei pacchetti per tipo di file, quindi non può dire quanta parte dell’ingombro su disco dipenda dalle stoplist.

La questione manutenzione, affrontata con cautela

Le misure di manutenzione datate usate qui sono l’ultimo push del repository e l’ultima release su PyPI, entrambe 2025-02-25. Erano diciassette mesi prima del test. Otto release totali, 91 fork, 9 issue aperte, non archiviato.

I classifier di PyPI indicano supporto Python fino alla 3.9. Io l’ho eseguito su 3.14.2 e si è installato, importato in 0,777 s ed estratto su 19 fixture su 22 senza una sola eccezione.

Quindi i metadati sono indietro di cinque versioni Python rispetto alla realtà, e la realtà è che funziona. Questa è la distinzione utile: un repository silenzioso è un segnale sul supporto, non automaticamente sulla funzionalità. Per una libreria il cui intero algoritmo è un metodo pubblicato nel 2011 più un insieme di word list, “finito” è uno stato plausibile — c’è poco altro da cambiare, e le stoplist non si degradano come una workaround anti-bot.

Cosa significa davvero un repo silenzioso: se trovi un bug, lo risolvi tu o fai un fork. Da valutare insieme alle 9 issue aperte, che non sono il profilo di una libreria sommersa da problemi irrisolti.

Memoria e cosa ci fa l’HTML rotto

Qui sono misurate separatamente due domande operative.

Il contesto più ampio del test di stress è nel confronto su memoria e HTML malformato tra dieci librerie.

Memoria residente di picco, tramite /usr/bin/time -l, un processo fresco per ogni cella — il floor di import è il costo della libreria caricata e inattiva, i picchi includono il documento.

LibraryRuntimeImport floor226 KB peak10 MB peak
html2textpython3.1418.719.971.2
pyquerypython3.1430.333.9172.5
resiliparsepython3.1420.525.1225.1
markdownifypython3.1423.928.9278.5
goose3python3.1444.152.4398.5
cheerionode2266.876.5398.5
justextpython3.1430.336.6431.2
newspaper4kpython3.1452.661.8668.5
trafilaturapython3.1452.564.8927.1
turndownnode2247.868.42947.1

memory-results.json. I baseline di Python e Node non sono confrontabili tra loro; l’interprete è presente in entrambi.

Il floor di jusText è 30,3 MiB e il suo picco su questa fixture da 10 MB è 431,2 MiB, circa 14,2 volte il floor di import e 43,1 volte la dimensione dell’input in RSS assoluto. Una fixture e un processo non bastano per definire una curva di scaling generale; anche i baseline di Python e Node restano non confrontabili.

HTML rotto. Dodici documenti, ognuno con esattamente un difetto diverso — tag non chiusi, elementi inline annidati male, attributi non quotati con spazi, chiusure isolate, nessun <html> affatto, attributi duplicati, un documento troncato a metà tag, entità errate, uno <script> non chiuso, una dichiarazione di charset falsa, un commento che contiene markup e 600 livelli di annidamento — più due controlli ben formati di dimensioni corrispondenti, perché “non ha restituito nulla” dice qualcosa sulla malformazione solo se la libreria non tace anche su un documento pulito della stessa dimensione.

justext ha generato un’eccezione in 0 su 14 e non ha restituito nulla in 13, recuperando 0/33 sentinel valutati tra le fixture rotte (malformed-results.json). Anche il controllo breve ben formato ha restituito 0 caratteri; il controllo lungo ben formato è stato l’unico risultato non vuoto, con 1.333 caratteri. Tutte e dodici le fixture malformate sono rimaste vuote, e il caso con <script> non chiuso è escluso dal punteggio di sopravvivenza dei sentinel. Questo batch mostra quindi tolleranza del parser — nessuna eccezione — ma non consente di attribuire il silenzio alla malformazione piuttosto che alla soglia di dimensione già misurata.

Pro e contro

A favore. 100 stoplist linguistiche, e un classificatore davvero costruito attorno a esse invece che tradotto dentro di esse. Il numero più basso di dipendenze nel confronto: 3 pacchetti. Estrazione mediana da 0,56 ms. Nove costanti di tuning documentate e leggibili. BSD 2-Clause. Funziona pulitamente su Python 3.14 nonostante i classifier si fermino a 3.9.

Contro. Il più alto leak di boilerplate in questo test sintetico ai default: 47%, con 74 token contaminanti. Il test con paragrafi brevi ha restituito una stringa vuota quando nessun paragrafo ha superato length_high. Il recall era 0.8378 su questo set. L’ultimo push e l’ultima release registrati risalgono a diciassette mesi prima del test, quindi la questione della manutenzione va valutata.

Chi dovrebbe usarlo e chi no

Valuta jusText per corpus multilingue, perché la superficie delle stoplist specifiche per lingua è esplicita e ampia. Questo test ha censito 100 stoplist ma non ha misurato la qualità multilingue. È anche un candidato quando una dipendenza di tre pacchetti e controlli espliciti delle soglie si adattano al deployment.

Evitalo se stai alimentando un modello token per token, dove 74 token contaminanti contro lo zero di goose3 e newspaper4k hanno un costo diretto. Evitalo per pagine con paragrafi brevi — descrizioni di prodotto, listing, changelog, voci FAQ — a meno che tu non abbia impostato length_high in modo deliberato. Ed evitalo se ti serve una dipendenza attivamente mantenuta per ragioni di compliance o procurement, che è un vincolo reale anche quando il codice funziona.

Se decidi di usarlo, calibra length_high su un campione di validazione etichettato invece di copiare il default o una regola percentile. Prova soglie plausibili e misura sia il recall dell’articolo sia la precisione sul boilerplate; abbassare il limite può recuperare prosa breve ma anche promuovere blocchi vicini indesiderati.

Dove si inserisce un’API gestita

jusText prende HTML che hai già, come tutto il resto di questo confronto. Nessuna di queste librerie recupera una pagina, rende JavaScript o gestisce un layer anti-bot.

Per le stesse fixture su tutti e sei gli estrattori, vedi il confronto di estrazione tra sei librerie.

Un servizio hosted di fetch/render/extraction, incluso il nostro Thunderbit, copre un confine di responsabilità diverso. Thunderbit non è stato benchmarkato qui. La distinzione è tra classificazione del testo HTML fornito e un servizio che acquisisce e processa un URL; questo articolo non offre un confronto di qualità misurato con le stesse metriche.

La lettura corretta è questa: le stoplist multilingue di jusText sono una capacità reale e gratuita. Se il tuo problema è recuperare pagine in molte lingue anziché classificare la prosa al loro interno, stai comprando qualcosa di diverso.

Per il panorama più ampio, il nostro roundup delle web scraping API copre le opzioni hosted e il pillar sugli scraper open source copre quelle self-hosted. Se l’output è destinato a un modello, convertire HTML in Markdown in Python è il punto in cui si perde gran parte della fedeltà.

Prova Thunderbit per l’estrazione di dati dal Web

Dovresti usare jusText?

È un candidato se il corpus è multilingue o se la distribuzione delle lunghezze dei paragrafi beneficia di una regolazione esplicita delle soglie. Verifica entrambe le proprietà prima del deploy.

Le 100 stoplist incluse sono una caratteristica di design reale, ma l’accuratezza multilingue non è stata testata. Il salto netto della soglia è regolabile; se un valore più basso sia accettabile dipende dal recall e dalla precisione sul boilerplate misurati su un campione etichettato.

Su questo set sintetico inglese ai valori predefiniti, newspaper4k non ha disperso alcuna unità di boilerplate etichettata e ha recuperato 0.9865 delle unità di articolo. Questo lo rende un candidato di confronto per questo carico di lavoro, non una raccomandazione di sostituzione universale.

Prova Thunderbit per l’estrazione di dati dal Web Get Started Free

FAQ

Perché jusText restituisce una stringa vuota invece di un’estrazione parziale? Il suo classificatore ha due passaggi. Un paragrafo ottiene la classe good da solo solo sopra length_high (200 caratteri di default); la seconda passata poi promuove i blocchi vicini neargood. Se nessun paragrafo supera la soglia non c’è nessun seme, quindi ogni candidato degrada a boilerplate e il risultato è vuoto. È tutto-o-nulla per costruzione, non un fallimento nel trovare una risposta parziale.

jusText è abbandonato? L’ultimo push del repository e l’ultima release su PyPI sono entrambi del 2025-02-25 — diciassette mesi prima del test — e i classifier di PyPI si fermano a Python 3.9. Ma si è installato ed eseguito su Python 3.14.2 senza eccezioni, e 9 issue aperte non sono un backlog enorme. Leggi le date come un rischio di manutenzione, non come prova di comportamento rotto; il rischio pratico è che potresti dover correggere i tuoi bug da solo.

Perché perde più boilerplate di Readability? Su questo set di fixture, blocchi vicini dall’aspetto discorsivo hanno oltrepassato il confine di output secondo le regole di contesto predefinite. La promozione dipende da classe del blocco, distanza e contesto, non è automatica per ogni vicino. Il risultato misurato è stato un leak del 47% di unità di boilerplate e 74 token contaminanti ai valori di default.

Come lo uso per un’altra lingua? justext.justext(html, justext.get_stoplist("German")). get_stoplists() restituisce tutte le 100 disponibili. La stoplist è l’input lessicale specifico per lingua di un classificatore che usa anche lunghezza del paragrafo, densità dei link, segmentazione derivata dall’HTML, distanza dagli heading e contesto dei blocchi vicini. Questo cambia l’input linguistico; non valida da solo la qualità dell’estrazione in tedesco.

Cosa non è stato testato qui? Pagine reali, in assoluto — queste sono fixture controllate con unità etichettate. La capacità multilingue, che è il principale punto di forza della libreria, è stata censita a 100 stoplist ma non valutata su testo non inglese. I casi limite di codifica, nonostante jusText esponga i parametri encoding, default_encoding e enc_errors. E max_heading_distance e le due soglie sul rapporto di stopword sono rimasti sempre ai default.

Ke
Ke
CTO di Thunderbit | Senior Data Scientist ed esperto di ML Con quasi un decennio di esperienza nel machine learning e nella data science, Ke Shen è un ex studente della Columbia University ed ex Senior Data Scientist presso Walmart Labs. Grazie a una profonda competenza, riconosciuta dai suoi pari, in Python, R, Java e statistica, condivide insight collaudati sul passaggio di algoritmi AI complessi dalla teoria a un'architettura pronta per la produzione.
Indice
Thunderbit · Agente AI per dati web

Estrai dati da qualsiasi pagina in 1 clic

Scelto da oltre 250.000 utenti
piano gratuito disponibile
Dalla pagina web al foglio di calcolo
Descrivi ciò che ti serve — l'agente AI di Thunderbit lo estrae ed esporta in Excel, Google Sheets, Airtable o Notion. Puoi iniziare gratis.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week