Use Cases

CAPTCHA İşleme ile Havayolu Ücret Takibi

Çok rotalı bir uçak bileti fiyat izleyicisi kurduğunuzda karşılaşacağınız ilk engel fiyat verisi değil, doğrulama ekranlarıdır: seyahat siteleri otomatik sorguları yavaşlatmak için reCAPTCHA v2, Cloudflare Turnstile ve istek sınırlama katmanları çalıştırır. Cevap basit — çözüm adımını bir API'ye devrederseniz izleyiciniz durmadan çalışmaya devam eder.

CaptchaAI tam da bu çözüm adımını üstlenir: sayfadaki sitekey'i çıkarır, doğrulamayı çözer ve size hedef siteye geri göndereceğiniz token'ı verir. Aşağıda, fiyat kontrolü sırasında CAPTCHA'yı algılayan, çözen ve isteği token'la yeniden gönderen tekrarlanabilir bir Python iş akışını sıfırdan kuruyoruz.


İzleme iş akışı nasıl işliyor

Schedule check → Request fare page → CAPTCHA detected?
                                         ↓ Yes
                                    Solve via CaptchaAI → Inject token → Retry request
                                         ↓ No
                                    Parse fare data → Store → Alert on price change

Pratikte her kontrol şu adımları izler:

  1. Zamanlayıcı rotayı tetikler ve izleyici fiyat sayfasını ister.
  2. Yanıtta bir CAPTCHA varsa sitekey çıkarılır ve çözüm CaptchaAI'ye devredilir.
  3. Dönen token isteğe eklenir ve sayfa yeniden istenir.
  4. Doğrulama yoksa ya da çözüldüyse fiyat verisi ayrıştırılır, saklanır ve değişimde uyarı üretilir.

Gerçek bir senaryo

Diyelim ki İstanbul'da serbest çalışan bir otomasyon geliştiricisisiniz ve bir seyahat acentesi için birkaç popüler rotanın fiyatını günde üç dört kez raporlayan bir araç yazıyorsunuz. Bu tür bir işte iki şey işinizi kolaylaştırır: öngörülebilir maliyet ve toplanan verinin sorumlu biçimde saklanması. CaptchaAI thread bazlı ücretlendirdiği için — örneğin BASIC ($15/ay, 5 thread) — aylık gideriniz TL kurundaki dalgalanmadan bağımsız olarak sabit kalır ve çözüm başına sürpriz fatura çıkmaz. Sakladığınız veride yolcu adı ya da e-posta gibi kişisel bilgiler varsa bunların KVKK kapsamına girdiğini unutmayın; izlemeyi yalnızca yetkiniz olan, herkese açık fiyat alanlarıyla sınırlı tutun.


Seyahat sitelerinde hangi doğrulamalar çıkar

Havayolu ve seyahat sitelerinin fiyat sayfaları tek bir CAPTCHA türüyle sınırlı kalmaz; izleyicinizin hepsini tanıyıp doğru yöntemle çözmesi gerekir:

  • reCAPTCHA v2 — arama formunu gönderdiğinizde çıkan onay kutusu ya da görüntü tabanlı doğrulama. Fiyat sayfalarında en sık karşılaşacağınız tür budur.
  • reCAPTCHA v3 — kullanıcıya hiçbir şey göstermeden arka planda bir puan üreten sürüm; puanınız düşükse istek sessizce reddedilir.
  • Cloudflare Turnstile — Cloudflare'in reCAPTCHA'ya alternatifi; giderek daha çok seyahat sitesi buna geçiyor.
  • Cloudflare doğrulama akışı — tam sayfa bir ara yüz; içeriğe hiç ulaşamadan araya girer ve ayrı bir yöntemle ele alınır.

İzleyicinizi bu türleri yanıtın HTML'inden algılayacak biçimde kurarsanız, hangi rotada hangi doğrulamanın çıktığından bağımsız olarak çalışmaya devam eder. Aşağıdaki iş akışı reCAPTCHA v2 ve Turnstile'ı otomatik ayırt eder; diğer türler için de aynı algıla-çöz-yeniden gönder kalıbını izleyebilirsiniz.

İzlemeyi yalnızca erişim yetkiniz olan, herkese açık fiyat alanlarıyla sınırlı tutun ve her sitenin kullanım koşullarına uyun. CaptchaAI doğrulama adımını çözer; hangi veriyi hangi sıklıkta topladığınızın sorumluluğu size aittir.


Başlamadan önce gerekenler

Gereksinim Ayrıntılar
CaptchaAI API anahtarı captchaai.com
Python 3.8+ requests ile
Proxy Seyahat siteleri için güvenilir bir proxy yapılandırması
pip install requests

CaptchaAI çözüm yardımcısı

Aşağıdaki iki yardımcı fonksiyon çözüm adımını kapsar: biri reCAPTCHA v2, diğeri Turnstile için. Her ikisi de sitekey ve pageurl alır, görevi CaptchaAI'ye gönderir, sonuç hazır olana kadar res.php uç noktasını sorgular ve hedef siteye göndereceğiniz token'ı döndürür. time.sleep değerleri türe göre farklıdır çünkü Turnstile genelde reCAPTCHA v2'den daha hızlı çözülür.

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

CAPTCHA işleyen fiyat izleyici sınıfı

FareMonitor sınıfı akışın tamamını bir araya getirir: fiyat sayfasını ister, yanıtta reCAPTCHA ya da Turnstile olup olmadığını kontrol eder, varsa sitekey'i çıkarıp ilgili çözücüyü çağırır ve isteği token'la yeniden gönderir. Her hedef site için uyarlamanız gereken tek yer _parse_fare yöntemidir; fiyat, para birimi ve tarih alanlarını o sitenin HTML yapısına göre burada ayrıştırın. Farklı rotaları tek bir Session üzerinden geçirerek çerezleri koruyabilir ve gereksiz doğrulama tekrarını azaltabilirsiniz.

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

Kontrolleri zamanlama

İzleyiciyi cron ya da bir görev zamanlayıcıyla düzenli aralıklarla çalıştırın:

# Check fares every 6 hours
0 */6 * * * cd /path/to/project && python fare_monitor.py >> /var/log/fares.log 2>&1

İzleyiciyi bir sunucuda çalıştırıyorsanız her koşunun çıktısını loglayın: bir rota sürekli hata veriyorsa bunu, sitenin CAPTCHA davranışındaki değişiklikten erken haber almanın en pratik yoludur. Aralığı ihtiyaca göre ayarlayın — sık kontrol daha çok CAPTCHA ve proxy maliyeti demektir.


Ücret yakalama kontrol listesi

  • Temel ücret, vergiler, para birimi ve ücret ailesini tek bir veri kaydında toplayın; böylece sonraki karşılaştırmalar tutarlı kalır.
  • Her ayrıştırıcı için en az iki yedek seçici tanımlayın ve ayrıştırma başarısız olduğunda ham HTML'in anlık görüntüsünü saklayın.
  • Her çözüm olayında rotayı, kalkış tarihini, toplama süresini ve CAPTCHA gecikmesini kaydedin; sorun gidermeyi bu loglar kolaylaştırır.

Sorun giderme

Uzun süre çalışan bir izleyicide sorunların çoğu birkaç kaynaktan gelir:

  • Doğrulama sıklığı beklenenden yüksekse, istek deseniniz siteye fazla "bot gibi" görünüyordur.
  • Fiyatlar değişmiyor gibi görünüyorsa, muhtemelen önbelleğe alınmış bir yanıt okuyorsunuzdur.
  • Çözüm sürekli başarısızsa, ilk bakılacak yer sitekey çıkarımıdır.

Aşağıdaki tablo bu belirtileri olası nedenleri ve düzeltmeleriyle eşleştirir:

Sorun Sebep Düzeltme
Sık sık CAPTCHA çıkıyor Aynı IP'den çok fazla istek İstekleri birden fazla IP'ye dağıtın ve kontrol sıklığını düşürün
Fiyatlar güncel değil Önbelleğe alınmış sayfalar Önbellek kıran başlıklar ekleyin veya istek parametrelerini rastgeleleştirin
IP engellendi İstek sınırlama Kontroller arasındaki gecikmeyi artırın ve farklı proxy'ler kullanın
CAPTCHA çözümü başarısız Yanlış sitekey çıkarımı Çıkarılan sitekey'in sayfadaki CAPTCHA ile eşleştiğini doğrulayın

SSS

Havayolu fiyatlarını izlemek KVKK'ya uygun mu?

Herkese açık fiyat verisini toplamak genellikle sorun değildir; sorumluluk verinin nasıl saklandığında başlar. Yolcu adı, e-posta veya rezervasyon bilgisi gibi kişisel veriler topluyorsanız bunlar KVKK kapsamına girer. İzlemeyi yetkiniz olan, kişisel veri içermeyen fiyat alanlarıyla sınırlı tutun.

Bu iş akışı aylık ne kadara mal olur?

İki kalem var: CaptchaAI planı ve proxy. CaptchaAI thread bazlı çalışır; birkaç rotayı günde birkaç kez kontrol eden bir izleyici için çoğu zaman BASIC ($15/ay, 5 thread) yeterlidir ve çözüm başına ek ücret yoktur. Kontrol sıklığını ve rota sayısını artırdıkça daha fazla thread'e geçebilirsiniz.

reCAPTCHA v3 kullanan bir siteyi de izleyebilir miyim?

Evet. reCAPTCHA v3 kullanıcıya bir şey göstermez, arka planda bir puan üretir; CaptchaAI bu tür için de token döndürür. Yalnızca isteklerinizin, puanı düşürecek kadar agresif olmamasına dikkat edin — kontrol aralığını makul tutmak (çoğu senaryoda 4–8 saat) burada da işe yarar.

CaptchaAI hangi CAPTCHA türlerini çözer?

Seyahat sitelerinde en sık görülen reCAPTCHA v2 ve v3, Cloudflare Turnstile ve görüntü tabanlı CAPTCHA'lar desteklenir. hCaptcha ise desteklenmez; bir hedef site hCaptcha kullanıyorsa iş akışınızı buna göre planlayın.

Cloudflare doğrulama akışı sayfalarını nasıl çözerim?

Tam sayfa Cloudflare doğrulama akışları için method=cloudflare_challenge parametresini bir proxy ile birlikte kullanın; döndürülen qa_session_cookie çerezi siteye erişim sağlar. Ayrıntılar için Cloudflare doğrulama akışı çözüm rehberine bakın.


Hemen başlayın

Ücretsiz bir hesap açıp API anahtarınızı captchaai.com üzerinden alın; fiyat izleme iş akışınızdaki CAPTCHA'ları ilk günden itibaren otomatik olarak çözün.


İlgili kılavuzlar

Bu makale için yorumlar devre dışı bırakılmıştır.