Node.js'te GeeTest v3 Nasıl Çözülür ve Geri Gönderilir

Neredeyse her CAPTCHA entegrasyonu bir token'ın girip bir token'ın çıktığını varsayar. GeeTest bu şekilde çalışmaz. Bir çözüm şunu döndürür: üç birlikte gönderilmesi gereken değerler ve başladığınız challenge, onu getirmenizden yaklaşık bir dakika sonra sona erer. Bu hataların hiçbiri kullanışlı bir hata mesajı üretmez; işte bu yüzden GeeTest zahmetli olmasıyla ün salmıştır.
İki girdi, biri kısa ömürlü
| Değer | Ömür boyu |
|---|---|
gt | Site başına statiktir. Serbestçe önbelleğe alın |
challenge | Tek kullanımlık, kabaca 60 saniyede ölür |
Her ikisi de sitenin kendi GeeTest init uç noktasından gelir. Sorguyu yeniden kullanılabilir olarak ele almak, entegrasyonların test aşamasında geçip, kuyruk gecikmesinin çözümü son kullanma süresinin ötesine ittiği üretim ortamında çökmesinin nedenidir.
Kurulum
npm install capskip
const { CapSkip } = require('capskip');
const solver = new CapSkip({
host: '127.0.0.1',
port: 8080,
recaptchaTimeout: 300, // GeeTest uses this, not defaultTimeout
});Bu ayrım önemlidir. defaultTimeout yalnızca görüntü CAPTCHA'larını yönetir; etkileşimli olan her şey şunu kullanır: recaptchaTimeout.
Çözme
const result = await solver.geetest( '81388ea1fc187e0c335c0a8907ff2625', // gt, static per site '7cf6a8b1a2c34d5e6f7089abcdef0123', // challenge, fetched seconds ago 'https://example.com/login', ); console.log(result.challenge, result.validate, result.seccode);
O üç özellik cevaptır. result.code da doldurulur, ancak GeeTest için gönderilebilir bir şey yerine ham JSON dizesini tutar, dolayısıyla alışkanlıktan buna uzanmak kafa karıştırıcı bir hataya yol açar.
Şunu kullanın: challenge geri gelen, geçirdiğiniz değil. Bunlar her zaman aynı değildir.
Akışın tamamı
const { CapSkip } = require('capskip');
const solver = new CapSkip();
const LOGIN = 'https://example.com/login';
// 1. Fresh pair, cache-busted. Cached init responses return spent challenges.
const init = await (await fetch(
`https://example.com/geetest/init?t=${Date.now()}`,
)).json();
// 2. Solve immediately. Nothing slow between here and the previous step.
const result = await solver.geetest(init.gt, init.challenge, LOGIN);
// 3. Post all three together with the real form fields.
const response = await fetch(LOGIN, {
method: 'POST',
body: new URLSearchParams({
geetest_challenge: result.challenge,
geetest_validate: result.validate,
geetest_seccode: result.seccode,
username: '...',
password: '...',
}),
});Önbellek kırıcı (cache-busting) zaman damgası gerçek bir iş yapar. GeeTest init endpoint'leri sıklıkla bir CDN veya proxy tarafından önbelleğe alınır ve önbelleğe alınmış bir yanıt, size birilerinin daha önce kullandığı bir doğrulama verir.
O alan adları olağan GeeTest v3 kuralıdır, ancak bir site bunları yeniden adlandırabilir. Varsaymadan önce gerçek formu kontrol edin.
Toplu işlem (batching) tuzağı
Node'un ergonomisinin size karşı çalıştığı yer burasıdır. Bariz paralel sürüm yanlıştır:
// WRONG: every challenge is fetched up front, so the later solves // start against pairs that have already expired. const pairs = await Promise.all(urls.map(fetchPair)); const results = await Promise.all( pairs.map((p, i) => solver.geetest(p.gt, p.challenge, urls[i])));
Getirme (fetch) ve çözme işlemini aynı görev içinde tutun, böylece her çift verilmesinden saniyeler içinde kullanılır:
// RIGHT: each task fetches its own pair immediately before solving.
const results = await Promise.all(urls.map(async (url) => {
const pair = await fetchPair(url);
return solver.geetest(pair.gt, pair.challenge, url);
}));AsyncCapSkip şunun takma adı olarak dışa aktarılır: CapSkip burada, bu yüzden uzanılacak ayrı bir async istemci yoktur. Promise.all hikâyenin tamamıdır.
Hatalar
const {
ValidationException, NetworkException, ApiException, TimeoutException,
} = require('capskip');
try {
const result = await solver.geetest(gt, challenge, pageUrl);
} catch (err) {
if (err instanceof ValidationException) { /* missing gt or challenge */ }
else if (err instanceof NetworkException) { /* CapSkip not running */ }
else if (err instanceof ApiException) { /* usually an expired challenge */ }
else if (err instanceof TimeoutException) { /* exceeded recaptchaTimeout */ }
else throw err;
}Çoğu GeeTest hatası şu şekilde gelir: ApiException ve challenge'ın sona erdiği anlamına gelir. Aynı ikiliyle yeniden denemek asla işe yaramaz. Yenisini getirin.
Sık sorulan sorular
Neden yalnızca result.code kullanamıyorum?
Çünkü GeeTest’in yanıtı üç değerdir. code eksiksizlik için ham JSON'ı tutar, SDK ise kullanışlı kısımları şuna genişletir: challenge, validate ve seccode. Onları gönderin.
gt değerini önbelleğe alabilir miyim?
Evet. gt bir site tanımlayıcısıdır ve nadiren değişir. challenge bozulabilir yarıdır ve her seferinde yeniden getirilmelidir.
Bu, GeeTest v4'ü işler mi?
The geetest metodu v3'ü hedefler, bir şeyin üzerine kurulan kaydırma bulmacası: gt ve challenge çift. v4 parametre modelini değiştirdi, bu yüzden geçerli olanı kontrol edin API dokümantasyonu aynı çağrının işe yaradığını varsaymadan önce.
Özet
Önbelleği atlatılmış bir çift alın, hemen çözün, sonra gönderin challenge, validate ve seccode birlikte. Döndürülen challenge'ı kullanın, yalnızca şunu önbelleğe alın: gt, ve paralel çalışırken getirme ile çözme işlemlerini aynı görevin içinde tutun.
Diğer diller şuradadır: GeeTest çözücü sayfa, şuradaki daha geniş Node yüzeyi Node.js CAPTCHA çözücü sayfası ve bizim üzerimizde canlı bir bulmaca var GeeTest v3 demosu. CapSkip yapar captcha atlatma yerel olarak; dolayısıyla çözüm hacmi hiçbir maliyet oluşturmaz.
