Cas d'Usage

Gestion des CAPTCHA pour la surveillance de l'état des vols

La surveillance du statut des vols nécessite des contrôles fréquents sur plusieurs portails de compagnies aériennes et d'aéroports. Ces portails protègent leurs données en temps réel avec Cloudflare Turnstile, reCAPTCHA et CAPTCHA personnalisés - en particulier lorsqu'ils détectent des requêtes automatisées répétées. Voici comment gérer les CAPTCHA tout en créant des outils de suivi de vol fiables.

Où apparaissent les CAPTCHA

Type de portail CAPTCHA Déclencheur
Page d'état des vols de la compagnie aérienne Cloudflare Turnstile Requêtes fréquentes depuis la même adresse IP
Arrivée à l'aéroportTableaux /departure Cloudflare Challenge Détection de robots
Moteurs de recherche de vols reCAPTCHA v2/v3 Envoi du formulaire de recherche
Vérification du statut de la réservation reCAPTCHA v2 Avant d'afficher l'itinéraire
Pages de limite de débit de l'API CAPTCHA personnalisé Après avoir dépassé les limites de requêtes

Architecture de surveillance des vols

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_of(node):
            return node.get_text(strip=True) if node else None

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

Surveillance périodique avec gestion 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")

Surveillance multi-compagnies aériennes (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());
  }
}

Fréquence de surveillance et taux de CAPTCHA

Vérifier la fréquence Taux CAPTCHA typique Recommandation
Toutes les 1 minutes Élevé (50 à 80 %) Trop agressif – augmenter l'intervalle
Toutes les 5 minutes Modéré (10 à 30 %) Acceptable pour les vols critiques
Toutes les 15 minutes Faible (5 à 10 %) Bon équilibre pour une surveillance de routine
Toutes les 30 minutes Très faible (<5%) Idéal pour le suivi à long terme
Toutes les heures Minime (<1%) Les CAPTCHA se déclenchent rarement

Optimisation des sessions

Réduisez les rencontres CAPTCHA en conservant l’état de la session :

Technique Effet
Conserver les cookies entre les vérifications Cloudflare cf_clearance valable 15 à 30 minutes
Utiliser un agent utilisateur cohérent Changer l’AU soulève de nouveaux défis
Maintenir la cohérence des proxys La même adresse IP réduit les soupçons
Espacer les demandes de manière uniforme Les modèles de rafales déclenchent des limites de débit

Dépannage

Problème Parce que Corriger
CAPTCHA à chaque chèque Session non persistante Réutiliser requests.Session() entre les chèques
Bloc Cloudflare (Erreur 1020) Trop de demandes Augmenter l'intervalle de contrôle
Données de vol obsolètes après CAPTCHA Le jeton a expiré pendant la résolution Utiliser la résolution juste à temps
Données différentes de celles affichées par le navigateur Rendu JavaScript manquant Utiliser l'automatisation du navigateur pour les sites utilisant beaucoup de JS

FAQ

À quelle fréquence dois-je vérifier le statut du vol ?

Toutes les 5 à 15 minutes sont typiques. Des contrôles plus fréquents déclenchent davantage de CAPTCHA et peuvent entraîner des blocages IP. CaptchaAI gère Turnstile avec un taux de réussite de 100 %, le facteur limitant est donc les limites de débit du portail, et non la résolution de CAPTCHA.

Puis-je surveiller les vols de plusieurs compagnies aériennes à la fois ?

Oui. Utilisez des sessions distinctes par compagnie aérienne et résolvez les CAPTCHA indépendamment pour chacune. CaptchaAI gère les demandes simultanées sur différents sites.

Les API mobiles des compagnies aériennes comportent-elles des CAPTCHA ?

Les API mobiles utilisent généralement une authentification différente (clés API, OAuth) plutôt que des CAPTCHA. Cependant, les points de terminaison Web qu’ils servent peuvent toujours bénéficier d’une protection Cloudflare.

Articles connexes

Prochaines étapes

Construisez une surveillance des vols fiable -récupérez votre clé API CaptchaAIet gérez automatiquement les CAPTCHA des compagnies aériennes.

Les commentaires sont désactivés pour cet article.