Solving captcha yang cepat: cara memangkas latensi di pipeline Anda
Solver captcha yang cepat adalah yang bisa Anda panggil di waktu yang tepat, secara paralel, tanpa membuang request. Panggilan solve Scarnox kembali saat token siap, jadi durasinya bergantung pada jenis captcha, situs target, dan beban saat itu. Panduan ini tidak menjanjikan waktu tetap. Panduan ini menunjukkan hal-hal yang bisa Anda kendalikan di kode sendiri, cara mengukurnya, dan cara menjalankan banyak solve sekaligus, agar waktu yang Anda habiskan digunakan dengan baik.
Apa yang menentukan waktu solve
Ada tiga hal yang penting, dan hanya satu di antaranya ada di tangan Anda:
- Captcha itu sendiri. Beberapa jenis tantangan memang lebih lama. Itu adalah sifat captcha situs tersebut, bukan kode Anda.
- Beban di solver. Periode yang sibuk bisa membuat satu panggilan lebih lambat. Logika retry seharusnya menanganinya, bukan membatalkan panggilan terlalu cepat.
- Pipeline Anda sendiri. Solve terlalu dini, memproses setiap request secara berurutan, dan menunggu pekerjaan yang tidak terkait semuanya menambah waktu yang bisa Anda hilangkan.
Fokuskan usaha Anda pada poin ketiga. Itulah bagian yang bisa Anda ukur dan ubah.
Ukur sebelum mengoptimasi
Bungkus panggilan dengan timer dan catat hasilnya. Anda ingin tahu waktu solve dan waktu yang dihabiskan kode Anda di sekitarnya:
import time
import requests
API_KEY = "scarnox_YOURAPIKEY"
URL = "https://api.scarnox.com/api/tasks/create"
def timed_solve(sitekey: str, page_url: str) -> dict:
started = time.perf_counter()
r = requests.post(
URL,
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"captcha_type": "PopularCaptchaTaskProxyless",
"site_key": sitekey,
"site_url": page_url,
},
timeout=185,
)
elapsed = time.perf_counter() - started
data = r.json()
if data.get("errorId") != 0:
return {"ok": False, "error": data.get("errorCode"), "seconds": elapsed}
return {"ok": True, "token": data["solution"]["token"], "seconds": elapsed}
result = timed_solve("10000000-ffff-ffff-ffff-000000000001", "https://example.com/signup")
print(result["ok"], round(result["seconds"], 2), "s")
Jalankan ini terhadap halaman yang Anda pedulikan, pada waktu Anda menjalankan job. Simpan angkanya. Angka itu memberi tahu Anda apakah sebuah perubahan benar-benar membantu.
Jalankan solve secara paralel
Setiap solve bersifat independen. Jika Anda punya sepuluh sitekey untuk ditangani, menunggu satu per satu membuang waktu yang bisa Anda pakai untuk yang lain. Thread pool sudah cukup untuk sebagian besar script karena setiap solve adalah satu request HTTP yang sebagian besar waktunya dihabiskan untuk menunggu:
from concurrent.futures import ThreadPoolExecutor
jobs = [
("10000000-ffff-ffff-ffff-000000000001", "https://example.com/signup"),
("10000000-ffff-ffff-ffff-000000000001", "https://example.com/register"),
("10000000-ffff-ffff-ffff-000000000001", "https://example.com/contact"),
]
def run(job):
sitekey, page_url = job
return timed_solve(sitekey, page_url)
# Mulai kecil. Naikkan jumlah worker hanya selama error tetap rendah.
with ThreadPoolExecutor(max_workers=5) as pool:
results = list(pool.map(run, jobs))
for r in results:
status = "ok" if r["ok"] else r["error"]
print(f"{r['seconds']:.2f} s {status}")
Jika Anda melihat error yang tampak seperti masalah rate limit atau kapasitas saat jumlah worker dinaikkan, turunkan lagi. Paralelisme hanya membantu jika server bisa mengimbanginya.
Jangan solve terlalu dini
Kode tercepat adalah kode yang tidak menunggu token yang belum akan dipakai. Meminta token jauh-jauh hari lalu menyimpannya adalah kesalahan yang paling umum. Token kedaluwarsa sekitar dua menit setelah diterbitkan, jadi token yang disimpan sering kali sudah basi saat Anda membutuhkannya. Lakukan solve saat form hampir dikirim. Alasan detailnya ada di captcha token kedaluwarsa: penyebab dan solusinya.
Jaga bagian lain dari jalur tetap pendek
- Gunakan satu sesi HTTP per situs agar Anda tidak menyambung ulang untuk setiap request.
- Jangan menjalankan parsing yang lambat atau pekerjaan database di antara solve dan pengiriman.
- Gunakan timeout yang wajar untuk request Anda sendiri. Panggilan solve memakai sekitar 185 detik karena ia memblokir sampai token siap. Panggilan Anda yang lain seharusnya jauh lebih singkat.
- Kirim proxy hanya saat task membutuhkannya. Tipe task proxy menerima field
proxydengan formathttp://user:pass@host:port, tetapi menambahkan proxy bukanlah cara untuk mempercepat.
Gunakan ulang apa yang tidak kedaluwarsa
Sebagian pekerjaan bisa dibagi dengan aman di antara solve. Jauhkan hal-hal ini dari jalur utama:
- Sitekey. Baca sitekey sekali per template halaman dan simpan. Sitekey tidak kedaluwarsa seperti token. Baca ulang hanya saat form mulai gagal.
- Koneksi HTTP. Sesi dengan keep-alive menghindari handshake TLS baru di setiap panggilan. Buat satu sesi per thread atau per worker, bukan satu per request.
- Konfigurasi yang sudah diparsing. Muat daftar target, daftar proxy, dan pengaturan Anda sekali saat start-up, alih-alih membaca file di dalam fungsi solve.
Perubahan ini murah dan menghilangkan overhead yang muncul di setiap panggilan.
Ukur ekor distribusinya, bukan rata-ratanya
Rata-rata waktu solve menyembunyikan panggilan lambat yang menahan sebuah batch. Catat waktu setiap solve, lalu lihat median dan persentil ke-95. Pipeline yang selesai dalam waktu job paling lambatnya dibatasi oleh ekor distribusinya, jadi perubahan kecil pada cara Anda me-retry panggilan yang lambat bisa lebih berpengaruh dibanding perubahan apa pun pada median:
import statistics
def summarise(seconds: list[float]) -> str:
ordered = sorted(seconds)
p95 = ordered[int(0.95 * (len(ordered) - 1))]
return f"median {statistics.median(ordered):.2f} s, p95 {p95:.2f} s, n={len(ordered)}"
print(summarise([r["seconds"] for r in results]))
Bandingkan ringkasannya sebelum dan sesudah setiap perubahan. Jika p95 hampir tidak bergerak, berarti waktunya dihabiskan di bagian lain dari kode Anda.
Periksa hasilnya, bukan hanya kecepatannya
Kegagalan yang cepat tetaplah kegagalan. Hitung solve yang mengembalikan error, dan anggap kenaikan tingkat error sebagai sinyal untuk memperlambat. Solve yang gagal tidak dikenai biaya, tetapi waktu yang dihabiskan untuknya tetap waktu yang hilang dari pipeline Anda. Pola retry lengkapnya ada di penanganan error solver captcha.