goose3 gaf geen gelabelde boilerplate terug. Twee keer kwam er zelfs helemaal niets uit.

Laatst bijgewerkt op August 17, 2026
goose3 gaf geen gelabelde boilerplate terug. Twee keer kwam er zelfs helemaal niets uit.
AI-samenvatting
In de tests waar een lek überhaupt meetbaar is, haalde goose3 1.0000 content-token precisie en nul verontreinigende tokens. Geen enkel woord uit navigatie, advertenties, sidebar, reacties of promo belandde in de output. Geen enkele andere tool in een vergelijking met zes bibliotheken deed dat evenaren. Tegelijkertijd heeft het de laagste article recall in de set — 0.8243 over alle 22 fixtures, tegenover 1.0000 voor Mozilla Readability — omdat het op twee daarvan een lege string teruggaf. Die cijfers hangen samen door de scoringsmethode: een leeg resultaat draagt niets bij aan conditionele precisie, terwijl recall de gemiste match vastlegt.

In de tests waar überhaupt een lek meetbaar was, haalde goose3 1.0000 content-token precisie en nul vervuilende tokens. Geen enkel woord uit navigatie, advertenties, de sidebar, reacties of promo belandde in de output. Geen enkele andere tool in een vergelijking met zes bibliotheken deed dat even goed.

Tegelijkertijd heeft het de laagste article recall in de set — 0.8243 over alle 22 fixtures, tegenover 1.0000 voor Mozilla Readability — omdat het op twee daarvan een lege string teruggaf.

Die cijfers hangen samen door de scoringsmethode: een leeg resultaat draagt niets bij aan conditionele precisie, terwijl recall de gemiste match vastlegt.

Wat goose3 is

goose3 is de Python 3-voortzetting van een lijn die begint bij Gravity Labs' Goose in Scala en verderloopt via python-goose. Het is een artikel-extractor met metadata, geen simpele tekst-dumper: je maakt een Goose-object aan, roept extract() aan, en krijgt een Article-object terug met ongeveer achtentwintig toegankelijke velden — opgeschoonde tekst, titel, auteurs, publicatiedatum, hoofdafbeelding, meta description, tags, links, tweets en meer.

Officiële referentie: de officiële repository van goose3.

System diagram: From HTML to Article Fields

Geteste versie: 3.1.22, Apache-licensed, 912 GitHub-sterren, laatste push op 2026-07-23 — op het moment van testen actief onderhouden. Python 3.14.2.

De API bestaat uit twee aanroepen en één verplichting:

from goose3 import Goose
g = Goose()
try:
    article = g.extract(raw_html=html)
    text = article.cleaned_text
finally:
    g.close()          # sluit expliciet af na gebruik

Die close() is het benoemen waard, omdat je het makkelijk vergeet en er geen waarschuwing voor komt. In deze review is geen loop-test uitgevoerd om te meten hoeveel sessies, verbindingen of geheugen achterblijven als sluiten wordt overgeslagen, dus “resource leak” zou sterker zijn dan het bewijs. Zie expliciet sluiten als de lifecycle-eis die uit het API-gebruik hier volgt.

De afweging, gemeten

Zes extractors, één geannoteerde fixture-set, één scorer. Elk blok van elke fixture is gelabeld als article of boilerplate en heeft een unieke sentinel-token, dus “heeft het deze eenheid teruggevonden” is exacte substring-lidmaatschap in plaats van een gelijkenisscore.

BibliotheekArticle recall (alle 22)Boilerplate-lekContent-token precisieVerontreinigende tokensGeproduceerde output
Readability1.00000.23530.91093522/22
trafilatura0.98650.05880.9411422/22
newspaper4k0.98650.00000.9452022/22
resiliparse0.90540.05880.9381722/22
jusText0.83780.47060.87607419/22
goose30.82430.00001.0000020/22

sixway-scores.json. Recall geldt over alle 22 fixtures; leak rate en precisie over de 11 die zowel article- als boilerplate-units bevatten.

Lees de precisiekolom altijd samen met de laatste kolom. Precisie is hier conditioneel op output — een bibliotheek die een lege string teruggeeft op een fixture draagt niets bij aan teller of noemer, dus niets teruggeven is in dit gemiddelde gratis. De teller is de multiset-overlap tussen geëxtraheerde niet-stopwoord-tokens en gelabelde article-tokens; de noemer is elk geëxtraheerd niet-stopwoord-token. “Vervuilende tokens” is nauwer: overlap alleen met de gelabelde boilerplate-tokens. Een extra geëxtraheerd token dat noch met article noch met boilerplate overeenkomt, verlaagt precisie zonder die contaminatie-telling te verhogen; herhaalde tokens buiten de article-multiset kunnen hetzelfde effect hebben. Daarom kan newspaper4k 0 vervuilende tokens tonen en toch onder 1.0000 precisie zitten. goose3’s 1.0000 werd gescoord op 10 van de 11 fixtures; Readability, trafilatura, newspaper4k en resiliparse werden op 11 van 11 gescoord.

Binnen deze synthetische set blijft 1.0000 waardevol. Over de tien gescoorde fixtures liet goose3 geen enkele gelabelde boilerplate-token zien; Readability liet er op dezelfde pagina’s 35 doorheen glippen. Als een model de output gebruikt, betekent dit in die tien fixtures geen token-uitgave aan boilerplate-labels. Het bewijst geen nulverspilling op echte pagina’s, en een leeg resultaat kan elders in de pipeline fallback- of retry-kosten veroorzaken.

De twee stiltes, en wat ze betekenen

goose3 gaf op precies twee fixtures niets terug. Eén daarvan is verdedigbaar en één is een echte beperking.

Het bijna lege document. Een pagina met één artikel-eenheid van 32 tekens. goose3 weigert. jusText ook. In deze fixture-set produceerde Readability op alle 22 pagina’s output, dus die uitkomst ondersteunt goose3’s stilte hier niet. Of het weigeren van dit piepkleine document acceptabel is, hangt af van de minimum-inhoudsafspraak van de aanroepende code.

System diagram: Treat Empty Output as Failure

Het artikel dat volledig uit <li>-elementen bestaat. Zes article-units, geen daarvan in een <p>-tag. goose3 geeft een lege string terug.

Dat tweede verraste me, omdat goose3’s eigen standaardconfiguratie parse_lists=True leest. Dus testte ik dat — drie configuraties tegen een werkende controle, want één onproductieve run is nog geen uitspraak over een bibliotheek:

ConfiguratiePagina met alleen lijsten<p>-controle
defaults0 tekens937 tekens
strict=False0 tekens937 tekens
parse_lists=True (expliciet)0 tekens937 tekens

list-only-probe.json.

In alle drie nul, terwijl de controle in alle drie 937 tekens teruggeeft. Dus parse_lists=True bepaalt of lijsten binnen een artikel dat goose3 al heeft gevonden behouden blijven — het maakt niet dat de scoringslogica een lijst als artikel herkent. goose3’s nodescoring heeft blokken in paragraafvorm nodig om de body überhaupt te vinden, en een pagina waarvan de body een lijst is, heeft die niet.

De ondersteunde conclusie is smaller: een body zoals deze synthetische fixture — zes article-units, allemaal <li>, zonder paragraaf-kandidaat — leverde een lege string op. Changelogs, API-referenties, recepten, FAQ-pagina’s en vergelijkingsartikelen zijn logische risico-samples voor een echte herhaling, omdat ze veel lijsten kunnen bevatten, maar deze ene fixture bewijst niet dat die paginacategorieën in het algemeen falen.

De lege string is alleen machine-detecteerbaar als de aanroeper niet-lege output controleert. Dat is makkelijker af te schermen dan geloofwaardig ogende tekst zonder enige article-inhoud, maar het blijft een stille mislukking in monitoring die alleen op exceptions let. In productie heb je een minimum-outputcheck en een fallback of expliciete mislukte-paginaregistratie nodig.

Praktijk van de installatie

pip install goose3 haalt 16 pakketten en 44.3 MiB binnen in ongeveer 6 tot 9 seconden. Koude import gemeten in een nieuwe subprocess: 2.181 s.

Officiële referentie: goose3 op PyPI.

BibliotheekPakkettensite-packagesKoude importExtractie 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. Elke bibliotheek in een eigen lege virtualenv, dus niets wordt geërfd van een buurpakket.

Middenmoot qua gewicht, middenmoot qua snelheid. Het installeerde en importeerde schoon op Python 3.14.2, wat in deze categorie niet vanzelfsprekend is.

Drie defaults die je moet kennen vóór je gaat uitrollen

System diagram: Three defaults worth knowing before you deploy

Als je het meegeleverde Configuration-object leest in plaats van de docs, kom je negentien instellingen tegen. Drie daarvan verrassen waarschijnlijk iemand.

Het meldt zichzelf. browser_user_agent staat standaard op Goose/3.1.22. Als je goose3 zelf laat ophalen, logt elke server die je raakt de bibliotheeknaam en exacte versie. Dat is eerlijk, maar ook een fingerprint. Stel dit bewust in, of haal de HTML zelf op en geef raw_html door.

Het wijst naar een MacPorts-binary. imagemagick_convert_path staat standaard op /opt/local/bin/convert en imagemagick_identify_path op /opt/local/bin/identify. Op mijn machine bestaat geen van beide — /opt/local is MacPorts, iets wat de meeste mensen niet hebben; Homebrew zet binaries in /opt/homebrew. De default doet niets zolang je image fetching niet aanzet (enable_image_fetching staat logisch genoeg op False), maar als je dat wel doet in de verwachting dat top-image-extractie werkt, dan werkt het hier stilletjes niet.

Het gaat uit van Engels. target_language staat standaard op en met use_meta_language=True, dus het volgt de taalverklaring van de pagina zelf wanneer die er is en valt anders terug op Engels. Prima voor Engelstalig werk, maar voor andere talen verstandig om expliciet in te stellen.

De rest is redelijk: parser_class is lxml, http_timeout 30 seconden, strict aan, log_level ERROR, parse_headers en keep_footnotes aan, images_min_bytes 4.000.

Geheugen, en wat kapotte HTML daarmee doet

Twee dingen die in elke review in deze batch als niet-getest stonden, zijn nu gemeten.

De bredere stresstestcontext staat in de vergelijking van tien bibliotheken voor geheugen en foutieve HTML.

Piek resident memory, via /usr/bin/time -l, één verse procesrun per cel — de importvloer is wat de bibliotheek kost geladen en in rust, de pieken bevatten het document.

BibliotheekRuntimeImportvloer226 KB piek10 MB piek
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. Python- en Node-baselines zijn onderling niet vergelijkbaar; de interpreter zit in beide inbegrepen.

goose3’s vloer is 44.1 MiB en het piekt op 398.5 MiB bij een document van 10 MB. De importvloer is de derde hoogste van de getoonde Python-bibliotheken, iets om rekening mee te houden bij een cold-start-gevoelige uitrol.

Kapotte HTML. Twaalf documenten die elk precies één ding breken — niet-gesloten tags, verkeerd geneste inline-elementen, niet-geciteerde attributen met spaties, losse sluiters, geen <html> helemaal, dubbele attributen, een document afgekapt midden in een tag, slechte entiteiten, een niet-gesloten <script>, een onjuiste charset-declaratie, een commentaar met markup en 600 niveaus nesting — plus twee goed gevormde controles van dezelfde grootte, omdat “het gaf niets terug” alleen iets zegt over malformedness als de bibliotheek ook op een schoon document van dezelfde omvang niet stil blijft.

goose3 gaf op 0 van 14 een exception en op 10 niets terug, en herstelde 2/33 sentinel-tokens over de kapotte fixtures (malformed-results.json). Eén fixture telt niet mee in die score: volgens HTML5 is alles na een niet-gesloten <script> scriptinhoud, dus dat daar verliezen is correct en het terughalen daarvan is de afwijking.

Voor- en nadelen

Pluspunten. Nul gelabelde boilerplate-tokens over de tien content-fidelity-fixtures waarin het output produceerde. Ongeveer achtentwintig article-velden zijn beschikbaar, al is de nauwkeurigheid daarvan geïnventariseerd en niet gescoord. Verstandige default voor image fetching (uit). Schoon geïnstalleerd op Python 3.14. Actief onderhouden. Apache-2.0. Een leeg resultaat is eenvoudig af te vangen als de aanroeper dat expliciet controleert.

Minpunten. De laagste article recall in de set: 0.8243, volledig veroorzaakt door helemaal niets terug te geven en niet door het verkeerde terug te geven. Een pagina waarvan het artikel een lijst is, levert ongeacht de configuratie een lege string op. 44.3 MiB en een koude import van 2,2 seconden zijn zwaar naast resiliparse’s 21.0 MiB en 15 ms. Vereist close(). Twee defaults verwijzen naar dingen die op de meeste machines niet kloppen.

Wie het wel en niet zou moeten gebruiken

Gebruik goose3 als kandidaat wanneer geëxtraheerde tekst in een model of database terechtkomt waar gelabelde boilerplate duur is en de pagina’s gewone artikelen met paragrafen zijn. In deze fixture-set produceerde het geen gelabelde boilerplate-tokens wanneer het antwoord gaf. Het metadata-oppervlak is beschikbaar maar hier niet gevalideerd; titel, auteur, datum en afbeelding vragen aparte ground-truth fixtures voordat ze een selectievoordeel worden.

Sla het over als je corpus veel lijsten bevat — dan krijg je lege strings zonder uitleg. Sla het over als cold-start-kosten belangrijk zijn, want resiliparse importeert 145× sneller. En sla het over als je op elke pagina een antwoord nodig hebt, want “geen antwoord” is hier een reële uitkomst: twee van de 22 fixtures, en beide stil, in de zin dat een lege string geen exception is.

Een combinatie die het testen waard is: goose3 als primaire extractor met een fallback wanneer cleaned_text leeg is of onder je minimum-inhoudsregel valt. Readability herstelde elke article-eenheid in deze set van 22 fixtures, inclusief beide lege gevallen van goose3. Dat synthetische resultaat ondersteunt het architectuurpatroon, niet de belofte dat de fallback op echte pagina’s nooit mist.

Waar een managed API past

Deze benchmark testte goose3’s raw_html-extractieroute: de HTML was al opgehaald voordat goose3 hem zag. goose3 heeft ook een eigen netwerk-fetch-pad, zoals de User-Agent-instelling laat zien, maar dat pad is hier niet getest. JavaScript-rendering en anti-botgedrag zijn evenmin getest.

Voor dezelfde fixtures over alle zes extractors, zie de vergelijking van zes extractiebibliotheken.

Een beheerde fetch/render/extract-service, inclusief onze eigen Thunderbit, dekt een andere verantwoordelijkheidsgrens. Thunderbit is in deze test niet gebenchmarkt. Het relevante onderscheid is aangeleverde HTML-artikel-extractie versus een hosted service die een URL ophaalt en verwerkt; dit artikel biedt geen vergelijking op dezelfde metrics voor snelheid of kwaliteit.

De eerlijke vergelijking: goose3 heeft een vaste, artikelvormige field-set, precies goed als je pagina’s artikelen zijn en fout als het productlijsten zijn. Als je de HTML al hebt en je pagina’s zijn artikelen, dan is goose3 gratis en erg schoon.

Voor de hosted kant is onze round-up van web scraping API’s het bredere beeld; voor self-hosted alternatieven is er de open-source scraper-pagina. Als de tekst bedoeld is voor een model, laat HTML naar Markdown converteren in Python zien waar de fidelity echt verloren gaat.

Probeer Thunderbit voor webdata-extractie

Moet je goose3 gebruiken?

Ja, als artikelen in paragraafvorm overeenkomen met je workload en de aanroeper lege output als mislukte extractie behandelt, niet als succes.

In deze fixture-set gaf goose3 geen gelabelde boilerplate-tokens terug wanneer het antwoord gaf, en het leverde twee lege strings op. Eén was een bijna lege pagina en één was de synthetische body met alleen lijsten. Dat is een afruil tussen precisie en dekking, geen bewijs van een brede productkaraktereigenschap.

Als recall belangrijker is, test dan een fallback met een expliciete minimum-outputbewaking. Readability herstelde in deze 22 fixtures elke article-eenheid; newspaper4k liet nul gelabelde boilerplate-leak zien en 0.9865 recall, terwijl het op alle 22 pagina’s output produceerde. Die resultaten plaatsen deze synthetische set op defaults, niet op onbekende productiebelastingen.

goose3 verdient zijn plek wanneer de prijs van één fout woord hoger is dan de prijs van een ontbrekende pagina.

Probeer Thunderbit voor webdata-extractie Get Started Free

Veelgestelde vragen

Is goose3’s perfecte precisie echt, of een artefact van weigeren? Beide, en die twee zijn uit elkaar te trekken. Het werd gescoord op 10 van de 11 fixtures met boilerplate, dus één fixture ontbreekt in het gemiddelde — dat deel is een artefact van weigeren. Maar op die tien gaf het nul vervuilende tokens terug tegenover bewust vijandige boilerplate, terwijl Readability er 35 liet lekken. De precisie is echt voor pagina’s waarop het antwoord geeft; de recall-kolom laat zien waar weigeren zichtbaar wordt.

Waarom geeft goose3 niets terug op een pagina waarvan het artikel een lijst is? De kandidaat-scoring heeft paragrafenachtige blokken nodig om de artikelbody te lokaliseren, en een pagina die uit <li>-elementen is opgebouwd, heeft die niet. De standaard parse_lists=True verandert dat niet — ik heb het expliciet geprobeerd, samen met strict=False, en kreeg in alle drie configuraties nul tekens, terwijl een controle op basis van <p> in alle drie 937 tekens teruggaf. parse_lists bepaalt alleen of lijsten behouden blijven binnen een artikel dat al gevonden is.

Moet ik close() aanroepen? Sluit het expliciet af met try/finally, zoals hierboven getoond. Deze review heeft niet gemeten wat zich opbouwt als je sluiten overslaat, dus claimt geen gekwantificeerde loop-leak; wel staat vast dat Goose een lifecycle heeft die de aanroeper moet beheren.

Welke User-Agent stuurt goose3? Standaard Goose/3.1.22 — de bibliotheeknaam en exacte versie. Dat geldt alleen als je het laat ophalen; met raw_html omzeil je dit volledig. Als je het wel laat ophalen, stel de User-Agent dan bewust in; de default vertelt elke server precies wat er op bezoek is.

Wat heeft deze review niet getest? Echte webpagina’s, helemaal niet — dit zijn gecontroleerde fixtures. Meertalige extractie, ondanks dat target_language een eersteklas instelling is. De metadata-velden (titel, auteurs, datum, hoofdafbeelding) zijn geïnventariseerd maar niet op nauwkeurigheid gescoord. Image fetching, dat standaard uit staat en waarvan de ImageMagick-paden verwijzen naar een pakketbeheerder die de meeste machines niet hebben. Gelijktijdig of langdurig geheugengedrag, plus throughput onder belasting; de geheugentabel mat één verse procesrun die één document verwerkt.

Ke
Ke
CTO bij Thunderbit | Senior Data Scientist & ML-expert Met bijna tien jaar ervaring in machine learning en data science is Ke Shen alumnus van Columbia University en voormalig Senior Data Scientist bij Walmart Labs. Met diepgaande, door vakgenoten erkende expertise in Python, R, Java en statistiek deelt hij praktijkgerichte inzichten over hoe je complexe AI-algoritmen van theorie naar productieklare architectuur brengt.
Inhoudsopgave
Thunderbit · AI-webdata-agent

Gegevens extraheren van elke pagina in 1 klik

Vertrouwd door meer dan 250.000 gebruikers
gratis abonnement beschikbaar
Van webpagina naar spreadsheet
Beschrijf wat je nodig hebt — Thunderbit's AI Agent scrapt het en exporteert het naar Excel, Google Sheets, Airtable of Notion. Gratis om te starten.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week