Captura de dados na Web com HTTPX em Python

Explore o HTTPX, um poderoso cliente HTTP Python para web scraping. Aprenda sobre a configuração, os recursos, as técnicas avançadas e como eles se comparam com o Requests.
15 min read
web scraping with httpx and python blog image

Neste artigo, você vai aprender:

  • O que é HTTP e os recursos que ele oferece
  • Como usar HTTPX para web scraping em uma seção guiada
  • Recursos avançados de HTTPX para captura de dados na web
  • Uma comparação entre HTTPX vs. Pedidos para requisições automatizadas

Vamos lá!

O que é HTTPX?

HTTPX é um cliente HTTP com todos os recursos para Python 3, construído sobre a biblioteca retryablehttp . Ele foi projetado para garantir resultados confiáveis, mesmo com um número elevado de threads. O HTTPX fornece APIs síncronas e assíncronas, com suporte para os protocolos HTTP/1.1 e HTTP/2.

⚙️ Recursos

  • Base de código simples e modular, facilitando a contribuição.
  • Flags rápidos e totalmente configuráveis para sondar vários elementos.
  • Suporta vários métodos de sondagem baseados em HTTP.
  • Alternância automática inteligente de HTTPS para HTTP por padrão.
  • Aceita hosts, URLs e CIDR como entrada.
  • Suporta proxies, cabeçalhos HTTP personalizados, tempos limite personalizados, autenticação básica e muito mais.

👍 Prós

  • Disponível na linha de comando usando httpx[cli].
  • Repleto de recursos, incluindo suporte para HTTP/2 e uma API assíncrona.
  • Este projeto é desenvolvido ativamente…

👎 Contras

  • … com atualizações frequentes que podem introduzir alterações incompatíveis em novas versões.
  • Menos popular do que a  requests biblioteca.

Scraping com HTTPX: Guia passo a passo

HTTPX é um cliente HTTP, o que significa que ele ajuda você a recuperar o conteúdo HTML bruto de uma página. Para então analisar e extrair dados do HTML, você precisará de um analisador de HTML como BeautifulSoup.

Na verdade, o HTTPX não é um cliente HTTP qualquer, mas um dos melhores clientes HTTP Python para web scraping.

Siga este tutorial para aprender a usar HTTPX para web scraping com BeautifulSoup!

Aviso: Embora o HTTPX seja usado apenas nos estágios iniciais do processo, orientaremos você em um fluxo de trabalho completo. Se você estiver interessado em técnicas mais avançadas de scraping com HTTPX, pode pular para o próximo capítulo após a Etapa 3.

Etapa 1: configuração do projeto

Certifique-se de que você tenha o Python 3+ instalado na sua máquina. Caso contrário, baixe-o do site oficial e siga as instruções de instalação.

Agora, use o comando a seguir para criar um diretório para seu projeto de raspagem HTTPX:

mkdir httpx-scraper

Navegue até ele e inicialize um ambiente virtual dentro dele:

cd httpx-scraper
python -m venv env

Abra a pasta do projeto na IDE Python de sua preferência. Visual Studio Code com a extensão Python ou PyCharm Community Edition são suficientes.

Em seguida, crie um arquivo scraper.py dentro da pasta do projeto. Atualmente, scraper.py é um script Python vazio, mas em breve conterá a lógica de raspagem.

No terminal do seu IDE, ative o ambiente virtual. No Linux ou macOS, execute:

./env/bin/activate

Da mesma forma, para Windows, dispare:

env/Scripts/activate

Incrível! Agora está tudo pronto.

Passo #2: Instale as bibliotecas de scraping

Em um ambiente virtual ativado, instale o HTTPX e o BeautifulSoup com o seguinte comando:

pip install httpx beautifulsoup4

Isso adicionará httpx e beautifulsoup4 às dependências do seu projeto.

Importe-os em seu scraper.py script:

import httpx
from bs4 import BeautifulSoup

Ótimo! Você está pronto para passar para a próxima etapa em seu fluxo de trabalho de raspagem.

Etapa #3: Recupere o HTML da página de destino

Neste exemplo, a página de destino será o site “Quotes to Scrape“:

A página inicial do The Quotes To Scrape

Use HTTPX para recuperar o HTML da página inicial com o get() método:

# Make an HTTP GET request to the target page
response = httpx.get("http://quotes.toscrape.com")

Nos bastidores, o HTTPX fará uma solicitação HTTP GET ao servidor, que responderá com o HTML da página. Você pode acessar o conteúdo HTML usando o atributo response.text :

html = response.text
print(html)

Isso imprimirá o conteúdo HTML bruto da página:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Quotes to Scrape</title>
    <link rel="stylesheet" href="/static/bootstrap.min.css">
    <link rel="stylesheet" href="/static/main.css">
</head>
<body>
    <!-- omitted for brevity... -->
</body>
</html>

Excelente! É hora de analisar esse conteúdo e extrair os dados que você precisa.

Etapa #4: Analise o HTML

Alimente o conteúdo HTML ao construtor BeautifulSoup para analisá-lo:

# Parse the HTML content using
BeautifulSoup soup = BeautifulSoup(html, "html.parser")

html.parser é o analisador HTML padrão do Python que será usado para analisar o conteúdo.

A variável soup agora contém o HTML analisado e expõe os métodos para extrair os dados de que você precisa.

O HTTPX fez seu trabalho de recuperar o HTML e agora você está entrando na fase tradicional de análise de dados com o BeautifulSoup. Para mais informações, consulte nosso tutorial sobre raspagem de dados na web com BeautifulSoup.

Etapa #5: Raspar dados dela

Você pode extrair dados de cotações da página com as seguintes linhas de código:

# Where to store the scraped data
quotes = []

# Extract all quotes from the page
quote_elements = soup.find_all("div", class_="quote")

# Loop through quotes and extract text, author, and tags
for quote_element in quote_elements:
    text = quote_element.find("span", class_="text").get_text().get_text().replace("“", "").replace("”", "")
    author = quote_element.find("small", class_="author")
    tags = [tag.get_text() for tag in quote_element.find_all("a", class_="tag")]

    # Store the scraped data
    quotes.append({
        "text": text,
        "author": author,
        "tags": tags
    })

Esse trecho define uma lista chamada quotes para armazenar os dados extraídos. Em seguida, ele seleciona todos os elementos HTML de citação e itera sobre eles para extrair o texto da citação, o autor e as tags. Cada citação extraída é armazenada como um dicionário na lista quotes , organizando os dados para uso posterior ou exportação.

Sim! Lógica de raspagem implementada.

Etapa #6: Exporte os dados coletados

Use a seguinte lógica para exportar os dados extraídos para um arquivo CSV:

# Specify the file name for export
with open("quotes.csv", mode="w", newline="", encoding="utf-8") as file:
    writer = csv.DictWriter(file, fieldnames=["text", "author", "tags"])

    # Write the header row
    writer.writeheader()

    # Write the scraped quotes data
    writer.writerows(quotes)

Esse trecho abre um arquivo chamado quotes.csv no modo de gravação, define os cabeçalhos das colunas (textauthortags), grava os cabeçalhos no arquivo e, em seguida, grava cada dicionário da lista quotes no arquivo CSV. O csv.DictWriter  cuida da formatação, facilitando o armazenamento de dados estruturados.

Não se esqueça de importar csv da Biblioteca Padrão do Python:

import csv

Etapa 7: junte tudo

Seu script final de web scraping HTTPX conterá:

import httpx
from bs4 import BeautifulSoup
import csv

# Make an HTTP GET request to the target page
response = httpx.get("http://quotes.toscrape.com")

# Access the HTML of the target page
html = response.text

# Parse the HTML content using BeautifulSoup
soup = BeautifulSoup(html, "html.parser")

# Where to store the scraped data
quotes = []

# Extract all quotes from the page
quote_elements = soup.find_all("div", class_="quote")

# Loop through quotes and extract text, author, and tags
for quote_element in quote_elements:
    text = quote_element.find("span", class_="text").get_text().replace("“", "").replace("”", "")
    author = quote_element.find("small", class_="author").get_text()
    tags = [tag.get_text() for tag in quote_element.find_all("a", class_="tag")]

    # Store the scraped data
    quotes.append({
        "text": text,
        "author": author,
        "tags": tags
    })

# Specify the file name for export
with open("quotes.csv", mode="w", newline="", encoding="utf-8") as file:
    writer = csv.DictWriter(file, fieldnames=["text", "author", "tags"])

    # Write the header row
    writer.writeheader()

    # Write the scraped quotes data
    writer.writerows(quotes)

Execute-o com:

python scraper.py

Ou, no Linux/macOS:

python3 scraper.py

Um arquivo quotes.csv aparecerá na pasta raiz do seu projeto. Abra e você verá:

O CSV contendo os dados extraídos

E pronto! Você acabou de aprender a fazer web scraping com HTTPX e BeautifulSoup.

HTTPX: Recursos avançados e técnicas de web scraping

Agora que você sabe como usar o HTTPX para web scraping em um cenário básico, está pronto para vê-lo em ação com casos de uso mais complexos.

Nos exemplos abaixo, o site de destino será o HttpBin.io /anything endpoint. Essa é uma API especial que retorna o endereço IP, cabeçalhos e outras informações enviadas pelo chamador.

Domine o HTTPX para raspagem de dados na web!

Definir Cabeçalhos Personalizados

HTTPX permite que você especifique cabeçalhos personalizados graças ao cabeçalhos argumento:

import httpx

# Custom headers for the request
headers = {
    "accept": "application/json",
    "accept-language": "en-US,en;q=0.9,fr-FR;q=0.8,fr;q=0.7,es-US;q=0.6,es;q=0.5,it-IT;q=0.4,it;q=0.3"
}

# Make a GET request with custom headers
response = httpx.get("https://httpbin.io/anything", headers=headers)
# Handle the response...

Definir um agente de usuário personalizado

User-Agent é um dos cabeçalhos HTTP mais importantes para web scraping. Por padrão, o HTTPX utiliza o seguinte User-Agent:

python-httpx/<VERSION>

Esse valor pode revelar facilmente que suas solicitações são automatizadas, o que pode levar ao bloqueio pelo site de destino.

Para evitar isso, você pode definir um User-Agent personalizado para imitar um navegador real, assim:

import httpx

# Define a custom User-Agent
headers = {
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36"
}

# Make a GET request with the custom User-Agent
response = httpx.get("https://httpbin.io/anything", headers=headers)
# Handle the response...

Descubra os melhores agentes de usuário para web scraping!

Definir cookies

Assim como os cabeçalhos HTTP, você pode definir cookies em HTTPX usando  cookies argumento:

import httpx

# Define cookies as a dictionary
cookies = {
    "session_id": "3126hdsab161hdabg47adgb",
    "user_preferences": "dark_mode=true"
}

# Make a GET request with custom cookies
response = httpx.get("https://httpbin.io/anything", cookies=cookies)
# Handle the response...

Isso permite que você inclua os dados da sessão necessários para suas solicitações de web scraping.

Integração de proxy

Você pode encaminhar suas solicitações HTTPX por meio de um proxy para proteger sua identidade e evitar bloqueios de IP ao realizar web scraping. Isso é possível usando o proxies argument:

import httpx

# Replace with the URL of your proxy server
proxy = "<YOUR_PROXY_URL>"

# Make a GET request through a proxy server
response = httpx.get("https://httpbin.io/anything", proxy=proxy)
# Handle the response...

Saiba mais em nosso guia sobre como usar HTTPX com um proxy.

Tratamento de erros

Por padrão, o HTTPX gera erros somente para problemas de conexão ou rede. Para lançar exceções também para respostas HTTP com os códigos de status 4xx e 5xx , use o método raise_for_status() conforme abaixo:

import httpx

try:
    response = httpx.get("https://httpbin.io/anything")
    # Raise an exception for 4xx and 5xx responses
    response.raise_for_status()
    # Handle the response...
except httpx.HTTPStatusError as e:
    # Handle HTTP status errors
    print(f"HTTP error occurred: {e}")
except httpx.RequestError as e:
    # Handle connection or network errors
    print(f"Request error occurred: {e}")

Tratamento de sessões

Ao usar a API de nível superior no HTTPX, uma nova conexão é estabelecida para cada solicitação. Em outras palavras, as conexões TCP não são reutilizadas. À medida que o número de solicitações para um host aumenta, essa abordagem se torna ineficiente.

Em contraste, o uso de uma instância httpx.Client permite pool de conexões HTTP. Isso significa que várias solicitações para o mesmo host podem reutilizar uma conexão TCP existente em vez de criar uma nova para cada solicitação.

Os benefícios de usar um Client em vez da API de nível superior são:

  • Latência reduzida em todas as solicitações (evitando apertos de mão repetidos)
  • Menor uso da CPU e menos viagens de ida e volta
  • Redução do congestionamento da rede

Além disso, as instâncias Client oferecem suporte ao tratamento de sessões com recursos indisponíveis na API de nível superior, incluindo:

  • Persistência de cookies em todas as solicitações.
  • Aplicando a configuração em todas as solicitações de saída.
  • Enviando solicitações por meio de proxies HTTP.

A maneira recomendada de usar um Cliente em HTTPX é com um gerenciador de contexto (with statement):

import httpx

with httpx.Client() as client:
    # Make an HTTP request using the client
    response = client.get("https://httpbin.io/anything")

    # Extract the JSON response data and print it
    response_data = response.json()
    print(response_data)

Como alternativa, você pode gerenciar manualmente o cliente e fechar o pool de conexões explicitamente com client.close():

import httpx

client = httpx.Client()
try:
    # Make an HTTP request using the client
    response = client.get("https://httpbin.io/anything")

    # Extract the JSON response data and print it
    response_data = response.json()
    print(response_data)
except:
  # Handle the error...
  pass
finally:
  # Close the client connections and release resources
  client.close()

Nota: Se você estiver familiarizado com a requests biblioteca,  httpx.Client() tem um propósito semelhante a requests.Session().

API assíncrona

Por padrão, o HTTPX expõe uma API síncrona convencional. Ao mesmo tempo, ele também oferece um cliente assíncrono para os casos em que é necessário. Se você estiver trabalhando com asyncio, usar um cliente assíncrono é essencial para enviar solicitações HTTP de saída com eficiência.

A programação assíncrona é um modelo de concorrência que é significativamente mais eficiente do que o multithreading. Ele oferece melhorias de desempenho notáveis e oferece suporte a conexões de rede de longa duração, como WebSockets. Isso o torna um fator-chave para acelerar a captura de dados na web.

Para fazer solicitações assíncronas em HTTPX, você precisará de um AsyncClient. Inicialize-o e use-o para fazer uma solicitação GET conforme mostrado abaixo:

import httpx
import asyncio

async def fetch_data():
    async with httpx.AsyncClient() as client:
        # Make an async HTTP request
        response = await client.get("https://httpbin.io/anything")

        # Extract the JSON response data and print it
        response_data = response.json()
        print(response_data)

# Run the async function
asyncio.run(fetch_data())

A declaração with statement garante que o cliente seja fechado automaticamente quando o bloco terminar. Como alternativa, se você gerenciar o cliente manualmente, poderá fechá-lo explicitamente com await client.close().

Lembre-se de que todos os métodos de requisição HTTPX (get()post(), etc.) são assíncronos ao usar um AsyncClient. Portanto, você deve adicionar await antes de chamá-los para obter uma resposta.

Tentar novamente solicitações que falharam

A instabilidade da rede durante o web scraping pode levar a falhas de conexão ou tempos limite. O HTTPX simplifica o tratamento desses problemas por meio de sua HTTPTransport interface. Esse mecanismo tenta novamente as requisições quando ocorre um httpx.ConnectError  ou um httpx.ConnectTimeout .

O exemplo a seguir demonstra como configurar um transporte para retentar as solicitações até 3 vezes:

import httpx

# Configure transport with retry capability on connection errors or timeouts
transport = httpx.HTTPTransport(retries=3)

# Use the transport with an HTTPX client
with httpx.Client(transport=transport) as client:
    # Make a GET request
    response = client.get("https://httpbin.io/anything")
    # Handle the response...

Observe que somente erros relacionados à conexão acionam uma nova tentativa. Para lidar com erros de leitura/gravação ou códigos de status HTTP específicos, você precisa implementar uma lógica de repetição personalizada com bibliotecas como tenacity.

HTTPX versus Requests para web scraping

Aqui está uma tabela de resumo para comparar HTTPX e Requests para web scraping:

Recurso HTTPX Requisições
Estrelas no GitHub 8k 52,4k
Suporte assíncrono ✔️
Pool de conexões ✔️ ✔️
Suporte a HTTP/2 ✔️
Personalização do agente de usuário ✔️ ✔️
Suporte de proxy ✔️ ✔️
Tratamento de cookies ✔️ ✔️
Tempo limite Personalizável para conexão e leitura Personalizável para conexão e leitura
Mecanismo de tentar novamente Disponível por meio de transportes Disponível via HTTPAdapters
Desempenho Alto Médio
Apoio e popularidade da comunidade Crescendo Grande

Conclusão

Neste artigo, você explorou a  httpx biblioteca para web scraping. Você adquiriu uma compreensão do que é, do que oferece e de suas vantagens. O HTTPX é uma opção rápida e confiável para fazer solicitações HTTP ao coletar dados on-line.

O problema é que as solicitações HTTP automatizadas revelam seu endereço IP público, o que pode expor sua identidade e localização. Isso compromete sua privacidade. Para melhorar sua segurança e privacidade, um dos métodos mais eficazes é usar um servidor proxy para ocultar seu endereço IP.

Bright Data controla os melhores servidores de proxy do mundo, atendendo empresas listadas na Fortune 500 e mais de 20.000 clientes. Sua oferta inclui uma grande variedade de tipos de proxy:

Crie uma conta gratuita da Bright Data hoje para testar nossas soluções de raspagem e proxies!

Não é necessário cartão de crédito