Uçuş durumunun izlenmesi, birden fazla havayolu ve havaalanı portalında sık sık kontrol yapılmasını gerektirir. Bu portallar, gerçek zamanlı verilerini Cloudflare Turnstile, reCAPTCHA ve özel CAPTCHA'larla (özellikle tekrarlanan otomatik sorguları tespit ettiklerinde) korur. Güvenilir uçuş takip araçları oluştururken CAPTCHA'ları nasıl yöneteceğiniz burada açıklanmıştır.
CAPTCHA'ların Göründüğü Yer
| Portal türü | CAPTCHA | Tetikleyici |
|---|---|---|
| Havayolu uçuş durumu sayfası | Cloudflare Turnstile | Aynı IP'den sık istekler |
| Havaalanına varış/departure panoları | Cloudflare doğrulama akışı | Bot tespiti |
| Uçuş arama motorları | reCAPTCHA v2/v3 | Arama formu gönderimi |
| Rezervasyon durumu kontrolü | reCAPTCHA v2 | Seyahat planını göstermeden önce |
| API hız sınırı sayfaları | Özel CAPTCHA | İstek sınırlarını aştıktan sonra |
Uçuş İzleme Mimarisi
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()
}
CAPTCHA İşleme ile Periyodik İzleme
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")
Çoklu Havayolu İzleme (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());
}
}
İzleme Sıklığı ve CAPTCHA Oranları
| Frekansı kontrol edin | Tipik CAPTCHA oranı | Tavsiye |
|---|---|---|
| Her 1 dakikada bir | Yüksek (%50-80) | Çok agresif – aralığı artırın |
| Her 5 dakikada bir | Orta (%10-30) | Kritik uçuşlar için kabul edilebilir |
| Her 15 dakikada bir | Düşük (%5-10) | Rutin izleme için iyi denge |
| Her 30 dakikada bir | Çok düşük (<%5) | Uzun vadeli izleme için en iyisi |
| Her saat | Minimal (<%1) | CAPTCHA'lar nadiren tetiklenir |
Oturum Optimizasyonu
Oturum durumunu koruyarak CAPTCHA karşılaşmalarını azaltın:
| Teknik | Etki |
|---|---|
| Kontroller arasında çerezlerin kalıcı olmasını sağlayın | Cloudflare qa_session_cookie 15-30 dakika süreyle geçerlidir |
| Tutarlı Kullanıcı Aracısı kullanın | UA'yı değiştirmek yeni zorlukları tetikliyor |
| Proxy tutarlılığını koruyun | Aynı IP şüpheyi azaltır |
| Eşit alan istekleri | Patlama modelleri hız sınırlarını tetikler |
Sorun giderme
| Sorun | Sebep | Düzeltme |
|---|---|---|
| CAPTCHA her kontrolde | Oturum devam etmedi | requests.Session()'yi kontrollerde yeniden kullanın |
| Cloudflare bloğu (Hata 1020) | Çok fazla istek | Kontrol aralığını artırın |
| CAPTCHA'dan sonra uçuş verileri güncelliğini yitirdi | Çözüm sırasında belirtecin süresi doldu | Tam zamanında çözmeyi kullanın |
| Tarayıcının gösterdiğinden farklı veriler | Eksik JavaScript oluşturma | JS ağırlıklı siteler için tarayıcı otomasyonunu kullanın |
SSS
Uçuş durumunu ne sıklıkla kontrol etmeliyim?
Her 5-15 dakikada bir normaldir. Daha sık kontroller daha fazla CAPTCHA'yı tetikler ve IP engellemelerine neden olabilir. CaptchaAI Turnstileyi %100 başarı oranıyla yönetir, dolayısıyla sınırlayıcı faktör CAPTCHA çözümü değil, portalın hız sınırlarıdır.
Birden fazla havayolunun uçuşlarını aynı anda izleyebilir miyim?
Evet. Her havayolu için ayrı oturumlar kullanın ve her biri için CAPTCHA'ları bağımsız olarak çözün. CaptchaAI, farklı sitelerdeki eşzamanlı istekleri yönetir.
Havayolu mobil API'lerinin CAPTCHA'ları var mı?
Mobil API'ler genellikle CAPTCHA'lar yerine farklı kimlik doğrulama (API anahtarları, OAuth) kullanır. Ancak hizmet verdikleri web uç noktaları hâlâ Cloudflare korumasına sahip olabilir.
İlgili Makaleler
- Geetest ve Cloudflare Turnstile Karşılaştırması
- Cloudflare Turnstile 403 Token Düzeltmesinden Sonra
- Cloudflare Turnstile Widget Modlarının Açıklaması
Sonraki Adımlar
Güvenilir uçuş izleme sistemi oluşturun —CaptchaAI API anahtarınızı alınve havayolu CAPTCHA'larını otomatik olarak yönetin.