Scarnox · Blog

PopularCaptcha'yı Playwright ve Puppeteer ile çözme (Node.js)

Tarayıcı otomasyonu, bir PopularCaptcha çıktığı anda durur. Bir betikten resim ızgarası üzerinden tıklamak yavaştır ve kırılgandır. Bir çözüm API'sinden token almak ve onu sayfaya koymak tek bir istek gerektirir; betiğinizin geri kalanı normal şekilde devam eder.

Bu rehber Node.js ile Playwright ve Puppeteer'ı kapsar. Akış ikisinde de aynıdır ve örnekler proxysiz çözümleri kullanır; bunları Scarnox kendi ağında çalıştırır. PopularCaptcha, Scarnox'un bugün çözdüğü tiptir. Diğer captcha tipleri yakında geliyor; bu yüzden aşağıdaki kod yalnızca PopularCaptcha içindir.

Akış

  1. Sitekey'i sayfadan okuyun.
  2. Scarnox'tan tek bir bloklayan POST isteğiyle bir token isteyin.
  3. Token'ı yanıt alanına koyun ya da sitenin callback'ine verin, sonra formu gönderin.

Anahtarı ayarlayın

Hesap oluşturun ve ücretsiz deneme kredisiyle başlayın; kart gerekmez. Anahtarı test kodunda değil, her zaman bir ortam değişkeninde tutun:

export SCARNOX_KEY="scarnox_YOURAPIKEY"

Node 18 ve sonrası fetch içerir, bu yüzden API çağrısı ek paket gerektirmez.

Playwright

import { chromium } from "playwright";

const API_KEY = process.env.SCARNOX_KEY;

async function solve(sitekey, url) {
  const r = await fetch("https://api.scarnox.com/api/tasks/create", {
    method: "POST",
    headers: { Authorization: `Bearer ${API_KEY}`, "Content-Type": "application/json" },
    body: JSON.stringify({ captcha_type: "PopularCaptchaTaskProxyless", site_key: sitekey, site_url: url }),
  });
  const data = await r.json();
  if (data.errorId !== 0) throw new Error(`${data.errorCode}: ${data.errorDescription}`);
  return data.solution.token;
}

const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto("https://example.com/signup");

const sitekey = await page.getAttribute("[data-sitekey]", "data-sitekey");
const token = await solve(sitekey, page.url());

// Sitenin okuyabileceği iki yanıt alanının ikisine de token'ı koyun.
await page.evaluate((t) => {
  for (const name of ["h-captcha-response", "g-recaptcha-response"]) {
    document.querySelectorAll(`[name="${name}"]`).forEach((el) => { el.value = t; });
  }
}, token);

await page.fill("#email", "you@example.com");
await page.click("button[type=submit]");

site_url değerinin page.url() üzerinden geldiğine dikkat edin. Çözücünün ihtiyacı olan, widget'ın bulunduğu sayfadır. Çözüm sayfa yüklendikten sonra yapılır, bu yüzden sitekey DOM'dadır.

Puppeteer

Puppeteer yalnızca seçici API'sinde farklılaşır. Yukarıdaki solve fonksiyonunu yeniden kullanın ve sayfa çağrılarını değiştirin:

const sitekey = await page.$eval("[data-sitekey]", (el) => el.dataset.sitekey);
const token = await solve(sitekey, page.url());

await page.evaluate((t) => {
  document.querySelectorAll('[name="h-captcha-response"],[name="g-recaptcha-response"]')
    .forEach((el) => { el.value = t; });
}, token);

Site bir callback kullandığında

Bazı siteler gizli alanı okumaz. Bunun yerine widget'ın JavaScript callback'ini bekler. Widget'ın data-callback özniteliğinde adı verilen fonksiyonu bulun ve token ile çağırın:

await page.evaluate((t) => {
  const name = document.querySelector("[data-sitekey]")?.dataset.callback;
  if (name && typeof window[name] === "function") window[name](t);
}, token);

Site ikisini de kullanıyorsa, alanı ayarlayın ve callback'i çağırın. İkisini birden yapmak zararsızdır.

Görünmez widget'lar

Görünmez bir widget'ta onay kutusu yoktur. Site widget'ı kendi kodundan başlatır; genellikle ziyaretçi gönder düğmesine bastığında. Aynı isteği, isteğe bağlı is_invisible alanını true yaparak gönderin:

body: JSON.stringify({
  captcha_type: "PopularCaptchaTaskProxyless",
  site_key: sitekey,
  site_url: url,
  is_invisible: true,
}),

Görünmez captcha rehberi bu widget'ların nasıl fark edileceğini ve token'ın nasıl geri verileceğini açıklar.

Zamanlama ipuçları

Kendi akışınızı test etmek

Örneği daha büyük bir şeye bağlamadan önce, kendi sahip olduğunuz bir formda çalıştırın. Üç şeyi kontrol edin: token kabul ediliyor, form gönderiliyor ve bir sonraki sayfa açılıyor. Akış uçtan uca çalıştığında, her çalıştırmada tek bir gerçek çözümle CI'da yeşil tutun.

Ücretsiz deneyin

Hesap oluşturun ve ücretsiz deneme kredisiyle başlayın; kart gerekmez. Bu, tüm akışı kurmak ve denemek için yeterlidir. Hacimde çözümün maliyeti için güncel fiyatlandırmaya bakın.

Reddedilen bir token'ı ayıklamak

Site bir token'ı reddettiğinde, tek bir istek ve tek bir sayfa yüklemesiyle akışı yeniden üretin; başka bir şeyi değiştirmeden önce. Şunları sırayla kontrol edin:

Başarısızlık anında sayfa HTML'ini await page.content() ile kaydedin. Bu HTML'i çalışan bir çalıştırmayla karşılaştırmak, farkı genellikle bir bakışta gösterir: farklı bir sitekey, eksik bir alan ya da farklı bir modda render edilmiş bir widget.

Sonraki adımlar