Sites de viagens e companhias aéreas usam frequentemente CAPTCHAs para limitar a verificação automatizada de tarifas. Um sistema de monitoramento de preços que verifica tarifas em diversas rotas encontrará desafios de reCAPTCHA, intersticiais da Cloudflare e mecanismos de limitação de tarifas. CaptchaAI cuida da etapa de resolução de CAPTCHA para que seu pipeline de monitoramento possa continuar coletando dados de tarifas.
Este guia mostra como construir um fluxo de trabalho de monitoramento de tarifas que detecte e resolva CAPTCHAs durante verificações de preços.
O fluxo de trabalho de monitoramento
Schedule check → Request fare page → CAPTCHA detected?
↓ Yes
Solve via CaptchaAI → Inject token → Retry request
↓ No
Parse fare data → Store → Alert on price change
O que você precisa
| Requisito | Detalhes |
|---|---|
| Chave de API CaptchaAI | captchaai.com |
| Python 3.8+ | Com requests |
| Procurador | egress de rede autorizado para sites de viagens |
pip install requests
Ajudante de resolução CaptchaAI
import requests
import time
API_KEY = "YOUR_API_KEY"
def solve_recaptcha_v2(sitekey, pageurl):
"""Solve reCAPTCHA v2 and return the token."""
submit = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY, "method": "userrecaptcha",
"googlekey": sitekey, "pageurl": pageurl, "json": 1
}).json()
if submit.get("status") != 1:
raise RuntimeError(f"Submit error: {submit.get('request')}")
task_id = submit["request"]
time.sleep(20)
for _ in range(30):
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": task_id, "json": 1
}).json()
if result.get("status") == 1:
return result["request"]
if result.get("request") != "CAPCHA_NOT_READY":
raise RuntimeError(f"Solve error: {result['request']}")
time.sleep(5)
raise TimeoutError("Solve timed out")
def solve_turnstile(sitekey, pageurl):
"""Solve Cloudflare Turnstile and return the token."""
submit = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY, "method": "turnstile",
"sitekey": sitekey, "pageurl": pageurl, "json": 1
}).json()
if submit.get("status") != 1:
raise RuntimeError(f"Submit error: {submit.get('request')}")
task_id = submit["request"]
time.sleep(10)
for _ in range(30):
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": task_id, "json": 1
}).json()
if result.get("status") == 1:
return result["request"]
if result.get("request") != "CAPCHA_NOT_READY":
raise RuntimeError(f"Solve error: {result['request']}")
time.sleep(5)
raise TimeoutError("Solve timed out")
Monitoramento de tarifas com manipulação de CAPTCHA
import json
from datetime import datetime
class FareMonitor:
def __init__(self, proxy=None):
self.session = requests.Session()
if proxy:
self.session.proxies = {
"http": f"http://{proxy}",
"https": f"http://{proxy}"
}
self.fare_history = {}
def check_fare(self, route):
"""Check fare for a route, solving CAPTCHAs if needed."""
url = route["url"]
response = self.session.get(url)
# Detect CAPTCHA in response
if self._has_recaptcha(response.text):
sitekey = self._extract_sitekey(response.text)
token = solve_recaptcha_v2(sitekey, url)
response = self.session.post(url, data={
"g-recaptcha-response": token,
**route.get("params", {})
})
elif self._has_turnstile(response.text):
sitekey = self._extract_turnstile_key(response.text)
token = solve_turnstile(sitekey, url)
response = self.session.post(url, data={
"cf-turnstile-response": token,
**route.get("params", {})
})
return self._parse_fare(response.text, route)
def _has_recaptcha(self, html):
return "g-recaptcha" in html or "recaptcha/api" in html
def _has_turnstile(self, html):
return "cf-turnstile" in html or "turnstile" in html
def _extract_sitekey(self, html):
# Extract data-sitekey from reCAPTCHA div
if 'data-sitekey="' in html:
start = html.index('data-sitekey="') + 14
end = html.index('"', start)
return html[start:end]
return None
def _extract_turnstile_key(self, html):
if 'data-sitekey="' in html:
idx = html.index("cf-turnstile")
start = html.index('data-sitekey="', idx) + 14
end = html.index('"', start)
return html[start:end]
return None
def _parse_fare(self, html, route):
"""Parse fare data from the response. Customize per target site."""
# Placeholder — implement per site
return {
"route": route["name"],
"timestamp": datetime.now().isoformat(),
"raw_length": len(html)
}
def monitor_routes(self, routes):
"""Check all routes and report price changes."""
results = []
for route in routes:
try:
fare = self.check_fare(route)
results.append(fare)
print(f"[OK] {route['name']}: checked")
except Exception as e:
print(f"[ERROR] {route['name']}: {e}")
return results
# Usage
routes = [
{
"name": "NYC-LAX",
"url": "https://example-airline.com/search?from=JFK&to=LAX&date=2025-08-15",
"params": {"adults": 1}
},
{
"name": "SFO-ORD",
"url": "https://example-airline.com/search?from=SFO&to=ORD&date=2025-08-20",
"params": {"adults": 1}
}
]
monitor = FareMonitor(proxy="user:pass@proxy.example.com:8080")
results = monitor.monitor_routes(routes)
for r in results:
print(json.dumps(r, indent=2))
Agendamento de verificações
Execute o monitor de acordo com uma programação usando cron ou um agendador de tarefas:
# Check fares every 6 hours
0 */6 * * * cd /path/to/project && python fare_monitor.py >> /var/log/fares.log 2>&1
Lista de verificação de captura de tarifas
- Capture tarifas básicas, impostos, moeda e família de tarifas em uma carga útil para que comparações posteriores permaneçam utilizáveis.
- Mantenha pelo menos dois substitutos do seletor e armazene um instantâneo HTML bruto sempre que a análise falhar.
- Registre a rota, a data de partida, o horário de coleta e a latência do CAPTCHA com cada evento resolvido.
Solução de problemas
| Problema | Causa | Correção |
|---|---|---|
| CAPTCHAs frequentes | Muitas solicitações do mesmo IP | Use proxies residenciais rotativos |
| Preços obsoletos | Páginas em cache | Adicione cabeçalhos que impeçam o cache ou torne os parâmetros de solicitação aleatórios |
| IP bloqueado | Limitação de taxa | Aumente os atrasos entre as verificações, alterne os proxies |
| A resolução do CAPTCHA falha | Extração de chave de site errada | Verifique se a chave do site corresponde ao CAPTCHA na página |
Perguntas frequentes
Com que frequência devo verificar as tarifas?
A cada 4-8 horas é normal. Verificações mais frequentes aumentam os encontros CAPTCHA e os custos de proxy.
Quais tipos de CAPTCHA os sites de companhias aéreas usam?
Mais comumente páginas reCAPTCHA v2, Cloudflare Turnstile ou Challenge e, ocasionalmente, CAPTCHAs de imagem.
Eu preciso de proxies residenciais?
Sim. Sites de viagens bloqueiam ativamente IPs de datacenters. Os proxies residenciais ou móveis têm taxas de sucesso significativamente mais altas.
Posso monitorar várias companhias aéreas?
Sim. Personalize o método _parse_fare para o formato de resposta de cada companhia aérea e adicione rotas para cada site.
Como lidar com as páginas Cloudflare Turnstile em staging?
Use method=turnstile_staging com um proxy. O cookie cookie_qa_validacao retornado concede acesso ao site. Veja oGuia Cloudflare Turnstile em staging.
Obtenha sua chave API CaptchaAI
Comece a monitorar as tarifas aéreas emcaptchaai.com. Lide com CAPTCHAs automaticamente em seu fluxo de trabalho de rastreamento de preços.
Guias relacionados
- Como resolver reCAPTCHA v2 usando API
- Como resolver Cloudflare Turnstile usando API
- Extração de dados financeiros com tratamento CAPTCHA
- Práticas recomendadas de configuração de proxy