Anwendungsfälle

CAPTCHA-Behandlung zur Flugstatusüberwachung

Die Überwachung des Flugstatus erfordert häufige Überprüfungen über mehrere Fluglinien- und Flughafenportale hinweg. Diese Portale schützen ihre Echtzeitdaten mit Cloudflare Turnstile, reCAPTCHA und benutzerdefinierten CAPTCHAs – insbesondere, wenn sie wiederholte automatisierte Abfragen erkennen. Hier erfahren Sie, wie Sie mit CAPTCHAs umgehen und gleichzeitig zuverlässige Flugverfolgungstools erstellen.

Wo CAPTCHAs erscheinen

Portaltyp CAPTCHA Auslöser
Flugstatusseite der Fluggesellschaft Cloudflare Turnstile Häufige Anfragen von derselben IP
Ankunft am Flughafen/departure Tafeln Cloudflare Challenge Bot-Erkennung
Flugsuchmaschinen reCAPTCHA v2/v3 Übermittlung des Suchformulars
Überprüfung des Buchungsstatus reCAPTCHA v2 Bevor Sie die Reiseroute anzeigen
API-Ratenbegrenzungsseiten Benutzerdefiniertes CAPTCHA Nach Überschreiten der Anforderungslimits

Flugüberwachungsarchitektur

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()
        }

Regelmäßige Überwachung mit CAPTCHA-Verwaltung

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")

Multi-Airline-Überwachung (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());
  }
}

Überwachungshäufigkeit und CAPTCHA-Raten

Frequenz prüfen Typische CAPTCHA-Rate Empfehlung
Alle 1 Minute Hoch (50–80 %) Zu aggressiv – Intervall verlängern
Alle 5 Minuten Mäßig (10–30 %) Für kritische Flüge akzeptabel
Alle 15 Minuten Niedrig (5–10 %) Gute Balance für die Routineüberwachung
Alle 30 Minuten Sehr niedrig (<5 %) Am besten für die Langzeitverfolgung geeignet
Jede Stunde Minimal (<1 %) CAPTCHAs werden selten ausgelöst

Sitzungsoptimierung

Reduzieren Sie CAPTCHA-Begegnungen, indem Sie den Sitzungsstatus beibehalten:

Technik Wirkung
Behalten Sie Cookies zwischen Überprüfungen bei Cloudflare cf_clearance gültig für 15–30 Minuten
Verwenden Sie einen konsistenten User-Agent Der Wandel von UA bringt neue Herausforderungen mit sich
Behalten Sie die Proxy-Konsistenz bei Gleiche IP verringert den Verdacht
Platzbedarf gleichmäßig verteilen Burst-Muster lösen Ratenbegrenzungen aus

Fehlerbehebung

Problem Ursache Lösung
Zu viele CAPTCHAs in kurzer Zeit Abrufrate oder Parallelität ist für die Quelle zu aggressiv Drossele Intervalle, halte Sessions stabil und prüfe die Qualität deiner Proxys
Daten fehlen trotz gelöster CAPTCHA Der Parser liest eine alte oder unvollständige Ansicht aus Extrahiere Daten erst nach erfolgreicher Token-Anwendung in derselben Sitzung
Kosten steigen stärker als erwartet Zu viele Wiederholungen oder unnötige Seitenaufrufe lösen zusätzliche Challenges aus Löse nur kritische Schritte und protokolliere Wiederholungen pro Quelle

Verwandte Leitfäden

  • Cloudflare Turnstile per API lösen
  • Airline-Ticketpreise überwachen
  • Geschützte Websites scrapen
Kommentare sind für diesen Artikel deaktiviert.