PyQuery ergänzt jQuery-Syntax, ohne in diesem Benchmark einen entscheidenden Selector-Overhead zu verursachen

Zuletzt aktualisiert am August 18, 2026
PyQuery ergänzt jQuery-Syntax, ohne in diesem Benchmark einen entscheidenden Selector-Overhead zu verursachen
KI-Zusammenfassung
PyQuery setzt eine jQuery-ähnliche API auf lxml auf. Über fünf Seitengrößen von 1 KB bis 10 MB lagen alle fünf angezeigten Medianwerte unter denen von rohem lxml, einschließlich eines Unterschieds von 1,5 % bei der größten Größe. Der Benchmark belegt jedoch nicht, dass der Wrapper schneller ist; er zeigte keinen Unterschied, der diese Entscheidung zwischen Selector und Auslesen ändern würde. Ab 10 KB lag PyQuery in den angezeigten Medianen außerdem innerhalb weniger Prozentpunkte von selectolax entfernt. Ohne vorab festgelegte Äquivalenzgrenze ist das ein knappes Ergebnis, aber kein statistisches Unentschieden.

PyQuery setzt eine jQuery-ähnliche API auf lxml auf. Über fünf Seitengrößen von 1 KB bis 10 MB lagen alle fünf angezeigten Medianwerte unter denen von reinem lxml, einschließlich eines Unterschieds von 1,5 % bei der größten Größe. Der Benchmark belegt jedoch nicht, dass der Wrapper schneller ist; er zeigte keinen Unterschied, der diese Entscheidung zwischen Selector und Auslesen ändern würde.

Ab 10 KB lag PyQuery in den angezeigten Medianen außerdem innerhalb weniger Prozentpunkte von selectolax entfernt. Ohne vorab festgelegte Äquivalenzgrenze ist das ein knappes Ergebnis, aber kein statistisches Unentschieden.

Was PyQuery ist

PyQuery ist eine Python-Bibliothek, die Ihnen die Selector- und Chain-API von jQuery für einen lxml-Dokumentbaum bereitstellt. Getestete Version: 2.1.0, BSD-lizenziert, 2.380 GitHub-Stars, 59 offene Issues, zuletzt gepusht am 2026-07-27.

Offizielle Referenz: PyQuery-Dokumentation.

Systemdiagramm: jQuery-Syntax auf 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")]

Die Elemente, die PyQuery zurückgibt, sind lxml-Elemente. Alles, was Sie mit lxml können, funktioniert also weiterhin. Genau das ist das Konzept: PyQuery ist eine Komfortschicht, kein Parser. pip install pyquery bringt 3 Pakete mit — lxml, cssselect und PyQuery selbst — sowie 20,1 MiB, fast alles davon entfällt auf lxmls kompilierte Erweiterungen.

Wenn Sie in Node schon mit cheerio gearbeitet haben, ist das hier im Grunde dieselbe API-Idee für Python. Die beiden hier getesteten Selector funktionierten in beiden Fällen; der Test belegt jedoch keine vollständige Sprachparität zwischen cssselect und cheerio.

Die Messung

Die zugrunde liegende Benchmark-Basis hatte bereits einen Vorteil, den viele Tests nicht haben: eine Paritätsprüfung, die extrahierte Inhalte hasht — sortierte Titel plus sortierte Hrefs — und mit einem Referenzparser vergleicht. Ein Library-Kandidat kann also kein schnelleres Ergebnis erreichen, indem er einfach Arbeit weglässt. Fünf Seitengrößen, 50 Iterationen, drei unabhängige Durchläufe.

PyQuery in diesen Aufbau zu integrieren erforderte zwei Dinge.

Die Referenz neu auszuführen. selectolax lief erneut im selben Prozess. Der Content-Hash stimmte bei 5 von 5 Größen überein, und sein p50 lag zwischen 0,989× und 1,079× des veröffentlichten Werts — also ist das hier dieselbe Maschine und dieselbe Testumgebung.

Auch lxml im selben Prozess auszuführen. Im veröffentlichten Benchmark sind Maschine und Python-Version dokumentiert, nicht aber die Library-Versionen. Der dortige lxml-Wert könnte daher aus einer anderen lxml-Version stammen als der, den PyQuery hier verwendet. Ein Vergleich über diese Lücke hinweg hätte zwei lxml-Versionen miteinander verglichen und daraus einen Wrapper-Aufschlag gemacht. Wenn lxml direkt daneben gemessen wird, entfällt dieses Problem — beide sind in diesem venv lxml 6.1.1.

SeitengrößeselectolaxPyQuerylxmlPyQuery 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 Millisekunden, Median von drei Durchläufen, alles in einem Prozess. parser-bench.json. Alle drei Content-Hashes stimmten bei jeder Größe mit der Referenz überein.

Der Wrapper-Aufpreis, der keiner war

Gemessene Ergebnisse: PyQuery und lxml auf demselben Testdatensatz

PyQuery lag bei jedem angezeigten Median auf oder unter rohem lxml. Das ist kein Beweis dafür, dass ein Wrapper Parsen beschleunigt. Drei Durchlauf-Mediane und keine vorgegebene Äquivalenzgrenze stützen nur die engere Aussage, dass dieser Testdatensatz keinen entscheidenden Selector-Overhead gezeigt hat.

Bei 10 MB lagen die drei PyQuery-Läufe bei 162.86, 163.17 und 161.13 ms; lxml lag bei 169.46, 165.25 und 164.18 ms. Die Spannen sind nah beieinander, überlappen aber nicht. Bei 1 MB unterscheiden sich die beiden Mediane um 0,5 %. Diese kleinen Läufe tragen eine praktische Bewertung, keine statistische Äquivalenzbehauptung.

Systemdiagramm: Grenzen zwischen Wrapper und Parser

Der Mechanismus ist recht einfach: pq(html) baut den lxml-Baum einmal auf, d("h3.title") kompiliert den CSS-Selector über cssselect genauso wie tree.cssselect(), und die zurückgegebenen Elemente sind lxml-Elemente. In diesem gemessenen Hot Path bleibt daher nur wenig Arbeit für PyQuery selbst. Traversierung, Manipulation, wiederholte Abfragen, Import und Speicherverbrauch liegen außerhalb der hier gemachten Selector-Zeit-Aussage.

Knappe Ergebnisse ab 10 KB

Das nützlichere Ergebnis steht in der ersten Spalte.

Ab 10 KB betrug die Spreizung zwischen dem schnellsten und dem langsamsten Median unter selectolax, lxml und PyQuery 4,5 % bei 10 KB, 5,4 % bei 100 KB, 0,5 % bei 1 MB und 4,5 % bei 10 MB. Dieser Lauf war kein Äquivalenztest; praktisch heißt das vor allem, dass diese Abstände bei diesem Workload für die meisten Parser-Entscheidungen keine Rolle spielen dürften.

selectolax ist bei 1 KB tatsächlich schneller — 0.0286 ms gegenüber 0.0456 und 0.0508 — aber diese Zeile ist nicht belastbar. Über alle drei Parser beträgt die Spanne bei dieser Größe 77,6 %, und die drei selectolax-Läufe reichten von 0.0267 bis 0.0404 ms. Bei 28 Mikrosekunden dominieren Timer und Scheduler. Dort würde ich nichts gewichten.

Für diesen Selector-und-Lese-Workload sollten Sie zwischen diesen drei Varianten nach API- und gemessenen Abhängigkeitsfakten wählen, nicht nach einer angenommenen Geschwindigkeitsrangfolge. PyQuery zeigte gegenüber lxml keinen entscheidenden Nachteil. selectolax nutzt einen anderen Parser-Stack, aber dieser Artikel hat weder den Installationsumfang, die Wheel-Abdeckung noch die Build-Anforderungen auf derselben Basis gemessen.

Zum Vergleich wurden im veröffentlichten Benchmark noch zwei weitere Python-Optionen mit demselben 10-MB-Testdatensatz erfasst, und genau dort liegen die echten Unterschiede:

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

Veröffentlichte Werte aus bench_parse.json.

Die historischen Benchmark-Zeilen zeigen BeautifulSoup auf diesem Datensatz mehr als eine Größenordnung über den schnelleren Parser-Medianen. Diese Werte wurden nicht gemeinsam mit dem aktuellen PyQuery/lxml-Paar erneut ausgeführt, daher sind sie eher Kontext als ein kontrollierter Multiplikator für das Haupturteil.

Die gespeicherte cheerio-Zeile lag bei 2.927,89 ms (2927.8857 in parser-bench.json) und die extrahierten Inhalte stimmten per Hash überein. Dieses Ergebnis über Laufzeitgrenzen hinweg hängt ebenfalls von Node, Paketversionen und den historischen Laufkontrollen ab; man sollte es nicht als isolierten Library-Geschwindigkeitsfaktor lesen.

Realität der Einrichtung

LibraryPaketeSpeicherbedarfLizenzStarsLetzter Push
PyQuery320.1 MiBBSD2,3802026-07-27
cheerio (Node)22 (npm)9.0 MiBMIT30,4492026-08-11

Offizielle Referenz: PyQuery auf PyPI.

metadata-snapshot.json.

Drei Pakete sind ein überschaubarer Footprint, und zwei davon — lxml und cssselect — gehören ohnehin zu vielen Python-Scraping-Projekten. In diesem Fall kostet PyQuery also nur wenige Dutzend Kilobyte zusätzlich.

Die 20,1 MiB entfallen auf lxmls kompilierte Erweiterungen, nicht auf PyQuery. Das sind dieselben rund 20 MiB, die Sie auch zahlen, wenn Sie lxml direkt nutzen.

Die Bibliothek ist BSD-lizenziert. Zum Zeitpunkt des Snapshots hatte sie 59 offene Issues und einen Push drei Wochen vor dem Test; daraus allein lässt sich weder Wartungsqualität noch künftige Kompatibilität ableiten.

Speicher und was kaputtes HTML damit macht

Zwei Dinge, die in jeder Review dieser Runde zunächst als ungetestet galten, wurden nun gemessen.

Der breitere Kontext des Stresstests findet sich im Vergleich von zehn Bibliotheken zu Speicherverbrauch und fehlerhaftem HTML.

Spitzenwert des residenten Speichers mittels /usr/bin/time -l, pro Zelle ein frischer Prozess — die Import-Basis ist das, was die Bibliothek im geladenen und idle Zustand kostet; die Spitzenwerte enthalten das Dokument.

LibraryRuntimeImport-BasisPeak bei 226 KBPeak bei 10 MB
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- und Node-Baselines sind untereinander nicht direkt vergleichbar; der Interpreter steckt in beiden mit drin.

PyQuery ist bei dem großen Dokument leichter als resiliparse — 172,5 MiB gegenüber 225,1 — trotz höherer Import-Basis. lxmls Baum ist kompakt, und der Großteil von PyQuerys 30,3 MiB Basis entfällt darauf, dass lxml geladen wird, nicht auf eine zusätzliche Eigenleistung von PyQuery.

Defektes HTML. Zwölf Dokumente, die jeweils genau eine Sache kaputt machen — ungeschlossene Tags, falsch verschachtelte Inline-Elemente, ungequotete Attribute mit Leerzeichen, übrig gebliebene schließende Tags, gar kein <html>, doppelte Attribute, ein mitten im Tag abgeschnittenes Dokument, fehlerhafte Entities, ein nicht geschlossenes <script>, eine falsche Charset-Deklaration, ein Kommentar mit Markup und 600 Ebenen Verschachtelung — plus zwei wohlgeformte Kontrollen in passenden Größen, denn „es kam nichts zurück“ sagt nur dann etwas über Defekte aus, wenn die Bibliothek bei einem sauberen Dokument derselben Größe nicht ebenfalls stumm bleibt.

pyquery warf bei 0 von 14 eine Ausnahme und gab bei 1 nichts zurück; es stellte 10/22 Sentinel-Werte über die kaputten Fixtures wieder her (malformed-results.json). Eine Fixture ist aus dieser Zählung ausgenommen: Nach HTML5 ist alles nach einem nicht geschlossenen <script> tatsächlich Script-Inhalt, also ist der Verlust dort korrekt und die Wiederherstellung die Abweichung. Ohne die direkten Alternativen zum Vergleich sind 10/22 eine Robustheitsbeobachtung, keine Rangliste für die Parser-Auswahl.

Vor- und Nachteile

Spricht dafür. jQuery-Syntax, vertraut für alle, die Frontend-JavaScript geschrieben oder cheerio genutzt haben. In diesem Test trat kein entscheidender Selector-Overhead gegenüber rohem lxml auf. Nur 3 Pakete, und 2 davon haben Sie wahrscheinlich ohnehin schon im Projekt. Es liefert lxml-Elemente zurück, daher bleiben lxml-Techniken nutzbar. BSD. Die Content-Hashes stimmten bei allen fünf Größen mit der Referenz überein.

Spricht dagegen. 20,1 MiB, wegen lxml. 2.380 Sterne bedeuten eine deutlich kleinere Community als cheerios 30.449 — also weniger Praxisbeispiele, wenn etwas ungewöhnlich ist. Es ist eine Komfortschicht, also kann es nichts, was lxml grundsätzlich nicht kann. Und wer gehofft hat, die jQuery-API bringe Performance, liegt falsch: Sie bringt Ergonomie, und die eigentliche Arbeit erledigt der Parser darunter.

Wer PyQuery nutzen sollte — und wer nicht

PyQuery nutzen, wenn Sie oder Ihr Team in Python lieber mit jQuery-ähnlichen Selector arbeiten. Der gemessene Pfad aus Erzeugen, zwei Selektionen und Auslesen zeigte keinen entscheidenden Nachteil gegenüber lxml; andere PyQuery-Operationen wurden nicht gemessen.

lxml direkt nutzen, wenn Sie XPath bevorzugen oder ein Paket weniger wollen. Dieser Lauf zeigte keinen selector-basierten Geschwindigkeitsgrund, zwischen beiden zu wählen.

selectolax prüfen, wenn seine Parser-API und sein Abhängigkeitsstack zu Ihrem Projekt passen. Die 1-KB-Zeile ist ausdrücklich nicht gerankt, und dieser Artikel stützt keine Behauptung über das „kleinste“ Dependency-Set.

In Node ist cheerio die entsprechende API-Form. Die gespeicherten Cross-Runtime-Werte waren hier langsamer, aber Unterschiede zwischen Laufzeit und historischem Lauf verhindern ein sauberes Fazit nur über die Library.

Wo eine verwaltete API passt

PyQuery verarbeitet HTML, das Sie bereits haben. Es lädt keine Seiten, rendert kein JavaScript und kümmert sich nicht um Anti-Bot-Schichten — kein Parser in diesem Vergleich tut das, und bei vielen echten Zielen ist genau dieser Teil die schwierigere Hälfte.

Hinweis der Redaktion: Thunderbit ist unsere verwaltete Option für Abruf/Rendering per URL und Extraktion. Sie wurde hier nicht gegen PyQuery benchmarked. Die relevante Grenze ist: Liegt Ihnen bereits HTML vor und Sie wollen lokale Selector, oder möchten Sie Seitenabruf und Extraktion als Service betreiben lassen?

Die ehrliche Einordnung: Wenn Sie das HTML bereits haben und Ihre Selector kennen, ist PyQuery kostenlos und angenehm. Wenn die Selector ständig brechen oder Sie in großem Umfang abrufen, ist das eine andere Investition.

Für den breiteren Markt deckt unsere Übersicht zu Web-Scraping-APIs gehostete Optionen ab und unser Open-Source-Scraper-Überblick die selbst gehosteten Varianten. Wenn die extrahierten Daten in ein Modell fließen, ist HTML in Python zu Markdown konvertieren der Punkt, an dem am meisten Qualität verloren geht.

Thunderbit für Web-Datenextraktion testen

Sollten Sie PyQuery verwenden?

Ja, wenn Sie in Python jQuery-ähnliche Syntax möchten und der gemessene Selector-/Lese-Pfad Ihrem Workload entspricht.

Der Benchmark zeigte keinen entscheidenden Selector-Overhead gegenüber lxml, während die Content-Hash-Parität erhalten blieb. Er hat jedoch nicht bewiesen, dass die Bibliothek insgesamt null Kosten hat.

Über fünf Größen hinweg blieben die drei Python-Parser-Mediane eng genug beieinander, dass für diese Aufgabe die API-Passung wahrscheinlich wichtiger ist als reine Geschwindigkeit. Definieren Sie eine Äquivalenzgrenze und messen Sie die exakten Alternativen erneut, bevor Sie daraus eine breitere Parser-Rangfolge ableiten.

Thunderbit für Web-Datenextraktion testen Get Started Free

FAQs

Verlangsamt PyQuery lxml? In diesem Lauf trat kein entscheidender Selector-Overhead auf. Über fünf Seitengrößen lagen die Mediane bei oder unter denen von rohem lxml, beide mit lxml 6.1.1 im selben Prozess. Bei 10 MB überlappten die knappen Spannen nicht: PyQuery 161.13–163.17 ms und lxml 164.18–169.46 ms. pq(html) baut einen lxml-Baum auf, und die getesteten Selector werden über cssselect kompiliert.

Ist selectolax schneller als PyQuery? Bei 1 KB war der Median niedriger, aber diese Zeile ist nicht gerankt, weil die Schwankung im Mikrosekundenbereich dominiert. Ab 10 KB lagen die Median-Abstände bei 0,5 % bis 5,4 %. Für diesen Workload ist das nah beieinander, kein Beweis für Äquivalenz oder für überlappende Spannen in jedem Fall.

Warum lxml neu messen, statt die veröffentlichte Zahl zu zitieren? Weil der veröffentlichte Benchmark zwar Maschine und Python-Version dokumentiert, nicht aber die Library-Versionen. Der lxml-Wert dort könnte von einer anderen lxml-Version stammen als der, den PyQuery heute verwendet, und eine Versionslücke hätte wie ein Wrapper-Aufpreis ausgesehen, der gar nicht existiert. Wenn beide im selben Prozess mit lxml 6.1.1 laufen, verschwindet die Unklarheit.

Wie schneidet es im Vergleich zu cheerio ab? Die API-Idee ist dieselbe, das Ökosystem ist anders. Die beiden hier getesteten Selector funktionierten in beiden, und die Content-Hashes stimmten bei allen fünf Größen überein; das beweist aber keine vollständige Selector-Kompatibilität. Die gespeicherten cheerio-Zeiten waren langsamer, doch Cross-Runtime- und historische Laufkontrollen verhindern eine reine Library-Multiplikator-Aussage.

Was wurde hier nicht getestet? Der Speicher wurde als Peak-RSS für reinen Import, ein 226-KB-Dokument und ein 10-MB-Dokument gemessen. Fehlerhaftes HTML wurde mit 12 kaputten Dokumenten plus zwei passenden Kontrollen getestet. Weiterhin ungetestet sind PyQuerys Manipulations- und Traversierungsleistung, Caching bei wiederholten Abfragen, URL-Fetching, Parallelität und repräsentative Real-World-Workloads. Die 1-KB-Zeit bleibt nicht gerankt.

Ke
Ke
CTO bei Thunderbit | Senior Data Scientist & ML-Experte Mit fast zehn Jahren Erfahrung in Machine Learning und Data Science ist Ke Shen Absolvent der Columbia University und ehemaliger Senior Data Scientist bei Walmart Labs. Mit tiefgreifender, von Fachkollegen anerkannter Expertise in Python, R, Java und Statistik teilt er praxiserprobte Einblicke dazu, wie sich komplexe KI-Algorithmen von der Theorie in eine produktionsreife Architektur überführen lassen.
Inhaltsverzeichnis
Thunderbit · KI-Web-Daten-Agent

Daten von jeder Seite in 1 Klick extrahieren

Vertraut von über 250.000 Nutzern
kostenloser Plan verfügbar
Von der Webseite zur Tabelle
Beschreibe einfach, was du brauchst — Thunderbits KI-Agent erfasst es und exportiert es nach Excel, Google Sheets, Airtable oder Notion. Kostenlos loslegen.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week