Cara Memecahkan CAPTCHA di Node-RED dengan Function Node

node-red captcha - How to Solve CAPTCHAs in Node-RED With a Function Node

Langkah captcha di Node-RED adalah dua node jika Anda lewat API mentah, atau satu function node jika Anda lebih suka menulis lima baris JavaScript. Keduanya memanggil solver yang berjalan di hardware Anda sendiri, jadi tidak ada yang menghitung biaya per pemecahan. Bagian yang membuat orang tersandung bukan pemecahannya. Masalahnya, function node tidak bisa melakukan require pada paket npm sampai Anda mengaktifkannya di settings.js, dan Node-RED sangat sering berjalan di Raspberry Pi sementara solver-nya tidak.

Apa yang Anda butuhkan

  • Node-RED 3 atau yang lebih baru, berjalan di mana pun Anda suka.
  • CapSkip yang berjalan dan mendengarkan. Mode Local ketika Node-RED ada di mesin Windows yang sama, Mode Server ketika tidak. Keduanya dijelaskan di pengaturan koneksi.
  • URL halaman formulir yang terproteksi, beserta sitekey-nya.
  • Akses editor ke settings.js jika Anda ingin jalur SDK alih-alih jalur API mentah.

Tidak ada satu pun di sini yang butuh browser. Node-RED tidak mengendalikan Chrome, melainkan melakukan panggilan HTTP, jadi flow-nya membaca sitekey dari HTML halaman dan mengirim token kembali sebagai field formulir biasa.

Dua cara memanggil solver dari sebuah flow

Pilih satu sebelum Anda mulai merangkai, karena keduanya menghasilkan flow yang sangat berbeda.

Jalur manaApa yang harus Anda siapkanKapan ini pilihan yang tepat
Node http request langsung ke API mentahSatu node pengirim, satu delay, satu node polling, dan satu switch untuk mengulangAnda tidak bisa mengedit settings.js, atau Anda ingin flow-nya mudah dibaca di canvas
SDK Node di dalam function nodeSatu baris di settings.js dan satu modul di tab SetupAnda ingin polling, backoff, dan timeout ditangani untuk Anda

Jalur kedua lebih pendek karena alasan yang layak diketahui. API mentah menyuruh Anda menunggu lima belas detik lalu polling setiap lima detik, dan flow yang dirakit tangan mengikutinya secara harfiah. SDK justru mulai polling pada 250ms lalu melambat sampai batas atas, jadi biasanya token kembali jauh lebih cepat daripada yang bisa dicapai node delay.

Jalur satu: node http request dan API mentah

API-nya kompatibel dengan 2captcha, yang berarti ada dua endpoint. Anda mengirim ke in.php dan mendapat id kembali, lalu Anda polling res.php dengan id itu sampai jawabannya tidak lagi berstatus belum siap. Empat node, dirangkai dalam satu loop.

Node di dalam flowPengaturan
Node http request yang mengirimPOST ke http://127.0.0.1:8080/in.php, Return disetel ke objek JSON yang sudah di-parse
Function node yang menyimpan id-nyaSimpan msg.payload.request sebagai msg.captchaId
Node delayDelay tetap, 15 detik untuk reCAPTCHA v2
Node http request yang melakukan pollingGET ke http://127.0.0.1:8080/res.php, Return disetel ke objek JSON yang sudah di-parse
Node switchKembali ke node delay selama balasannya masih CAPCHA_NOT_READY

Node pengirim mengambil body-nya dari msg.payload, jadi bangun itu di function node sebelumnya. Menyetel json ke 1 adalah yang membuat balasannya berupa JSON, bukan teks lama yang dipisahkan pipa, sehingga Anda tidak perlu memecah string.

// Feed this into the submit node. No npm module needed.
msg.url = "http://127.0.0.1:8080/in.php";
msg.method = "POST";
msg.payload = {
    key: env.get("CAPSKIP_KEY") || "capskip",
    method: "userrecaptcha",
    googlekey: "YOUR_SITEKEY",
    pageurl: "https://example.com/page-with-recaptcha",
    json: 1
};
return msg;

Node polling butuh id itu kembali di query string. Bangun URL-nya di function node agar node http request tidak perlu melakukan templating apa pun.

// After the delay. Loop back here until the answer arrives.
const key = env.get("CAPSKIP_KEY") || "capskip";
msg.url = "http://127.0.0.1:8080/res.php?key=" + key +
          "&action=get&id=" + msg.captchaId + "&json=1";
msg.method = "GET";
return msg;

Dua hal tentang balasannya. Status 0 dengan request berisi CAPCHA_NOT_READY bukan error, itu berarti jawabannya masih diproses, dan itulah cabang yang dikirim node switch Anda kembali ke delay. Status 1 berarti msg.payload.request berisi token. Batasi loop-nya pada jumlah putaran yang masuk akal agar tantangan yang memang tidak terpecahkan tidak berputar selamanya. Status polling dibahas lebih dalam di panduan balasan CAPCHA_NOT_READY, dan setiap parameter tercantum di dokumentasi API CapSkip.

Jalur dua: SDK di dalam function node

Function node berjalan di sandbox yang secara default tidak punya akses ke paket npm. Ada dua pengaturan yang mengendalikannya, dan keduanya berperilaku berbeda.

Yang lebih lama adalah functionGlobalContext, di mana Anda melakukan require modul di settings.js dan membacanya kembali dengan panggilan global.get di dalam node. Ini bekerja, tetapi semua function node di instance itu melihatnya, dan menambah modul berarti me-restart Node-RED.

Yang lebih baik adalah functionExternalModules. Setel ke true di settings.js dan function node akan mendapat tab Setup tempat Anda menyebutkan nama modul dan variabel tempat modul itu muncul. Node-RED memasangnya ke direktori user Anda saat deploy, dan hanya node itu yang melihatnya.

// settings.js, in your Node-RED user directory.
module.exports = {
    // Lets a function node declare its own npm modules
    // on the Setup tab, installed on deploy.
    functionExternalModules: true,

    // The older, instance-wide alternative.
    // functionGlobalContext: { capskip: require("capskip") },
}

Restart Node-RED, buka function node, masuk ke tab Setup, lalu tambahkan modul capskip dengan nama variabel capskip. Deploy sekali dan modulnya terpasang. Setelah itu body node bisa langsung memakainya.

Langkah 1: pecahkan di dalam function node

Pemecahan adalah panggilan jaringan yang memakan waktu beberapa detik, jadi node-nya harus selesai secara asinkron. Artinya, jangan mengembalikan pesan secara biasa. Aturan Node-RED di sini spesifik: kerjakan di dalam blok async, dorong pesannya keluar dengan panggilan node.send, dan kembalikan null dari body node agar tidak ada yang terkirim dua kali.

// npm install capskip - or add it on the Setup tab
const solver = new capskip.CapSkip({
    host: "127.0.0.1",
    port: 8080,
    apiKey: env.get("CAPSKIP_KEY") || "capskip"
});

(async () => {
    try {
        const result = await solver.recaptcha(msg.sitekey, msg.pageUrl);
        msg.token = result.code;    // inject this into the form
        node.send(msg);
    } catch (err) {
        node.error(err, msg);       // routes to a catch node
    }
    node.done();
})();

return null;

Mengoper msg sebagai argumen kedua ke node.error adalah yang memungkinkan catch node menangkap kegagalannya. Tanpa itu, error-nya mendarat di sidebar debug dan flow-nya berhenti begitu saja, dan itulah alasan paling umum sebuah cabang captcha di Node-RED terlihat seolah tidak melakukan apa pun.

Satu metode mencakup reCAPTCHA v2, Invisible, Enterprise, dan v3. Varian-varian itu adalah opsi, bukan panggilan terpisah, jadi widget invisible adalah baris yang sama dengan objek opsi berisi invisible bernilai 1, dan v3 adalah version bernilai v3 ditambah satu action. Turnstile dan GeeTest punya metodenya sendiri dengan bentuk yang sama, dan semuanya tercantum di halaman SDK pemecahan CAPTCHA.

Langkah 2: seluruh flow dalam satu node

Ambil halamannya, tarik sitekey dari HTML, pecahkan, lalu kirim token kembali bersama sisa formulirnya. Ini versi yang bisa Anda tempel jika ingin flow-nya terdiri dari satu inject node, function node ini, dan satu debug node.

// Module on the Setup tab: capskip. fetch is built in
// from Node 18, which Node-RED 3 and 4 both require.
const PAGE = "https://example.com/page-with-recaptcha";
const solver = new capskip.CapSkip({ host: "127.0.0.1", port: 8080 });

(async () => {
    try {
        const html = await (await fetch(PAGE)).text();
        const found = html.match(/data-sitekey=["']([^"']+)/);
        if (!found) { throw new Error("No data-sitekey on the page."); }

        // Solve, then submit straight away. Tokens go stale.
        const result = await solver.recaptcha(found[1], PAGE);
        const reply = await fetch(PAGE, {
            method: "POST",
            body: new URLSearchParams({
                "g-recaptcha-response": result.code
            })
        });

        msg.payload = { status: reply.status, token: result.code };
        node.send(msg);
    } catch (err) {
        node.error(err, msg);
    }
    node.done();
})();

return null;

Pecahkan pada langkah tepat sebelum submit, jangan pernah di cabang lebih awal yang lalu menunggu hal lain. Token reCAPTCHA berlaku sekitar dua menit dan hanya diterima satu kali, jadi flow yang memecahkan, lalu berhenti di node delay, lalu mengirim akan mendapat penolakan yang sama sekali tidak terlihat seperti masalah solver. Mode kegagalan itu layak dibaca lebih lanjut di panduan kedaluwarsa token reCAPTCHA.

Menjalankan Node-RED dan solver di mesin berbeda

Hal ini lebih berpengaruh di Node-RED daripada di kebanyakan tool, karena sebagian besar instalasi berjalan di Raspberry Pi, NAS, atau mesin Linux kecil, sementara CapSkip adalah aplikasi Windows. Jika itu menggambarkan setup Anda, 127.0.0.1 adalah si Pi, solver tidak ada di sana, dan panggilannya gagal dengan connection refused sebelum sempat mencapai API.

Mode Server adalah jawabannya dan itu perubahan pengaturan, bukan produk yang berbeda. Mode Local mengikat ke 127.0.0.1 dan hanya melayani perangkat itu. Mode Server mengikat ke IP jaringan atau IP publik Anda, jadi flow di Pi, di host container, atau di instance Node-RED terkelola bisa memanggil mesin Windows lewat API yang sama. IP publik statis menjaga alamat itu tetap stabil. Keduanya tetap hardware Anda sendiri dan tetap tanpa meter, jadi flow yang sibuk tidak lebih mahal daripada yang santai.

// Same call, same SDK. Only the host moves.
const solver = new capskip.CapSkip({
    host: "10.0.0.12",
    port: 8080,
    apiKey: env.get("CAPSKIP_KEY")
});

Nyalakan validasi key begitu solver mendengarkan di alamat jaringan, dan beri setiap instance Node-RED key-nya sendiri agar satu key bisa dicabut tanpa mengusik yang lain. Simpan key-nya di variabel environment, bukan di body node: file flows berupa JSON di disk dan sering berakhir di repositori git. Kedua mode dibahas langkah demi langkah di panduan penyiapan CapSkip.

Kesalahan umum dan artinya

Apa yang Anda lihatPenyebabPerbaiki
capskip is not definedModulnya tidak pernah dideklarasikan di tab SetupSetel functionExternalModules ke true, lalu tambahkan modulnya dan deploy
Function node tidak mengeluarkan apa punPesannya dikembalikan, bukan dikirim dari blok asyncPanggil node.send dan kembalikan null dari body node
Flow berhenti tanpa error yang terlihatnode.error dipanggil tanpa argumen pesanOper msg sebagai argumen kedua dan pasang catch node
connect ECONNREFUSED 127.0.0.1:8080Node-RED tidak berada di mesin yang menjalankan solverAlihkan solver ke Mode Server dan setel host ke alamatnya
Loop polling tidak pernah berhentiNode switch tidak punya batas percobaanHitung putarannya di variabel context dan berhenti setelah mencapai batas
Formulir menolak token yang tampak baik-baik sajaPemecahannya dilakukan beberapa node sebelumnyaPecahkan tepat sebelum submit, bukan di cabang sebelumnya
ERROR_GOOGLEKEYSitekey-nya tidak cocok dengan URL halaman tersebutBaca ulang data-sitekey dari halaman tujuan pengiriman Anda

FAQ

Apakah saya butuh SDK, atau cukup dengan node http request?

Keduanya bekerja. Jalur http request tidak butuh akses ke settings.js dan membuat setiap langkah tetap terlihat di canvas, yang disukai sebagian tim untuk keperluan audit. Jalur SDK menangani polling, backoff, dan timeout untuk Anda, dan biasanya mengembalikan token lebih cepat karena mulai memeriksa setelah seperempat detik, bukan setelah lima belas detik.

Bisakah instance Node-RED terkelola menjangkau solver di meja saya?

Hanya dalam Mode Server. Instance terkelola berjalan di infrastruktur milik orang lain, jadi 127.0.0.1 di sana adalah container mereka, bukan mesin Anda. Ikat solver ke alamat yang bisa dijangkau, taruh di balik aturan firewall yang hanya mengizinkan alamat keluar milik platform tersebut, lalu nyalakan validasi key. Halaman pengaturan koneksi membahas seluruh penyiapannya.

Bagaimana cara mencegah satu flow membanjiri solver?

Pasang node delay dalam mode rate limit sebelum node pemecahan. Node itu mengantrekan pesan dan melepaskannya pada laju tetap, dan itulah throttle yang Anda butuhkan ketika tiga jadwal mengarah ke mesin yang sama. Memecahkan dalam loop tanpa batas adalah cara paling umum sebuah batch berubah jadi tumpukan timeout.

Apakah ini sama dengan melakukannya di n8n?

Sisi solver-nya identik, sisi flow-nya tidak. n8n menjalankan Code node-nya di sandbox terkunci tanpa instalasi npm, jadi di sana pilihannya node HTTP atau tidak sama sekali. Node-RED dengan senang hati memasang paket untuk satu function node, dan itulah sebabnya jalur SDK ada di sini. Versi n8n-nya ditulis di panduan workflow CAPTCHA n8n.

Versi singkatnya

Nyalakan functionExternalModules, tambahkan capskip di tab Setup, dan kerjakan pemecahannya di blok async yang diakhiri panggilan node.send lalu mengembalikan null. Pasang catch node dan oper pesannya ke node.error agar kegagalan terlihat. Jika Node-RED tinggal di Pi sementara solver tinggal di Windows, itu berarti Mode Server dan satu string host yang diubah. Sisa permukaan Node.js-nya ada di halaman pemecah CAPTCHA Node.js, dan opsi reCAPTCHA-nya ada di halaman pemecah reCAPTCHA v2.

Satu hal terakhir yang layak diketahui sebelum Anda menyetel flow itu pada jadwal lima menitan. CapSkip adalah pemecah captcha lokal yang berjalan di hardware yang sudah Anda miliki, jadi flow yang berjalan setiap lima menit selamanya biayanya sama persis dengan yang Anda picu manual.