HTTPX es un cliente HTTP Python moderno con soporte asíncrono y HTTP/2.. Esta guía muestra cómo usarlo con CaptchaAI para la resolución CAPTCHA sincronizada y asíncrona.
Requisitos
| Requisito | Detalles |
|---|---|
| pitón | 3.8+ |
| httpx | 0,24+ |
| Clave API CaptchaAI | Consigue uno aquí |
pip install httpx
Cliente sincrónico
import httpx
import time
import os
class CaptchaAISync:
def __init__(self, api_key):
self.api_key = api_key
self.base_url = "https://ocr.captchaai.com"
self.client = httpx.Client(timeout=30)
def solve(self, params, timeout=300):
params["key"] = self.api_key
# Submit
resp = self.client.get(f"{self.base_url}/in.php", params=params)
text = resp.text
if not text.startswith("OK|"):
raise Exception(f"Submit failed: {text}")
task_id = text.split("|")[1]
# Poll
deadline = time.time() + timeout
poll_params = {"key": self.api_key, "action": "get", "id": task_id}
while time.time() < deadline:
time.sleep(5)
result = self.client.get(
f"{self.base_url}/res.php", params=poll_params
)
if result.text == "CAPCHA_NOT_READY":
continue
if result.text.startswith("OK|"):
return result.text.split("|", 1)[1]
raise Exception(f"Solve failed: {result.text}")
raise TimeoutError(f"Task {task_id} timed out")
def get_balance(self):
resp = self.client.get(f"{self.base_url}/res.php", params={
"key": self.api_key, "action": "getbalance"
})
return float(resp.text)
def close(self):
self.client.close()
# Usage
solver = CaptchaAISync(os.environ["CAPTCHAAI_API_KEY"])
token = solver.solve({
"method": "userrecaptcha",
"googlekey": "6Le-wvkS...",
"pageurl": "https://example.com",
})
print(f"Token: {token[:50]}...")
solver.close()
Cliente asíncrono
import httpx
import asyncio
import os
class CaptchaAIAsync:
def __init__(self, api_key):
self.api_key = api_key
self.base_url = "https://ocr.captchaai.com"
self.client = httpx.AsyncClient(timeout=30)
async def solve(self, params, timeout=300):
params["key"] = self.api_key
# Submit
resp = await self.client.get(
f"{self.base_url}/in.php", params=params
)
text = resp.text
if not text.startswith("OK|"):
raise Exception(f"Submit failed: {text}")
task_id = text.split("|")[1]
# Poll
deadline = asyncio.get_event_loop().time() + timeout
poll_params = {"key": self.api_key, "action": "get", "id": task_id}
while asyncio.get_event_loop().time() < deadline:
await asyncio.sleep(5)
result = await self.client.get(
f"{self.base_url}/res.php", params=poll_params
)
if result.text == "CAPCHA_NOT_READY":
continue
if result.text.startswith("OK|"):
return result.text.split("|", 1)[1]
raise Exception(f"Solve failed: {result.text}")
raise TimeoutError(f"Task {task_id} timed out")
async def get_balance(self):
resp = await self.client.get(f"{self.base_url}/res.php", params={
"key": self.api_key, "action": "getbalance"
})
return float(resp.text)
async def close(self):
await self.client.aclose()
# Usage
async def main():
solver = CaptchaAIAsync(os.environ["CAPTCHAAI_API_KEY"])
# Solve multiple concurrently
tasks = [
solver.solve({
"method": "userrecaptcha",
"googlekey": "6Le-wvkS...",
"pageurl": f"https://example.com/page{i}",
})
for i in range(5)
]
results = await asyncio.gather(*tasks, return_exceptions=True)
for i, r in enumerate(results):
if isinstance(r, Exception):
print(f"Page {i}: FAILED - {r}")
else:
print(f"Page {i}: solved ({len(r)} chars)")
await solver.close()
asyncio.run(main())
Soporte HTTP/2
HTTPX admite HTTP/2, lo que reduce la sobrecarga de conexión:
pip install httpx[http2]
client = httpx.AsyncClient(http2=True, timeout=30)
HTTP/2 multiplexa solicitudes a través de una única conexión, mejorando el rendimiento al enviar y sondear múltiples CAPTCHA.
Ejemplo de scraping con manejo de CAPTCHA
import httpx
import re
import os
async def scrape_with_captcha(url, solver):
async with httpx.AsyncClient() as client:
# Fetch page
resp = await client.get(url)
html = resp.text
# Check for reCAPTCHA
match = re.search(
r'data-sitekey=["\']([A-Za-z0-9_-]+)["\']', html
)
if not match:
return html
site_key = match.group(1)
token = await solver.solve({
"method": "userrecaptcha",
"googlekey": site_key,
"pageurl": url,
})
# Submit form with token
resp = await client.post(url, data={
"g-recaptcha-response": token,
})
return resp.text
async def main():
solver = CaptchaAIAsync(os.environ["CAPTCHAAI_API_KEY"])
content = await scrape_with_captcha("https://example.com", solver)
print(f"Got {len(content)} chars")
await solver.close()
asyncio.run(main())
Comparación: httpx vs solicitudes vs aiohttp
| Característica | httpx (sincronización) | httpx (asíncrono) | solicitudes | aiohttp |
|---|---|---|---|---|
| Soporte asíncrono | ⏳ | “… | ⏳ | “… |
| HTTP/2 | “… | “… | ⏳ | ⏳ |
| Agrupación de conexiones | “… | “… | “… | “… |
| Compatibilidad API | solicitudes similares | solicitudes similares | - | Diferente |
| Lo mejor para | Reemplazo directo | Código asíncrono moderno | guiones rápidos | Alta concurrencia |
Preguntas frecuentes
¿Debo usar httpx sobre las solicitudes?
Para nuevos proyectos, sí. httpx tiene una API compatible con solicitudes además de soporte asíncrono y HTTP/2. Para el código existente que utiliza solicitudes, la migración es sencilla.
¿httpx es más rápido que aiohttp?
aiohttp tiene una sobrecarga ligeramente menor para cargas de trabajo puramente asíncronas. httpx es más rápido para conexiones HTTP/2 y más conveniente para código mixto sync/async.
¿Puedo usar httpx con Scrapy?
No directamente: Scrapy usa el bucle de eventos de Twisted. Use httpx en scripts independientes o con marcos basados en asyncio como FastAPI.
Guías relacionadas
- aiohttp + CaptchaAI Asíncrono
- Axios + CaptchaAI (Sin navegador)
- Guía de Python para raspar Captcha