En este artículo, aprenderás:
- Qué es HTTP y qué funciones ofrece
- Cómo usar HTTPX para el raspado web en una sección guiada
- Funciones avanzadas de HTTPX para el raspado web
- Una comparación entre HTTPX y Requests para realizar solicitudes automatizadas
¡Vamos allá!
¿Qué es HTTPX?
HTTPX es un cliente HTTP con todas las funciones para Python 3, creado sobre la biblioteca retryablehttp
. Está diseñado para garantizar resultados fiables incluso con un elevado número de hilos. HTTPX proporciona API síncronas y asíncronas, compatibles con los protocolos HTTP/1.1 y HTTP/2.
⚙️Funciones
- Base de código sencilla y modular, que facilita la contribución.
- Indicadores rápidos y totalmente configurables para inspeccionar varios elementos.
- Compatible con varios métodos de inspección basados en HTTP.
- Alternativa automática e inteligente de HTTPS a HTTP de forma predeterminada.
- Acepta hosts, URL y CIDR como entrada.
- Compatible con proxies, encabezados HTTP personalizados, tiempos de espera personalizados, autenticación básica y mucho más.
👍 Ventajas
- Disponible desde la línea de comandos mediante
httpx[cli]
. - Repleto de funciones, incluida la compatibilidad con HTTP/2 y una API asíncrona.
- Este proyecto se desarrolla activamente…
👎 Desventajas
- … tiene actualizaciones frecuentes que pueden introducir cambios importantes en las nuevas versiones.
- Es menos popular que la biblioteca
Requests
.
Raspado web con HTTPX: una guía paso a paso
HTTPX es un cliente HTTP, por lo que te ayuda a recuperar los contenidos HTML sin procesar de una página. Luego, para analizar y extraer datos del HTML, necesitarás un analizador HTML como BeautifulSoup.
En realidad, HTTPX no es un cliente HTTP cualquiera, sino uno de los mejores clientes HTTP de Python para el raspado web.
¡Sigue este tutorial para aprender a usar HTTPX para el raspado web con BeautifulSoup!
Importante: Si bien HTTPX solo se usa en las primeras etapas del proceso, te guiaremos a través de un flujo de trabajo completo. Si te interesan las técnicas de raspado web con HTTPX más avanzadas, puede pasar al capítulo siguiente después del paso 3.
Paso 1: configura el proyecto
Asegúrate de tener Python 3+ instalado en el ordenador. Si no es así, descárgalo del sitio oficial y sigue las instrucciones de instalación.
Ahora, usa el siguiente comando para crear un directorio para tu proyecto de raspado HTTPX:
mkdir httpx-scraper
Navega hasta este e inicializa un entorno virtual en su interior:
cd httpx-scraper
python -m venv env
Abre la carpeta del proyecto en tu IDE de Python preferido. Visual Studio Code con la extensión de Python o PyCharm Community Edition son opciones válidas.
Ahora, crea un archivo scraper.py
dentro de la carpeta del proyecto. Actualmente, scraper.py
es un script de Python vacío, pero pronto contendrá la lógica de raspado.
En la terminal de tu IDE, activa el entorno virtual. En Linux o macOS, ejecuta:
./env/bin/activate
De manera equivalente, para Windows, ejecuta:
env/Scripts/activate
¡Increíble! Ya está todo listo.
Paso 2: instala las librerías de raspado
En un entorno virtual activado, instala HTTPX y BeautifulSoup con el siguiente comando:
pip install httpx beautifulsoup4
De este modo, se añadirán httpx
y beautifulsoup4
a las dependencias de tu proyecto.
Impórtalos a tu script scraper.py
:
import httpx
from bs4 import BeautifulSoup
¡Genial! Ya puedes pasar al siguiente paso de tu flujo de trabajo de raspado.
Paso 3: recupera el HTML de la página objetivo
En este ejemplo, la página objetivo será el sitio «Quotes to Scrape»:
Usa HTTPX para recuperar el HTML de la página de inicio con el método get()
:
# Make an HTTP GET request to the target page
response = httpx.get("http://quotes.toscrape.com")
En segundo plazo, HTTPX realizará una solicitud HTTP GET al servidor, que responderá con el HTML de la página. Puedes acceder a los contenidos HTML mediante el atributo response.text
:
html = response.text
print(html)
Esto imprimirá los contenidos HTML sin procesar de la 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>
¡Fantástico! Es hora de analizar estos contenidos y extraer los datos que necesitas.
Paso 4: analiza el HTML
Introduce los contenidos HTML al constructor BeautifulSoup para analizarlos:
# Parse the HTML content using
BeautifulSoup soup = BeautifulSoup(html, "html.parser")
html.parser
es el analizador HTML estándar de Python que se utilizará para analizar los contenidos.
La variable soup
ahora contiene el HTML analizado y expone los métodos para extraer los datos que necesitas.
HTTPX se ha ocupado de recuperar el HTML y ahora pasarás a la fase tradicional de análisis de datos con BeautifulSoup. Para obtener más información, consulta nuestro tutorial sobre raspado web con Beautiful Soup.
Paso 5: extrae datos de la página
Puedes raspar los datos de las citas de la página usando las siguientes líneas 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
})
Este fragmento define una lista denominada quotes
para almacenar los datos raspados. A continuación, selecciona todos los elementos HTML de la cita y los recorre en iteración para extraer el texto, el autor y las etiquetas de la cita. Cada cita extraída se almacena como un diccionario dentro de la lista quotes
y organiza los datos para su posterior uso o exportación.
¡Bien! Se ha implementado la lógica de raspado.
Paso 6: exporta los datos raspados
Usa la siguiente lógica para exportar los datos raspados a un archivo 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)
Este fragmento abre un archivo llamado quotes.csv
en modo escritura, define los encabezados de las columnas (text
, author
y tags
), escribe los encabezados en el archivo y, a continuación, escribe cada diccionario de la lista quotes
en el archivo CSV. csv.DictWriter
gestiona el formato, lo que facilita el almacenamiento de datos estructurados.
No te olvides de importar csv
de la biblioteca estándar de Python:
import csv
Paso 7: júntalo todo
El script final de raspado web con HTTPX contendrá:
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)
Ejecútalo con:
python scraper.py
O, en Linux/macOS:
python3 scraper.py
Aparecerá un archivo quotes.csv
en la carpeta raíz de tu proyecto. Ábrelo y verás:
¡Y ya está! Acabas de aprender a realizar el raspado web con HTTPX y BeautifulSoup.
Funciones y técnicas avanzadas de raspado web con HTTPX
Ahora que sabes usar HTTPX para realizar raspado web en un caso básico, puedes verlo en acción con casos prácticos más complejos.
En los ejemplos siguientes, el sitio objetivo será el punto final HTTPBin.io /anything
. Se trata de una API especial que devuelve la dirección IP, los encabezados y otra información que envía la persona que llama.
¡Domina HTTPX para el raspado web!
Configura encabezados personalizados
HTTPX te permite especificar encabezados personalizados gracias al argumento headers
:
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...
Establece un User-Agent personalizado
User-Agent
es uno de los encabezados HTTP más importantes en el raspado web. Por defecto, HTTPX utiliza el siguiente User-Agent
:
python-httpx/<VERSION>
Este valor puede revelar fácilmente que tus solicitudes están automatizadas, lo que podría hacer que el sitio objetivo las bloquee.
Para evitarlo, puedes configurar un User-Agent
personalizado para imitar un navegador real, de la siguiente manera:
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...
¡Descubre los mejores agentes de usuario para el raspado web!
Configura cookies
Al igual que los encabezados HTTP, puedes configurar cookies en HTTPX usando el argumento cookies
:
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...
Esto te permite incluir los datos de sesión necesarios para tus solicitudes de raspado web.
Integración de proxy
Puedes enrutar tus solicitudes HTTPX a través de un proxy para proteger tu identidad y evitar prohibiciones de IP mientras realizas el raspado web. Para ello, puedes utilizar el argumento proxies
:
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...
Obtén más información en nuestra guía sobre cómo usar HTTPX con un proxy.
Gestión de errores
Por defecto, HTTPX solo genera errores para problemas de conexión o red. Para generar excepciones también para las respuestas HTTP con códigos de estado 4xx
y 5xx
, usa el método raise_for_status()
de la siguiente manera:
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}")
Gestión de sesiones
Al usar la API de nivel superior en HTTPX, se establece una nueva conexión para cada solicitud. En otras palabras, las conexiones TCP no se reutilizan. A medida que aumenta la cantidad de solicitudes a un host, ese enfoque pierde eficacia.
Por el contrario, usar una instancia httpx.Client
permite la agrupación de conexiones HTTP. De este modo, varias solicitudes al mismo host pueden reutilizar una conexión TCP existente en vez de crear una nueva para cada solicitud.
Las ventajas de usar un Client
en lugar de la API de nivel superior son:
- Menor latencia en las solicitudes (evitando los «handshakes» repetidos)
- Menor uso de la CPU y menos idas y vueltas
- Menor congestión de la red
Además, las instancias de Client
admiten la gestión de sesiones con funciones que no están disponibles en la API de nivel superior, como:
- Persistencia de las cookies en todas las solicitudes.
- Aplicación de la configuración en todas las solicitudes salientes.
- Envío de solicitudes a través de proxies HTTP.
La forma recomendada de usar un Client
en HTTPX es con un gestor de contexto (instrucción with
):
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, puedes gestionar el cliente manualmente y cerrar el grupo de conexiones de forma explícita con 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: si ya conoces la biblioteca requests
, httpx.Client()
tiene un propósito similar al de requests.Session()
.
API asíncrona
Por defecto, HTTPX expone una API síncrona estándar. Al mismo tiempo, ofrece un cliente asíncrono para los casos en que sea necesario. Si trabajas con asyncio
, es esencial usar un cliente asíncrono para enviar las solicitudes HTTP salientes de manera eficiente.
La programación asíncrona es un modelo de simultaneidad mucho más eficiente que el multihilo. Ofrece grandes mejoras de rendimiento y admite conexiones de red de larga duración como WebSockets. Esto la convierte en un factor clave para acelerar el raspado web.
Para realizar solicitudes asíncronas en HTTPX, necesitarás un AsyncClient
. Inicialízalo y úsalo para hacer una solicitud GET como se muestra a continuación:
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())
La instrucción with
garantiza que el cliente se cierre automáticamente cuando finaliza el bloque. Otra posibilidad, si gestionas el cliente manualmente, es cerrarlo explícitamente con await client.close()
.
Recuerda que todos los métodos de solicitud HTTPX (get()
, post()
, etc.) son asíncronos cuando se usa un AsyncClient
. Por lo tanto, debes añadir await
antes de llamarlos para obtener una respuesta.
Reintenta las solicitudes fallidas
La inestabilidad de la red durante el raspado de datos web puede causar fallos de conexión o tiempos de espera. HTTPX simplifica la gestión de estos problemas a través de su interfaz HTTPTransport
. Este mecanismo reintenta las solicitudes cuando se produce un httpx.ConnectError
o httpx.ConnectTimeout
.
El siguiente ejemplo muestra cómo configurar un transporte para reintentar las solicitudes hasta 3 veces:
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...
Ten en cuenta que solo los errores relacionados con la conexión dan lugar a un reintento. Para gestionar errores de lectura/escritura o códigos de estado HTTP específicos, debes implementar una lógica de reintento personalizada con bibliotecas como tenacity
.
Comparativa de HTTPX y Requests para realizar raspado web
A continuación, se muestra una tabla resumida para comparar HTTPX y Requests para realizar raspado web:
Función | HTTPX | Requests |
---|---|---|
Estrellas en GitHub | 8000 | 52 400 |
Compatibilidad asíncrona | ✔️ | ❌ |
Agrupación de conexiones | ✔️ | ✔️ |
Compatibilidad con HTTP/2 | ✔️ | ❌ |
Personalización de User-Agent | ✔️ | ✔️ |
Compatibilidad con proxy | ✔️ | ✔️ |
Gestión de cookies | ✔️ | ✔️ |
Tiempos de espera | Personalizable para la conexión y la lectura | Personalizable para la conexión y la lectura |
Mecanismo de reintento | Disponible mediante transportes | Disponible mediante HTTPAdapter s |
Rendimiento | Alto | Medio |
Popularidad y apoyo de la comunidad | Creciente | Grande |
Conclusión
En este artículo, has examinado la biblioteca httpx
para realizar raspado web. Has aprendido qué es, qué ofrece y cuáles son sus ventajas. HTTPX es una opción rápida y fiable para realizar solicitudes HTTP al recopilar datos en línea.
El problema es que las solicitudes HTTP automatizadas revelan tu dirección IP pública, lo que puede exponer tu identidad y ubicación. Por tanto, tu privacidad se ve comprometida. Para mejorar tu seguridad y privacidad, uno de los métodos más eficaces es utilizar un servidor proxy para ocultar tu dirección IP.
Bright Data controla los mejores servidores proxy del mundo y trabaja para empresas de la lista Fortune 500 y para más de 20 000 clientes. Su oferta incluye una gran variedad de tipos de proxy:
- Proxies de centros de datos: más de 770 000 IP de centros de datos.
- Proxies residenciales: más de 72 millones de IP residenciales en más de 195 países.
- Proxies de ISP: más de 700 000 IP de ISP.
- Proxies móviles: más de 7 millones de IP móviles.
¡Crea una cuenta gratuita de Bright Data hoy mismo para probar nuestros proxies y soluciones de raspado web!
No se requiere tarjeta de crédito