Patchright’ta Stealth'i Bozmadan CAPTCHA Nasıl Çözülür

patchright captcha - How to Solve CAPTCHA in Patchright Without Breaking Stealth

Patchright’ta bir captcha akışı diğerlerinin hepsiyle aynı üç hamleden oluşur: sitekey'i okuyun, bir çözücüye gönderin, token'ı sayfaya geri koyun. Bu kütüphanenin insanları şaşırttığı yer üçüncü hamledir. Patchright, JavaScript'inizi varsayılan olarak yalıtılmış bir bağlamda çalıştırır ve yalıtılmış bir bağlam sayfanın DOM'unu paylaşır ama sayfanın JavaScript global'ini paylaşmaz. Yani token yazma işlemi yerine ulaşır, textarea değeri gerçekten tutar ve sitenin kendi callback'i hiç çalışmaz; çünkü kodunuzun çalıştığı kapsamda o callback yoktur. Bunu fazladan bir argüman düzeltir.

Neye ihtiyacınız var

  • Python 3.10 veya üstü, ya da JavaScript paketini tercih ediyorsanız Node.js. Patchright her iki çalışma zamanı için de yayımlanır ve her ikisinde de Playwright’ın yerine doğrudan geçer.
  • Patchright’ın kendi kurucusuyla indirilmiş bir Chromium tarayıcısı. Firefox ve WebKit yamalanmaz ve desteklenmez.
  • Korumalı formun sayfa URL’si. Sitekey çalışma zamanında okunur.
  • Betik ile çözücü aynı makinedeyse Yerel modda, değilse Sunucu modunda çalışan CapSkip. Her ikisi de şurada açıklanıyor: bağlantı ayarları.
# pip install patchright
pip install -U capskip patchright

# Pulls the browser. Real Chrome is the recommended channel,
# and the maintainers say so explicitly.
patchright install chrome

Patchright gerçekte neyi değiştirir

Patchright, bariz otomasyon izleri kaldırılmış Playwright’tır. Öne çıkan yama, Runtime.enable'ı hiç çağırmamasıdır; bu, standart bir Playwright oturumunun yaydığı en gürültülü tek sinyaldir ve Patchright bunu, script'lerinizi bunun yerine yalıtılmış ExecutionContexts içinde çalıştırarak başarır. Ayrıca Console API'yi tamamen devre dışı bırakır, navigator.webdriver'ı gizleyen bayrağı ekler ve bir oturumu otomatik olarak işaretleyen birkaç Playwright varsayılanını kaldırır: otomasyon bayrağının kendisi, pop-up engelleyici geçersiz kılması, bileşen güncelleme engeli ve varsayılan uygulamalarla uzantıları devre dışı bırakan anahtarlar.

Bunlardan ikisinin CAPTCHA işi için doğrudan sonuçları var ve ikisine de takılmak kolay.

Konsolun kapalı olması, sayfanın içinden log'ladığınız hiçbir şeyin size ulaşmaması demektir. Patchright’ta konsol işlevselliği hiç çalışmaz; dolayısıyla bir evaluate çağrısının içine bir log satırı bırakıp onu sürücüden okuma alışkanlığı burada işe yaramaz. Bunun yerine çağrıdan bir değer döndürün. Zaten daha iyi bir pratik bu ve elinizdeki tek seçenek de bu.

Uzantıların yeniden etkinleştirilmesi ise daha dost canlısı olanı. Playwright normalde uzantılar devre dışı olarak başlar, Patchright bu anahtarı kaldırır; böylece kalıcı bir profile yüklenmiş bir tarayıcı uzantısı gerçekten çalışır. Bu kodların hiçbirini yazmak istemiyorsanız, CapSkip tarayıcı uzantısı sayfadaki widget'ı halleder; siz de formu, sanki bir insan doğrulamayı geçmiş gibi sürersiniz.

Bilmeye değer bir yetenek daha: Patchright, sıradan locator'lar ve XPath'lerle kapalı shadow root'ların içine ulaşır. İşaretlemesini kapalı bir root arkasına saklayan widget'lara hiçbir özel işlem yapmadan erişilebilir.

Adım 1: geliştiricilerin önerdiği şekilde başlatın

Patchright’ın stealth'i, yamalar kadar başlatma yapılandırmasına da bağlıdır. Belgelenen kurulum şudur: gerçek Chrome kanalında kalıcı bir bağlam, görünür bir pencere ve viewport geçersiz kılması olmadan, ayrıca hiçbir özel user agent veya header olmadan. Son ikisi önemli: elle ayarlanmış bir user agent, parmak izinin geri kalanıyla çelişir ve yapılan işi boşa çıkarır.

# pip install patchright
from patchright.sync_api import sync_playwright

with sync_playwright() as p:
    context = p.chromium.launch_persistent_context(
        user_data_dir="C:\\profiles\\scraper",
        channel="chrome",
        headless=False,
        no_viewport=True,
        # Do not set user_agent or extra headers here.
    )
    page = context.new_page()
    page.goto("https://example.com/page-with-recaptcha")

Görünür pencereye dikkat edin. Tespit bütçesinin çoğu headless'a harcanır ve önerilen yapılandırma headless kullanmaz. Windows’ta bu, betiği çalıştıran hesabın etkileşimli bir masaüstü oturumuna ihtiyaç duyduğu anlamına gelir; bunu bir sunucuya kurmadan önce planlamakta fayda var.

Adım 2: sitekey'i sayfadan okuyun

Sitekey, widget iframe’inin içinde değil, ana belgede yer alır ve sıradan bir locator bunu okur. Locator'lar herhangi bir yürütme bağlamından değil, tarayıcı protokolü üzerinden gider; dolayısıyla yalıtılmış dünyayla ilgili hiçbir şey bu adımı etkilemez.

# Locators auto-wait, so this doubles as a wait condition
# for a widget that renders late.
holder = page.locator("div.g-recaptcha")
holder.wait_for(state="attached", timeout=15000)

sitekey = holder.get_attribute("data-sitekey")
print(sitekey)   # 6Lxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Bazı siteler anahtarı ana sayfaya hiç koymaz ve yalnızca widget iframe URL'sinde geçirir. Bu durumda anahtarı sorgu dizesinden okuyun ve bir çözüm harcamadan önce kontrol edin; çünkü boş bir değer ta çözücüye kadar gider ve şu şekilde geri döner: ERROR_GOOGLEKEY, yani asıl başarısız olan okumadan çok uzak bir noktada.

# Fallback: the k= parameter on the anchor iframe.
from urllib.parse import urlparse, parse_qs

src = page.locator("iframe[src*='recaptcha/api2/anchor']").get_attribute("src")
sitekey = parse_qs(urlparse(src).query)["k"][0]

Adım 3: kendi makinenizde çözün

Python SDK'sı CapSkip ile port 8080 üzerinden konuşur ve token'ı düz bir dize olarak geri verir. Tek bir metot reCAPTCHA v2, Invisible, Enterprise ve v3'ü kapsar; varyantlar ayrı çağrılar olarak değil, seçenek olarak geçirilir.

# pip install capskip
from capskip import CapSkip

solver = CapSkip(host="127.0.0.1", port=8080)

# Invisible v2 takes invisible=1, Enterprise takes enterprise=1,
# and v3 takes version="v3" with an action.
result = solver.recaptcha(sitekey=sitekey, url=PAGE_URL)

token = result["code"]   # the g-recaptcha-response value

Turnstile ve GeeTest'in kendi metotları vardır ve aynı biçimi alır. Turnstile ayrıca çözümün yapıldığı user agent'ı da döndürür; bir challenge sayfası, o user agent token ile birlikte geri gönderilmedikçe token'ı reddeder. Onu yalnızca form isteğinde gönderin. Tarayıcı başlatıcısına vermeyin; çünkü elle ayarlanmış bir user agent, tam da stealth yapılandırmasının kaçınmanızı söylediği şeydir. Tam parametre listeleri şurada: CapSkip API dokümantasyonu.

Adım 4: token'ı sayfanın kullanabileceği yere koyun

Bu kütüphaneye özgü olan kısım burası. Yanıt textarea'sı display:none ile gizlenmiştir; dolayısıyla içine hiçbir şey yazamaz ve değerin JavaScript ile atanması gerekir. Bu atama yalıtılmış bağlamdan çalışır, çünkü DOM paylaşılır. Dizeyi f-string yerine json.dumps ile oluşturun; çünkü bir JSON dize değişmezi, tırnaklama ve kaçış dahil, aynı zamanda geçerli bir JavaScript dize değişmezidir.

# A DOM write is fine from the isolated context.
import json

page.evaluate(
    "document.getElementById('g-recaptcha-response').value = "
    + json.dumps(token)
)

page.click("button[type=submit]")

Bu, formu gönderim sırasında textarea'yı okuyan siteleri kapsar. Pek çok site bunu yapmaz. Widget'a bir başarı callback'i kaydederler ve textarea'ya hiç bakmazlar; dolayısıyla token'ın, sayfanın tanımladığı bir fonksiyona verilmesi gerekir. Patchright’ın yalıtılmış bağlamının kendi JavaScript global'i vardır; bu da sayfanın fonksiyonlarının ve reCAPTCHA istemci yapılandırmasının orada hiç bulunmadığı anlamına gelir. Çağrı bir referans hatasıyla başarısız olur ve ne kadar yeniden denerseniz deneyin bu değişmez.

Patchright’ın buna yanıtı fazladan bir argüman. evaluate, evaluate_handle ve evaluate_all metotlarının üçü de isolated_context alır, varsayılanı True'dur ve False yapıldığında script sayfanın kendi main world'ünde çalışır.

# The main world is where the page's own globals live.
page.evaluate(
    "token => window.onRecaptchaSuccess(token)",
    token,
    isolated_context=False,
)

Callback adını tahmin etmek yerine sayfanın işaretlemesinden okuyun. main world'ü yalnızca enjeksiyon için kullanın, başka hiçbir şey için değil: orada çalışan kod siteye görünür ve yalıtılmış bağlamın varsayılan olmasının bütün nedeni budur. Her iki gönderim biçimi de altta sıradan reCAPTCHA v2'dir ve ikisi de şurada anlatılıyor: reCAPTCHA v2 çözücü sayfası.

Tam çalışan örnek

Yukarıdakilerin hepsi tek bir betikte. Çözücü bir kez oluşturulur, üzerine bir çözüm harcanmadan önce sitekey kontrol edilir ve token, sayfanın içinde log alarak değil, bir uzunluk döndürülerek doğrulanır.

# pip install capskip patchright
import json
from patchright.sync_api import sync_playwright
from capskip import CapSkip

PAGE_URL = "https://example.com/page-with-recaptcha"

solver = CapSkip(host="127.0.0.1", port=8080)

with sync_playwright() as p:
    context = p.chromium.launch_persistent_context(
        user_data_dir="C:\\profiles\\scraper",
        channel="chrome",
        headless=False,
        no_viewport=True,
    )
    page = context.new_page()
    page.goto(PAGE_URL)

    holder = page.locator("div.g-recaptcha")
    holder.wait_for(state="attached", timeout=15000)
    sitekey = holder.get_attribute("data-sitekey")
    if not sitekey:
        raise RuntimeError("Widget found but data-sitekey was empty.")

    token = solver.recaptcha(sitekey=sitekey, url=PAGE_URL)["code"]
    page.evaluate(
        "document.getElementById('g-recaptcha-response').value = "
        + json.dumps(token)
    )

    length = page.evaluate(
        "document.getElementById('g-recaptcha-response').value.length"
    )
    print(length)   # 0 means the injection did not land

    page.click("button[type=submit]")
    page.wait_for_load_state("networkidle")
    context.close()

Çözücüyü başka bir makinede çalıştırmak

Patchright genelde betiği yazdığınız makineden daha büyük bir makinede çalışmaya başlar ve önerilen görünür pencere kurulumu insanları epey hızlı biçimde ayrılmış bir VM'e yöneltir. Çözücünün onunla birlikte taşınması gerekmez.

CapSkip'in iki bağlantı modu var. Local, 127.0.0.1 adresine bağlanır ve yalnızca o cihaza yanıt verir; uygulamanın çalıştığı makinede betiği yazarken doğru olan budur. Server ise ağınıza veya genel IP'nize bağlanır; böylece bir scraping VM'i, ikinci bir iş istasyonu ya da bunların bütün bir havuzu API üzerinden aynı Windows makinesini çağırır. Statik bir genel IP o adresi sabit tutar. Kodda host dışında hiçbir şey değişmez, maliyetle ilgili de hiçbir şey değişmez; çünkü bu hâlâ sizin sahip olduğunuz donanım.

# Same SDK, same call. Only the host moves.
solver = CapSkip(host="10.0.0.12", port=8080, apiKey="YOUR_API_KEY")

Çözücü bir ağ adresini dinlemeye başladığında anahtar doğrulamasını açın ve her makineye kendi anahtarını verin; böylece biri, diğerlerine dokunulmadan iptal edilebilir. Her iki mod da şurada adım adım anlatılıyor: CapSkip kurulum kılavuzu.

Sık görülen hatalar ve anlamları

GördüğünüzNedenDüzeltme
textarea token'ı tutuyor ama form başarısız oluyorSite bir callback kullanıyor ve textarea'yı hiç okumuyorCallback'i isolated_context=False ile çağırın
Bir sayfa fonksiyonunu adlandıran referans hatasıSayfa global'leri yalıtılmış bağlamda bulunmazAynı çözüm: o tek çağrıyı main world'de çalıştırın
Sayfadaki bir konsol log'undan hiçbir şey gelmiyorPatchright, Console API'yi tamamen devre dışı bırakırLog almak yerine evaluate'ten bir değer döndürün
Firefox veya WebKit düz Playwright gibi davranıyorYalnızca Chromium tarayıcıları yamalanırChromium veya Chrome kanalını kullanın
Yamalara rağmen engelleniyorÖzel bir user agent veya header parmak iziyle çelişiyorBunları kaldırın ve Chrome üzerinde kalıcı bir bağlam kullanın
ERROR_GOOGLEKEYÇözücüye boş bir sitekey ulaştırecaptcha çağrısından önce değeri doğrulayın
NetworkExceptionCapSkip çalışmıyor ya da ana makine adresi yanlışUygulamayı başlatın veya host değerini sunucu adresine yöneltin
TimeoutExceptionÇözüm recaptchaTimeout süresini aştıVarsayılan 300 saniyenin üzerine çıkarın

FAQ

Playwright betiğimi değiştirmeden taşıyabilir miyim?

Import'u değiştirin, çoğu çalışır. Locator'lar, bağlamlar, route'lar, bekleyişler ve gezinme eskisi gibi davranır. Üç şeye ikinci kez bakmak gerekir: sayfanın tanımladığı bir şeye dokunan her evaluate çağrısı, ki artık fazladan argümana ihtiyaç duyar; konsol çıktısına dayanan her şey, ki artık yok; ve her Firefox veya WebKit hedefi, ki yamalanmamıştır. Daha geniş Playwright tablosu şurada: Playwright CAPTCHA çözücü sayfası.

Main world kullanmak beni tespit ettirir mi?

Prensipte evet, çünkü sayfa orada çalışan kodu görebilir. Pratikte maruziyet, mikrosaniyeler süren tek bir fonksiyon çağrısıdır ve bir insan doğrulamayı geçtiğinde widget'ın kendi script'inin yaptığıyla aynı görünür. Diğer her şeyi yalıtılmış bağlamda tutun, enjeksiyonu birkaç çağrı yerine tek bir çağrıda yapın; yüzey küçük kalsın.

Token enjekte etmek yerine Turnstile widget'ına tıklamalı mıyım?

Bazen. Tarayıcı inandırıcı göründüğünde, managed moddaki bir Turnstile onay kutusu kendi başına geçebilir; Patchright tam da bunun içindir. Bu yüzden önce tıklamayı denemeye ve gerekirse çözüme geri dönmeye değer. Bir reCAPTCHA onay kutusuna tıklamak yalnızca bir görsel doğrulama açar, dolayısıyla orada kazanılacak bir şey yok. Widget tarafı şurada ele alınıyor: Cloudflare Turnstile çözücü sayfasını.

Crawler'ım Linux’ta çalışıyor. CapSkip nereye kurulur?

Kontrolünüzdeki bir Windows makinesine, Server modu açık olarak. Linux makinesi ona API üzerinden, tıpkı diğer iç servisler gibi çağrı yapar; böylece Patchright ile çözücünün aynı işletim sistemini, hatta aynı ağ segmentini paylaşması gerekmez. host argümanını o adrese yönlendirin, anahtar doğrulamasını etkinleştirin ve crawler'a kendi anahtarını verin.

Kısa özet

Patchright’ı kurun, Chrome kanalında görünür bir pencereyle ve özel bir user agent olmadan kalıcı bir bağlam başlatın, sitekey'i sıradan bir locator ile okuyun ve 127.0.0.1:8080 üzerindeki CapSkip ile çözün. Token'ı varsayılan yalıtılmış bağlamdan doğrudan textarea'ya yazın ve isolated_context=False'a yalnızca site bir callback'in çağrılmasını istediğinde başvurun. Selenium ve Playwright dahil Python dünyasının geri kalanı için şuraya bakın: Python CAPTCHA çözücü sayfası.

Bir taramayı ölçeklendirmeden önce bilmeye değer bir şey var. CapSkip şudur: sınırsız captcha çözücü ve zaten sahip olduğunuz donanımda çalışır, dolayısıyla bin sayfayı yeniden denemek tam olarak on sayfayı yeniden denemek kadar tutar.