Eğitimler

Tek Sayfalı Uygulamalarda reCAPTCHA: Dinamik Yükleme Modelleri

Tek sayfalı uygulamalar reCAPTCHA'yı dinamik olarak yükler; widget ilk HTML'de mevcut değildir. Bir React oturum açma formu CAPTCHA'yı yalnızca bileşen bağlandığında işler. Bir Vue ödeme sayfası, kullanıcı "Sipariş Ver'i tıkladıktan sonra reCAPTCHA'yı yükler. Geleneksel sayfa kaynağı kazıma bunları tamamen gözden kaçırır. Dinamik olarak yüklenen reCAPTCHA'ları nasıl tespit edip çözeceğiniz aşağıda açıklanmıştır.

SPA'lar Neden Farklıdır?

Geleneksel sayfa SPA
İlk HTML'de reCAPTCHA betiği Rota değişikliğinden sonra eklenen komut dosyası
Widget sayfa yüklendiğinde görüntüleniyor Widget bileşen montajında işleniyor
Sayfa kaynağındaki site anahtarı JavaScript paketindeki site anahtarı
Form POST aracılığıyla gönderilir Form XHR/fetch aracılığıyla gönderilir

Bir SPA'da reCAPTCHA widget'ı, belirli bir kullanıcı eylemi onu tetikleyene kadar mevcut olmayabilir. Otomasyonunuz widget'ın görünmesini beklemelidir.

reCAPTCHA Widget'ını algılama

Elementi bekleyin

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=False)
    page = browser.new_page()
    page.goto("https://staging.example.com/qa-login")

    # SPA may need a click or navigation to trigger reCAPTCHA
    page.click("#show-login-form")

    # Wait for reCAPTCHA iframe to appear
    recaptcha_frame = page.wait_for_selector(
        "iframe[src*='recaptcha']",
        timeout=15000
    )
    print("reCAPTCHA detected:", recaptcha_frame.get_attribute("src"))

Site Anahtarını Çıkarın

Site anahtarı bir SPA'da birden fazla konumda olabilir:

# Method 1: From the iframe src
iframe_src = recaptcha_frame.get_attribute("src")
# src contains: ...?k=6LcR_RsTAAAAADge...
import re
match = re.search(r'[?&]k=([^&]+)', iframe_src)
site_key = match.group(1) if match else None

# Method 2: From data-sitekey attribute
site_key = page.eval_on_selector(
    "[data-sitekey]",
    "el => el.getAttribute('data-sitekey')"
)

# Method 3: From JavaScript bundle (last resort)
site_key = page.evaluate("""
    () => {
        // Check for grecaptcha render calls
        const scripts = document.querySelectorAll('script');
        for (const s of scripts) {
            const match = s.textContent.match(/sitekey['":\s]+(['"])(6L[^'"]+)\\1/);
            if (match) return match[2];
        }
        return null;
    }
""")

reCAPTCHA'yı çözme

Site anahtarını aldıktan sonra CaptchaAI'ye gönderin:

import requests
import time

def solve_recaptcha(site_key, page_url):
    # Submit task
    resp = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": "YOUR_API_KEY",
        "method": "userrecaptcha",
        "googlekey": site_key,
        "pageurl": page_url,
        "json": 1
    })
    task_id = resp.json()["request"]

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

Tokenın SPA'ya enjekte edilmesi

SPA'lar geleneksel formlar sunmaz. Belirteci uygulamanın beklediği yere enjekte etmeniz gerekir.

Yöntem 1: Gizli Metin Alanını Ayarlama

token = solve_recaptcha(site_key, "https://staging.example.com/qa-login")

# Inject into the g-recaptcha-response textarea
page.evaluate(f"""
    document.getElementById('g-recaptcha-response').value = '{token}';
""")

# Submit the form
page.click("#login-button")

Yöntem 2: Geri Aramayı Tetikleyin

Birçok SPA reCAPTCHA uygulaması geri çağırma işlevini kullanır:

# Find the callback function name
callback = page.evaluate("""
    () => {
        const widget = document.querySelector('.g-recaptcha');
        return widget?.getAttribute('data-callback') || null;
    }
""")

# Call it with the token
if callback:
    page.evaluate(f"window['{callback}']('{token}')")
else:
    # Try the default grecaptcha callback
    page.evaluate(f"""
        if (window.grecaptcha) {{
            // Set the response and trigger verification
            document.getElementById('g-recaptcha-response').value = '{token}';
            // Find and call any registered callbacks
            const form = document.querySelector('form');
            if (form) form.dispatchEvent(new Event('submit'));
        }}
    """)

Yöntem 3: XHR'yi Durdurun (JavaScript / Puppeteer)

const puppeteer = require('puppeteer');

async function solveRecaptchaInSPA() {
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();

  // Intercept the API call and inject the token
  await page.setRequestInterception(true);
  page.on('request', request => {
    if (request.url().includes('/api/login')) {
      const postData = JSON.parse(request.postData() || '{}');
      // Token already set via page.evaluate — let it pass
      request.continue();
    } else {
      request.continue();
    }
  });

  await page.goto('https://staging.example.com/qa-login');
  await page.waitForSelector('[data-sitekey]');

  const siteKey = await page.$eval(
    '[data-sitekey]',
    el => el.getAttribute('data-sitekey')
  );

  // Solve with CaptchaAI (implementation omitted — same as Python)
  const token = await solveCaptcha(siteKey, page.url());

  // Inject token and trigger callback
  await page.evaluate((t) => {
    document.getElementById('g-recaptcha-response').value = t;
    const callback = document.querySelector('.g-recaptcha')
      ?.getAttribute('data-callback');
    if (callback && window[callback]) {
      window[callback](t);
    }
  }, token);
}

Çerçeveye Özel Desenler

Tepki (tepki-google-recaptcha)

React uygulamaları genellikle react-google-recaptcha paketini kullanır. Bileşen eşzamansız olarak işlenir:

# Wait for React to mount the component
page.wait_for_selector(".g-recaptcha", state="attached")

# The sitekey is in the rendered div's data attribute
site_key = page.eval_on_selector(
    ".g-recaptcha", "el => el.dataset.sitekey"
)

Vue (vue-recaptcha)

# Vue may use v-if to conditionally render
# Navigate or interact to trigger the condition
page.click("#proceed-to-checkout")
page.wait_for_selector("iframe[src*='recaptcha']")

Açısal

# Angular apps may lazy-load reCAPTCHA modules
# Wait for the specific Angular component
page.wait_for_selector("re-captcha, app-recaptcha, [data-sitekey]")

Rota Değişikliklerini Ele Alma

SPA'lar sayfayı yeniden kullanır; gezinme, tam yeniden yükleme olmadan gerçekleşir:

# Listen for reCAPTCHA appearing after SPA navigation
page.goto("https://example.com")

# Navigate within the SPA
page.click("a[href='/login']")

# The URL changed but no page reload happened
# Wait for the CAPTCHA to render in the new "page"
page.wait_for_selector("iframe[src*='recaptcha']", timeout=10000)

Sorun giderme

Sorun Sebep Düzeltme
g-recaptcha-response metin alanı bulunamadı SPA henüz widget'ı oluşturmadı wait_for_selector'yi yeterli zaman aşımı ile kullanın
Jeton enjekte edildi ancak form gönderilmiyor Geri arama tetiklenmedi data-callback işlevini bulun ve çağırın
Site anahtarı sayfa kaynağında değil JS'de paketlenir veya dinamik olarak yüklenir Widget'ın oluşturulmasını bekleyin, ardından iframe src'den çıkarın
Jeton bir kez çalışır, sonra başarısız olur SPA bileşeni yeniden oluşturuyor ve jetonu temizliyor Formu göndermeden hemen önce jetonu enjekte edin
Widget, jeton enjeksiyonundan sonra yeniden işleniyor React/Vue reaktivitesi değeri temizler Textarea'yi ayarlamak yerine data-callback yaklaşımını kullanın

SSS

Tarayıcıyı atlayıp SPA reCAPTCHA'larını yalnızca HTTP istekleriyle çözebilir miyim?

Site anahtarını çıkarabilir ve form gönderme API çağrısını çoğaltabilirseniz evet. Birçok SPA formu bir REST API uç noktası aracılığıyla gönderilir; bunu doğrudan belirteçle çağırabilirsiniz. Ancak önce site anahtarını ve API uç noktasını keşfetmek için bir tarayıcıya ihtiyacınız vardır.

Yalnızca belirli kullanıcı işlemlerinde görünen reCAPTCHA'yı nasıl halledebilirim?

Tetikleyici eylemi otomatikleştirin (bir düğmeyi tıklayın, bir formu doldurun, bir rotaya gidin), ardından reCAPTCHA öğesinin görünmesini bekleyin. wait_for_selector'yi makul bir zaman aşımı süresiyle kullanın.

CaptchaAI, reCAPTCHA'nın bir SPA'da olup olmadığını önemsiyor mu?

Hayır. CaptchaAI yalnızca site anahtarına ve sayfa URL'sine ihtiyaç duyar. Widget'ın sayfada nasıl yüklendiği, çözümü etkilemez.

İlgili Makaleler

Sonraki Adımlar

Herhangi bir SPA'da dinamik olarak yüklenen reCAPTCHA'ları çözün -CaptchaAI API anahtarınızı alın.

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