BeautifulSoup i 2026: Den mest brukervennlige HTML-parseren er også den tregeste (med 12–17x)

Sist oppdatert July 17, 2026
BeautifulSoup i 2026: Den mest brukervennlige HTML-parseren er også den tregeste (med 12–17x)
AI-sammendrag
Denne gjennomgangen måler BeautifulSoup som den mest tilgjengelige HTML-parseren for Python, og setter en presis kostnad på den brukervennligheten. Den sammenligner bs4 med C-baserte parserne på hastighet, toleranse for feilformatert HTML, dekning av CSS-selektorer, objektbevaring og gjenoppretting av koding. Artikkelen viser at BeautifulSoup er dramatisk tregere, ofte med 12 til 17 ganger, men forklarer også hvorfor utviklere likevel velger den: lesbar API, tilgivende parsing, sterk støtte for soupsieve-selektorer og svært god ergonomi for rotete, små og tilfeldige scraping-oppgaver. Det er en praktisk guide til når hastighetsavgiften er akseptabel, og når en raskere parser er det bedre tekniske valget.

BeautifulSoup er biblioteket nesten alle tyr til første gang de skal skrape en nettside i Python, og det er faktisk det tregeste av de seriøse HTML-parserne. Begge deler stemmer, og ingen av delene er en kritikk. Det interessante er at «tregest» viser seg å være et presist tall du kan forholde deg til, ikke bare en vag følelse.

Jeg kjørte bs4 (altså beautifulsoup4, versjon 4.15.0, publisert i juni 2026, med MIT-lisens) gjennom en blanding av ferske funksjonstester og gjenbrukt tidsmåling fra samme benchmark-oppsett, og bildet er tydelig: du bytter bort rundt en hel størrelsesorden i hastighet mot den mest brukervennlige API-en og den sterkeste feiltoleransen i feltet. Om det er et smart bytte avhenger helt av arbeidslasten din, så denne gjennomgangen holder begge sider av saken på bordet.

Hva BeautifulSoup faktisk er – og ikke er

De fleste guider hopper over det viktigste: BeautifulSoup parser ikke HTML. Det er et omslag. Under panseret sender den dokumentet ditt videre til en av tre ekte parser-motorer – Python sin innebygde html.parser, lxml, eller html5lib – og pakker deretter treet de lager inn i én samlet, svært brukervennlig navigasjons- og søke-API. Jobben til bs4 er ikke å parse. Den er å gjøre resultatet behagelig å jobbe med.

Opphavspersonen omtaler den selv som et «screen-scraping library», og salgsargumentet har alltid vært det samme: pek den mot HTML som er så rotete at en nettleser ville rynket på nesen, og den skal fortsatt klare å hente ut dataene du ba om. Det ryktet er fortjent, med ett forbehold som vi kommer tilbake til.

Noen fakta er verdt å slå fast med en gang:

FeltVerdi
Pakkebeautifulsoup4 (importeres som bs4)
Testet versjon4.15.0 (lastet opp 2026-06-07)
Python-krav>=3.7.0
LisensMIT
Offisiell hjemmesidecrummy.com/software/BeautifulSoup
Kilde + feilregisterLaunchpadikke GitHub
VedlikeholdAktivt (4.15.0 i juni 2026, seks utgivelser siste året)

Linjen «ikke GitHub» betyr mer enn den ser ut til. bs4 er et 20 år gammelt bibliotek som lever på crummy.com og Launchpad, så den vanlige GitHub-baserte «helse-sjekken» passer ikke. Vurder helsen ut fra hvor ofte det kommer nye utgivelser, og der ser det bra ut.

Et lite, men viktig lisenspoeng for deg som må svare til et compliance-team: omslaget er MIT-lisensiert, men hva «å bruke bs4» faktisk drar inn i avhengighetstreet ditt avhenger av hvilken backend du installerer. html.parser er en del av standardbiblioteket i Python (PSF-lisens, ingen ekstra avhengigheter). lxml er BSD-lisensiert, men bygger på libxml2/libxslt – en ekstern C-avhengighet du enten kompilerer selv eller henter som ferdig wheel. html5lib er ren Python og MIT. Hvis du vil ha det reneste avhengighetsfotavtrykket, gir den innebygde html.parser deg det – som tilfeldigvis også er backend-en med den største fellen. Mer om det straks.

Hastighetsavgiften, satt på tall

La oss ta tallet først, for det er hovedpoenget, og det ville vært uredelig å gjemme det bort. På en realistisk oppgave der du parser og så henter ut data – parser strengen, trekk ut alle <h3 class="title"> og alle <a href> – er BeautifulSoup den tregeste parseren i denne sammenligningen, og det er ikke i nærheten.

BeautifulSoup speed tax: 232 ms versus 15 ms C parsers

Disse målingene er gjenbrukt fra selectolax-benchmarkoppsettet (samme maskin, samme 3-kjøringsmetodikk, per 2026-07-13); denne gjennomgangen kjører ikke egne tidsbenchmarks på nytt, for å unngå CPU-konkurranse og dobbeltarbeid. Median p50-latens, i millisekunder:

Sidestørrelsebs4 (html.parser)bs4 (lxml)selectolax-Lexborlxmlbs4-hp tregerebs4-lxml tregere
1 KB0.3230.2810.0270.03612.0x10.5x
10 KB2.0491.7050.1600.16612.8x10.7x
100 KB20.59916.5401.4641.42314.1x11.3x
1 MB232.558181.85514.90114.17715.6x12.2x
10 MB2788.7462261.557159.935172.93317.4x14.1x

bs4(html.parser) kjører altså rundt 12–17x tregere enn en C-basert parser som selectolax-Lexbor, og selv med lxml som backend ender du fortsatt på 10.5–14x tregere – altså fremdeles et helt størrelsesordenssprang bak. Grunnen er strukturell, ikke en bug: uansett hvilken backend som parser, bygger bs4 et komplett Python-objekt (Tag eller NavigableString) for hver eneste node. Det er en objektisering C-parserne slipper.

Legg merke til at multiplikatoren øker med sidestørrelsen – 12.0x ved 1 KB, 17.4x ved 10 MB. Det forteller deg at dette ikke er en fast oppstartsavgift du kan «spise opp» over tid. Det er en per-node-avgift som vokser lineært med antallet noder du bygger.

Og så kommer nyanseringen, for «10x tregere» høres skumlere ut enn det ofte er. På en side på 1 MB er det 232 ms mot 15 ms. Hvis jobben din er «skrap noen hundre til noen få tusen sider på noen hundre KB hver», er den absolutte forskjellen praktisk talt usynlig – du merker den ikke, og å optimalisere den bort gir deg ingenting. Hvis jobben din er en pipeline på én million sider, er det samme forholdet forskjellen mellom en jobb som blir ferdig og en som ikke gjør det. Samme tall, motsatt dom. Vurder det opp mot faktisk volum, ikke opp mot benchmarken.

Nei, å bytte backend løser det ikke

Det finnes en seiglivet myte om at du kan gi bs4 lxml som backend og få lxml-fart. Det kan du ikke, og det er verdt å forstå hvorfor. På en CSS-spørring over 100 000 noder (velg alle <a> og les href, med treet allerede bygget) er gjennomstrømmingen tydelig forskjellig:

ParserQuery p50Noder/sek
lxml33.30 ms3,002,646
selectolax-Modest34.19 ms2,924,550
selectolax-Lexbor39.46 ms2,534,027
bs4 (lxml)250.56 ms399,111

bs4(lxml) klarer omtrent 399 000 noder i sekundet – rundt 6.3–7.5x tregere enn de tre C-motorene, selv om backend-en dens faktisk er lxml. Backend-en akselererer byggingen av treet. Spørring og traversering går fortsatt via soupsieve inn i bs4 sine Tag-objekter, og hver matchet node blir fortsatt pakket inn i Python. Så mentalmodellen «gi bs4 lxml, og den blir lxml-rask» er feil: backend-en gjør én fase raskere, og den tregeste fasen er ikke den fasen.

Minnebruk og kaldstart setter prislappen helt tydelig. På et dokument på 10 MB bruker bs4 omtrent 1.5–1.75x så mye resident minne som selectolax eller lxml (218–226 MB mot 129–145 MB) – samme rotårsak, ett Python-objekt per node. Og import av bs4 tar rundt 33.4 ms mot 14.1 ms for lxml.html, så det er 2.36x tregere å importere. Det siste er i praksis småpenger i et langtlevende program, men for et CLI-verktøy eller en serverless-funksjon som kaldstarter hele tiden, er det en liten, reell kostnad det er greit å kjenne til.

Hvorfor flere tråder ikke redder deg

Hvis instinktet ditt ved en treg, CPU-bindende oppgave er «kast tråder på den», vil bs4 straffe det instinktet. På en side på 1 MB som parses 48 ganger, én tråd mot fire tråder:

Parser1 tråd4 tråderHastighetsøkning
selectolax-Lexbor0.563 s0.159 s3.54x
lxml0.459 s0.378 s1.21x
bs4 (lxml)6.945 s26.842 s0.26x

Les nederste rad to ganger. Fire tråder gjorde bs4 omtrent 3.9x tregere, ikke raskere. Det empirien peker mot er «holder sannsynligvis GIL»: bs4 sin trebygging er ren Python, så den serialiseres under Global Interpreter Lock, og flere tråder legger bare til planleggings-overhead på en jobb som uansett ikke kan kjøre parallelt. selectolax får sin ~3.5x oppskalering fordi C-kjernen slipper låsen; bs4 har ikke den muligheten.

For free-threading-epoken er det praktiske rådet dette: Hvis du må parallellisere BeautifulSoup, bruk multiprosessering (ProcessPoolExecutor), ikke tråder. selectolax og lxml kan skalere med tråder; bs4 kan ikke. Ett forbehold om metodisk strenghet: Dette er én observasjon ved én trådinnstilling (4) på én sidestørrelse (1 MB), og mekanismen «holder GIL» er en hypotese utledet fra klokketid, ikke noe jeg bekreftet ved å instrumentere nøyaktig hvilken kodevei som holder låsen. Retningen er klar; den eksakte mekanismen er foreløpig.

Standard-backend er fella. Les dette først.

Hvis du tar med deg én ting fra denne gjennomgangen, så ta med dette. En vanlig BeautifulSoup(html) uten andre argument bruker html.parser, og html.parser implementerer ikke HTML5s regler for valgfrie slutt-tagger. Det høres akademisk ut helt til det stille korrumperer dataene dine.

BeautifulSoup backend tolerance matrix: html.parser 12/15, lxml and html5lib 15/15

Jeg kjørte 15 bevisst feilformatert HTML-prøver gjennom alle tre backendene, med en backend-agnostisk strukturell forventning forhåndsregistrert for hver test før kjøring (så ingen kan velge vinneren i etterkant). Resultatene:

BackendOppfyller forventning / 15
lxml15
html5lib15
html.parser12

De tre feilene har samme rotårsak. Ta en uavsluttet tabell: <table><tr><td>a<td>b<tr><td>c<td>d</table>. Med html.parser blir den uttrukne celleteksten ['abcd','bcd','cd','d'] – hver <td> svelger alt som kommer etter, fordi parseren nestede cellene i stedet for å lukke dem. lxml og html5lib gir riktig ['a','b','c','d']. Bare listeelementer oppfører seg på samme måte: <li>a<li>b<li>c gir den nestede varianten ['abc','bc','c'] under html.parser, og den rene ['a','b','c'] under de to andre. Dupliserte attributter snur også: <div id="first" id="second"> beholder "second" under html.parser, men "first" under lxml/html5lib, og HTML5-spesifikasjonen sier at første skal beholdes.

Her er hvorfor dette er farlig, ikke bare irriterende: det skjer uten at det kastes en feil. En scraper som bare gjør BeautifulSoup(html) og møter en uavsluttet tabell eller liste – noe som er deprimerende vanlig på gamle nettsteder, håndskrevet HTML og maler som har glemt en avsluttende tagg – vil blande sammen nabotekst i ett felt, levere skitne data og aldri klage. Fiksen er ett argument: BeautifulSoup(html, "lxml") eller BeautifulSoup(html, "html5lib").

For å være rettferdig mot html.parser: de andre 12 av 15 feilformatert-prøvene kom ut identisk på alle tre backendene – feil nestede tagger som <b><i></b></i>, manglende html/body-skjelett, ukvoterte attributter, foreldreløse slutt-tagger, uavsluttede kommentarer, nestede skjemaer, blandet bokstavstørrelse og mer. Bs4 sin toleranse er virkelig sterk gjennomgående; avvikene er nesten helt konsentrert rundt familien av valgfrie slutt-tagger. Og dette er ikke noen ny oppdagelse – bs4 sin egen dokumentasjon om «Differences between parsers» sier allerede at html.parser er «less lenient» med enkle ord. Det denne testen tilfører, er konkrete og gjentakbare tilfeller der «mindre tolerant» blir til feil output.

Det du ikke gir opp: API-et og CSS-støtten er den beste delen

Så bs4 er treg, single-threaded, og har en felle i standard-backend. Folk bruker den fortsatt, fordi den «vennlige» delen av kompromisset er helt reell – og det holder i test.

BeautifulSoup soupsieve CSS coverage wins with 41/41 plus 20/20

Jeg kjørte 29 API-prober som dekket søk, CSS, tre-navigasjon, tekstuttrekk og DOM-modifikasjon. Alle 29 besto, og for hver probe ble resultatet beregnet ved å sammenligne faktisk returverdi mot en forventet verdi, ikke bare ved subjektiv vurdering. To av disse egenskapene er ergonomi som C-parserne rett og slett ikke tilbyr:

  • Funksjonspredikater i find / find_all. Du kan skrive soup.find(lambda t: t.name == "a" and "btn" in t.get("class", [])) og uttrykke en komplisert betingelse på én linje Python – ingen «hent alt, filtrer etterpå»-løsning i to steg.
  • Navngitt, toveis tre-navigasjon. .parent, .next_sibling, .find_parent, .stripped_strings, .descendants – traverseringene leses nesten som vanlig språk og går begge veier. selectolax krever flere steg for noen av disse, eller tilbyr dem ikke i det hele tatt.

Det er den konkrete versjonen av «kjøper deg utviklertid». Ikke markedsføring, men 29 grønne sjekker.

To feller er verdt å merke seg, siden en rettferdig vurdering må nevne begge sider. Først boolske attributter: <input disabled> gir en tom streng "" for disabled i bs4 (selectolax gir None). Begge er falsy, så if node.get("disabled") overser stille en boolsk attributt som faktisk finnes i begge bibliotekene – den trygge testen er "disabled" in tag.attrs. For det andre: get_text(strip=True) setter sammen nodetekst uten mellomrom etter stripping, så "...with " + "link1" blir "withlink1". Send inn separator=" " når du trenger ordgrenser. Ingen av fellene er bs4-spesifikke; begge er fellgruver på tvers av biblioteker.

Og nå delen som overrasker folk: Å velge bs4 koster deg ikke CSS-dekning. CSS-motoren, soupsieve, er den mest komplette implementasjonen i hele denne sammenligningen. På basismatrisen med 41 tilfeller (gjenbrukt fra selectolax-oppsettet) fikk soupsieve 41/41 – den eneste perfekte scoringen i feltet, foran selectolax-Lexbor med 39/41 og cssselect (lxml/parsel) med 37/41. Deretter kjørte jeg 20 ekstra utvidede tilfeller som dokumentasjonen til soupsieve annonserer, og den gikk 20/20, inkludert selektorer Lexbor avviser direkte: :lang(en), den soupsieve-spesifikke :-soup-contains('featured'), :is(), :where() og :has(> a). De eneste reelle hullene er XPath (soupsieve er kun CSS) og parsel sine ::text / ::attr() pseudo-elementer, som er Scrapy-utvidelser. Lever du i XPath-verdenen, vil den migreringen gjøre vondt.

Konklusjonen for denne delen er klar: Det du ofrer når du velger BeautifulSoup er hastighet. Det er ikke API-ergonomi, og definitivt ikke CSS-dekning.

To produksjonsfeller det er verdt å budsjettere for

Utover standard-backend finnes det to ting som vil bite deg, spesielt i lange kjøringer eller i arbeidslaster som ikke er UTF-8.

Referansesirkler: kall decompose() i lange løkker

Hver bs4-Tag holder en referanse til forelderen og til barna sine, og det skaper en referansesirkel. CPythons referansetelling kan ikke rydde opp i en sirkel alene – det er generasjonsbasert garbage collection som må gjøre jobben. For å se hvor mye dette betyr, bygde og slettet jeg et tre 300 ganger med GC slått av, og telte deretter hvor mange Tag-objekter som fortsatt lå i minnet:

BeautifulSoup reference cycles retain 120,900 objects with GC off and 0 with GC on

ScenarioTags beholdt etter del
GC av120,900 (300 sykluser, ingenting frigjort)
GC på26,598 (generasjons-GC slo inn midt i løkken)
Etter tvungen gc.collect()0 (alt frigjort)
Kontroll uten sirkel (liste med strenger, GC av)delta 0

Med GC av frigjorde del soup ingenting – alle de 120 900 objektene ble liggende, fordi referansesirkelen ødelegger referansetellingens evne til å rydde opp. En enkel gc.collect() fjernet alt. Kontrollgruppen uten sirkel (en vanlig liste med strenger, kjent for å ikke ha noen sirkel) hadde et delta på null, som beviser at opphopningen kom fra bs4-sirkelen og ikke fra målefeil. Bs4s egen dokumentasjon sier at objektene er «densely interconnected ... exactly the sort a garbage collector would have trouble with», så dette er dokumentert oppførsel; det testen tilfører er antall beholdte objekter og beviset på at collect() nuller det ut.

Den praktiske regelen: I en pipeline som parser mange store sider i en tett løkke, hvis koden din (eller en høy-ytelsesinnstilling) slår av GC eller ikke lar den kjøre ofte nok, vil bs4-trær bli hengende igjen og minnet vokse. Kall soup.decompose() etter hver side – bs4 tilbyr nettopp det for å bryte sirkelen og frigjøre tidlig. C-trærne fra selectolax og lxml har ikke dette problemet i det hele tatt.

Encoding: UnicodeDammit er bs4s stille fordel

bs4 leverer en komponent de raske parserne ikke har: UnicodeDammit, som gjetter dokumentets tegnkoding og konverterer det til Unicode automatisk. Jeg ga den en 8-case matrise for «oppgitt vs. faktisk charset»:

BeautifulSoup UnicodeDammit recovers 5 of 8 encoding cases

CaseFaktisk encodingUnicodeDammit gjettetGjenopprettet?
utf8_no_declutf-8utf-8Ja
utf16_bomutf-16utf-16leJa
gbk_chinesegbkgb18030Ja (superset)
shiftjisshift_jiscp932Ja (superset)
latin1_declared_utf8latin-1 (oppgitt utf-8)iso-8859-1Ja (ignorerte løgnen)
latin1_no_decllatin-1cp720Nei
cp1252_no_declcp1252cp862Nei
utf8_declared_latin1utf-8 (oppgitt latin-1)iso-8859-1Nei (fulgte løgnen)

Fem av åtte ble gjenopprettet. UTF-8, UTF-16 med BOM, GBK, Shift-JIS og til og med feilmerket latin-1 kom tilbake riktig, og superset-gjetningene (GBK→gb18030, Shift-JIS→cp932) dekoder fortsatt fint. De to feilmønstrene er verdt å kjenne til: korte latin-1/cp1252-byteprøver blir ofte feiltolket som DOS-kodesider, fordi den statistiske detektoren ikke er pålitelig på korte inputs og DOS-tegninger overlapper med Latin-1s kodepunkter; og når en <meta charset>-deklarasjon rett og slett er feil, stoler UnicodeDammit på deklarasjonen. Bs4s dokumentasjon advarer om begge – en prøve kan være «so short that Unicode, Dammit can't get a lock on it», og jo mer data du har, desto bedre gjetning får du.

Sammenlignet med selectolax, som stille korrumperer ikke-UTF-8-bytes og forventer at du dekoder dem selv, er dette en reell fordel: bs4 prøver i det minste å gjette, og lykkes ofte. Men det er ikke en garanti. Har du kjent encoding, dropp gjettingen og vær eksplisitt: BeautifulSoup(bytes, from_encoding="...").

Er det faktisk forskjell mellom backendene på ekte sider?

Den feilaktige matrisen viser at backendene kan skille lag på bevisst ødelagt input. Det åpenbare neste spørsmålet er om det betyr noe i praksis, så jeg kjørte alle tre backendene over 11 ekte, hentede sider – BBC, Wikipedia, Craigslist, MDN, old.reddit, Python-dokumentasjonen, Hacker News, Books to Scrape, webscraper.io, whitehouse.gov og en JS-renderet quotes-side – og sammenlignet antall lenker, overskrifter og bilder.

Alle tre var enige på alle 11 sider. Null avvik. Det betyr at backend-uenigheten fra felle-seksjonen bare dukker opp på bevisst feilformatert HTML; når et moderne produksjonsnettsted er strukturert godt nok – selv om det er «rotete» – endrer ikke backend-valget det du trekker ut. Praktisk lesning: For vanlige, velstrukturerte nettsteder er html.parser helt fin og sparer deg for avhengigheter. Bare når du skraper åpenbart ustandardisert, håndskrevet eller gammel HTML, begynner backend-valget å påvirke resultatene, og da bør du bytte til lxml eller html5lib.

Et lite sidepoeng fra den testen, siden det er et reelt hjørnetilfelle. MDN-siden inneholder et <template>-element, og alle bs4-backendene returnerte 508 lenker – altså flater bs4 ut innholdet i <template> inn i hovedtreet. Det setter bs4 på samme side som lxml, og motsatt selectolax-Lexbor, som følger HTML5-spesifikasjonen strengt (<template> er et inaktivt DocumentFragment) og returnerer 497, og dermed stilltiende dropper de 11 lenkene inni template-en. Så bs4 vil fange opp data inne i en <template> – nyttig, men også en måte å plukke opp «spøkelsesinnhold» en nettleser aldri ville rendret. Ingen av oppførslene er feil; de tolker spesifikasjonen ulikt, og du bør vite hvilken du får.

Hvor BeautifulSoup passer – og hvor den ikke gjør det

I stedet for å presse alt inn i én score fra 0 til 100 (som ville skjult akkurat de avveiningene som betyr noe), er dette en scorecard på dimensjonsnivå, med et forbehold på hver rad:

DimensjonHva testene fantForbehold for leseren
Installasjon / første kjøringRent omslag, ingen nettleser/oppsett; html.parser null avhengigheter; alle ferdigbygde wheelslxml-backend trenger en C-avhengighet
Hastighet vs C-parserne12–17x tregere (html.parser) / 10.5–14x (lxml-backend), alle størrelserÉn rigg; gjenbrukt selectolax-data
CSS-spørringer~6–7.5x tregere på 100k noder; lxml-backend redder det ikkeGjenbrukt; betaler Python Tag-avgiften
Minne1.5–1.75x selectolax/lxml; tyngstGjenbrukt; målt med RSS
Kaldstart ved import2.36x tregere (33.4 vs 14.1 ms)Gjenbrukt; liten post
Trådingbs4-lxml ~3.9x tregere med 4 tråder (holder GIL)Én observasjon; bruk multiprosessering
API-ergonomi29/29 prober; funksjonspredikat i find + toveis navigasjonTom streng for boolsk attributt og strip-/ordgrense-feller
CSS-dekningsoupsieve sterkest: 41/41 base + 20/20 utvidet; støtter :langIngen XPath, ingen ::text
Toleranse på 3 backend-erlxml/html5lib 15/15; html.parser 12/15Avvik bare på feilformatert HTML
Konsistens på ekte sider3 backend-er enige 11/11; alle flater ut <template> (508)Velstrukturerte sider: backend spiller liten rolle
GC ved referansesirklerTreet er en sirkel; 300 løkker beholdt 120 900 objekter, collect nullstilte detLange løkker trenger decompose()
EncodingUnicodeDammit gjenoppretter 5/8; bommer på korte prøver, følger feil deklarasjonerÉn observasjon
VedlikeholdAktivt (4.15.0, juni 2026); MITHjemme på crummy/Launchpad, ikke GitHub

Så hvem er BeautifulSoup for? Alle som verdsetter en lesbar API og tilgivende parsing fremfor rå ytelse, og som jobber med moderat volum – prototyper, engangsscrapes, interne verktøy, team der utviklertid koster mer enn kjøretid. Hvem bør se andre steder? Million-siders pipelines der hastighetsavgiften blir til reelle kostnader, arbeidslaster som trenger parallellisering på trådnivå, og alle som er låst til XPath.

En liten note om hvor dette passer inn i en reell scraping-stack, og hvor vårt eget verktøy kommer inn. BeautifulSoup forutsetter at du allerede har HTML-en. Den henter ikke sider, renderer ikke JavaScript og gjør ingenting med anti-bot-forsvar eller CAPTCHAs – det er en helt separat og virkelig vanskelig jobb på dagens nett. Det er her en AI-scraping-API ligger på et annet lag: Thunderbit sin utviklerstack – en REST API, en MCP-server og et CLI – håndterer henting, JS-rendering og anti-bot-problemet, og returnerer enten ren Markdown (POST /distill) eller strukturert JSON som matcher skjema (POST /extract) uten at du trenger å skrive selektorer i det hele tatt. De to er ikke konkurrenter; de utfyller hverandre. bs4 parser HTML du allerede har, mens Thunderbit sin API, MCP og CLI skaffer HTML-en du ellers vanskelig ville nådd. Hvis flaskehalsen din er parsing, er bs4 et helt fint svar. Hvis flaskehalsen din er anskaffelse, er det et annet lag.

Prøv Thunderbit for uttrekking av webdata

Kort fortalt

BeautifulSoup gir deg den mest brukervennlige API-en, den sterkeste toleransen for feilformatert HTML og den mest komplette CSS-motoren i denne sammenligningen – kjøpt med en hastighetsavgift på omtrent en hel størrelsesorden og det tyngste minnefotavtrykket. Det er hele byttet, sagt rett ut. Standard-backend html.parser er den ene virkelige fellen: den ødelegger stille uavsluttede tabeller og lister, så send alltid inn "lxml" eller "html5lib" når inputen kan være stygg. Tråder gjør den ikke raskere – multiprosessering gjør. Og i lange løkker bør du kalle decompose() for hver side, så ikke referansesirklene hoper seg opp.

To begrensninger til slutt. Alt her er målt på én plattform (macOS arm64, Python 3.14, ferdigbygde wheels), og hastighetsmultiplikatorene er gjenbrukt fra selectolax-oppsettet (samme benk, per 2026-07-13) i stedet for å bli kjørt på nytt – så de arver den plattformbegrensningen, og et Linux x86_64- eller kildekompilert oppsett kan flytte de eksakte tallene. Og ingenting i disse resultatene er noen ny oppdagelse: bs4 er et 20 år gammelt bibliotek, så alt som er testet er enten dokumentert eller offentlig kjent fra før. Verdien ligger ikke i en scoop. Den ligger i å sette konkrete tall på avveininger dokumentasjonen bare beskriver kvalitativt.

Ofte stilte spørsmål

Er BeautifulSoup treg?
Ja, og det er målbart. På en oppgave med parsing pluss uttrekk kjører den omtrent 12–17x tregere enn en C-parser som selectolax-Lexbor med standard-backend html.parser, og 10.5–14x tregere med lxml-backend, fordi den bygger et Python-objekt for hver node. Om det betyr noe, avhenger av skalaen: på en side på 1 MB er det 232 ms mot 15 ms, ubetydelig for noen tusen sider, men avgjørende for en pipeline på én million sider.

Hvilken BeautifulSoup-parser bør jeg bruke — html.parser, lxml eller html5lib?
For velstrukturerte, vanlige nettsteder er standarden html.parser helt grei og gir ingen ekstra avhengigheter. Men den implementerer ikke HTML5s valgfrie slutt-tagger, så på uavsluttede tabeller eller lister blander den sammen nabotekst uten feil. Når inputen kan være feilformatert, håndskrevet eller gammel, bør du sende inn "lxml" eller "html5lib" eksplisitt – begge fikk 15/15 på en feilformatert-HTML-matrise der html.parser fikk 12/15.

Kan BeautifulSoup parse parallelt med tråder?
Nei. bs4 sin trebygging er ren Python og holder GIL, så flere tråder gjør den tregere, ikke raskere – i testene var fire tråder omtrent 3.9x tregere enn én tråd på en 1 MB parse. For å parallellisere bs4 bør du bruke multiprosessering (ProcessPoolExecutor). Biblioteker med C-kjerner, som selectolax og lxml, er de som faktisk kan få gevinst av trådnivå-parallellisme.

Håndterer BeautifulSoup ødelagt HTML godt?
Generelt ja – på tvers av en rekke feilformatert-prøver (feil nestede tagger, manglende skjelett, ukvoterte attributter og mer) kom alle tre backendene seg greit gjennom. Den ene svakheten er standarden html.parser og valgfrie slutt-tagger: uavsluttede <td>/<li> blir nestet i stedet for lukket, og det korrumperer teksten som trekkes ut. Bytt til lxml eller html5lib, så forsvinner den typen problem.

BeautifulSoup vs lxml — hva er best?
De er forskjellige verktøy. lxml er mye raskere både i trebygging og spørringer, og støtter XPath. BeautifulSoup pakker lxml (blant annet) inn i en langt mer brukervennlig API og har faktisk bredere CSS-støtte via soupsieve. Bare ikke forvent at lxml-backend skal gjøre bs4 lxml-rask – backend-en akselererer bare parsing, mens spørringer og traversering fortsatt betaler bs4 sin per-node Python-objektkostnad, noe som gjør den omtrent 6–7.5x tregere på store batch-utvalg.

Prøv Thunderbit for uttrekking av webdata Get Started Free

Ke
Ke
CTO i Thunderbit | Senior Data Scientist og ML-ekspert Med nesten ti års erfaring innen maskinlæring og datavitenskap er Ke Shen alumnus fra Columbia University og tidligere Senior Data Scientist hos Walmart Labs. Med solid, anerkjent ekspertise i Python, R, Java og statistikk deler han velprøvde innsikter om hvordan komplekse AI-algoritmer kan tas fra teori til produksjonsklar arkitektur.

Prøv Thunderbit

Hent leads og andre data med bare 2 klikk. Drevet av AI.

Få Thunderbit Det er gratis
Hent data med AI
Overfør enkelt data til Google Sheets, Airtable eller Notion
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week