niquests Web Scraping: Requisições HTTP/2 Modernas para Python
Senior Web Scraping Engineer
TL;DR:
- niquests é um substituto integrado para requests com a mesma API, além de HTTP/2, HTTP/3 e multiplexação de conexões — troque a importação e seu código continua funcionando.
- O que niquests não faz é renderizar JavaScript. É um cliente HTTP; em uma página construída por scripts, ele retorna a marcação que o servidor enviou, que não contém nenhum conteúdo.
- A lacuna aparece em um script. niquests busca uma página de demonstração renderizada em JavaScript via HTTP/2 e encontra 0 blocos de citação nela.
- niquests também é o cliente que chama Scrapeless. Uma execução ao vivo usou a mesma sessão para POSTAR a URL para a API Universal de Scraping Scrapeless, recebeu o HTML renderizado de volta e extraiu todos os 10 autores dele.
- Um cliente HTTP para ambos os trabalhos. Busca diretas onde funcionam, a API Scrapeless onde a renderização é necessária — mesma
Session, mesma API. - Gratuito para começar do lado da busca. Crie sua chave API Scrapeless em app.scrapeless.com.
O que é niquests e o que não é
niquests é um fork de requests que mantém a API que você já conhece — Session, get, post, json() — e adiciona os recursos de transporte que requests nunca teve: HTTP/2 e HTTP/3, multiplexação de conexões e DNS-over-HTTPS. Para um scraper, a vantagem prática é que import niquests as requests atualiza uma base de código existente para HTTP moderno sem reescrita, e o transporte multiplexado move muitas requisições por menos conexões.
O que não é é um navegador. niquests fala HTTP, então retorna exatamente o que o servidor envia; não executa o JavaScript que constrói o conteúdo de uma página moderna. Um transporte mais rápido e moderno não muda isso — uma página vazia buscada via HTTP/2 ainda está vazia. Portanto, um scraper niquests tem duas funções para um cliente: buscar as páginas que servem seu conteúdo diretamente e, para as páginas que o constroem com scripts, chamar uma API de renderização. Este guia usa a API Universal de Scraping Scrapeless para a segunda função, com o niquests fazendo essa chamada. Para uma caixa de ferramentas mais ampla, o tutorial de scraping web em Python é o companion.
Instalar
niquests é toda a cadeia de ferramentas — não precisa de um parser separado para este guia. A versão para a qual este guia foi escrito é niquests 3.20.1:
bash
pip install "niquests==3.20.1"
Mantenha sua chave no ambiente, nunca no código-fonte:
bash
export SCRAPELESS_API_KEY="sk_your_scrapeless_key"
A busca direta e onde ela para
Aponte niquests para uma página renderizada em JavaScript e duas coisas são verdadeiras ao mesmo tempo: o transporte é moderno e o conteúdo está faltando. A conexão negocia HTTP/2 — um protocolo definido pelo padrão HTTP/2 que requests não fala — porém a marcação retornada tem zero blocos de citação, porque o conteúdo é construído do lado do cliente, conforme a especificação de script HTML:
python
# direct.py — transporte moderno, conteúdo ausente
import niquests
session = niquests.Session()
resp = session.get("https://quotes.toscrape.com/js/", timeout=30)
print("versão http:", resp.conn_info.http_version)
print("blocos de citação da página js:", resp.text.count('class="quote"'))
O transporte é HTTP/2; o conteúdo não está lá:
text
versão http: HttpVersion.h2
blocos de citação da página js: 0
Esse zero não é uma falha do niquests — é o resultado correto para um cliente HTTP em uma página cujo conteúdo chega depois que os scripts são executados. A solução é uma camada de busca que renderiza.
A busca renderizada, com niquests chamando Scrapeless
Mantenha a mesma sessão e mude o alvo: em vez da página, POST a URL para a API Universal de Scraping Scrapeless, que renderiza do lado do servidor e retorna o HTML final. niquests trata essa solicitação como qualquer outra, então um cliente cobre ambos os caminhos — a camada de solicitação e resposta aqui segue o padrão de semântica HTTP:
python
# rendered.py — niquests chama a API de renderização, então extrai
import os
import re
import niquests
session = niquests.Session()
resp = session.post(
"https://api.scrapeless.com/api/v2/unlocker/request",
headers={"x-api-token": os.environ["SCRAPELESS_API_KEY"]},
json={"actor": "unlocker.webunlocker", "input": {"url": "https://quotes.toscrape.com/js/", "js_render": True}},
timeout=120,
)
resp.raise_for_status()
html = resp.json()["data"]
authors = re.findall(r'<small class="author">(.*?)</small>', html)
print("blocos de citação renderizados:", html.count('class="quote"'))
print("autores extraídos:", len(authors))
print("primeiro autor:", authors[0])
Agora o conteúdo está presente e é extraível:
text
blocos de citação renderizados: 10
autores extraídos: 10
primeiro autor: Albert Einstein
Esse é o scraper completo, e ele nunca deixou niquests: uma `Session` fazendo uma solicitação direta onde isso funciona e uma solicitação Scrapeless onde a renderização é necessária. A [Universal Scraping API](https://www.scrapeless.com/pt/product/universal-scraping-api?utm_source=website&utm_medium=blog&utm_campaign=universalscrapingapi&utm_term=niquests-web-scraping) faz a renderização; niquests faz o HTTP.
> Obtenha sua chave de API no plano gratuito: [app.scrapeless.com](https://app.scrapeless.com/passport/login?utm_source=website&utm_medium=blog&utm_campaign=universalscrapingapi&utm_term=niquests-web-scraping)
## Padrões avançados
- **Migre com uma linha.** `import niquests as requests` permite que um código existente de `requests` adote HTTP/2 e multiplexação sem outras alterações; a API é a mesma.
- **Reutilize a sessão.** Uma única `niquests.Session()` agrupa e multiplica conexões, onde a vantagem de transporte aparece em muitas solicitações — construa uma vez e passe adiante.
- **Adicione um parser real quando você ultrapassar regex.** O regex aqui mantém o exemplo em uma única dependência; para qualquer coisa além de uma lista simples, forneça `resp.json()["data"]` a uma biblioteca de seleção e selecione campos estruturados.
- **Deixe que ele negocie.** Niquests escolhe HTTP/2 ou HTTP/3 quando o servidor o oferece e retorna limpo quando não oferece; você não configura a versão, você a lê de `conn_info` quando deseja confirmar.
## Resolução de problemas
- **`conn_info.http_version` é HTTP/1.1.** O servidor não ofereceu HTTP/2 para essa solicitação, ou um intermediário o rebaixou. Isso é normal e não é um erro; niquests utiliza a melhor versão disponível.
- **Zero blocos de uma página que você pode ver em um navegador.** O conteúdo é renderizado em JavaScript e a busca direta retornou HTML pré-renderizado — o caso `js-page quote blocks: 0`. Rote essa URL através da chamada Scrapeless com `js_render` em vez disso.
- **`json()` gera erro na resposta do Scrapeless.** A solicitação falhou antes da renderização. Chame `raise_for_status()` primeiro e confirme se a chave está definida e o ator e a entrada estão moldados conforme mostrado.
- **Timeouts em páginas lentas.** A renderização leva mais tempo do que uma busca estática. Dê ao POST do Scrapeless um `timeout` generoso, como o exemplo faz, em vez do curto padrão que você usaria para uma solicitação direta.
## Conclusão
Niquests conquista seu lugar como o único cliente HTTP que um scraper precisa: a API `requests` com transporte moderno, lidando tanto com a busca direta quanto com a chamada a uma API de renderização. A camada que transforma uma página construída por script em conteúdo é a busca — o resultado de zero blocos da solicitação direta confirma isso — e um POST Scrapeless, feito pelo próprio niquests, fecha a lacuna. Conecte os dois caminhos em uma única sessão e os dez autores da página de demonstração voltam via HTTP que você não precisou reescrever.
[Criar uma conta gratuita no Scrapeless](https://app.scrapeless.com/passport/login?utm_source=website&utm_medium=blog&utm_campaign=universalscrapingapi&utm_term=niquests-web-scraping) para obter uma chave de API, e a [documentação para desenvolvedores](https://docs.scrapeless.com?utm_source=website&utm_medium=blog&utm_campaign=universalscrapingapi&utm_term=niquests-web-scraping) cobre os parâmetros `unlocker.webunlocker`. Confira [preços do Scrapeless](https://www.scrapeless.com/pt/pricing?utm_source=website&utm_medium=blog&utm_campaign=universalscrapingapi&utm_term=niquests-web-scraping) quando planejar um trabalho recorrente.
## FAQ
**P: O niquests pode raspar páginas renderizadas em JavaScript por si só?**
Não. Niquests é um cliente HTTP, não um navegador; ele retorna a marcação que o servidor envia e não executa scripts. Em uma página que constrói seu conteúdo no lado do cliente, a busca direta retorna com o conteúdo faltando — o resultado de zero blocos do guia. Rote essas páginas através da Universal Scraping API Scrapeless, que as renderiza, e o niquests faz essa chamada também.
**P: Como niquests é diferente de requests?**
Mesma API, transporte mais novo. Niquests é um fork do `requests` que adiciona HTTP/2, HTTP/3, multiplexação de conexão e DNS sobre HTTPS, mantendo `Session`, `get`, `post` e `json()` idênticos. `import niquests as requests` geralmente é toda a migração.
**P: Eu preciso de um parser separado?**
Para uma lista simples de campos, um regex ou a biblioteca padrão é suficiente, como mostrado. Para extração aninhada ou estruturada, combine niquests com uma biblioteca de seleção — niquests busca, o parser seleciona. Este guia se mantém em uma única dependência de propósito.
**P: O HTTP/2 ajuda a raspar blocos?**
É uma atualização de transporte, não uma medida anti-bloqueio. A multiplexação HTTP/2 melhora o rendimento em muitas solicitações, mas não renderiza JavaScript ou elimina desafios de acesso — esse é o trabalho da camada de busca, que é por isso que o caminho renderizado passa pela Scrapeless.
**P: É legal raspar com niquests?**
O cliente HTTP não altera as regras de coleta. Busque apenas páginas públicas, respeite os termos do site e as diretrizes de robôs padronizadas pelo <a href="https://datatracker.ietf.org/doc/html/rfc9309" rel="nofollow"><strong>Protocolo de Exclusão de Robôs</strong></a>, mantenha os volumes limitados e trate quaisquer dados pessoais de acordo com as leis que se aplicam a você.
Na Scorretless, acessamos apenas dados disponíveis ao público, enquanto cumprem estritamente as leis, regulamentos e políticas de privacidade do site aplicáveis. O conteúdo deste blog é apenas para fins de demonstração e não envolve atividades ilegais ou infratoras. Não temos garantias e negamos toda a responsabilidade pelo uso de informações deste blog ou links de terceiros. Antes de se envolver em qualquer atividade de raspagem, consulte seu consultor jurídico e revise os termos de serviço do site de destino ou obtenha as permissões necessárias.



