PyQuery voegt jQuery-syntax toe zonder beslissingsrelevante selector-overhead in deze benchmark

Laatst bijgewerkt op August 18, 2026
PyQuery voegt jQuery-syntax toe zonder beslissingsrelevante selector-overhead in deze benchmark
AI-samenvatting
PyQuery plaatst een jQuery-achtige API bovenop lxml. Over vijf paginagroottes van 1 KB tot 10 MB lagen alle vijf getoonde medianen lager dan die van kale lxml, inclusief een verschil van 1,5% bij de grootste omvang. De benchmark bewijst niet dat de wrapper sneller is; hij vond geen verschil groot genoeg om deze keuze voor selecteren en uitlezen te veranderen. Vanaf 10 KB lag het ook binnen enkele procenten van selectolax in de getoonde medianen. Zonder vooraf gedefinieerde equivalentiemarge is dat een dicht resultaat, geen statistisch gelijkspel.

PyQuery zet een jQuery-achtige API bovenop lxml. Over vijf paginagroottes, van 1 KB tot 10 MB, lagen alle vijf getoonde medianen onder die van kale lxml, inclusief een verschil van 1,5% bij de grootste omvang. De benchmark bewijst dus niet dat de wrapper sneller is; hij liet simpelweg geen verschil zien dat groot genoeg is om je keuze voor selecteren en uitlezen te veranderen.

Vanaf 10 KB lag het resultaat in de getoonde medianen ook binnen enkele procenten van selectolax. Zonder vooraf gedefinieerde equivalentiemarge is dat gewoon een dicht resultaat, geen statistische gelijkstand.

Wat PyQuery is

PyQuery is een Python-bibliotheek die je de selector- en chain-API van jQuery geeft bovenop een lxml-documentboom. Geteste versie: 2.1.0, BSD-licentie, 2.380 GitHub-stars, 59 open issues, laatst gepusht op 2026-07-27.

Officiële referentie: PyQuery-documentatie.

System diagram: jQuery Syntax Over lxml

from pyquery import PyQuery as pq
d = pq(html)
titles = [e.text_content() for e in d("h3.title")]
hrefs = [e.get("href") for e in d("a")]

De elementen die het oplevert zijn lxml-elementen, dus alles wat je met lxml kunt doen, blijft gewoon werken. Dat is precies het idee: PyQuery is een ergonomielaag, geen parser. pip install pyquery haalt 3 pakketten binnen — lxml, cssselect en PyQuery zelf — en 20,1 MiB, waarvan bijna alles uit de gecompileerde extensies van lxml komt.

Als je cheerio in Node hebt gebruikt, is dit in Python ongeveer hetzelfde API-concept. De twee selectors die hier zijn getest werkten in beide; de test bewijst geen volledige gelijkwaardigheid van de selectortaal tussen cssselect en cheerio.

De meting

Deze onderzoeksbasis had al een parserbenchmark met een eigenschap die de meeste benchmarks missen: een pariteitscontrole die de geëxtraheerde content hasht — gesorteerde titels plus gesorteerde hrefs — tegen een referentieparser, zodat een bibliotheek niet snel kan lijken door werk over te slaan. Vijf paginagroottes, 50 iteraties, drie onafhankelijke runs.

PyQuery toevoegen vereiste twee dingen.

De referentie opnieuw draaien. selectolax draaide opnieuw in hetzelfde proces. De contenthash kwam overeen op 5 van 5 groottes en de p50 lag tussen 0,989× en 1,079× van de gepubliceerde waarde — dus dit is dezelfde machine en hetzelfde testbed.

lxml ook in hetzelfde proces draaien. De gepubliceerde benchmark vermeldt de machine en de Python-versie, maar niet de bibliotheekversies, dus de lxml-regel daar kan uit een andere lxml-release komen dan de versie die PyQuery hier omhult. Vergelijken over die kloof heen zou twee lxml-versies met elkaar vergelijken en dat een wrapper-tax noemen. Door lxml ernaast te draaien, verdwijnt die onzekerheid — beide zijn lxml 6.1.1 in deze venv.

PaginagrootteselectolaxPyQuerylxmlPyQuery vs lxml
1 KB0,0286 ms0,0456 ms0,0508 ms0,90Ă—
10 KB0,1725 ms0,1728 ms0,1802 ms0,96Ă—
100 KB1,4855 ms1,4093 ms1,4145 ms1,00Ă—
1 MB14,97 ms14,96 ms15,03 ms1,00Ă—
10 MB158,10 ms162,86 ms165,25 ms0,99Ă—

p50 in milliseconden, mediaan van drie runs, allemaal in één proces. parser-bench.json. Alle drie contenthashes kwamen op elke grootte overeen met de referentie.

De wrapper-tax die er niet is

Measured results chart: PyQuery and lxml on the same fixture

PyQuery kwam op of onder kale lxml uit bij elke getoonde mediaan. Dat is geen bewijs dat een wrapper parseren sneller maakt. Drie-run-medianen en geen vooraf gedefinieerde equivalentiemarge ondersteunen alleen de smallere conclusie dat deze fixture geen beslissingsrelevante selector-overhead liet zien.

Bij 10 MB waren PyQuery’s drie runs 162,86, 163,17 en 161,13 ms; lxml’s waren 169,46, 165,25 en 164,18. De bereiken liggen dicht bij elkaar, maar overlappen niet. Bij 1 MB verschillen de twee medianen met 0,5%. Deze kleine runs ondersteunen een praktische conclusie, geen statistische equivalentieclaim.

System diagram: Wrapper and Parser Boundaries

Het mechanisme is eenvoudig genoeg: pq(html) bouwt één keer een lxml-boom, d("h3.title") compileert de CSS-selector via cssselect zoals tree.cssselect() dat ook doet, en de teruggegeven elementen zijn lxml-elementen. Er zit weinig PyQuery-werk in deze gemeten hot path. Traversal, mutatie, herhaalde queries, import en geheugen vallen buiten de timingclaim rond de selector.

Nauwe resultaten vanaf 10 KB

De bruikbaarste bevinding is de eerste kolom.

Vanaf 10 KB was het verschil tussen snelste en langzaamste mediaan onder selectolax, lxml en PyQuery 4,5% bij 10 KB, 5,4% bij 100 KB, 0,5% bij 1 MB, en 4,5% bij 10 MB. Deze run was geen equivalentietest; de praktische conclusie is dat deze verschillen voor deze workload voor de meeste parserkeuzes niet doorslaggevend zijn.

selectolax is oprecht sneller bij 1 KB — 0,0286 ms tegenover 0,0456 en 0,0508 — maar die rij is niet bruikbaar. Over de drie parsers is de spreiding daar 77,6%, en de drie runs van selectolax liepen uiteen van 0,0267 tot 0,0404 ms. Bij 28 microseconden domineren timer en scheduler. Daar zou ik niets rangschikken.

Voor deze taak van selecteren en uitlezen kun je beter kiezen op basis van API-voorkeur en gemeten afhankelijkheden dan op basis van een veronderstelde snelheidsrangorde. PyQuery liet tegen lxml geen beslissingsrelevante penalty zien. Selectolax gebruikt een andere parserstack, maar dit artikel heeft de geĂŻnstalleerde footprint, wheel-ondersteuning of buildvereisten daarvan niet op dezelfde basis gemeten.

Ter vergelijking zette de gepubliceerde benchmark nog twee andere Python-opties op dezelfde 10 MB-fixture, en die verschillen echt:

Parser (10 MB)p50
selectolax (lexbor)159,93 ms
lxml172,93 ms
parsel231,85 ms
selectolax (modest)247,95 ms
BeautifulSoup + lxml2.261,56 ms
BeautifulSoup + html.parser2.788,75 ms

Gepubliceerde cijfers uit bench_parse.json.

De historische benchmarkrijen zetten BeautifulSoup meer dan een orde van grootte boven de snellere parsermedianen op deze fixture. Die rijen zijn niet opnieuw gedraaid met de huidige PyQuery/lxml-combinatie in hetzelfde proces, dus het is nuttige context en geen gecontroleerde vermenigvuldigingsfactor voor het hoofdresultaat.

De opgeslagen cheerio-waarde was 2.927,89 ms (2927.8857 in parser-bench.json) met overeenkomende hashes van de geëxtraheerde content. Ook dit cross-runtime-resultaat hangt af van Node, pakketversies en de historische run-controls; lees het niet als een losse snelheidsvermenigvuldiger van de bibliotheek zelf.

De realiteit van de setup

BibliotheekPakkettenSchijfLicentieStarsLaatste push
PyQuery320,1 MiBBSD2.3802026-07-27
cheerio (Node)22 (npm)9,0 MiBMIT30.4492026-08-11

Officiële referentie: PyQuery op PyPI.

metadata-snapshot.json.

Drie pakketten is een nette afhankelijkheidsvoetafdruk, en twee daarvan — lxml en cssselect — heb je in veel Python-scrapingprojecten waarschijnlijk al in huis. In dat geval is de marginale kost van PyQuery slechts een paar tiental kilobyte.

Die 20,1 MiB komt van lxml’s gecompileerde extensies, niet van PyQuery. Dat is dezelfde 20 MiB die je betaalt als je lxml rechtstreeks gebruikt.

De bibliotheek heeft een BSD-licentie. Op basis van de snapshot had ze 59 open issues en een push drie weken vóór de test; die observaties alleen zeggen niets definitiefs over onderhoudskwaliteit of toekomstige compatibiliteit.

Geheugen, en wat kapotte HTML daarmee doet

Twee dingen die in elke review in deze batch als ongetest stonden, zijn nu gemeten.

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

Piek resident geheugen, via /usr/bin/time -l, één vers proces per cel — de importvloer is wat de bibliotheek kost als ze geladen en idle is, de pieken bevatten ook 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.

PyQuery is lichter dan resiliparse op het grote document — 172,5 MiB tegenover 225,1 — ondanks een hogere importvloer. lxml’s boomstructuur is compact, en het grootste deel van PyQuery’s 30,3 MiB vloer komt door het inladen van lxml, niet door iets wat PyQuery zelf doet.

Foutieve HTML. Twaalf documenten die elk precies één fout bevatten — niet-afgesloten tags, verkeerd geneste inline-elementen, attributen zonder quotes met spaties, losse sluit-tags, helemaal geen <html>, dubbele attributen, een document dat halverwege een tag is afgebroken, foute entiteiten, een niet-afgesloten <script>, een onjuiste charset-declaratie, een commentaar met markup, en 600 niveaus nesting — plus twee goed gevormde controles met passende grootte, omdat “het gaf niets terug” alleen iets zegt over malformedness als de bibliotheek ook op een schoon document van dezelfde grootte stil blijft.

pyquery gooide op 0 van 14 een fout en gaf in 1 geval niets terug, en herstelde 10/22 sentinels over de kapotte fixtures heen (malformed-results.json). Eén fixture telt niet mee in die telling: volgens HTML5 is alles na een niet-afgesloten <script> scriptinhoud, dus dat daar verliezen is correct en dat terugvinden zou juist de afwijking zijn. Zonder de sentinelresultaten van de directe alternatieven erbij is 10/22 een robuustheidsobservatie, geen parserkeuzerangschikking.

Plus- en minpunten

In het voordeel. jQuery-syntax, vertrouwd voor iedereen die front-end JavaScript heeft geschreven of cheerio heeft gebruikt. Er verscheen geen beslissingsrelevante selector-overhead tegenover kale lxml in deze fixture. Slechts 3 pakketten, en 2 daarvan heb je waarschijnlijk al in je tree. Het levert lxml-elementen op, dus lxml-technieken blijven beschikbaar. BSD. Contenthashes kwamen op alle vijf groottes overeen met de referentie.

Tegen. 20,1 MiB, vanwege lxml. 2.380 stars betekent een veel kleinere community dan cheerio’s 30.449 — minder uitgewerkte voorbeelden als iets vreemd doet. Het is een gemaklaag, dus wat lxml niet kan, kan het zelf ook niet. En als je hoopte dat de jQuery-API prestaties oplevert, doet hij dat niet: hij levert ergonomie, en de parser eronder doet het werk.

Wie het wel en niet moet gebruiken

Gebruik PyQuery als jij of je team jQuery-achtige selectors in Python prettig vindt. De gemeten constructie-, twee selecties- en uitleesroute liet geen beslissingsrelevante penalty zien tegenover lxml; andere PyQuery-operaties zijn niet getimed.

Gebruik lxml direct als je XPath prefereert of één pakket minder wilt. Deze run gaf geen selector-snelheidsreden om tussen beide te kiezen.

Evalueer selectolax als diens parser-API en afhankelijkheden bij je project passen. De 1 KB-rij is expliciet niet gerangschikt, en dit artikel ondersteunt geen claim over de “kleinste afhankelijkheidsvoetafdruk”.

In Node is cheerio de vergelijkbare API-vorm. De opgeslagen cross-runtime-rijen waren hier trager, maar verschillen in runtime en historische runs maken een zuivere conclusie op basis van alleen de bibliotheek onmogelijk.

Waar een managed API past

PyQuery parseert HTML die je al hebt. Het haalt niets op, rendert geen JavaScript en handelt geen anti-botlaag af — geen enkele parser in deze vergelijking doet dat, en bij veel echte doelwitten is juist dát de moeilijkere helft.

Opmerking van de auteur: Thunderbit is onze managed optie voor het ophalen/renderen van URL’s en extractie. Deze is hier niet tegen PyQuery gebenchmarkt. De relevante grens is of je al HTML in handen hebt en lokale selectors wilt, of dat je pagina-acquisitie en extractie als dienst wilt laten draaien.

De eerlijke insteek: als je de HTML al hebt en je selectors kent, is PyQuery gratis en prettig. Als selectors steeds breken, of je schaalt in het ophalen, dan koop je iets anders.

Voor het bredere veld behandelt onze round-up van web scraping API’s de gehoste opties en de open-source scraper-pijler de zelf-gehoste. Als de geparse output een model voedt, is HTML naar Markdown converteren in Python de plek waar fidelity verloren gaat.

Probeer Thunderbit voor webdata-extractie

Moet je PyQuery gebruiken?

Ja, als je jQuery-stijl syntax in Python wilt en het gemeten selecteren-en-uitlezen-pad overeenkomt met jouw workload.

De benchmark vond geen beslissingsrelevante selector-overhead tegenover lxml, terwijl contenthash-pariteit behouden bleef. Daarmee is niet bewezen dat de bibliotheek als geheel nul kost heeft.

Over vijf groottes bleven de drie Python-parsermedianen dicht genoeg bij elkaar dat API-fit voor deze taak waarschijnlijk belangrijker is dan pure snelheid. Definieer een equivalentiemarge en draai de exacte alternatieven opnieuw voordat je die conclusie omzet in een bredere parserranglijst.

Probeer Thunderbit voor webdata-extractie Get Started Free

Veelgestelde vragen

Maakt PyQuery lxml langzamer? In deze run verscheen geen beslissingsrelevante selector-overhead. Over vijf paginagroottes lagen de medianen op of onder kale lxml, waarbij beide lxml 6.1.1 gebruikten in hetzelfde proces. Bij 10 MB overlapten de nauwe bereiken niet: PyQuery 161,13–163,17 ms en lxml 164,18–169,46 ms. pq(html) bouwt een lxml-boom, en de geteste selectors compileren via cssselect.

Is selectolax sneller dan PyQuery? De mediaan bij 1 KB was lager, maar die rij is niet gerangschikt omdat variatie op microseconde-schaal overheerst. Vanaf 10 KB lagen de mediane verschillen tussen 0,5% en 5,4%. Dat is voor deze workload dicht bij elkaar, geen bewijs voor equivalentie of overlappende bereiken in elk geval.

Waarom lxml opnieuw draaien in plaats van het gepubliceerde getal citeren? Omdat de gepubliceerde benchmark de machine en de Python-versie vermeldt, maar niet de bibliotheekversies. De lxml-rij daar kan afkomstig zijn van een andere lxml dan degene die PyQuery vandaag omhult, en een versiekloof zou eruitzien als een wrapper-tax die er niet is. Door beide in één proces op lxml 6.1.1 te draaien, verdwijnt die ambiguïteit.

Hoe verhoudt het zich tot cheerio? Hetzelfde algemene API-idee, ander ecosysteem. De twee hier geteste selectors werkten in beide en contenthashes kwamen op alle vijf groottes overeen; dat bewijst geen volledige selectorcompatibiliteit. De opgeslagen cheerio-tijden waren trager, maar cross-runtime- en historische-run-controls maken een claim op basis van alleen de bibliotheek onmogelijk.

Wat is hier niet getest? Geheugen is gemeten als piek-RSS voor alleen import, een document van 226 KB en een document van 10 MB. Foutieve HTML is getest met 12 kapotte documenten plus twee gematchte controles. Nog ongetest zijn PyQuery’s mutatie- en traversalprestaties, caching van herhaalde queries, URL-fetching, concurrency en representatieve echte websites. De timing bij 1 KB blijft niet gerangschikt.

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 250.000+ gebruikers
gratis plan beschikbaar
Van webpagina naar spreadsheet
Beschrijf wat je nodig hebt — Thunderbit's AI Agent scrapt het en exporteert naar Excel, Google Sheets, Airtable of Notion. Gratis om te beginnen.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week