PyQuery Adiciona a Sintaxe do jQuery Sem Sobrecarregar a Decisão Neste Benchmark

Atualizado em August 18, 2026
PyQuery Adiciona a Sintaxe do jQuery Sem Sobrecarregar a Decisão Neste Benchmark
Resumo com IA
PyQuery coloca uma API no estilo jQuery sobre o lxml. Em cinco tamanhos de página, de 1 KB a 10 MB, todas as cinco medianas exibidas ficaram abaixo das do lxml puro, incluindo uma diferença de 1,5% no maior tamanho. O benchmark não prova que o wrapper seja mais rápido; ele não encontrou diferença grande o bastante para mudar esta decisão entre seleção e leitura. Também ficou dentro de poucos por cento do selectolax a partir de 10 KB nas medianas exibidas. Sem uma margem de equivalência definida, esse é um resultado próximo, não um empate estatístico.

PyQuery coloca uma API no estilo jQuery sobre o lxml. Em cinco tamanhos de página, de 1 KB a 10 MB, todas as cinco medianas exibidas ficaram abaixo das do lxml puro, incluindo uma diferença de 1,5% no maior tamanho. O benchmark não prova que o wrapper seja mais rápido; ele não encontrou diferença grande o bastante para mudar esta decisão entre selecionar e ler.

Também ficou dentro de poucos por cento do selectolax a partir de 10 KB nas medianas exibidas. Sem uma margem de equivalência definida מראש, isso é um resultado próximo, não um empate estatístico.

O que é o PyQuery

PyQuery é uma biblioteca Python que oferece a API de seleção e encadeamento do jQuery sobre uma árvore de documentos lxml. Versão testada: 2.1.0, licença BSD, 2.380 estrelas no GitHub, 59 issues abertas, último push em 2026-07-27.

Referência oficial: documentação do PyQuery.

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")]

Os elementos retornados são elementos lxml, então tudo o que você sabe fazer com lxml continua funcionando. Esse é o objetivo do projeto: PyQuery é uma camada de ergonomia, não um parser. pip install pyquery instala 3 pacotes — lxml, cssselect e o próprio PyQuery — e ocupa 20,1 MiB, quase tudo vindo das extensões compiladas do lxml.

Se você já usou cheerio no Node, a ideia geral da API é a mesma em Python. Os dois seletores testados aqui funcionaram em ambos; o teste não comprova paridade completa da linguagem de seleção entre cssselect e cheerio.

A medição

Esta base de pesquisa já tinha um benchmark de parser com uma propriedade que a maioria não tem: uma etapa de paridade que calcula hash do conteúdo extraído — títulos ordenados mais hrefs ordenados — contra um parser de referência, para que uma biblioteca que pule trabalho não possa registrar um tempo artificialmente rápido. Cinco tamanhos de página, 50 iterações, três execuções independentes.

Adicionar PyQuery a isso exigiu duas coisas.

Executar novamente a referência. selectolax rodou de novo no mesmo processo. O hash do conteúdo foi reproduzido em 5 de 5 tamanhos e o p50 ficou entre 0,989× e 1,079× do valor publicado — portanto, é a mesma máquina e o mesmo ambiente de teste.

Rodar lxml no mesmo processo também. O benchmark publicado registra a máquina e a versão do Python, mas não as versões das bibliotecas, então a linha de lxml poderia ter vindo de uma versão diferente daquela que o PyQuery encapsula aqui. Comparar atravessando essa diferença teria comparado duas versões de lxml e chamado isso de custo do wrapper. Executar lxml junto elimina a dúvida — ambos estão em lxml 6.1.1 neste ambiente virtual.

Tamanho da páginaselectolaxPyQuerylxmlPyQuery 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 em milissegundos, mediana de três execuções, tudo no mesmo processo. parser-bench.json. Todos os três hashes de conteúdo corresponderam à referência em todos os tamanhos.

O custo do wrapper que não apareceu

Measured results chart: PyQuery and lxml on the same fixture

PyQuery ficou no mesmo nível ou abaixo do lxml puro em todas as medianas exibidas. Isso não é prova de que um wrapper torne o parsing mais rápido. Três medianas de execução e nenhuma margem de equivalência predefinida sustentam apenas a conclusão mais restrita de que, neste fixture, não houve overhead de seletor relevante para a decisão.

Em 10 MB, as três execuções do PyQuery foram 162,86, 163,17 e 161,13 ms; as do lxml foram 169,46, 165,25 e 164,18. Os intervalos são próximos, mas não se sobrepõem. Em 1 MB, as duas medianas diferem em 0,5%. Essas execuções pequenas sustentam uma avaliação prática, não uma afirmação estatística de equivalência.

System diagram: Wrapper and Parser Boundaries

O mecanismo é simples: pq(html) constrói a árvore lxml uma única vez, d("h3.title") compila o seletor CSS via cssselect, como tree.cssselect() faz, e os elementos devolvidos são elementos lxml. Há pouco trabalho do PyQuery nesse caminho quente medido. Traversal, manipulação, consultas repetidas, importação e memória ficam fora da afirmação sobre tempo de seleção.

Resultados próximos a partir de 10 KB

A descoberta mais útil é a primeira coluna.

A partir de 10 KB, a diferença entre o mais rápido e o mais lento entre selectolax, lxml e PyQuery foi de 4,5% em 10 KB, 5,4% em 100 KB, 0,5% em 1 MB, e 4,5% em 10 MB. Esta execução não foi um teste de equivalência; o julgamento prático é que essas diferenças não mudariam a maioria das escolhas de parser para esta carga de trabalho.

selectolax é de fato mais rápido em 1 KB — 0,0286 ms contra 0,0456 e 0,0508 — mas essa linha não serve para ranqueamento. Entre os três parsers, a variação nesse tamanho é de 77,6%, e as três execuções do próprio selectolax variaram de 0,0267 a 0,0404 ms. Em 28 microssegundos, o timer e o escalonador dominam. Eu não classificaria nada ali.

Para esta carga de trabalho de seleção e leitura, escolha entre esses três com base na API e nos fatos medidos de dependência, e não por uma hierarquia presumida de velocidade. PyQuery não mostrou penalidade relevante em relação ao lxml. selectolax usa uma pilha de parsing diferente, mas este artigo não mediu seu footprint instalado, cobertura de wheels ou requisitos de build no mesmo critério.

Para contraste, o benchmark publicado colocou mais duas opções Python no mesmo fixture de 10 MB, e elas são as que realmente diferem:

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

Valores publicados de bench_parse.json.

As linhas históricas do benchmark colocam o BeautifulSoup mais de uma ordem de grandeza acima das medianas dos parsers mais rápidos neste fixture. Essas linhas não foram repetidas com o par PyQuery/lxml no processo atual, então servem como contexto, não como multiplicador controlado para o veredito principal.

A linha armazenada do cheerio foi 2.927,89 ms (2927.8857 em parser-bench.json) com hashes de conteúdo extraído correspondentes. Esse resultado entre runtimes também depende do Node, das versões dos pacotes e dos controles da execução histórica; não deve ser lido como um multiplicador isolado de velocidade da biblioteca.

Realidade de configuração

BibliotecaPacotesDiscoLicençaEstrelasÚltimo push
PyQuery320,1 MiBBSD2.3802026-07-27
cheerio (Node)22 (npm)9,0 MiBMIT30.4492026-08-11

Referência oficial: PyQuery no PyPI.

metadata-snapshot.json.

Três pacotes é uma pegada de dependência enxuta, e dois deles — lxml e cssselect — já fazem parte de muitos projetos Python de scraping. Nesse caso, o custo marginal do PyQuery é de apenas algumas dezenas de kilobytes.

Os 20,1 MiB são das extensões compiladas do lxml, não do PyQuery. É o mesmo custo de cerca de 20 MiB que você paga para usar lxml diretamente.

A biblioteca tem licença BSD. No snapshot datado, havia 59 issues abertas e um push três semanas antes do teste; essas observações, sozinhas, não provam qualidade de manutenção nem compatibilidade futura.

Memória, e o que HTML quebrado faz com ela

Duas coisas que todas as avaliações deste lote listavam como não testadas agora foram medidas.

O contexto mais amplo do teste de estresse está na comparação de memória e HTML malformado entre dez bibliotecas.

Memória residente máxima, via /usr/bin/time -l, um processo novo por célula — o piso de importação é o custo da biblioteca carregada e ociosa; os picos incluem o documento.

BibliotecaRuntimePiso de importaçãoPico 226 KBPico 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. Os baselines de Python e Node não são comparáveis entre si; o interpretador está dentro dos dois.

PyQuery é mais leve que resiliparse no documento grande — 172,5 MiB contra 225,1 — apesar de ter um piso de importação maior. A árvore do lxml é compacta, e a maior parte dos 30,3 MiB do piso do PyQuery vem do carregamento do lxml, não de algo que o PyQuery faça.

HTML quebrado. Doze documentos, cada um quebrando exatamente uma coisa — tags não fechadas, elementos inline mal aninhados, atributos sem aspas com espaços, fechamentos soltos, ausência total de <html>, atributos duplicados, documento truncado no meio de uma tag, entidades inválidas, um <script> não fechado, uma declaração de charset mentirosa, um comentário contendo marcação e 600 níveis de aninhamento — mais dois controles bem formados em tamanhos correspondentes, porque “não retornou nada” só diz algo sobre malformação se a biblioteca também não ficar muda num documento limpo do mesmo tamanho.

pyquery lançou exceção em 0 de 14 e não retornou nada em 1, recuperando 10/22 marcadores sentinela nos arquivos quebrados (malformed-results.json). Um arquivo é excluído dessa conta: segundo HTML5, tudo depois de um <script> não fechado é conteúdo de script, então perder isso ali está correto e recuperá-lo seria a divergência. Sem os resultados dos sentinelas das alternativas diretas lado a lado, 10/22 é uma observação de robustez, não um ranking de seleção de parser.

Prós e contras

A favor. Sintaxe jQuery, familiar para quem escreveu JavaScript de front-end ou usou cheerio. Não apareceu overhead de seletor relevante em relação ao lxml puro neste fixture. Apenas 3 pacotes, e 2 deles provavelmente já estão na sua árvore. Ele retorna elementos lxml, então as técnicas do lxml continuam disponíveis. BSD. Os hashes de conteúdo corresponderam à referência em todos os cinco tamanhos.

Contra. 20,1 MiB, por causa do lxml. 2.380 estrelas significam uma comunidade bem menor que a do cheerio, com 30.449 — menos exemplos práticos quando algo sai do padrão. É uma camada de conveniência, então tudo o que o lxml não faz, ele também não faz. E, se você esperava que a API do jQuery trouxesse performance, não traz: ela traz ergonomia, e o parser por baixo é quem faz o trabalho.

Quem deve usar e quem não deve

Use PyQuery se você ou seu time preferem seletores no estilo jQuery em Python. A construção medida, as duas seleções e as leituras não mostraram penalidade relevante em relação ao lxml; outras operações do PyQuery não foram medidas.

Use lxml diretamente se você prefere XPath ou quer um pacote a menos. Esta execução não mostrou motivo de velocidade de seletor para escolher entre eles.

Avalie selectolax se a API do parser e a pilha de dependências combinarem com seu projeto. A linha de 1 KB está explicitamente sem classificação, e este artigo não sustenta uma alegação de “menor conjunto de dependências”.

No Node, cheerio é a forma de API equivalente. As linhas históricas entre runtimes foram mais lentas aqui, mas as diferenças entre runtime e execução histórica impedem uma conclusão limpa apenas sobre a biblioteca.

Onde uma API gerenciada faz sentido

PyQuery faz parsing do HTML que você já tem. Ele não busca páginas, não renderiza JavaScript e não lida com camadas anti-bot — nenhum parser nesta comparação faz isso, e, em muitos alvos reais, essa é a metade mais difícil.

Nota do autor: Thunderbit é nossa opção gerenciada para busca/renderização por URL e extração. Ela não foi comparada com PyQuery aqui. A fronteira relevante é: você já tem o HTML e quer seletores locais, ou quer aquisição da página e extração operadas como serviço.

A formulação honesta é: se você já tem o HTML e conhece seus seletores, PyQuery é gratuito e agradável de usar. Se os seletores continuam quebrando, ou se você está extraindo em escala, isso é uma compra diferente.

Para o panorama mais amplo, nosso resumo de APIs de web scraping cobre opções hospedadas, e o guia principal de scrapers open source cobre as opções auto-hospedadas. Se a saída parseada alimentar um modelo, converter HTML em Markdown em Python é onde a fidelidade costuma se perder.

Experimente Thunderbit para Extração de Dados Web

Vale a pena usar PyQuery?

Sim, se você quer sintaxe no estilo jQuery em Python e o caminho medido de seleção/leitura representa sua carga de trabalho.

O benchmark não encontrou overhead de seletor relevante contra o lxml, mantendo a paridade de hash do conteúdo. Ele não provou custo zero para a biblioteca como um todo.

Em cinco tamanhos, as três medianas dos parsers Python ficaram próximas o suficiente para que o encaixe da API provavelmente pese mais nesta tarefa. Defina uma margem de equivalência e rode as alternativas exatas novamente antes de transformar esse julgamento em um ranking mais amplo de parsers.

Experimente Thunderbit para Extração de Dados Web Get Started Free

Perguntas frequentes

PyQuery deixa o lxml mais lento? Não apareceu overhead de seletor relevante nesta execução. Em cinco tamanhos de página, as medianas ficaram iguais ou abaixo das do lxml puro, ambos usando lxml 6.1.1 no mesmo processo. Em 10 MB, os intervalos próximos não se sobrepuseram: PyQuery 161,13–163,17 ms e lxml 164,18–169,46 ms. pq(html) constrói uma árvore lxml, e os seletores testados são compilados via cssselect.

selectolax é mais rápido que PyQuery? A mediana de 1 KB foi menor, mas essa linha não entra no ranking porque a variação domina na escala de microssegundos. A partir de 10 KB, as diferenças entre medianas ficaram entre 0,5% e 5,4%. Isso é próximo para esta carga de trabalho, não uma prova de equivalência nem de faixas sobrepostas em todos os casos.

Por que rodar lxml de novo em vez de citar o número publicado? Porque o benchmark publicado registra a máquina e a versão do Python, mas não as versões das bibliotecas. A linha de lxml poderia vir de um lxml diferente daquele encapsulado pelo PyQuery hoje, e uma diferença de versão apareceria como um custo do wrapper que não existe. Rodar ambos no mesmo processo com lxml 6.1.1 elimina a ambiguidade.

Como ele se compara com cheerio? A mesma ideia geral de API, ecossistema diferente. Os dois seletores testados aqui funcionaram em ambos, e os hashes de conteúdo corresponderam em todos os cinco tamanhos; isso não comprova compatibilidade completa de seletores. Os tempos armazenados do cheerio foram mais lentos, mas os controles entre runtimes e execuções históricas impedem uma afirmação de multiplicador apenas da biblioteca.

O que não foi testado aqui? A memória foi medida como RSS máxima para importação apenas, um documento de 226 KB e um documento de 10 MB. O HTML malformado foi exercitado com 12 documentos quebrados mais dois controles correspondentes. Ainda não foram testados o desempenho de manipulação e traversal do PyQuery, cache de consultas repetidas, busca por URL, concorrência e cargas representativas de sites reais. O tempo de 1 KB continua sem classificação.

Ke
Ke
CTO na Thunderbit | Cientista de Dados Sênior e Especialista em ML Com quase uma década de experiência em machine learning e data science, Ke Shen é ex-aluno da Columbia University e foi Cientista de Dados Sênior na Walmart Labs. Com profunda experiência, reconhecida pelos pares, em Python, R, Java e Estatística, ele compartilha insights testados em batalha sobre como levar algoritmos complexos de IA da teoria à arquitetura pronta para produção.
Índice
Thunderbit · Agente de dados web com IA

Extraia dados de qualquer página em 1 clique

Confiado por mais de 250.000 usuários
plano grátis disponível
Da página web para a planilha
Descreva o que você precisa — o Agente de IA da Thunderbit extrai e exporta para Excel, Google Sheets, Airtable ou Notion. Comece grátis.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week