Jokainen kirjoitus aiheesta ”nopein Pythonin HTML-parseri” mainitsee lopulta selectolaxin, ja lähes jokainen päätyy lopulta toteamaan, että se on ”selvästi nopeampi kuin BeautifulSoup”. Se pitää paikkansa. Se, mikä yleensä jätetään sanomatta, on mitä tapahtuu, kun selectolax asetetaan vierekkäin lxml:n kanssa — silloin tuo ”nopein” saa pienen tähden.
Tein siis vertailun kunnolla: selectolaxin molemmat backendit lxml:ää vastaan sekä BeautifulSoupia html.parser- ja lxml-parserilla ja lisäksi parselia vastaan. Aineistona oli viisi sivukokoa 1 KB:sta 10 MB:iin, ja jokainen mittaus oli kolmen erillisen prosessiajon mediaani. selectolax pieksi BeautifulSoupin selvästi ja päätyi tasoihin puhtaan lxml:n kanssa — mutta hävisi pelkän parsintavaiheen lxml:lle. Kaikki alla olevat luvut ovat alustavia ja yhdeltä koneelta (macOS arm64, Python 3.14.2); skriptit ovat tallessa, joten aja ne omalla koneellasi ennen kuin siteeraat minua.
Mitä selectolax oikeastaan on — ja mitä se ei ole
selectolax on Python-sidonta kahteen C-moottoriin — Modestiin ja Lexboriin — jotka jäsentävät HTML5:n ja hakevat siitä tietoa CSS-valitsimilla. Se ei ole crawleri, ei selain eikä ”scraper” siinä mielessä, että painat nappia ja kaikki tapahtuu. Se on työkalu, jolle annat HTML-möykyn sen jälkeen, kun olet jo hakenut sisällön. Ylläpitäjän oma tiivistelmä kuuluu: ”Nopea HTML5-parseri CSS-valitsimilla, kirjoitettu Cythonilla, käyttäen Modest- ja Lexbor-moottoreita.”
Taustamoottoreita on kaksi, ja erolla on enemmän merkitystä kuin dokumentaatio antaa ymmärtää:
LexborHTMLParser(Lexbor-moottori) — se, jota README suosittelee käytettäväksi vuodesta 2024 alkaen.HTMLParser(Modest-moottori) — alkuperäinen vaihtoehto, jonka taustalla oleva C-kirjasto ”ei ole enää ylläpidossa”, kuten samassa README:ssä todetaan.
Ennen kuin mennään nopeuteen, on hyvä tietää pari asiaa. Reposivun tilannekuvassa 2026-07-10 selectolaxilla oli 1 653 tähteä, viimeisin julkaisu oli v0.4.10 (toukokuu 2026), ja PyPI rajaa tuen Python-versioihin >=3.9,<3.15. Asennus on koko tämän arvioinnin vähiten dramatiikkaa sisältävä osa: pip install selectolax toi 2.3 MB:n valmiiksi käännetyn cp314-wheelin ja toimi heti Python 3.14:ssä — ei selaimen latausta, ei doctor-vaihetta, ei kääntämistä. Siinä on puhtaan parserin hiljainen etu selainpohjaiseen työkaluun verrattuna. Se vain importoituu ja toimii.
Yksi lisenssiin liittyvä huomio kannattaa sanoa heti eikä haudata loppuun: Python-sidonta on MIT-lisensoitu, mutta wheel sisältää valmiiksi käännetyt moottorit, joilla on omat lisenssinsä — Modest on LGPL-2.1, Lexbor on Apache-2.0. Eli väite ”selectolax on MIT” pitää paikkansa Python-koodin osalta, mutta ei koko binääripaketin osalta, jonka oikeasti jaat eteenpäin. Jos lakitiimisi välittää toimitettavista komponenteista, tämä on se yksityiskohta, joka kannattaa nostaa esiin.
Nopeuskysymys, vastattuna oikeilla numeroilla
Tässä oli tehtävä, jonka mittasin: jäsennä HTML-merkkijono, poimi jokaisen <h3 class="title">-elementin teksti, poimi jokaisen <a>-linkin href. Mediaaniviive millisekunteina, laskettuna kolmen erillisen prosessiajon mediaanina; eri ajokertojen vaihtelu pysyi C-pohjaisilla parserilla enintään noin 5 %:ssa useimmissa kokoluokissa. Ennen kuin yhtäkään solua ajoitettiin, jokaisen parserin tulos tiivistettiin sisältöhajautukseksi, jotta parseri, joka tekisi salaa vähemmän töitä, huomattaisiin ja suljettaisiin pois — näillä sivuilla kaikki kuusi täsmäsivät jokaisessa koossa, joten vertailu on aidosti vertailukelpoinen. Koko aineisto löytyy versionhallintaan lisätystä bench_parse.json-tiedostosta.

| Sivun koko | selectolax (Lexbor) | selectolax (Modest) | lxml | parsel | BS (lxml) | BS (html.parser) |
|---|---|---|---|---|---|---|
| 1 KB | 0.027 | 0.029 | 0.036 | 0.044 | 0.281 | 0.323 |
| 10 KB | 0.160 | 0.171 | 0.166 | 0.228 | 1.705 | 2.049 |
| 100 KB | 1.464 | 1.565 | 1.423 | 2.020 | 16.5 | 20.6 |
| 1 MB | 14.901 | 16.9 | 14.177 | 20.9 | 181.9 | 232.6 |
| 10 MB | 159.9 | 247.9 | 172.9 | 231.9 | 2261.6 | 2788.7 |
Verrattuna BeautifulSoupiin: noin 12–17x, ja yleinen käsitys aliarvioi eron
Kun nuo luvut muutetaan suhdeluvuiksi, selectolax-Lexbor osoittautuu noin 12x nopeammaksi kuin BeautifulSoup(html.parser) 1 KB:n sivulla ja jopa noin 17x nopeammaksi 10 MB:lla, sekä noin 10–14x nopeammaksi kuin BeautifulSoup(lxml) samalla alueella. Verkossa kiertävä väite — ”selectolax on noin 4–5 kertaa nopeampi kuin BeautifulSoup” — on liian vaatimaton suhteessa html.parser-versioon ja suunnilleen oikein vain lxml-pohjaiseen BeautifulSoupiin verrattuna. Todellinen kerroin riippuu siitä, mitä BeautifulSoup-versiota tarkoitat ja kuinka paljon dataa sivulta poimit.
Tämä myös sopii yhteen README:n oman vertailun kanssa, jossa selectolaxilla vihjataan olevan 25,5x etu BeautifulSoup(html.parser)-versioon nähden. Kumpikaan luku ei ole väärin. README:n tehtävässä (otsikko, linkit, skriptit ja metatiedot pieniltä etusivuilta) tehdään pienillä sivuilla vähemmän poimintaa, jolloin BeautifulSoupin per-parsinnan ylikustannus painottuu enemmän. Käytännön tasolla tästä tulee: selectolax on realistisessa parse-and-extract-työssä suunnilleen 10–15x nopeampi kuin BeautifulSoup, pienillä sivuilla ja kevyellä poiminnalla vieläkin enemmän.
Jos nykyinen pullonkaulasi on kasa BeautifulSoup-koodia, joka jauhaa sivuja läpi, tämä on juuri sellainen siirto, joka maksaa itsensä takaisin. Se tapaus ei ole kiistanalainen. Seuraava on.
Verrattuna lxml:ään: tasapeli — ja lxml voittaa sen osan, jonka kaikki unohtavat erottaa
Katso 100 KB:n ja 1 MB:n rivejä. Lexbor ja lxml ovat noin 5 %:n sisällä toisistaan, niiden ajokertakohtaiset vaihteluvälit menevät päällekkäin, ja oman mittaustapani mukaan se on tasapeli — ei voittajaa, ei ”nopeampaa”. Ainoa kohta, jossa selectolax oikeasti kirii ohi, on 10 MB:n sivu (159.9 ms vs 172.9 ms, eli 8.1 % ero ilman päällekkäisiä vaihteluvälejä). Eli koko tehtävässä selectolax vastaa lxml:ää ja voittaa sen vain kaikkein suurimmissa dokumenteissa.

Sitten erotin puun rakentamisen CSS-hakemisesta, ja tulos kääntyi tavalla, jonka moni kirjoitus jättää huomaamatta. Pelkässä parsinnassa, ilman yhtään hakua, lxml oli tällä koneella johdonmukaisesti noin 33–34 % nopeampi kuin selectolax-Lexbor — 77.9 ms vs 116.6 ms 10 MB:n sivulla. Koko tehtävässä nämä kaksi kuitenkin lähestyvät toisiaan, ja oma työhypoteesini (ei mitään, minkä olisin todistanut attribuointikokeella) on, että näillä sivuilla CSS-haku on vain pieni osa kokonaisajasta, joten lxml:n etu parsintavaiheessa laimenee, kunnes kokonaisajat osuvat yhteen.
Tämä on koko katsauksen helpoimmin haastettava väite, ja haluan sanoa suoraan miksi. Se on vastoin yleistä käsitystä, ja yksi löytämäni julkaistu vertailu, joka erottelee pelkän parsinnan — aows.jpt.sh — raportoi päinvastaista ja antaa selectolaxille noin 4x edun. Siksi rajasin tuloksen: se on yhden alustan mittaus (macOS arm64, Python 3.14, valmiiksi käännetyt cp314-wheelit — Linux x86_64:ää tai lähdekoodista kääntämistä ei testattu), se varmennettiin neljällä sivukoolla ja pysyi samana kaikissa, ja se tarkistettiin uudelleen kahdella eri lxml-API:lla, jotta API-artefakti voitaisiin sulkea pois. Molemmat lxml-API:t voittivat selectolax-Lexborin jokaisessa koossa. En väitä, että ”lxml parsii nopeammin” olisi lopullinen totuus — väitän vain, että tämä on se, mitä oma mittaukseni tuotti, skripti mukana, suhteessa useimpiin julkaistuihin lukuihin. Aja se omallasi.
Yksi lisäsarja vielä: kun 100 000 <a>-linkkiä poimittiin tasaiselta sivulta, lxml ja selectolax-Modest olivat tasoissa (33.30 ms vs 34.19 ms, vaihteluvälit päällekkäin), kun taas selectolax-Lexbor jäi molemmista noin 15 %. Kaikkia kolmea C-moottoria yhdistää se, että ne ovat 5–7x nopeampia kuin parsel tai BeautifulSoup massavalinnassa, jossa todellinen hidaste on Python-objekti jokaiselle solmulle -malli. Eli väite ”selectolax on nopein massiivisessa CSS-valinnassa” ei sekään pidä täysin paikkaansa — Modest on vain tasoissa lxml:n kanssa, ja Lexbor häviää sille.
Se johtopäätös, jonka seison oikeasti takana, on tämä: selectolaxin etu lxml:ään nähden ei ole laaja, koko tehtävän nopeus. Se voittaa vain kaikkein suurimmassa sivussa. Sen vahvuudet löytyvät muualta — API:n käytettävyydestä, virheellisen syötteen käsittelystä ja modernista CSS:stä — ja niissä loppuosa arviosta elää.
Muisti ja kylmäkäynnistys: vertaa RSS:llä, älä profilerilla
Muisti on kohta, jossa joudun korjaamaan omia aiempia lukuja, ja korjaus on tässä juuri se pointti. 10 MB:n sivulla mitattuna RSS-muutoksena, tracemalloc pois päältä, BeautifulSoup käyttää noin 1.5–1.8x enemmän muistia kuin selectolax tai lxml — vaihteluväli kulkee 1.51x:stä (BS-lxml, 218.4 MB vs Lexbor, 144.6 MB) aina 1.75x:iin yläpäässä. selectolax ja lxml jakavat saman kevyen luokan; lxml on RSS:n perusteella kaikkein kevein.

Aiempi passini raportoi ”noin 3x”, ja luku oli väärä opettavasta syystä: mittauksessa oli tracemalloc päällä, ja tracemallocin per-allokaatio-kirjanpito käytännössä kaksinkertaistaa eniten allokoivan parserin näennäisen RSS:n. Eli huomio kaikille, jotka mittaavat parserin muistia: vertailkaa RSS:n perusteella profiler pois päältä. Parserien vertaaminen tracemallocin huippuarvolla asettaa erityisesti C-pohjaiset parserit väärään järjestykseen — se sai selectolax-Lexborin näyttämään raskaammalta kuin Modest, vaikka todellisessa RSS:ssä ne ovat lähellä toisiaan. BeautifulSoup on tässä aidosti raskain; se ei vain ole 3x-raskaampi, kuten likainen mittari ensin näytti.
Kylmäkäynnistys on pieni mutta todellinen etu: selectolax importoituu noin 14 ms:ssa, eli suunnilleen samaa luokkaa kuin lxml ja noin 2.3x nopeammin kuin bs4 tai parsel. Jos julkaiset CLI-työkalun tai serverless-funktion, jossa importointiaika kuuluu jokaiseen kutsuun, tämä ero kannattaa huomata.
CSS-valitsimien kattavuus: vahva, mutta muutama oikea aukko löytyy
CSS-tuen kattavuus testattiin 41 tapauksen matriisilla, jossa jokainen valitsin ajettiin fixturea vasten, jolle tiedettiin oikea vastausjoukko, sekä erillisellä virheenkalastelukierroksella, jonka tarkoitus oli rikkoa Lexbor-moottori. Jokainen tapaus ajettiin omassa subprocessissa, mikä osoittautui välttämättömäksi — yksi niistä kaataa koko tulkin. Tulokset:

| Moottori | PASS | VÄÄRIN | TUEMATON | PROCESS_ABORT |
|---|---|---|---|---|
| soupsieve | 41 | 0 | 0 | 0 |
| selectolax Lexbor | 39 | 0 | 2 | 0 |
| lxml (cssselect) | 37 | 1 | 3 | 0 |
| parsel (cssselect) | 37 | 1 | 3 | 0 |
| selectolax Modest | 35 | 3 | 2 | 1 |
Kun joukkoon otetaan vihamielisiä valitsimia, Lexbor ei olekaan selvä voittaja — soupsieve on, puhtaalla 41/41-tuloksella Lexborin 39/41:tä vastaan. Lexborin kaksi epäonnistumista ovat :lang(en) ja :dir(rtl), jotka se hylkää parse-virheellä. Muussa se on täydellinen, mukaan lukien :has(), :is(), :where() ja kirjainkokoriippumattomat attribuutit.
Lexborin vahvuus näkyy cssselect-pinon rinnalla. README:n lippulaivavalitsin — div > :nth-child(2n+1):not(:has(a)) — palauttaa oikean joukon molemmilla selectolax-moottoreilla ja soupsievellä, mutta väärän joukon lxml:ssä ja parselsa ilman virheilmoitusta. Scraper, joka kopioi tuon valitsimen Scrapyyn tai parselsa, saa hiljaa väärät tulokset. Tarkennettuna: cssselect on tukenut :has()-valitsinta versiosta 1.2.0 (2022) lähtien, ja testasin versiota 1.4.0, joten kyse on ”tuettu mutta yhdistelmä arvioitu väärin” -tilanteesta, ei siitä että ominaisuus olisi tuettu puutteellisesti. Tämän nimenomaisen yhdistelmän hiljainen väärä tulos ei myöskään näy cssselectin trackerissa, jossa :has()-rajoitukset on kirjattu virheinä. Lexbor käsittelee myös kirjainkokoriippumatonta attribuuttiflagia [data-role="LEAD" i], jonka cssselect hylkää kokonaan.
Kaksi aukkoa ratkaisee kuitenkin migraatioita. selectolax ei tue lainkaan XPathia — kumpikaan backend ei tarjoa xpath()-metodia — eikä myöskään ::text- tai ::attr()-pseudo-elementtejä, koska ne ovat parsel/Scrapy-laajennus eivätkä varsinaista CSS:ää. Jos nykyiset scraperisi nojautuvat XPathiin, se on suurin muuri, johon törmäät; selektorit pitää kirjoittaa uudelleen, ei vain vaihtaa kirjastoa. Toisaalta Lexbor tuo mukanaan :lexbor-contains("text" i) -pseudo-luokan kirjainkokoriippumattomaan tekstihakuun, jota lxml, parsel tai tavallinen CSS eivät tarjoa, ja se toimii dokumentaation mukaisesti.
Kestävyys rumaa HTML:ää vastaan, ja juuri siinä selectolax ansaitsee paikkansa
Oikea scraping tarkoittaa sitä, että parserille syötetään roskaa ja toivotaan, ettei se kaadu. Ajoin 18 vihamielistä syötettä, ja tämä on alue, jossa selectolaxin asema lxml:ään verrattuna on vahvin.
Anna lxml.html.fromstring-funktiolle tyhjä merkkijono tai pelkkää whitespacea, ja se nostaa ParserError("Document is empty")-virheen. Molemmat selectolax-moottorit palauttavat sen sijaan kelvollisen, tyhjän puun. Jos scraper kiertää läpi URL-listaa, jossa osa vastauksista tulee tyhjinä, yksi try/except-kerros vähemmän on jo voitto. selectolax selviytyi myös 100 000 elementistä ilman pinon ylivuotoa.
Syvä sisäkkäisyys tuotti terävimmän eron. Kun <div>-elementtejä oli sisäkkäin 1 000 tai 5 000 tasoa, lxml pudotti syvimmän sisällön hiljaa, kun taas selectolax säilytti sen. libxml2 rajaa jäsentämisen syvyyden noin 256 tasoon ja typistää puun ilmoittamatta virheestä, joten syvin teksti muuttuu yksinkertaisesti saavuttamattomaksi. Molemmat selectolax-moottorit palauttavat koko puun. Tämä on peilikuva <template>-ansasta, johon palaan seuraavaksi: siellä Lexbor pudottaa sisältöä, jonka muut säilyttävät; tässä lxml pudottaa sisältöä, jonka selectolax säilyttää.
Kaikki ei silti ollut voittoa. Modest-backend kaataa koko Python-tulkin SIGABRT-signaalilla, kun se kohtaa :dir()-valitsimen — ei siis nostettu poikkeus, jonka voisit napata kiinni, vaan suora prosessin tappaminen. Se on todellinen kestävyysriski kaikille, jotka ovat vielä vanhassa backendissä, ja juuri sellainen ongelma, joka pysyy piilossa siihen asti, kunnes tuotantotyö kaatuu kolmen aikaan yöllä.
Kaksi hiljaista datan menettämisen ansaa, jotka pitää tietää ennen tuotantoon vientiä
Mikään näistä ei ole uusi löytö — molemmat on dokumentoitu upstreamissa — mutta molemmat aiheuttavat oikeaa datan menetystä hiljaa, eikä kumpikaan huuda README:ssä.
Lexbor pudottaa <a>-linkit <template>-elementin sisältä
Livenä testaamallani MDN-sivulla selectolax-Lexbor löysi 497 linkkiä, kun taas lxml, molemmat BeautifulSoup-backendit ja jopa selectolaxin oma Modest-backend löysivät 508. Puuttuvat yksitoista olivat kielivalitsin ja keskustelulinkki, jotka sijaitsivat <template>-elementeissä (sivu käyttää Lit-webkomponentteja).

Syy on täysin legitiimi: HTML5-spesifikaation mukaan <template>-sisältö jäsennetään erilliseen, inerttiin fragmenttiin eikä normaaliin DOM-puuhun, ja Lexbor noudattaa tätä tarkasti — tree.css("a") ei sukella template-sisältöön. lxml, molemmat BeautifulSoup-backendit ja Modest litistävät template-sisällön pääpuuhun, joten ne löytävät nuo linkit. Tämä on dokumentoitu avoin ongelma (selectolax#146, ja moottorin juurisyy on lexbor#170), ja molemmat tulkinnat ovat puolustettavissa — Lexbor on ehkä jopa spesifikaation kannalta oikeampi. Mutta kehittäjä, joka käyttää suositeltua backendia, voi silti menettää tämän datan hiljaa ilman virheilmoitusta. Käänteinen huomio on myös tärkeä: muut parserit paljastavat inertin template-sisällön, jota selain ei koskaan renderöi, joten ne voivat antaa sinulle haamudataa, jota käyttäjä ei näe. Luotettava kiertotie juuri tähän sivuun on Modest-backend tai jokin toinen kirjasto.
Ei-UTF-8 -baitit rikkovat .text()-tuloksen hiljaa
Jos syötät selectolaxille bittejä, jotka eivät ole kelvollista UTF-8:aa, jäsentäminen onnistuu — korruptio näkyy vasta myöhemmin, ja se on pahempi kuin siisti kaatuminen. Esimerkiksi kun "<p>café éè</p>".encode("latin-1") annetaan sisään, Lexborin .text() palauttaa korvausmerkkejä, Modestin .text() tiputtaa virheelliset baitit pois hiljaa, ja molemmat moottorit nostavat UnicodeDecodeError-virheen vasta, kun kosket .html-ominaisuuteen. Sidonta purkaa datan takaisin luettaessa tiukasti UTF-8:na, ei jo parsinnan aikana. Tämä liittyy tunnettuun selectolax-ongelmaan, joka koskee encode/decode-strictnessiä.
Korjaus on yksi rivi ja kannattaa opetella ulkoa: dekoodaa baitit itse ensin — LexborHTMLParser(resp.content.decode("latin-1")) — niin molemmat moottorit palauttavat oikein 'café éè'. Käytännössä anna selectolaxille aina str, älä koskaan raakaa ei-UTF-8 bytes-dataa. README ei sano tätä suoraan.
Tuotannon kannalta kiinnostavat mittarit (yhden havainnon perusteella, joten suuntaa-antavina)
Seuraavat tulokset mittasin kerran enkä kolmen ajon keskiarvona, joten merkitsen ne signaaleiksi enkä lopullisiksi luvuiksi.
Säikeistys on kiinnostavin kohta. Kun 1 MB:n sivu parsittiin 48 kertaa neljän säikeen yli, selectolax näytti noin 3.5–3.9x nopeutuksen — empiirinen merkki siitä, että kirjasto vapauttaa GILin C-parsinnan aikana — kun taas BeautifulSoup(lxml) hidastui monisäikeisenä useita kertoja, mikä kertoo GILin sitovasta serialisoitumisesta. lxml sijoittui väliin eikä antanut selvää johtopäätöstä. Pythonin siirtyessä kohti free-threading-aikakautta on aidosti, vaikkakin alustavasti, etu siitä, että selectolax parallelisoituu säikeiden yli siellä, missä BeautifulSoup ei. Tämä perustuu yhteen säiekokoon ja yhteen sivukokoon, ja mekanismi on hypoteesi, ei suoraan C-koodia instrumentoinut todistus.
Vuodoista: kun 1 MB:n sivulla tehtiin 2 000 parse-extract-drop-toistoa, yksikään kolmesta parserista ei näyttänyt lineaarista RSS-nousua, joka viittaisi vuotoon — jokainen asettui rajattuun työjoukkokaistaan. Luotan tähän erityisesti siksi, että ajoin tunnetusti vuotavan kalibrointikohteen saman mittarin läpi, ja se nousi suunnitellusti +198 MB:iin, mikä todistaa, että mittari olisi nähnyt vuodon, jos sellainen olisi ollut parserissa. Ja node-kahva, joka pidettiin elossa sen omistavan puun poistuttua näkyvistä, pysyi käyttökelpoisena ilman segfaultia. Kaikki nämä ovat yhden havainnon tuloksia, eivät usean tunnin rasitustestin tuloksia.
Mihin selectolax sopii — ja missä sen vastuu päättyy
Kaikki yllä sanottu koskee yhtä tehtävää: muuntaa jo hankkimasi HTML rakenteiseksi dataksi nopeasti. selectolax on tässä tehtävässä erinomainen. Se ei tarkoituksella hae sivua, renderöi JavaScriptiä, pyöritä proxyja, ratkaise CAPTCHAsia tai päätä, mitä elementtejä haluat. Kaikki se on edelleen sinun koodiasi. selectolax on parse-kerros, eikä se esitä olevansa mitään muuta.
Tässä kohdassa hallittu poimintapalvelu sijoittuu parserin yläpuolelle eikä korvaa sitä. Jos et halua itse rakentaa ja ylläpitää fetch-render-anti-bot-extract-pinoa, Thunderbit tarjoaa sen API:n, MCP-palvelimen ja CLI:n kautta — POST /distill muuntaa sivun puhtaaksi Markdowniksi ja POST /extract palauttaa skeemaan sopivaa jäsenneltyä JSONia, ja JS-renderöinti sekä anti-bot-hoito hoidetaan puolestasi. Se on eri kerros samaa ongelmaa: tarttuisit selectolaxiin, kun sinulla on jo HTML ja haluat raakaa parsintanopeutta omassa hallinnassasi, ja johonkin Thunderbitin API:in, MCP-palvelimeen tai CLI:hin, kun haluat haun ja poiminnan valmiiksi hoidettuna ja tarvitset vain rakenteisen datan takaisin. Ei vaihto, vaan eri korkeus samassa pinossa.
Kokeile Thunderbitia verkkodatan poimintaan
Plussat, miinukset ja kenelle tämä oikeasti sopii
Missä selectolax voittaa:
- Noin 12–17x nopeampi kuin BeautifulSoup realistisessa parse-and-extract-työssä, ja ero pysyy vakaana kolmen kertaluokan sivukokovälillä.
- Kevyt muistijälki (lxml-luokkaa, noin 1.5–1.8x kevyempi kuin BeautifulSoup) ja noin 14 ms:n import-aika.
- Kestää hyvin syötteet, jotka kaatavat lxml:n — tyhjät, pelkän whitespace:n sisältävät ja patologisen syvästi sisäkkäiset.
- Moderni CSS, mukaan lukien
:has(),:is(),:where(), kirjainkokoriippumattomat attribuutit ja vain Lexborissa oleva:lexbor-contains(). - None-safe DOM-luku ja -muokkaus: puuttuvat elementit palauttavat
Nonetai[]virheen sijaan, ja puuta voi oikeasti muokata ja serialisoida uudelleen. - Aktiivinen ylläpito (v0.4.10, kesä 2026) ja helppo asennus.
Missä se ei voita:
- Ei laajemmin nopeampi kuin lxml — koko tehtävässä tasapeli, ja puhtaassa parsinnassa lxml voitti omassa mittauksessani.
- Ei XPathia eikä
::text/::attr()-laajennuksia — kova migraatiomuuri XPath-pohjaisille scrapaajille. - Kaksi hiljaista datan menetyksen ansaa:
<template>-sisältö Lexborissa ja ei-UTF-8-baitit.text()-polulla. - Modest-backend on vanha ja antaa SIGABRT:n
:dir()-valitsimesta. - Jokainen luku tässä on yhden alustan mittaus (macOS arm64, Python 3.14) ja alustava.
Kannattaako selectolaxia käyttää? Kyllä, jos haluat lxml-tasoisen parsintanopeuden, mutta ystävällisemmän ja None-safe-API:n sekä selvästi paremman käytöksen tyhjällä ja rikkinäisellä syötteellä — ja jos CSS-only-rajat sopivat sinulle. Jos koodipohjasi nojaa XPathiin, uudelleenkirjoituksen kustannus on todellinen ja se pitää arvioida rehellisesti. Ja jos tavoitteesi on ”yksittäinen nopein parseri”, tämän mittauksen perusteella oikea vastaus on, että selectolax ja lxml ovat niin lähellä toisiaan, että ratkaisun tekee käytettävyys ja kestävyys, ei raaka nopeus. Se on muutenkin parempi syy valita työkalu.
Kokeile Thunderbitia verkkodatan poimintaan Get Started Free
Usein kysytyt kysymykset
Onko selectolax nopeampi kuin BeautifulSoup?
Kyllä, selvästi — noin 12–17x nopeampi kuin BeautifulSoup(html.parser) ja 10–14x nopeampi kuin BeautifulSoup(lxml) realistisessa parse-and-extract-tehtävässä, ja ero pysyy vakaana 1 KB:n ja 10 MB:n sivuilla (macOS arm64, Python 3.14). Yleisesti siteerattu ”4–5x” aliarvioi eron html.parser-versioon.
Onko selectolax nopeampi kuin lxml? Ei laajasti. Koko parse-and-extract-tehtävässä ne ovat tasoissa 100 KB:ssa ja 1 MB:ssa, ja selectolax voittaa vain 10 MB:n sivulla. Pelkässä parsinnassa ilman hakua lxml oli tällä koneella itse asiassa noin 33–34 % nopeampi — vastakkaiseen suuntaan menevä tulos, jonka olen rajannut yhden alustan havainnoksi, joten varmista se omalla raudallasi.
Pitäisikö käyttää Lexbor- vai Modest-backendiä?
Lexboria lähes aina — se on ylläpidetty ja ominaisuuksiltaan kattavin moottori, jota README suosittelee, ja sillä on parempi CSS-tuki. Ainoa poikkeus on sivu, joka piilottaa sisältöä <template>-elementtien sisään, jolloin Lexborin spesifikaationmukainen käytös pudottaa kyseisen sisällön ja Modest sattuu säilyttämään sen. Modestissa on myös teräviä kulmia, mukaan lukien tulkin kaatava :dir()-bugi.
Tukeeko selectolax XPathia?**
Ei. Kumpikaan backend ei tarjoa xpath()-metodia — selectolax on vain CSS:ää varten. Jos scraperisi riippuvat XPathista, siirtyminen tarkoittaa selektorien kirjoittamista uudelleen, ja se on lxml- tai parsel-pohjaisesta pinosta siirtymisen suurin yksittäinen kustannus.
Miksi selectolaxin tulos on sekaisin tai elementtejä puuttuu?
Yleensä syynä on kaksi asiaa. Jos teksti tulee takaisin korvausmerkeillä tai aksentit puuttuvat, olet todennäköisesti antanut sisään raakaa ei-UTF-8-bittiä — dekoodaa ne ensin str-muotoon (resp.content.decode("latin-1")) ennen parsintaa. Jos linkkejä tai elementtejä puuttuu modernilta sivulta, ne saattavat sijaita <template>-tageissa, joiden sisään Lexbor-backend ei sukella; vaihda siihen sivuun Modestiin tai toiseen parseriin.


