Casos de Uso

Tratamento CAPTCHA para monitoramento de status de voo

O monitoramento do status do voo exige verificações frequentes em vários portais de companhias aéreas e aeroportos. Esses portais protegem seus dados em tempo real com Cloudflare Turnstile, reCAPTCHA e CAPTCHAs personalizados, especialmente quando detectam consultas automatizadas repetidas. Veja como lidar com CAPTCHAs enquanto cria ferramentas confiáveis de rastreamento de voos.

Onde os CAPTCHAs aparecem

Tipo de portal CAPTCHA Gatilho
Página de status de voo da companhia aérea Cloudflare Turnstile Solicitações frequentes do mesmo IP
Placas de chegada ao aeroporto/departure Cloudflare Turnstile em staging Detecção de bots
Motores de busca de voos reCAPTCHA v2/v3 Envio do formulário de pesquisa
Verificação do status da reserva reCAPTCHA v2 Antes de mostrar o itinerário
Páginas com limite de taxa de API CAPTCHA personalizado Depois de exceder os limites de solicitação

Arquitetura de monitoramento de voo

import requests
import time
from datetime import datetime

class FlightMonitor:
    def __init__(self, api_key):
        self.api_key = api_key
        self.session = requests.Session()
        self.session.headers.update({
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
        })

    def check_flight(self, airline_url, flight_number):
        """Check flight status, handling CAPTCHAs if encountered."""
        response = self.session.get(
            f"{airline_url}/flight-status/{flight_number}"
        )

        if self._is_captcha_page(response):
            response = self._solve_and_retry(response, airline_url)

        return self._parse_flight_data(response.text)

    def _is_captcha_page(self, response):
        return (
            response.status_code == 403 or
            "cf-turnstile" in response.text or
            "g-recaptcha" in response.text
        )

    def _solve_and_retry(self, response, url):
        import re

        # Detect CAPTCHA type
        if "cf-turnstile" in response.text:
            match = re.search(r'data-sitekey="(0x[^"]+)"', response.text)
            token = self._solve_turnstile(match.group(1), url)
            field = "cf-turnstile-response"
        else:
            match = re.search(r'data-sitekey="([^"]+)"', response.text)
            token = self._solve_recaptcha(match.group(1), url)
            field = "g-recaptcha-response"

        return self.session.post(url, data={field: token})

    def _solve_turnstile(self, site_key, page_url):
        resp = requests.post("https://ocr.captchaai.com/in.php", data={
            "key": self.api_key,
            "method": "turnstile",
            "sitekey": site_key,
            "pageurl": page_url,
            "json": 1
        })
        task_id = resp.json()["request"]
        return self._poll_result(task_id)

    def _solve_recaptcha(self, site_key, page_url):
        resp = requests.post("https://ocr.captchaai.com/in.php", data={
            "key": self.api_key,
            "method": "userrecaptcha",
            "googlekey": site_key,
            "pageurl": page_url,
            "json": 1
        })
        task_id = resp.json()["request"]
        return self._poll_result(task_id)

    def _poll_result(self, task_id):
        for _ in range(60):
            time.sleep(3)
            result = requests.get("https://ocr.captchaai.com/res.php", params={
                "key": self.api_key,
                "action": "get",
                "id": task_id,
                "json": 1
            })
            data = result.json()
            if data["status"] == 1:
                return data["request"]
        raise TimeoutError("CAPTCHA solve timed out")

    def _parse_flight_data(self, html):
        # Parse flight status from HTML
        from bs4 import BeautifulSoup
        soup = BeautifulSoup(html, "html.parser")

        def text_or_none(node):
            return node.text.strip() if node and node.text else None

        return {
            "status": text_or_none(soup.select_one(".flight-status")),
            "departure": text_or_none(soup.select_one(".departure-time")),
            "arrival": text_or_none(soup.select_one(".arrival-time")),
            "gate": text_or_none(soup.select_one(".gate-info")),
            "checked_at": datetime.now().isoformat()
        }

Monitoramento Periódico com Tratamento CAPTCHA

def monitor_flight(monitor, airline_url, flight_number, 
                   interval_seconds=300, max_checks=48):
    """Monitor a flight every N seconds, handling CAPTCHAs as needed."""
    history = []

    for check_num in range(max_checks):
        try:
            status = monitor.check_flight(airline_url, flight_number)
            history.append(status)

            # Alert on changes
            if len(history) > 1 and status["status"] != history[-2]["status"]:
                print(f"Status changed: {history[-2]['status']} → {status['status']}")

            print(f"Check {check_num + 1}: {status['status']} "
                  f"(Gate: {status.get('gate', 'Coming soon')})")

        except Exception as e:
            print(f"Check {check_num + 1} failed: {e}")

        time.sleep(interval_seconds)

    return history

# Usage
monitor = FlightMonitor("YOUR_API_KEY")
monitor_flight(monitor, "https://airline.example.com", "AA1234")

Monitoramento de múltiplas companhias aéreas (JavaScript)

class FlightTracker {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.flights = new Map();
  }

  async addFlight(airline, flightNumber, checkUrl) {
    this.flights.set(flightNumber, {
      airline,
      url: checkUrl,
      history: [],
      lastCheck: null
    });
  }

  async checkAll() {
    const results = [];

    for (const [flightNum, flight] of this.flights) {
      try {
        const status = await this.checkFlight(flight.url, flightNum);
        flight.history.push(status);
        flight.lastCheck = new Date();
        results.push({ flight: flightNum, ...status });
      } catch (error) {
        results.push({ flight: flightNum, error: error.message });
      }
    }

    return results;
  }

  async checkFlight(url, flightNumber) {
    const response = await fetch(`${url}/status/${flightNumber}`);
    const html = await response.text();

    // Check for CAPTCHA
    if (html.includes('cf-turnstile') || response.status === 403) {
      return this.solveAndRetry(url, flightNumber, html);
    }

    return this.parseStatus(html);
  }

  async solveAndRetry(url, flightNumber, html) {
    const siteKeyMatch = html.match(/data-sitekey="(0x[^"]+)"/);
    if (!siteKeyMatch) throw new Error('No sitekey found');

    const token = await this.solveTurnstile(siteKeyMatch[1], url);

    const response = await fetch(`${url}/status/${flightNumber}`, {
      method: 'POST',
      body: new URLSearchParams({ 'cf-turnstile-response': token })
    });

    return this.parseStatus(await response.text());
  }
}

Frequência de monitoramento e taxas de CAPTCHA

Verifique a frequência Taxa típica de CAPTCHA Recomendação
A cada 1 minuto Alto (50–80%) Muito agressivo – aumente o intervalo
A cada 5 minutos Moderado (10–30%) Aceitável para voos críticos
A cada 15 minutos Baixo (5–10%) Bom equilíbrio para monitoramento de rotina
A cada 30 minutos Muito baixo (<5%) mais adequado para rastreamento de longo prazo
A cada hora Mínimo (<1%) CAPTCHAs raramente são acionados

Otimização de Sessão

Reduza os encontros CAPTCHA mantendo o estado da sessão:

Técnica Efeito
Persistir cookies entre verificações Cloudflare cookie_qa_validacao válido por 15 a 30 minutos
Use User-Agent consistente Mudar a UA desencadeia novos desafios
Mantenha a consistência do proxy O mesmo IP reduz suspeitas
Solicitações de espaço uniformemente Padrões de explosão acionam limites de taxa

Solução de problemas

Problema Causa Correção
CAPTCHA a cada verificação Sessão não persistida Reutilize requests.Session() em cheques
Bloco Cloudflare (Erro 1020) Muitos pedidos Aumentar o intervalo de verificação
Dados de voo desatualizados após CAPTCHA O token expirou durante a resolução Use soluções just-in-time
Dados diferentes dos mostrados pelo navegador Falta de renderização de JavaScript Use a automação do navegador para sites com uso pesado de JS

Perguntas frequentes

Com que frequência devo verificar o status do voo?

A cada 5 a 15 minutos é normal. Verificações mais frequentes acionam mais CAPTCHAs e podem resultar em bloqueios de IP. CaptchaAI lida com o Turnstile com 100% de taxa de sucesso, portanto, o fator limitante são os limites de taxa do portal, não a resolução de CAPTCHA.

Posso monitorar voos de várias companhias aéreas ao mesmo tempo?

Sim. Use sessões separadas por companhia aérea e resolva CAPTCHAs de forma independente para cada uma. CaptchaAI lida com solicitações simultâneas em diferentes sites.

As APIs móveis das companhias aéreas têm CAPTCHAs?

APIs móveis normalmente usam autenticação diferente (chaves de API, OAuth) em vez de CAPTCHAs. No entanto, os endpoints da web que eles atendem ainda podem ter proteção Cloudflare.

Artigos relacionados

Próximas etapas

Crie monitoramento de voo confiável -obtenha sua chave API CaptchaAIe lidar com CAPTCHAs de companhias aéreas automaticamente.

Os comentários estão desativados para este artigo.