Use Cases

Python ile CAPTCHA çözme: requests ile veri kazıma rehberi

Bir Python kazıyıcısında CAPTCHA'yla karşılaştığınızda çoğu zaman Selenium'a ya da tam bir tarayıcıya ihtiyacınız yoktur: sitekey'i sayfadan çeker, CaptchaAI API'sine gönderir ve dönen token'ı forma enjekte edersiniz. Bu rehber, requests ve BeautifulSoup tabanlı kazıyıcılarınıza bu akışı uçtan uca nasıl ekleyeceğinizi — yeniden kullanılabilir bir çözücü sınıfından üretim için hata yönetimine kadar — gösterir. reCAPTCHA v2/v3, Cloudflare Turnstile ve resim tabanlı CAPTCHA'lar aynı deseni paylaşır; farklı olan yalnızca gönderdiğiniz method parametresidir.

Gereksinimler

Başlamadan önce ortamınızda şunların hazır olması yeterlidir:

Gereksinim Ayrıntılar
Python 3.7+ pip ile kurulu
requests pip install requests
beautifulsoup4 pip install beautifulsoup4
CaptchaAI API anahtarı captchaai.com üzerinden alın

API anahtarınızı kontrol panelinden kopyalayın ve kod içine sabitlemek yerine bir ortam değişkeninde tutun.

Yeniden kullanılabilir CaptchaAI çözücü sınıfı

Akışın kalbi tek bir yardımcı sınıftır: bir görevi in.php uç noktasına gönderir, sonucu res.php üzerinden sorgular ve token hazır olduğunda döndürür. Bu sınıfı bir kez yazın, tüm kazıyıcılarınızda yeniden kullanın:

import requests
import time

class CaptchaSolver:
    def __init__(self, api_key):
        self.api_key = api_key
        self.base = "https://ocr.captchaai.com"

    def _submit(self, params):
        params["key"] = self.api_key
        resp = requests.get(f"{self.base}/in.php", params=params)
        if not resp.text.startswith("OK|"):
            raise Exception(f"Submit error: {resp.text}")
        return resp.text.split("|")[1]

    def _poll(self, task_id, timeout=300):
        deadline = time.time() + timeout
        while time.time() < deadline:
            time.sleep(5)
            resp = requests.get(f"{self.base}/res.php", params={
                "key": self.api_key,
                "action": "get",
                "id": task_id
            })
            if resp.text == "CAPCHA_NOT_READY":
                continue
            if resp.text.startswith("OK|"):
                return resp.text.split("|")[1]
            raise Exception(f"Solve error: {resp.text}")
        raise TimeoutError("Solve timed out")

    def solve_recaptcha_v2(self, site_key, page_url):
        task_id = self._submit({
            "method": "userrecaptcha",
            "googlekey": site_key,
            "pageurl": page_url
        })
        return self._poll(task_id)

    def solve_recaptcha_v3(self, site_key, page_url, action="verify"):
        task_id = self._submit({
            "method": "userrecaptcha",
            "googlekey": site_key,
            "pageurl": page_url,
            "version": "v3",
            "action": action
        })
        return self._poll(task_id)

    def solve_turnstile(self, site_key, page_url):
        task_id = self._submit({
            "method": "turnstile",
            "sitekey": site_key,
            "pageurl": page_url
        })
        return self._poll(task_id)

    def solve_image(self, image_base64):
        task_id = self._submit({
            "method": "base64",
            "body": image_base64
        })
        return self._poll(task_id)

_poll metodu her beş saniyede bir sonucu sorgular ve varsayılan 300 saniyelik zaman aşımına kadar bekler. reCAPTCHA v3 için action değerini sayfadaki gerçek eylem adıyla eşleştirin; yanlış eylem, çözülen token'ın site tarafından reddedilmesine yol açar.

reCAPTCHA korumalı bir formu kazıma

Tipik akış beş adımdır: sayfayı yükleyin, sitekey'i çıkarın, CAPTCHA'yı çözün, token'ı forma ekleyin ve sonucu ayrıştırın. Aşağıdaki örnek, arama formu reCAPTCHA v2 ile korunan bir sayfada bu adımları uygular:

from bs4 import BeautifulSoup
import requests

solver = CaptchaSolver("YOUR_API_KEY")
session = requests.Session()
session.headers.update({
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
})

# Step 1: Load the page
url = "https://example.com/search"
page = session.get(url)
soup = BeautifulSoup(page.text, "html.parser")

# Step 2: Extract the site key
recaptcha_div = soup.find("div", class_="g-recaptcha")
site_key = recaptcha_div["data-sitekey"]

# Step 3: Solve the CAPTCHA
token = solver.solve_recaptcha_v2(site_key, url)

# Step 4: Submit the form with the token
form_data = {
    "q": "search term",
    "g-recaptcha-response": token
}
result = session.post(url, data=form_data)

# Step 5: Parse the results
result_soup = BeautifulSoup(result.text, "html.parser")
items = result_soup.find_all("div", class_="result-item")
for item in items:
    print(item.text.strip())

Kritik nokta 4. adımdır: token, formun beklediği g-recaptcha-response alanına yerleştirilmelidir. Alan adı farklıysa gönderim sessizce başarısız olur ve site CAPTCHA sayfasını yeniden döndürür. Oturum boyunca çerezleri korumak için tüm isteklerde aynı requests.Session() nesnesini kullanın.

Sayfalandırılmış sonuçları toplu kazıma

CAPTCHA'nın ardındaki çok sayfalı listelerde her sayfa için ayrı bir token gerekebilir. Aşağıdaki fonksiyon sayfaları sırayla dolaşır, boş sonuç geldiğinde durur ve istekler arasına kibar bir gecikme koyar:

def scrape_all_pages(base_url, site_key, max_pages=10):
    solver = CaptchaSolver("YOUR_API_KEY")
    session = requests.Session()
    session.headers.update({
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
    })
    all_results = []

    for page_num in range(1, max_pages + 1):
        page_url = f"{base_url}?page={page_num}"

        # Solve CAPTCHA for each page if needed
        token = solver.solve_recaptcha_v2(site_key, page_url)

        resp = session.get(page_url, params={
            "g-recaptcha-response": token,
            "page": page_num
        })

        soup = BeautifulSoup(resp.text, "html.parser")
        items = soup.find_all("div", class_="item")

        if not items:
            break

        all_results.extend([item.text.strip() for item in items])
        print(f"Page {page_num}: {len(items)} items")

        time.sleep(2)  # Polite delay

    return all_results

Her sayfa için ayrı bir çözüm istediğinizde eşzamanlı thread sayınız doğrudan verimi belirler — CaptchaAI planları tam da bu eşzamanlılık üzerinden faturalandırılır (aşağıdaki maliyet bölümüne bakın).

Resim tabanlı CAPTCHA'ları çözme

Bazı siteler reCAPTCHA yerine klasik, metin içeren resim CAPTCHA'ları kullanır. Bu durumda resmi indirir, base64'e kodlar ve solve_image ile gönderirsiniz:

import base64

def scrape_with_image_captcha(url):
    solver = CaptchaSolver("YOUR_API_KEY")
    session = requests.Session()

    page = session.get(url)
    soup = BeautifulSoup(page.text, "html.parser")

    # Find the CAPTCHA image
    captcha_img = soup.find("img", {"id": "captcha-image"})
    captcha_url = captcha_img["src"]

    # Download and encode the image
    img_resp = session.get(captcha_url)
    img_base64 = base64.b64encode(img_resp.content).decode()

    # Solve
    captcha_text = solver.solve_image(img_base64)

    # Submit
    form_data = {
        "captcha": captcha_text,
        "username": "user"
    }
    result = session.post(url, data=form_data)
    return result.text

Üretim için hata yönetimi ve yeniden deneme

Gerçek kazıyıcılarda ağ hataları ve geçici çözüm hataları kaçınılmazdır. Çözüm çağrısını yeniden deneme mantığıyla sarın; birkaç deneme sonrası hâlâ başarısızsa hatayı yukarı taşıyın:

def solve_with_retry(solver, site_key, page_url, max_retries=3):
    for attempt in range(max_retries):
        try:
            return solver.solve_recaptcha_v2(site_key, page_url)
        except Exception as e:
            if attempt == max_retries - 1:
                raise
            print(f"Attempt {attempt + 1} failed: {e}. Retrying...")
            time.sleep(2)

Daha sağlam bir üretim iş akışı için üstel geri çekilme (exponential backoff) ekleyin ve kalıcı olarak başarısız olan görevleri loglayın.

Sorun giderme

En sık karşılaşılan hatalar ve çözümleri:

Sorun Sebep Düzeltme
ERROR_WRONG_USER_KEY Geçersiz API anahtarı Anahtarı kontrol panelinden doğrulayın
ERROR_ZERO_BALANCE Bakiye yok Hesabınızı doldurun
Form gönderimi CAPTCHA sayfasını yeniden döndürüyor Token'ın süresi dolmuş veya alan adı yanlış Token'ı hemen kullanın; form alan adlarını kontrol edin
ConnectionError Ağ sorunu Üstel geri çekilmeli yeniden deneme mantığı ekleyin
Gönderimden sonra boş sonuç Site çerez/oturum gerektiriyor Çerezleri korumak için requests.Session() kullanın

Ölçeklendirme, maliyet ve KVKK

CaptchaAI thread bazlı faturalandırır: BASIC ($15/ay, 5 thread) küçük kazıma işleri için yeterlidir; eşzamanlı hacminiz arttıkça ADVANCE ($90/ay, 50 thread) gibi üst planlara geçebilirsiniz. Türkiye'deki geliştiriciler için USD bazlı sabit aylık ücret, TL dalgalanmasından bağımsız öngörülebilir bir maliyet anlamına gelir; her thread aylık sınırsız çözüm içerir, yani ödediğiniz şey görev başına değil, eşzamanlılıktır.

Yüksek hacimli işlerde istekleri sırayla beklemek yerine eşzamanlı çalıştırmak verimi ciddi biçimde artırır; aiohttp ile CaptchaAI API'sini birlikte kullanan asenkron entegrasyon rehberine bakın. Aynı IP'den yoğun istek engellenmeye yol açabileceğinden, istekler arasına gecikme koyun ve farklı çıkış IP'leri için proxy yapılandırması rehberini inceleyin.

Son olarak yasal çerçeveyi unutmayın: kazıdığınız veriler kişisel veri içeriyorsa KVKK (Kişisel Verilerin Korunması Kanunu) kapsamına girer. CaptchaAI'yi yalnızca yetkili olduğunuz kaynaklarda ve izinli QA/veri toplama iş akışları çerçevesinde kullanın.

SSS

Bu yöntem hangi CAPTCHA türlerini çözer?

CaptchaAI; reCAPTCHA v2/v3, Cloudflare Turnstile, GeeTest v3 ve resim/OCR tabanlı CAPTCHA'ları çözer. hCaptcha ve FunCaptcha (Arkose Labs) desteklenmez; bu türler için kod deseni farklıdır ve bir çözüm sağlamaz.

reCAPTCHA v3 skoru düşük gelirse ne yapmalıyım?

Önce action değerinin sayfadaki gerçek eylem adıyla birebir eşleştiğinden emin olun; yanlış eylem token'ın reddedilmesine ya da düşük skora yol açar. Token'ı ürettikten hemen sonra, gecikmeden gönderin.

Token'ı aldıktan sonra form neden yine CAPTCHA döndürüyor?

Genellikle iki nedenden: token'ın süresi dolmuştur (birkaç dakikada geçersizleşir) ya da yanlış form alanına yerleştirilmiştir. Token'ı g-recaptcha-response alanına koyduğunuzu ve aynı oturumu kullandığınızı doğrulayın.

Kazıma için hangi CaptchaAI planı yeterli?

Tek thread'le sıralı çalışan küçük kazıyıcılar için BASIC ($15/ay, 5 thread) yeterlidir. Çok sayfayı eşzamanlı çözüyorsanız thread sayısı verimi belirler; ADVANCE ($90/ay, 50 thread) daha yüksek eşzamanlılık sağlar. Güncel fiyatlar için captchaai.com/pricing sayfasına bakın.

Kazıdığım veriler KVKK'ya tabi mi?

Veriler gerçek kişilere ait bilgiler içeriyorsa evet, KVKK kapsamındadır. Yalnızca erişim yetkiniz olan kaynaklarda ve meşru bir işleme amacı çerçevesinde çalışın; kişisel veriyi gereksiz yere toplamayın.

İlgili kılavuzlar

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