Node.js’te Capy Puzzle Nasıl Çözülür ve Oturum Nasıl Korunur

Node.js ile Capy Puzzle çözmek için sayfayı çekin ve PUZZLE_ anahtarını widget script’inden okuyun. Anahtarı sayfa URL’siyle birlikte capskip paketinin capy metoduna verin. Ardından döndürdüğü üç değeri capy_captchakey, capy_challengekey ve capy_answer alanlarında, birlikte ve hemen, sayfayı çeken oturumun bir parçası olarak gönderin. Node kodunun genellikle bozulduğu yer bu son kısımdır. Node’un yerleşik fetch’i hiçbir çerezi saklamaz ve Referer göndermez. Bu durumda form gönderimi, sayfanın açtığı oturum olmadan ulaşır ve cevap ne kadar doğru olursa olsun site onu reddeder. CapSkip, Capy Puzzle desteğini 1.4.0 sürümünde ekledi. Bu rehber anahtarı, çağrıyı, iki saniyelik bekletmeyi, gönderimi, yeniden denemeleri ve aynı anda çok sayıda giriş işlemi çalıştırmayı ele alıyor.
Neye ihtiyacınız var
- Bir Windows makinesinde çalışan CapSkip 1.4.0 veya üzeri. Capy Puzzle desteği, CaptchaFox ve Friendly Captcha ile birlikte bu sürümle geldi.
- Node.js 20.18.1 veya üzeri; cheerio’nun desteklediği en eski sürüm budur. Yeni bir projede 22 ya da 24 kullanın, çünkü Node 20 Nisan 2026’da destek ömrünün sonuna ulaştı.
- capskip paketinin 1.3.0 veya üzeri bir sürümü; capy metodunu içeren ilk sürüm budur. Ayrıca formu okumak için cheerio.
- Bulmacayı gösteren sayfanın URL’si. Anahtar, Capy host’u ve form alanları hep bu sayfadan elde edilir.
- Çözücü için bir adres. Local modunda CapSkip 127.0.0.1 üzerinden yalnızca o cihaza yanıt verir; Server modunda ise ağ adresinizi veya genel IP’nizi dinler, böylece başka bir makinedeki bir betik onu API üzerinden çağırabilir. İkisi de şurada ayarlanır: bağlantı ayarları.
# capskip 1.3.0 added capy(); cheerio reads the form npm install capskip cheerio
Örnekler, üst düzey await kullanan ES modülleridir. Onları .mjs uzantısıyla kaydedin ya da package.json dosyanızdaki type alanını module olarak ayarlayın, çünkü npm init’in yeni sürümleri oraya commonjs yazar ve type alanı olmayan bir package.json da CommonJS sayılır. Projeniz CommonJS ise capskip paketi require ile de yüklenir.
1. Adım: sayfayı çekin, çerezlerini saklayın ve anahtarı bulun
Capy formları genellikle bir oturum çerezi ayarlayan ve forma bir CSRF token’ı koyan bir giriş veya kayıt sayfasının arkasında durur. Node’un fetch’i çağrılar arasında hiçbir çerezi saklamaz; dolayısıyla siz gönderene kadar o çerez çoktan kaybolmuştur ve token artık hiçbir şeyle eşleşmez. Çerezleri kendiniz taşıyın. Headers.getSetCookie() her Set-Cookie satırını ayrı bir öğe olarak döndürür ve aşağıdaki küçük addCookies yardımcısının ihtiyaç duyduğu tek şey de budur; MDN bunu şu başlık altında belgeliyor: Headers.getSetCookie().
// npm install capskip cheerio
import * as cheerio from "cheerio";
const PAGE_URL = "https://example.com/login";
// fetch() keeps no cookies between calls, so carry them yourself.
const jar = new Map();
function addCookies(res) {
for (const line of res.headers.getSetCookie()) {
const pair = line.split(";")[0];
const eq = pair.indexOf("=");
if (eq > 0) jar.set(pair.slice(0, eq).trim(), pair.slice(eq + 1).trim());
}
}
const page = await fetch(PAGE_URL);
addCookies(page);
const html = await page.text();
const $ = cheerio.load(html);
// The widget script's k= parameter, or a capy_captchakey input.
const key = html.match(/PUZZLE_[A-Za-z0-9_-]+/)?.[0];
// Everything before /puzzle/get_js/ is the Capy host.
const apiServer = html.match(/(https:\/\/[^"'\s<>]+?)\/puzzle\/get_js\//)?.[1];
// The form that holds the widget script or a capy_captchakey input.
const form = $("form")
.has('script[src*="/puzzle/get_js/"], input[name="capy_captchakey"]').first();
console.log(key, apiServer ?? "default host", form.length);Anahtar herkese açıktır ve her ziyaretçi için aynıdır; puzzle türündeki bir anahtar PUZZLE_ ile başlar. Çoğu sayfa onu widget script’inin URL’sindeki k parametresinde taşır ve bu URL, fetch’in indirdiği HTML’in içindedir. Bazı sayfalar formda ayrıca gizli bir capy_captchakey input alanı da oluşturur; widget bir tarayıcıda çalıştıktan sonra bu alan her zaman vardır ve DevTools onu orada gösterir. Tek bir düzenli ifade anahtarı iki yerde de bulur.
Oradayken script’in host’unu da not edin. Script URL’sinde /puzzle/get_js/ öncesindeki her şey, anahtarın arkasında durduğu Capy API’sidir ve CapSkip buna api_server der. Varsayılan değeri, canlı servisin çalıştığı https://jp.api.capy.me adresidir; dolayısıyla buna yalnızca bir sayfa widget’ı başka bir yerden yüklediğinde ihtiyacınız olur. Diğer çözücüler için yazılmış örnekler çoğu zaman bölgesel ön ek olmadan api.capy.me adresini gösterir ve bu host artık çözümlenmiyor; böyle bir örneği kopyaladıysanız bu değeri kaldırın. Regex bir https:// URL’si bekler; src bunun yerine // ile başlıyorsa, değeri vermeden önce host’un önüne https: ekleyin.
Koddaki form satırı, widget script’ini ya da bir capy_captchakey input alanını içeren formu seçer. Script’i head bölümünde veya formun altında yükleyen ve formun içinde capy_captchakey input alanı bulunmayan bir sayfada form.length 0 olarak kalır. Böyle bir sayfada formu bunun yerine id’sine veya action değerine göre seçin.
2. Adım: solver.capy() çağrısı
Node.js ile Capy Puzzle çözmek için tek bir metoda ihtiyacınız var. Metot anahtarı, sayfa URL’sini ve isteğe bağlı bir seçenekler nesnesini alır; varsayılan host üzerindeki bir sayfa için ilk ikisi yeterlidir.
// npm install capskip
import { CapSkip } from "capskip";
const solver = new CapSkip({
host: "127.0.0.1",
port: 8080,
// Capy answers after a two second hold; poll often enough to catch it.
pollingInterval: 0.5,
});
// undefined (no widget script in the HTML) is dropped, so CapSkip
// uses its default host.
const result = await solver.capy(key, PAGE_URL, { apiServer });
console.log(result.captchakey); // goes in capy_captchakey
console.log(result.challengekey); // goes in capy_challengekey
console.log(result.answer); // goes in capy_answerSonuç düz bir nesnedir. Adlandırılmış üç alanı okuyun. result.code, sunucunun cevabının tamamını, yani dört alanın hepsini içeren ve loglama için kullanışlı olan bir nesneyi tutar; result.respKey ise yalnızca diğer servislerle uyumluluk için var olan boş bir dizedir. Cevap, 0xax8ex0xax84x benzeri bir şeyle başlayan uzun bir dizedir: bir koordinat değil, parça hareket ederken widget’ın kaydedeceği sürükleme izidir.
Metodun kabul ettiği seçenekler
apiServer, api_server seçeneğinin takma adıdır ve metot, değeri undefined veya null olan her seçeneği çıkarır; yukarıdaki çağrının regex sonucunu her seferinde verebilmesinin nedeni budur. Metot ayrıca type ve uri anahtarlarına sahip bir proxy nesnesini ve useragent seçeneğini de alır; useragent, CapSkip’in bulmacayı çekmek için yaptığı tek istekte gönderilir. Bir version seçeneği de vardır, ancak yalnızca puzzle kabul edilir. Capy’nin diğer ailesi olan avatar, farklı bir endpoint’in arkasında duran başka bir challenge türüdür; bu yüzden SDK, sitenin reddedeceği bir cevap döndürmek yerine onu geri çevirir.
Çağrı başına verilen iki seçenek insanların ayağına takılır. Saniye cinsinden verilen bir timeout, yalnızca o çözüm için istemcinin defaultTimeout değerinin yerini alır. Yoklama aralığının üst sınırı da çağrı başına ayarlanabilir, ama yalnızca polling_interval olarak. camelCase yazılan pollingInterval constructor’a aittir; solver.capy() çağrısına verildiğinde seçeneğin adını belirten bir ValidationException fırlatır. TypeScript sizi uyarmaz, çünkü seçenekler türü her anahtarı kabul eder. Boş bir anahtar veya URL, bilinmeyen bir seçenek ve HTTP, HTTPS, SOCKS5 ya da SOCKS5H dışında bir proxy türü de, makinenizden daha hiçbir istek çıkmadan ValidationException fırlatır.
Bir Capy çözümü neden yaklaşık iki saniye sürer
Tespitin kendisi hızlıdır. CapSkip bulmaca görselini çeker, biraz piksel hesabıyla boşluğu bulur ve sürükleme izini oluşturur; işin içinde ne bir tarayıcı ne de bir model vardır. Sonra bilerek bekler.
Capy, bir bulmacanın çekilmesiyle cevabın alınması arasındaki süreyi ölçer ve bir insanın parçayı sürükleyebileceğinden daha hızlı gelen her şeyi reddeder. CapSkip’in Capy üzerindeki kendi testleri bu alt sınırı yaklaşık bir saniyeye koyuyor. Ret, yanlış bir cevapla aynı mesajı taşır; dolayısıyla fazla erken teslim edilen doğru bir çözüm tıpatıp bozuk bir çözücü gibi görünür. Bu yüzden CapSkip her Capy sonucunu, bulmacayı çektikten iki saniye sonrasına kadar bekletir. Bekleme bir sleep çağrısıdır, yani gecikme ekler ama CPU harcamaz.
Varsayılan ayarlarla bir çağrı dört saniyeye yakın sürer ve bunun nedeni yoklamadır. SDK, iş gönderilir gönderilmez sonucu ister, ardından çeyrek saniye sonra yeniden sorar. Aralığı her seferinde ikiye katlayarak pollingInterval değerine, yani varsayılan olarak 5 saniyeye kadar açar. Yoklamalar 0, 0.25, 0.75, 1.75 ve 3.75 saniyelerde gerçekleşir, dolayısıyla iki saniyelik bir cevap beşinci yoklamada alınır. Yukarıdaki gibi constructor’da pollingInterval: 0.5 ayarlandığında, testlerimizde çağrı iş gönderildikten yaklaşık 2.3 saniye sonra döndü. Gönderimden önce kendi gecikmenizi eklemeyin ve bekletmeyi kısaltmaya da çalışmayın: cevabın kabul edilmesini sağlayan tam olarak bu bekletmedir.
3. Adım: üç değerin hepsini sayfanın çerezleriyle gönderin
Üç değer, widget’ın forma kendisinin yazacağı alanlara girer. Onları birlikte, tek bir istekte, 1. adımdaki çerezlerle ve Referer olarak sayfanın URL’siyle gönderin. Gönderimi ayrıca redirect değeri manual olacak şekilde yapın; böylece sitenin geri verdiği oturum sizde kalır.
// The form's own fields, hidden CSRF token included.
const body = new URLSearchParams(
form.serializeArray().map((f) => [f.name, f.value]),
);
// Use the page's own field names, password included.
body.set("username", "YOUR_USERNAME");
body.set("capy_captchakey", result.captchakey);
body.set("capy_challengekey", result.challengekey);
body.set("capy_answer", result.answer);
const res = await fetch(new URL(form.attr("action") || PAGE_URL, PAGE_URL), {
method: "POST",
headers: {
cookie: [...jar].map(([k, v]) => `${k}=${v}`).join("; "),
// fetch sends no Referer; strict servers refuse a post without one.
referer: PAGE_URL,
},
body,
// A login answers 302 with a new session cookie; keep it.
redirect: "manual",
});
addCookies(res);
console.log(res.status, res.headers.get("location"));serializeArray, gizli CSRF token’ı dahil, bir tarayıcının göndereceği alanları toplar; böylece onları tek tek adlandırmanız gerekmez. Gönder düğmesini dışarıda bırakır; sunucu düğmenin adını kontrol ediyorsa onu body.set ile ekleyin. body.set ayrıca sayfanın kendisinin oluşturduğu bir capy_captchakey input alanının da yerini alır, böylece anahtar hiçbir zaman iki kez gönderilmez. Referer, çerez kadar önemlidir. fetch ne Referer ne de Origin gönderir; aralarında Django’nun da bulunduğu bazı framework’ler, doğru çerez, token ve cevapla bile, ikisi de olmayan bir HTTPS form gönderimini reddeder.
redirect ayarı, başarılı bir girişten sonra oturumu korur. Bir giriş isteği genellikle yeni bir oturum çereziyle birlikte 302 yanıtı verir, çünkü Django gibi framework’ler oturumu bu noktada yeniler. Kendi hâline bırakılan fetch, yönlendirmeyi bu çerez olmadan izler, yeniden giriş sayfasına düşer ve 200 bildirir. redirect manual olarak ayarlandığında 302 yanıtının kendisini alırsınız ve addCookies yeni çerezi sonraki istekler için cookie jar’a koyar.
Cevabı tam olarak döndüğü gibi gönderin. Sitenin backend’i onu çekilen bulmacaya göre kontrol eder; dolayısıyla kırpmak ya da yeniden kurmak onu geçersiz kılar. URLSearchParams gövdeye yüzde kodlaması (percent-encoding) uygular; bu sorun değildir, çünkü sunucu kontrol etmeden önce onu çözer. Ardından hemen gönderin. CapSkip her çözüm için yeni bir challenge anahtarı üretir ve Capy, çektiği bulmacayı bu anahtara bağlar. Dolayısıyla anahtar tek kullanımlıktır ve ömrü kısadır; bir çözüm de yalnızca bir gönderimi karşılar. Bazı sayfalar form gönderimi yerine kendi script’leri üzerinden bir JSON gövdesiyle gönderir. DevTools açıkken formu bir kez elle gönderin ve üç değeri sayfanın koyduğu yere koyun.
4. Adım: bir çözüm başarısız olduğunda yeniden denemeler
Node.js ile kayda değer bir hacimde Capy Puzzle çözdüğünüzde bazı çözümler başarısız olur. Başarısız bir çözüm, mesajı ERROR_CAPTCHA_UNSOLVABLE içeren bir ApiException olarak gelir; SDK’nın yokladığı endpoint olan res.php üzerinden bu tek kod iki farklı durumu kapsar. Bulunamayan bir boşluk ara sıra yaşanır ve bir sonraki deneme farklı bir fotoğraf üzerinde yepyeni bir bulmaca çeker, bu yüzden genellikle başarılı olur. Capy API’sinin reddettiği bir anahtar ise her denemede başarısız olur ve CapSkip’in Monitor sekmesindeki Capy kartında Bad Keys sayacı artar. İlkini yeniden deneyin, ikincisini düzeltin.
import { ApiException } from "capskip";
async function solveCapy(key, url, options = {}, attempts = 3) {
for (let attempt = 1; ; attempt++) {
try {
return await solver.capy(key, url, options);
} catch (err) {
// A missed hole reads as unsolvable, and the next try draws a
// new puzzle. Anything else, such as a wrong API key, is final.
const miss = err instanceof ApiException && err.message.includes("UNSOLVABLE");
if (!miss || attempt === attempts) throw err;
}
}
}ApiException mesajı, CapSkip’ten gelen ham yanıttır; bu yüzden kontrol hata kodunu doğrudan onun içinden okur. Reddedilen bir anahtar da çözülemez olarak görünür, dolayısıyla burada o da yeniden denenir ve her denemede aynı şekilde başarısız olur; onu ele veren de budur. Diğer yol, CapSkip’in ayarlarındaki Capy bölümünde bulunan Retries ayarıdır; 0 ile 3 arasında bir değer alır ve varsayılan olarak 0’dır. Bu durumda CapSkip bulunamayan bir boşluğu kendiliğinden yeniden dener, ama reddedilen bir anahtarı asla yeniden denemez, çünkü aynı şekilde yine reddedilirdi.
capy metodu, istemcinin 120 saniye olan defaultTimeout değeriyle yoklama yapar, çünkü bir Capy çözümü bir tarayıcı oturumu değil, tek bir çekme işlemi ve biraz aritmetiktir. CapSkip de kendi saatini işletir. Capy ayarlarında bir görev, 10 thread’den (Max. Threads) birini en fazla 250 saniye (Wait Timeout) bekleyebilir ve tek bir deneme 60 saniye (Row Timeout) alır. Normal bir çözüm bunların hepsine kat kat sığar. SDK ayrıca bağlantı hatalarına rağmen yoklamayı sürdürür; bu yüzden CapSkip çözümün ortasında durursa çağrı NetworkException ile değil, TimeoutException ile sona erer.
Tam çalışan örnek
İşte tüm akış tek bir dosyada. logIn sayfayı kendi cookie jar’ına çeker, anahtarı ve host’u okur, yeniden denemelerle çözer ve formu çerezleri ve bir Referer ile birlikte gönderir. Yanıtı ve cookie jar’ı döndürür; böylece girişten sonra yaptığınız istekler yeni oturumu taşır.
// npm install capskip cheerio
// login.mjs: run with node login.mjs
import * as cheerio from "cheerio";
import {
CapSkip, ApiException, CapSkipError, TimeoutException, ValidationException,
} from "capskip";
const PAGE_URL = "https://example.com/login";
const solver = new CapSkip({
apiKey: process.env.CAPSKIP_API_KEY ?? "capskip",
host: process.env.CAPSKIP_HOST ?? "127.0.0.1",
port: Number(process.env.CAPSKIP_PORT ?? 8080),
pollingInterval: 0.5,
});
async function solveCapy(key, url, options = {}, attempts = 3) {
for (let attempt = 1; ; attempt++) {
try {
return await solver.capy(key, url, options);
} catch (err) {
// A missed hole reads as unsolvable; the next try draws a new puzzle.
const miss = err instanceof ApiException && err.message.includes("UNSOLVABLE");
if (!miss || attempt === attempts) throw err;
console.log(`attempt ${attempt}: ${err.message}`);
}
}
}
function addCookies(jar, res) {
for (const line of res.headers.getSetCookie()) {
const pair = line.split(";")[0];
const eq = pair.indexOf("=");
if (eq > 0) jar.set(pair.slice(0, eq).trim(), pair.slice(eq + 1).trim());
}
}
async function logIn(pageUrl, username) {
// One jar per run, so runs side by side never share a session.
const jar = new Map();
const page = await fetch(pageUrl);
addCookies(jar, page);
const html = await page.text();
const $ = cheerio.load(html);
const key = html.match(/PUZZLE_[A-Za-z0-9_-]+/)?.[0];
if (!key) throw new Error("No PUZZLE_ key in the HTML; find it in DevTools.");
const apiServer = html.match(/(https:\/\/[^"'\s<>]+?)\/puzzle\/get_js\//)?.[1];
const form = $("form")
.has('script[src*="/puzzle/get_js/"], input[name="capy_captchakey"]').first();
if (!form.length) throw new Error("No form holds the widget; select it by id.");
const result = await solveCapy(key, pageUrl, { apiServer });
// All three together, straight away: the challenge key is single-use.
const body = new URLSearchParams(form.serializeArray().map((f) => [f.name, f.value]));
// Use the page's own field names, password included.
body.set("username", username);
body.set("capy_captchakey", result.captchakey);
body.set("capy_challengekey", result.challengekey);
body.set("capy_answer", result.answer);
const action = new URL(form.attr("action") || page.url, page.url);
const res = await fetch(action, {
method: "POST",
headers: {
cookie: [...jar].map(([k, v]) => `${k}=${v}`).join("; "),
referer: page.url,
},
body,
// A login answers 302 with a new session cookie. Keep the 302, so
// its Set-Cookie lands in the jar instead of being followed away.
redirect: "manual",
});
addCookies(jar, res);
return { res, jar };
}
try {
const { res, jar } = await logIn(PAGE_URL, "YOUR_USERNAME");
// A 302 to the account page means it worked; jar holds that session.
console.log(res.status, res.headers.get("location"), [...jar.keys()]);
} catch (err) {
if (err instanceof ValidationException) console.error(`not sent: ${err.message}`);
else if (err instanceof TimeoutException) console.error("gave up after defaultTimeout");
else if (err instanceof CapSkipError) console.error(`solve failed: ${err.name}: ${err.message}`);
else throw err;
process.exitCode = 1;
}Üç denemenin üçü de başarısız olursa her şeyden önce anahtara bakın, çünkü reddedilen bir anahtar her seferinde aynı şekilde başarısız olur, bir ıska ise neredeyse hiçbir zaman üç kez üst üste yaşanmaz. Anahtar kontrolü hata fırlatıyorsa sayfa widget’ı paketlenmiş bir script’ten oluşturuyordur: Network sekmesini açın, anahtarı ve host’u widget’ın kendi isteğinden kopyalayın. Bu metodun arkasındaki ham endpoint şurada belgelenmiştir: API referansının Capy bölümü.
Çok sayıda giriş işlemini yan yana çalıştırmak
Node’daki her CapSkip metodu bir Promise döndürür ve AsyncCapSkip aynı sınıfın yalnızca başka bir adıdır; bu yüzden çözümleri yan yana çalıştırmak düz JavaScript’tir. İhtiyacınız olan şey bir üst sınırdır. CapSkip varsayılan olarak aynı anda 10 Capy çözümü çalıştırır ve geri kalanını boş bir thread için bekletir; dolayısıyla aynı anda on çözümü işlemde tutan küçük bir havuz ona tam uyar. Bunu tam örneğin sonundaki try bloğunun yerine koyun:
// At most `limit` calls in flight; a failure becomes that item's Error.
async function mapLimited(items, limit, fn) {
const results = new Array(items.length);
let next = 0;
async function worker() {
while (next < items.length) {
const i = next++;
results[i] = await fn(items[i]).catch((err) => err);
}
}
await Promise.all(Array.from({ length: Math.min(limit, items.length) }, worker));
return results;
}
const users = ["YOUR_USERNAME_1", "YOUR_USERNAME_2", "YOUR_USERNAME_3"];
const results = await mapLimited(users, 10, (user) => logIn(PAGE_URL, user));
for (const r of results) console.log(r instanceof Error ? r.message : r.res.status);logIn her çağrıda kendi cookie jar’ını oluşturur; onu paralel çalışmada güvenli kılan da budur. On çalıştırmanın paylaştığı tek bir cookie jar, onların oturumlarını ve CSRF token’larını birbirine karıştırırdı. Ayrıca her çözümü kendi gönderimiyle eşli tutar. Önce yüz bulmacayı çözüp sonra göndermek, son çözümler biterken ilk challenge anahtarlarının eskimesine yol açar. Hacim arttığında proxy de ekleyin. Her çözüm Capy API’sinden yeni bir bulmaca çeker ve tek bir adresten gelen sürekli bir bulmaca akışı, hız sınırlamanın yakalamak için var olduğu kalıbın ta kendisidir. CapSkip’in Capy bölümünde bir proxy havuzu yapılandırın ya da her çağrıda bir proxy nesnesi verin; proxy yalnızca bulmacanın çekilmesini etkiler, bu da bir Capy çözümünün yaptığı tek istektir.
Çözücüyü başka bir makinede çalıştırmak
Betik ve CapSkip aynı Windows bilgisayarı paylaştığı sürece 127.0.0.1 doğru adrestir. Node kodu bir VPS’e, bir konteynere, bir CI runner’a ya da serverless bir fonksiyona taşındığında loopback yanlış makineyi gösterir ve ilk çözüm ECONNREFUSED içeren bir NetworkException fırlatır. CapSkip’i Server moduna alın; o zaman ağ adresinizi veya genel IP’nizi dinler, böylece bunların hepsi onu aynı API üzerinden çağırabilir. Rota internetten geçiyorsa statik bir genel IP kullanın ve API anahtarı doğrulamasını açın. CapSkip, Server modu başladığında portunu her adrese açar; portu yalnızca beklediğiniz makinelere açık tutmak için diğerlerine yönelik bir Windows Firewall engelleme kuralı ekleyin. Çözücü hâlâ sizin kendi Windows makinenizdir ve çözüm başına ücretlendirme hâlâ yoktur.
İstemci ortam değişkenlerini kendiliğinden okumaz. Tam örnekte olduğu gibi CAPSKIP_HOST, CAPSKIP_PORT ve CAPSKIP_API_KEY değerlerini kodunuzda okuyup constructor’a verin; böylece aynı betik hem masanızda hem de bir sunucuda çalışır.
Sık görülen hatalar ve anlamları
| Gördüğünüz | Neden | Düzeltme |
|---|---|---|
| solver.capy() üç değerin hepsini döndürdüğü hâlde site oturumun süresinin dolduğunu söylüyor | Gönderim, sayfanın ayarladığı çerezler olmadan yapıldı; bu yüzden CSRF alanı artık hiçbir oturumla eşleşmiyor | Sayfa çekiminden gelen çerezleri taşıyın, her çalıştırma için ayrı bir cookie jar kullanın |
| Site girişi kabul ettiği hâlde gönderim, 200 durum koduyla giriş sayfasını döndürüyor | Giriş isteği yeni bir oturum çereziyle 302 yanıtı verdi ve fetch yönlendirmeyi bu çerez olmadan izledi | redirect değerini manual yaparak gönderin ve 302 yanıtının Set-Cookie satırlarını cookie jar’a ekleyin |
| Doğru çerez ve üç değerin hepsi olduğu hâlde gönderimde 403 | fetch ne Referer ne de Origin gönderdi ve site bunları kontrol ediyor | Sayfa URL’sini Referer başlığı olarak gönderin |
| Site cevabın kendisini reddediyor | Cevap değiştirildi ya da değerlerden yalnızca biri veya ikisi forma ulaştı | result.answer değerini diğer iki değerle birlikte, birebir ve tek istekte gönderin |
| Bir kez çalışan gönderim ikinci seferde başarısız oluyor | Challenge anahtarı tek kullanımlıktır ve ömrü kısadır | Her gönderim için yeniden çözün ve hemen gönderin |
| Tek bir anahtar için her denemede bir ApiException | Capy API’si anahtarı reddetti ya da api_server yanlış host’u gösteriyor | Anahtarı ön eki dahil yeniden kopyalayın ve script etiketinin host’unu kontrol edin |
| Ara sıra gelen, ERROR_CAPTCHA_UNSOLVABLE içeren bir ApiException | CapSkip o bulmacadaki boşluğu bulamadı | Yeniden deneyin; bir sonraki deneme farklı bir bulmaca çeker |
| Daha hiçbir şey gönderilmeden ValidationException | Boş bir anahtar veya URL, metodun kabul etmediği bir seçenek (örneğin çağrı başına verilen bir pollingInterval), version olarak avatar ya da CapSkip’in kabul etmediği bir proxy türü | Anahtarın bulunduğunu kontrol edin ve mesajda adı geçen seçeneği düzeltin ya da çıkarın |
| İlk çağrıda ERROR_KEY_DOES_NOT_EXIST veya ERROR_WRONG_USER_KEY içeren bir ApiException | CapSkip’te API anahtarı doğrulaması açık ve betik varsayılan anahtarı gönderdi ya da hiç anahtar göndermedi | CAPSKIP_API_KEY değerini CapSkip’te yapılandırılmış bir anahtara ayarlayın |
| Her çağrı yaklaşık dört saniye sürüyor | Yoklamalar arasındaki aralık, varsayılan 5 saniyelik üst sınıra doğru ikiye katlanmaya devam ediyor, bu yüzden iki saniyede hazır olan bir cevap 3.75 saniyedeki yoklamayı bekliyor | Constructor’da pollingInterval: 0.5 ayarlayın |
| Yoğun paralel yük altında TimeoutException | Aynı anda işlemde olan giriş sayısı, 10 thread’in 120 saniye içinde bitirebileceğinden fazla ya da CapSkip çözümün ortasında durdu | Havuzu Max. Threads değeriyle sınırlayın ya da o çağrı için daha uzun bir timeout verin |
| İlk çağrıda, mesajında (host bir ad olduğunda ise err.cause.code içinde) ECONNREFUSED veya ETIMEDOUT bulunan bir NetworkException | CapSkip çalışmıyor, host veya port yanlış ya da bir güvenlik duvarı bağlantıyı düşürüyor | CapSkip’i başlatın, ardından Local modunda mı yoksa Server modunda mı olması gerektiğini kontrol edin |
FAQ
capskip paketi burada TypeScript ile çalışır mı?
Evet, kendi tür tanımlarıyla birlikte gelir. Capy için iki ayrıntı önemlidir. Sonuç türü captchakey, challengekey ve answer alanlarını isteğe bağlı olarak işaretler, çünkü diğer metotlar bunları ayarlamaz. Bu yüzden strict mod, onları body.set’e vermeden önce bir kontrol ya da bir non-null assertion ister. Ayrıca seçenekler türü her anahtarı kabul eder; dolayısıyla çağrı başına verilen bir pollingInterval gibi yanlış yazılmış ya da yanlış yere konmuş bir seçenek sorunsuz derlenir ve çalışma zamanında ValidationException ile başarısız olur.
node user agent’ı cevabın reddedilmesine yol açar mı?
Capy tarafında hayır. Capy cevabı bir tarayıcıya bağlı değildir, CapSkip onun için bir user agent döndürmez ve geçirebileceğiniz isteğe bağlı user agent da yalnızca bulmacayı çeken isteği değiştirir. Yine de sitenin kendisi, kendine ait nedenlerle, user agent’ı node olan bir isteği geri çevirebilir. Böyle olursa hem sayfa çekimine hem de gönderime bir tarayıcı user-agent başlığı ekleyin.
Bunun Python sürümünden farkı nedir?
Çağrı, bekletme ve kurallar aynıdır. Python’da requests.Session çerezleri sizin yerinize saklar, Node’da ise onları kendiniz taşırsınız; sonuç da orada bir dict, burada bir nesnedir. Python tarafı şurada ele alınıyor: Python ile Capy Puzzle çözme rehberi.
Barındırılan bir platformdaki Node betiği çözücüye erişebilir mi?
Evet. Bağlantı ayarlarından CapSkip’i Server moduna alın; böylece loopback yerine bir ağ adresini dinler. O adresi betiğinizde CAPSKIP_HOST değişkeninden okuyun ve constructor’a verin. Bir VPS, bir konteyner sunucusu, bir CI runner ve serverless bir fonksiyon; hepsi aynı HTTP API üzerinden bağlanır. Rota internetten geçiyorsa statik bir genel IP kullanın ve porta ulaşmaması gereken adresler için bir Windows Firewall engelleme kuralı ekleyin. Çözücü sizin sahip olduğunuz donanımda kalır, dolayısıyla çözümlerin nasıl sayıldığı konusunda hiçbir şey değişmez.
Kısa özet
Node.js ile Capy Puzzle çözmek için sayfayı bir cookie jar’a çekin, PUZZLE_ anahtarını tek bir regex ile çıkarın ve varsayılan olmayabileceği için widget script’inin host’unu not edin. solver.capy() metodunu, pollingInterval: 0.5 ile oluşturulmuş bir istemciden anahtar ve gerçek sayfa URL’siyle çağırın ve iki saniye kadar sürmesine izin verin. captchakey, challengekey ve answer değerlerini üç capy_ alanında birebir, birlikte ve hemen, sayfanın çerezleriyle ve Referer olarak sayfanın URL’siyle gönderin; bir 302 yanıtının geri verdiği çerezi de saklayın. Ara sıra yaşanan ıskalarda yeniden deneyin, aynı anda işlemde olan giriş sayısını Max. Threads değerinin üzerine çıkarmayın ve betik çözücünün makinesinden ayrıldığında Server moduna geçin.
- Bu türün nasıl çalıştığı ve çözücünün neleri kapsadığı: Capy Puzzle çözücü sayfası.
- Node.js paketinin desteklediği tüm CAPTCHA türleri: Node.js CAPTCHA çözücü sayfası.
O yeniden denemeyle ilgili son bir nokta. Her deneme farklı bir bulmaca çektiği için bir ıskanın doğru çaresi yeniden denemektir ve kendi makinenizde bir yerel captcha çözücü çalıştırdığınızda ikinci bir deneme, faturalanan yeni bir çözüme değil, yalnızca bir iki saniyeye mal olur.
