Cara Memecahkan CAPTCHA di APScheduler Tanpa Eksekusi yang Terlewat

Job CAPTCHA APScheduler adalah fungsi biasa yang memanggil CapSkip dan dijadwalkan dengan interval trigger. Pemecahannya sendiri hanya satu baris. Yang menjadi masalah adalah nilai default di sekitarnya. APScheduler hanya menjalankan satu instance job pada satu waktu. Klien sinkron milik SDK Python CapSkip tidak menyetel timeout pada pemanggilan HTTP-nya. Gabungan keduanya berarti satu pemecahan yang tidak pernah kembali akan memblokir setiap eksekusi berikutnya, dan satu-satunya tandanya adalah peringatan setiap sepuluh menit. Eksekusi yang dimulai lebih dari satu detik terlambat akan dibuang. Selain itu, di Windows dengan Python 3.13 atau lebih lama, Ctrl+C tidak berpengaruh apa pun sampai eksekusi berikutnya tiba waktunya. Panduan ini memperbaiki ketiga masalah itu pada job yang login ke sebuah situs di balik reCAPTCHA setiap sepuluh menit.
Apa yang Anda butuhkan
- CapSkip yang berjalan di komputer Windows, dengan solver reCAPTCHA diaktifkan.
- Python 3.10 atau lebih baru. Kode di bawah sudah dijalankan di Python 3.13.7 dan 3.14.0.
- APScheduler 3.11, lini stabil saat ini, ditambah paket capskip dan requests. Kunci versi APScheduler di bawah 4: pre-release 4.0 memiliki API yang berbeda, dan import di bawah gagal di sana.
- Sebuah alamat untuk pemecah CAPTCHA. Dalam mode Local, CapSkip menjawab di 127.0.0.1 hanya untuk perangkat itu. Dalam mode Server, CapSkip mendengarkan di alamat jaringan atau IP publik Anda, sehingga scheduler di mesin lain dapat memanggilnya melalui API. Keduanya diatur di pengaturan koneksi.
Langkah 1: job yang memecahkan CAPTCHA
Job APScheduler bisa berupa fungsi apa saja. Job ini meminta token reCAPTCHA ke CapSkip setiap sepuluh menit. Tulis 127.0.0.1, bukan localhost: di Windows, localhost mencoba alamat IPv6 lebih dulu, dan dalam pengujian kami hal itu menggandakan waktu untuk melaporkan pemecah CAPTCHA yang tidak berjalan, dari 2 detik menjadi 4.
# pip install "apscheduler<4" capskip
from apscheduler.schedulers.blocking import BlockingScheduler
from capskip import CapSkip
solver = CapSkip(host="127.0.0.1", port=8080)
def solve_login_captcha():
result = solver.recaptcha(sitekey="YOUR_SITEKEY", url="https://example.com/login")
print("token:", result["code"][:20], "...")
scheduler = BlockingScheduler()
scheduler.add_job(solve_login_captcha, "interval", minutes=10)
scheduler.start()BlockingScheduler berjalan di thread utama dan mengirim setiap eksekusi ke pool berisi 10 worker thread. Eksekusi pertama terjadi satu interval setelah start, bukan saat start. Itu tidak masalah sampai sebuah pemecahan berperilaku tidak semestinya, dan itulah yang dibahas sisa panduan ini. Contoh singkat memakai BlockingScheduler agar tetap ringkas. Di Windows dengan Python 3.13 atau lebih lama, gunakan loop dari skrip lengkap di bawah sebagai gantinya.
Mengapa pemecahan yang lambat membuat eksekusi berikutnya dilewati
Setiap job memiliki max_instances bernilai 1 secara default. Saat sebuah eksekusi tiba waktunya dan eksekusi sebelumnya masih berjalan, APScheduler tidak memulai eksekusi kedua. Sebagai gantinya, APScheduler mencatat peringatan, di level WARNING pada logger apscheduler.scheduler:
Execution of job "solve_login_captcha (trigger: interval[0:10:00], next run at: 2026-10-07 13:10:00 +08)" skipped: maximum number of running instances reached (1)
Untuk job CAPTCHA, default itu sudah tepat. Anda tidak pernah ingin ada dua pemecahan untuk login yang sama sekaligus. Pemecahan yang sedikit lebih lama dari interval hanya mengorbankan satu eksekusi yang dilewati, dan job berlanjut pada jadwal berikutnya. Dalam pengujian dengan interval 5 detik dan pemecahan 12.8 detik, dua eksekusi dilewati per pemecahan, dan eksekusi berikutnya dimulai pada jadwal sesudahnya, bukan segera setelah pemecahan selesai.
Masalah dimulai saat sebuah pemecahan tidak pernah selesai. Satu-satunya instance yang diizinkan lalu terus sibuk selamanya, dan setiap eksekusi berikutnya dilewati dengan peringatan yang sama. Job terlihat terjadwal, log terlihat hidup, tetapi tidak ada yang terjadi.
Langkah 2: beri SDK timeout HTTP
SDK Python CapSkip memanggil requests.post dan requests.get tanpa timeout. Jika CapSkip menerima koneksi tetapi tidak pernah menjawab, misalnya karena aplikasinya membeku, pemanggilan itu menunggu selamanya. recaptchaTimeout milik SDK, 300 detik secara default, tidak membantu, karena nilai itu hanya diperiksa di antara polling, dan polling yang macet tidak pernah berakhir. Dalam pengujian kami, job yang macet dengan cara ini tetap macet setelah pemecah CAPTCHA pulih, dan hanya mencatat peringatan eksekusi yang dilewati.
Dua perbaikan yang terlihat jelas tidak berhasil. socket.setdefaulttimeout tidak berpengaruh, karena requests selalu meneruskan nilai timeout-nya sendiri ke lapisan bawah, bahkan saat nilainya None. Selain itu, SDK tidak menerima objek session yang bisa Anda konfigurasi. Yang berhasil adalah memberi modul SDK sebuah pengganti kecil untuk paket requests, yang pemanggilan post dan get-nya selalu menyertakan timeout.
# pip install capskip requests
import functools
import types
import requests
import capskip.api
from capskip import CapSkip
# The SDK calls requests.post/get with no timeout. Hand its module a
# stand-in whose calls always pass one: 5 s to connect, 30 s to answer.
capskip.api.requests = types.SimpleNamespace(
RequestException=requests.RequestException,
post=functools.partial(requests.post, timeout=(5, 30)),
get=functools.partial(requests.get, timeout=(5, 30)),
) # do this before the first solve
solver = CapSkip(host="127.0.0.1", port=8080)Ini mengganti nama requests di dalam capskip.api, modul yang mengirim permintaan SDK ke CapSkip di capskip 1.3.0. Periksa lagi setelah Anda meng-upgrade SDK. Jalankan sekali, sebelum pemecahan pertama, dan setiap pemanggilan mendapat 5 detik untuk terhubung dan 30 detik untuk menjawab.
Kedua jenis macet itu lalu berakhir secara berbeda. Jika CapSkip berhenti menjawab saat tugas sedang dikirim, job gagal setelah 30 detik dengan NetworkException yang berisi read timed out. Jika CapSkip berhenti menjawab saat SDK sedang melakukan polling untuk hasilnya, SDK menganggap timeout itu sebagai belum siap dan terus melakukan polling, sehingga job berakhir saat recaptchaTimeout tercapai, dengan TimeoutException. Dengan nilai default, hal itu memakan waktu 333 detik dalam pengujian kami. Karena itu, kasus terburuknya sekitar lima setengah menit, yang masih muat dalam interval sepuluh menit, dan eksekusi berikutnya memecahkan CAPTCHA secara normal.
Langkah 3: tentukan nasib eksekusi yang terlambat
Default kedua adalah misfire_grace_time, yang bernilai 1 detik. Eksekusi yang dimulai lebih dari satu detik setelah jadwalnya akan dibuang, dan APScheduler mencatat peringatan bahwa waktu eksekusi terlewat, beserta besar keterlambatannya. Eksekusi lebih sering terlambat daripada yang Anda kira. Pool yang semua thread-nya sibuk memecahkan CAPTCHA, atau laptop yang tertidur saat jadwal eksekusi, sudah cukup.
# pip install "apscheduler<4" capskip
from datetime import datetime
from apscheduler.schedulers.blocking import BlockingScheduler
from capskip import CapSkip
solver = CapSkip(host="127.0.0.1", port=8080)
def solve_login_captcha():
result = solver.recaptcha(sitekey="YOUR_SITEKEY", url="https://example.com/login")
print("token:", result["code"][:20])
scheduler = BlockingScheduler()
scheduler.add_job(
solve_login_captcha, "interval", minutes=10,
next_run_time=datetime.now(), # first run now, not ten minutes from now
jitter=30, # add 0 to 30 s to each run
max_instances=1, # the default: a slow solve skips the next run
coalesce=True, # the default: after a stall, run once
misfire_grace_time=None, # default is 1 s; None runs late instead of dropping
)
scheduler.start()Setel misfire_grace_time ke None, dan eksekusi yang terlambat tetap terjadi, meski terlambat. Biarkan opsi coalesce pada default-nya, True, agar setelah jeda panjang beberapa eksekusi yang terlewat digabung menjadi satu, bukan dijalankan satu per satu berturut-turut. Kami menjeda scheduler selama 14 detik pada interval 4 detik untuk menyimulasikan komputer dalam mode sleep. Dengan nilai default, eksekusi susulan dibuang. Dengan misfire_grace_time bernilai None, eksekusi itu berjalan sekali. Dengan opsi coalesce juga bernilai False, eksekusi berjalan tiga kali berturut-turut, tiga pemecahan CAPTCHA untuk satu login.
Berikan next_run_time agar job langsung berjalan saat start. Opsi jitter menambahkan jeda acak hingga sebanyak jumlah detik itu ke setiap eksekusi, sehingga permintaan lebih tersebar. Setiap jeda ditambahkan ke waktu eksekusi sebelumnya, yang sudah mengandung jeda, sehingga periode rata-ratanya menjadi interval ditambah setengah jitter.
Langkah 4: lihat kegagalan saat terjadi
Exception yang dimunculkan di dalam job tidak menghentikan scheduler. APScheduler mencatatnya di level ERROR, dengan pesan bahwa job memunculkan exception beserta traceback lengkapnya, dan job tetap mengikuti jadwalnya. Listener menerima event yang sama dalam bentuk objek, sehingga Anda bisa menghitungnya, mengirim peringatan berdasarkan event itu, atau menuliskannya ke mana pun Anda mau.
# pip install "apscheduler<4" capskip
import logging
from apscheduler.events import EVENT_JOB_ERROR, EVENT_JOB_MAX_INSTANCES, EVENT_JOB_MISSED
from apscheduler.schedulers.blocking import BlockingScheduler
from capskip import CapSkip
logging.basicConfig(level=logging.INFO)
solver = CapSkip(host="127.0.0.1", port=8080)
def solve_login_captcha():
solver.recaptcha(sitekey="YOUR_SITEKEY", url="https://example.com/login")
def on_event(event):
if event.code == EVENT_JOB_ERROR:
logging.error("job %s failed: %r", event.job_id, event.exception)
elif event.code == EVENT_JOB_MAX_INSTANCES:
logging.warning("job %s still solving, this run skipped", event.job_id)
else:
logging.warning("job %s started too late, this run dropped", event.job_id)
scheduler = BlockingScheduler()
scheduler.add_listener(on_event, EVENT_JOB_ERROR | EVENT_JOB_MAX_INSTANCES | EVENT_JOB_MISSED)
scheduler.add_job(solve_login_captcha, "interval", minutes=10, id="login")
scheduler.start()Tiga event sudah mencakup job CAPTCHA. EVENT_JOB_ERROR membawa exception itu sendiri, misalnya ApiException dengan pesan ERROR_CAPTCHA_UNSOLVABLE. EVENT_JOB_MAX_INSTANCES terpicu sekali untuk setiap eksekusi yang dilewati, sehingga pemecahan yang macet terlihat sebagai hitungan yang terus naik. EVENT_JOB_MISSED terpicu untuk setiap eksekusi terlambat yang dibuang.
Job CAPTCHA APScheduler lengkap
Skrip ini mengambil halaman login dengan sesi requests, membaca sitekey dan field CSRF, memecahkan reCAPTCHA dengan CapSkip, lalu mengirim form beserta token. Skrip ini menangkap error CapSkip di dalam job, sehingga pemecahan yang gagal hanya menjadi satu peringatan dan eksekusi berikutnya mencoba lagi.
# pip install "apscheduler<4" capskip requests
import functools
import logging
import re
import time
import types
from datetime import datetime
import requests
import capskip.api
from apscheduler.schedulers.background import BackgroundScheduler
from capskip import CapSkip, CapSkipError
LOGIN_URL = "https://example.com/login"
USERNAME, PASSWORD = "YOUR_USERNAME", "YOUR_PASSWORD"
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s: %(message)s")
log = logging.getLogger("login-job")
# The SDK's HTTP calls have no timeout; give them one so a stuck CapSkip
# cannot hang the job.
capskip.api.requests = types.SimpleNamespace(
RequestException=requests.RequestException,
post=functools.partial(requests.post, timeout=(5, 30)),
get=functools.partial(requests.get, timeout=(5, 30)),
)
solver = CapSkip(host="127.0.0.1", port=8080)
def field(html, pattern):
match = re.search(pattern, html)
if not match:
raise ValueError(f"not found on the login page: {pattern}")
return match.group(1)
def login():
with requests.Session() as session:
page = session.get(LOGIN_URL, timeout=30)
sitekey = field(page.text, r'data-sitekey="([^"]+)"')
# The form's hidden CSRF field (Django names it csrfmiddlewaretoken).
csrf = field(page.text, r'name="csrfmiddlewaretoken" value="([^"]+)"')
try:
token = solver.recaptcha(sitekey=sitekey, url=LOGIN_URL)["code"]
except CapSkipError as exc:
log.warning("CapSkip could not solve: %s: %s", type(exc).__name__, exc)
return
reply = session.post(LOGIN_URL, timeout=30, headers={"Referer": LOGIN_URL}, data={
"csrfmiddlewaretoken": csrf,
"username": USERNAME,
"password": PASSWORD,
"g-recaptcha-response": token,
})
# Many sites answer a failed login with 200 and the form again;
# check for something only a logged-in page shows.
if reply.ok:
log.info("logged in (HTTP %s)", reply.status_code)
else:
log.warning("login refused (HTTP %s): %s", reply.status_code, reply.text[:200])
scheduler = BackgroundScheduler()
scheduler.add_job(
login, "interval", minutes=10,
next_run_time=datetime.now(), # first run now, not ten minutes from now
max_instances=1, # never two solves for the same account at once
coalesce=True, # after a stall, run once, not once per missed slot
misfire_grace_time=None, # a late run still runs instead of being dropped
)
scheduler.start()
try:
while True:
time.sleep(1) # Ctrl+C lands here at once, on any Python version
except KeyboardInterrupt:
log.info("stopping; a solve in flight finishes first")
scheduler.shutdown()Skrip ini memakai BackgroundScheduler dan loop sleep, bukan BlockingScheduler, karena alasan yang hanya muncul di Windows. Dengan BlockingScheduler di Python 3.13 atau lebih lama, thread utama menunggu pada lock yang tidak bisa diinterupsi Ctrl+C, sehingga KeyboardInterrupt baru tiba saat scheduler bangun pada jadwal berikutnya. Dengan interval sepuluh menit, itu bisa berarti sepuluh menit. Python 3.14 memperbaiki hal ini di Windows, tetapi loop ini berfungsi di setiap versi: Ctrl+C langsung menginterupsi time.sleep.
Penghentian tetap menunggu pemecahan yang sedang berjalan. Sebelum proses keluar, Python menunggu worker thread milik pool selesai, sehingga pemecahan yang sedang berjalan selesai lebih dulu. Hal itu terjadi baik Anda memanggil scheduler.shutdown() maupun tidak, dan dengan timeout dari Langkah 2, penantiannya paling lama sekitar lima setengah menit. Ctrl+C kedua tidak mempersingkatnya.
Sesi itu mengirim form dengan header Referer, karena requests tidak mengirimnya sendiri dan framework seperti Django menolak form post HTTPS tanpa header itu. Sesi juga menyimpan cookie yang menjadi pasangan field CSRF. Pecahkan tepat sebelum Anda mengirim form: token reCAPTCHA kedaluwarsa dua menit setelah diterbitkan. Widget invisible, key Enterprise, dan varian lainnya dibahas di panduan memecahkan reCAPTCHA v2 di Python.
Banyak akun dalam satu jadwal
Satu job per akun bekerja dengan baik, dengan satu klien CapSkip bersama, yang aman dipakai dari beberapa thread. Buat ukuran thread pool sama dengan jumlah akun.
# pip install "apscheduler<4" capskip
import logging
from datetime import datetime
from apscheduler.executors.pool import ThreadPoolExecutor
from apscheduler.schedulers.blocking import BlockingScheduler
from capskip import CapSkip
logging.basicConfig(level=logging.INFO)
solver = CapSkip(host="127.0.0.1", port=8080) # one client is safe to share across threads
ACCOUNTS = [f"user{i:02d}" for i in range(20)]
def login(account):
token = solver.recaptcha(sitekey="YOUR_SITEKEY", url="https://example.com/login")["code"]
logging.info("%s got a token %s", account, token[:12])
scheduler = BlockingScheduler(executors={"default": ThreadPoolExecutor(max_workers=20)})
for account in ACCOUNTS:
scheduler.add_job(login, "interval", minutes=10, args=[account], id=account,
next_run_time=datetime.now(), misfire_grace_time=None)
scheduler.start()Pool default memiliki 10 thread. Dengan 20 job yang jatuh tempo sekaligus, 10 eksekusi menunggu thread, dimulai 7.8 detik terlambat, dan dibuang karena melewati grace time default 1 detik. Separuh akun tidak pernah login, dan hanya peringatan eksekusi terlewat yang menunjukkannya. Pool berisi 20 thread, atau misfire_grace_time bernilai None, memperbaiki hal itu.
CapSkip punya batasnya sendiri. Pengaturan reCAPTCHA-nya mengizinkan 10 pemecahan sekaligus secara default, di Max. Threads, dan tugas berikutnya menunggu thread yang kosong. Dalam pengujian kami dengan 20 thread, 10 pemecahan memakan waktu 7.8 detik dan 10 lainnya 12.8 detik, karena tugas itu menunggu CapSkip selama 5 detik. Naikkan Max. Threads di CapSkip jika mesin Anda punya kapasitasnya, dan sebarkan akun dengan jitter jika tidak.
Dengan asyncio, bukan thread
Jika bagian lain kode Anda bersifat async, gunakan AsyncIOScheduler dengan AsyncCapSkip, klien async bawaan SDK. Job berupa coroutine berjalan di event loop, dan max_instances bekerja persis seperti sebelumnya.
# pip install "apscheduler<4" capskip
import asyncio
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from capskip import AsyncCapSkip
solver = AsyncCapSkip(host="127.0.0.1", port=8080)
async def solve_login_captcha():
result = await solver.recaptcha(sitekey="YOUR_SITEKEY", url="https://example.com/login")
print("token:", result["code"][:20], "...")
async def main():
scheduler = AsyncIOScheduler()
scheduler.add_job(solve_login_captcha, "interval", minutes=10)
scheduler.start()
await asyncio.Event().wait() # keep the event loop running
asyncio.run(main())Ada dua hal yang berbeda. AsyncCapSkip dibangun di atas httpx, yang memiliki timeout default 5 detik, sehingga CapSkip yang macet berakhir dengan exception meski tanpa patch dari Langkah 2: setelah 5 detik jika pengiriman tugas macet, dan saat recaptchaTimeout tercapai jika polling macet. NetworkException darinya bisa memiliki pesan kosong, jadi catat juga tipe exception-nya. Selain itu, penghentian membatalkan pemecahan yang sedang berjalan alih-alih menunggunya: job lalu mencatat CancelledError sebagai exception-nya. Traceback juga menampilkan NetworkException di atasnya, yang hanya merupakan sinyal belum siap dari SDK, bukan kegagalan jaringan. Ctrl+C keluar dalam sepersekian detik.
Menjalankan CapSkip di mesin lain
Scheduler dan pemecah CAPTCHA tidak harus berada di PC yang sama. Alihkan CapSkip ke mode Server di pengaturan koneksi, dan CapSkip akan mendengarkan di alamat jaringan atau IP publik Anda. Lalu arahkan klien ke sana.
# Replace the solver line with this when CapSkip runs in Server mode # on another Windows machine on your network. solver = CapSkip(apiKey="YOUR_API_KEY", host="192.168.1.50", port=8080)
Gunakan IP publik statis jika rutenya melewati internet, dan aktifkan validasi API key, dengan key yang sama di klien. CapSkip membuka port-nya untuk semua alamat saat mode Server dimulai, jadi untuk membatasi akses hanya pada mesin yang Anda harapkan, tambahkan aturan blokir Windows Firewall untuk alamat lainnya. Pemecah CAPTCHA tetap berupa mesin Windows milik Anda sendiri, dan pemecahannya tetap tanpa kuota.
Kesalahan umum CAPTCHA APScheduler
| Apa yang Anda lihat | Penyebab | Perbaiki |
|---|---|---|
| Skipped: maximum number of running instances reached (1), sesekali muncul | Sebuah pemecahan lebih lama dari interval | Tidak perlu apa-apa, atau perpanjang interval |
| Peringatan skipped yang sama di setiap eksekusi, dan tidak ada pemecahan | Satu pemecahan macet pada pemanggilan HTTP tanpa timeout | Beri SDK timeout, seperti di Langkah 2 |
| Run time of job was missed by, dengan selisih beberapa detik | Eksekusi dimulai lebih dari 1 detik terlambat dan dibuang | Setel misfire_grace_time ke None |
| Separuh akun tidak pernah berjalan | Job yang jatuh tempo lebih banyak daripada 10 thread di pool default | Sesuaikan ukuran pool dengan jumlah job |
| Ctrl+C tidak berpengaruh selama beberapa menit | BlockingScheduler di Windows dengan Python 3.13 atau lebih lama | Gunakan BackgroundScheduler dengan loop sleep, atau Python 3.14 |
| Job memunculkan exception, ApiException ERROR_CAPTCHA_UNSOLVABLE | CapSkip tidak bisa memecahkan tugas ini | Tangkap CapSkipError di dalam job; eksekusi berikutnya mencoba lagi |
| NetworkException: Read timed out. (read timeout=30) | CapSkip menerima tugas lalu berhenti menjawab | Pastikan CapSkip merespons; eksekusi berikutnya mencoba lagi |
| TimeoutException: timeout 300.0 exceeded | CapSkip berhenti menjawab, atau ditutup, saat SDK sedang melakukan polling | Pastikan CapSkip berjalan; eksekusi berikutnya mencoba lagi |
| NetworkException: mesin tujuan secara aktif menolak koneksi | CapSkip tidak berjalan, atau host atau port-nya salah | Jalankan CapSkip lalu cocokkan alamatnya dengan pengaturan koneksinya |
| ModuleNotFoundError: No module named apscheduler.schedulers | APScheduler 4 terinstal, misalnya versi pre-release | Instal APScheduler di bawah versi 4 |
| Situs menolak token | Token kedaluwarsa, atau kiriman form tidak menyertakan cookie, field tersembunyi, atau Referer | Pecahkan tepat sebelum mengirim, di sesi yang mengambil halaman tersebut |
FAQ
Bisakah saya menyimpan job ini di database?
Bisa, dengan SQLAlchemyJobStore, tetapi perhatikan apa yang disimpan. Fungsi job disimpan sebagai referensi, jadi fungsi itu harus berada di modul yang bisa di-import: lambda gagal dengan ValueError, dan fungsi dari skrip yang Anda jalankan sebagai __main__ akan dihapus saat program lain memuat store tersebut. Teruskan klien CapSkip melalui variabel modul, bukan melalui args job. Klien di dalam args di-pickle ke database beserta host, port, dan API key-nya, dan job yang tersimpan mempertahankan alamat itu sampai Anda menambahkan job lagi dengan id yang sama dan replace_existing bernilai True. Bagaimanapun juga, beri job sebuah id: tanpa id, setiap kali program dijalankan akan ditambahkan satu salinan lagi.
Mengapa tidak menyetel timeout pada pemanggilan recaptcha itu sendiri?
Karena SDK tidak menerimanya di sana. Memberikan argumen timeout ke solver.recaptcha memunculkan TypeError di capskip 1.3.0, dan pengaturan recaptchaTimeout pada klien hanya membatasi loop polling dan hanya diperiksa di antara permintaan. Keduanya tidak membatasi satu pemanggilan HTTP, itulah sebabnya Langkah 2 mem-patch pemanggilan requests itu sendiri.
Kapan task queue lebih cocok daripada APScheduler?
Saat kode lain yang membuat pekerjaannya, atau saat setiap pekerjaan harus disimpan dan dicoba ulang jika proses crash. APScheduler menjalankan job di dalam program Anda sendiri dengan timer. Queue seperti RQ menyimpan setiap job di Redis dan menjalankannya di worker terpisah, dengan timeout job tersendiri yang perlu diperhitungkan, seperti yang dijelaskan di panduan memecahkan CAPTCHA di job RQ.
Bisakah scheduler berjalan di mesin yang berbeda dari CapSkip?
Bisa. Alihkan CapSkip ke mode Server di pengaturan koneksi, agar ia mendengarkan di alamat jaringan, bukan di loopback, lalu berikan alamat itu sebagai host klien. Scheduler kemudian memanggilnya melalui API HTTP yang sama dari mesin mana pun yang bisa menjangkau port tersebut. Tambahkan aturan blokir Windows Firewall untuk alamat yang seharusnya tidak bisa menjangkaunya. Pemecah CAPTCHA tetap berjalan di perangkat milik Anda, dan tidak ada pemecahan yang melewati layanan pihak ketiga.
Versi singkatnya
Job CAPTCHA APScheduler membutuhkan lebih dari sekadar pemecahan. Beri pemanggilan HTTP milik SDK sebuah timeout, karena dengan max_instances bernilai 1, satu pemecahan yang macet membuat setiap eksekusi berikutnya dilewati. Setel misfire_grace_time ke None dan biarkan coalesce aktif, agar eksekusi yang terlambat tetap terjadi sekali, bukan dibuang. Sesuaikan ukuran thread pool dengan job Anda, tangkap CapSkipError di dalam job, dan gunakan BackgroundScheduler dengan loop sleep jika Anda menghentikannya dengan Ctrl+C di Windows dengan Python 3.13 atau lebih lama. Panduan pengguna APScheduler 3.x mendokumentasikan setiap opsi yang dipakai di sini.
- Setiap tipe CAPTCHA yang ditangani paket Python: halaman pemecah CAPTCHA Python.
- Cara kerja reCAPTCHA kotak centang dan apa saja yang dicakup pemecah CAPTCHA: halaman pemecah reCAPTCHA v2.
Job yang berjalan setiap sepuluh menit menghasilkan lebih dari empat ribu pemecahan per bulan. Jika semuanya dijalankan melalui sebuah pemecah captcha di mesin Windows Anda sendiri, angka itu tidak pernah berubah menjadi tagihan.
