Scarnox · Blog

การแก้ captcha ให้เร็วขึ้น: วิธีลด latency ใน pipeline ของคุณ

captcha solver ที่เร็วคือตัวที่คุณเรียกได้ในจังหวะที่ถูกต้อง พร้อมกันหลายงาน โดยไม่เสียคำขอ การเรียก solve ของ Scarnox จะส่งกลับเมื่อ token พร้อม ดังนั้นระยะเวลาขึ้นอยู่กับประเภทของ captcha เว็บเป้าหมาย และโหลดในขณะนั้น คู่มือนี้ไม่สัญญาเวลาที่แน่นอน แต่แสดงสิ่งที่คุณควบคุมได้ในโค้ดของตัวเอง วิธีวัดผล และวิธีรันการแก้จำนวนมากพร้อมกัน เพื่อให้เวลาที่คุณใช้ถูกใช้อย่างคุ้มค่า

อะไรกำหนดเวลาการแก้

มีสามสิ่งที่สำคัญ และมีเพียงสิ่งเดียวที่อยู่ในมือคุณ

ให้ความพยายามของคุณอยู่ที่ข้อที่สาม เพราะเป็นส่วนที่คุณวัดและเปลี่ยนแปลงได้

วัดก่อนจะปรับแต่ง

ห่อการเรียกด้วยตัวจับเวลาและบันทึกผล คุณต้องการรู้ทั้งเวลาการแก้และเวลาที่โค้ดของคุณใช้รอบ ๆ มัน

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")

รันสิ่งนี้กับหน้าที่คุณสนใจ ในเวลาที่คุณรันงานของคุณ เก็บตัวเลขไว้ ตัวเลขเหล่านั้นบอกคุณว่าการเปลี่ยนแปลงช่วยได้จริงหรือไม่

รันการแก้พร้อมกัน

การแก้แต่ละครั้งเป็นอิสระต่อกัน หากคุณมี sitekey สิบตัวที่ต้องจัดการ การรอทีละตัวเสียเวลาที่คุณอาจใช้กับตัวอื่นได้ thread pool เพียงพอสำหรับสคริปต์ส่วนใหญ่ เพราะการแก้แต่ละครั้งคือ HTTP หนึ่งคำขอที่ใช้เวลาส่วนใหญ่ไปกับการรอ

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)

# เริ่มจากจำนวนน้อย เพิ่มจำนวน worker เฉพาะเมื่อ error ยังต่ำอยู่
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}")

หากคุณเห็น error ที่ดูเหมือนปัญหาการจำกัดอัตราหรือความจุเมื่อเพิ่มจำนวน worker ให้ลดลง การทำงานพร้อมกันจะช่วยก็ต่อเมื่อเซิร์ฟเวอร์ตามทันเท่านั้น

อย่าแก้ล่วงหน้า

โค้ดที่เร็วที่สุดคือโค้ดที่ไม่รอ token ที่ยังไม่ได้ใช้ การขอ token ล่วงหน้าแล้วเก็บไว้เป็นความผิดพลาดที่พบบ่อยที่สุด token หมดอายุประมาณสองนาทีหลังออกให้ ดังนั้น token ที่เก็บไว้มักเก่าเกินไปเมื่อคุณต้องการใช้ แก้เมื่อฟอร์มกำลังจะถูกโพสต์ รายละเอียดการให้เหตุผลอยู่ในcaptcha token หมดอายุ: สาเหตุและวิธีแก้

เก็บเส้นทางที่เหลือให้สั้น

ใช้ซ้ำสิ่งที่ไม่หมดอายุ

งานบางอย่างสามารถแชร์ข้ามการแก้ได้อย่างปลอดภัย เก็บสิ่งเหล่านี้ให้พ้นจากเส้นทางที่ร้อนแรง

การเปลี่ยนแปลงเหล่านี้มีค่าใช้จ่ายน้อยและขจัดภาระที่ปรากฏในทุกการเรียก

วัดส่วนหาง ไม่ใช่ค่าเฉลี่ย

เวลาการแก้เฉลี่ยซ่อนการเรียกที่ช้าซึ่งทำให้ชุดงานค้าง บันทึกเวลาแก้แต่ละครั้ง แล้วดูค่ามัธยฐานและเปอร์เซ็นไทล์ที่ 95 ไปป์ไลน์ที่เสร็จภายในเวลาของงานที่ช้าที่สุดถูกจำกัดด้วยส่วนหาง การปรับวิธีลองใหม่การเรียกที่ช้าเพียงเล็กน้อยจึงอาจสำคัญกว่าการเปลี่ยนค่ามัธยฐาน

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]))

เปรียบเทียบสรุปก่อนและหลังการเปลี่ยนแปลงทุกครั้ง หาก p95 แทบไม่ขยับ แสดงว่าเวลาถูกใช้ไปที่อื่นในโค้ดของคุณ

ตรวจผลลัพธ์ ไม่ใช่แค่ความเร็ว

ความล้มเหลวที่เร็วยังคงเป็นความล้มเหลว นับการแก้ที่ส่ง error และถือว่าอัตรา error ที่เพิ่มขึ้นเป็นสัญญาณให้ชะลอลง การแก้ที่ล้มเหลวไม่ถูกเรียกเก็บเงิน แต่เวลาที่ใช้ไปกับมันก็ยังเป็นเวลาที่ไปป์ไลน์เสียไป รูปแบบการลองใหม่ฉบับเต็มอยู่ในการจัดการข้อผิดพลาดของ captcha solver

ขั้นตอนถัดไป