Cara Memecahkan CAPTCHA di Job Windows Task Scheduler

Untuk memecahkan CAPTCHA dari Windows Task Scheduler, daftarkan task yang menjalankan python.exe milik virtual environment Anda secara langsung, beri skrip percobaan ulang dan timeout HTTP-nya sendiri, dan biarkan batas waktu task menangkap semua masalah lainnya. Itulah seluruh penyiapan task scheduler captcha, dan CapSkip berjalan di PC yang sama, jadi tidak ada queue yang perlu di-host dan tidak ada biaya per pemecahan. Nilai default menyembunyikan empat jebakan, dan panduan ini membahas masing-masing. Folder kerjanya adalah System32, sehingga nama file relatif gagal. Satu eksekusi yang macet diam-diam menghentikan jadwal. Wrapper cmd membuat proses Python yang sebenarnya tetap berjalan saat scheduler mematikan task. Dan pengaturan restart saat gagal tidak me-restart skrip yang berakhir dengan error.
Apa yang Anda butuhkan
- CapSkip yang berjalan di PC Windows, dengan solver reCAPTCHA diaktifkan. CapSkip adalah aplikasi desktop, jadi task hanya berfungsi selama CapSkip terbuka.
- Python 3.10 atau lebih baru, versi minimum SDK CapSkip. Semua yang ada di bawah sudah dijalankan di Windows 11 dengan Python 3.14.0 dan capskip 1.3.0, di Windows PowerShell 5.1.
- Prompt PowerShell biasa, bukan yang dijalankan dengan hak administrator. Mendaftarkan dan menjalankan task tidak membutuhkan prompt administrator dalam pengujian.
- 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 task di mesin lain dapat memanggilnya melalui API. Keduanya diatur di pengaturan koneksi.
Langkah 1: buat folder job dan environment Python
Letakkan job di satu folder dengan virtual environment-nya sendiri. Task akan menjalankan python.exe di dalam environment itu dengan path lengkapnya, sehingga tidak membutuhkan apa pun dari PATH Anda dan tidak perlu shell yang sudah mengaktifkan environment.
# PowerShell: make a job folder with its own Python environment mkdir C:\CapSkipJobs cd C:\CapSkipJobs python -m venv venv .\venv\Scripts\python.exe -m pip install capskip==1.3.0 requests
Versi SDK dikunci karena patch timeout di Langkah 2 mengakses bagian internal SDK. Uji ulang patch itu sebelum Anda pindah ke versi yang lebih baru. Task Manager menampilkan dua proses python.exe untuk setiap eksekusi: launcher milik environment dan interpreter asli yang dijalankannya. Itu normal.
Langkah 2: baca pengaturan, catat log ke file, dan beri SDK timeout
Simpan kode dari Langkah 2 sampai 4 dalam satu file, C:\CapSkipJobs\job.py, sesuai urutan yang ditampilkan. Seluruh file diulang di akhir panduan ini. Job membaca pengaturannya dari variabel lingkungan dan meneruskannya sendiri ke klien, karena SDK tidak membacanya dengan sendirinya. Job juga memiliki nilai default, jadi file ini berjalan tanpa penyiapan apa pun. CAPSKIP_API_KEY hanya diperlukan jika Anda mengaktifkan validasi API key di CapSkip.
import functools
import logging
import os
import re
import sys
import time
import types
import requests
import capskip.api
from capskip import ApiException, CapSkip, NetworkException, TimeoutException
HOST = os.getenv('CAPSKIP_HOST', '127.0.0.1')
PORT = int(os.getenv('CAPSKIP_PORT', '8080'))
API_KEY = os.getenv('CAPSKIP_API_KEY', 'YOUR_API_KEY')
SITE = os.getenv('SITE_URL', 'https://example.com').rstrip('/')
USER = os.getenv('SITE_USER', 'YOUR_USERNAME')
PASSWORD = os.getenv('SITE_PASSWORD', 'YOUR_PASSWORD')
LOG_FILE = os.getenv('JOB_LOG', r'C:\CapSkipJobs\job.log')
ATTEMPTS = int(os.getenv('JOB_ATTEMPTS', '3'))
PAUSE = int(os.getenv('JOB_PAUSE', '30'))Task Scheduler tidak memiliki kolom untuk variabel lingkungan, dan task tidak melihat variabel yang Anda setel hanya di terminal. Variabel pengguna yang disetel dengan setx memang sampai ke task, bahkan yang disetel setelah task didaftarkan: eksekusi berikutnya mengambilnya, tanpa perlu keluar dari akun. Nilainya tersimpan di registry akun Anda sebagai teks biasa, kurang lebih sama privatnya dengan file .env.
# Task Scheduler has no environment field. User variables work: # the next run of the task sees them, with no sign-out needed. setx SITE_URL "https://example.com" setx SITE_USER "YOUR_USERNAME" setx SITE_PASSWORD "YOUR_PASSWORD"
Berikutnya adalah file log dan timeout untuk SDK. Task Scheduler membuang output program, sehingga print() tidak menampilkan apa pun di mana pun, dan job menulis file log di path absolut sebagai gantinya. Tanpa folder kerja yang ditetapkan, task berjalan di C:\Windows\System32, tempat nama file relatif seperti job.log gagal dengan PermissionError.
os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)
logging.basicConfig(filename=LOG_FILE, level=logging.INFO,
format='%(asctime)s pid=%(process)d %(levelname)s %(message)s')
log = logging.getLogger('job')
# The SDK sets no HTTP timeouts, so give every CapSkip call one: connect 5 s, read 30 s.
# This reaches into the SDK, so the guard fails loudly if a newer version changes it.
if not hasattr(capskip.api, 'requests'):
log.error('capskip.api.requests is gone: check the timeout patch')
sys.exit(1)
capskip.api.requests = types.SimpleNamespace(
RequestException=requests.RequestException,
post=functools.partial(requests.post, timeout=(5, 30)),
get=functools.partial(requests.get, timeout=(5, 30)))Baris-baris terakhir memperbaiki masalah yang tidak bisa diatasi scheduler. SDK Python CapSkip tidak menyetel timeout HTTP, jadi jika CapSkip menerima koneksi lalu tidak pernah menjawab, pemanggilan itu menunggu selamanya, dan pengaturan recaptchaTimeout hanya dihitung di antara polling. Patch memberi setiap pemanggilan SDK timeout koneksi 5 detik dan timeout baca 30 detik. Pengiriman tugas yang tidak pernah mendapat jawaban lalu gagal sebagai NetworkException setelah 30 detik. Polling hasil yang tidak pernah mendapat jawaban berakhir sebagai TimeoutException sesaat setelah recaptchaTimeout habis: 333 detik dengan nilai default 300. Pengaman di atas patch menghentikan job dengan satu baris di log jika SDK yang lebih baru tidak lagi memiliki atribut itu, alih-alih membiarkan job berjalan tanpa timeout. Anda bisa membaca panduan memecahkan CAPTCHA di APScheduler untuk penjelasan yang lebih rinci tentang patch yang sama.
Langkah 3: ambil form, pecahkan CAPTCHA-nya, lalu kirim
Job memuat halaman login dalam Session dari requests, membaca token CSRF dan sitekey dari halaman itu, lalu meminta token ke CapSkip. Satu Session membawa cookie yang berpasangan dengan token CSRF. Pengiriman form juga menyertakan Referer, karena beberapa framework, seperti Django lewat HTTPS, menolak form post tanpa Referer. Ganti path dan nama field dengan yang dipakai situs Anda.
def fetch_login(session):
"""Load the login page: the session cookie, the CSRF token and the sitekey."""
page = session.get(SITE + '/login', timeout=(5, 30))
if page.status_code != 200:
raise RuntimeError('login page returned HTTP %d' % page.status_code)
csrf = re.search(r'name="csrfmiddlewaretoken" value="([^"]+)"', page.text)
key = re.search(r'data-sitekey="([^"]+)"', page.text)
if not csrf or not key:
raise RuntimeError('login page has no CSRF token or no sitekey')
return csrf.group(1), key.group(1)
def solve(sitekey):
solver = CapSkip(apiKey=API_KEY, host=HOST, port=PORT)
return solver.recaptcha(sitekey=sitekey, url=SITE + '/login')['code']solver.recaptcha mengembalikan hasil yang field code-nya berisi token. Form post di bawah menaruh token itu di field g-recaptcha-response, di samping field form lainnya. Login yang gagal sering dijawab dengan status 200 dan form login lagi, jadi job juga menganggap halaman yang masih memiliki field password sebagai penolakan. Ubah pengecekan itu agar sesuai dengan situs Anda, karena job yang melaporkan berhasil untuk login yang ditolak lebih buruk daripada job yang gagal.
def submit(session, csrf, token):
"""Post the login form, the way the browser would, Referer included."""
resp = session.post(SITE + '/login', timeout=(5, 30),
headers={'Referer': SITE + '/login'},
data={'csrfmiddlewaretoken': csrf, 'username': USER,
'password': PASSWORD, 'g-recaptcha-response': token})
# Many sites answer a failed login with 200 and the form again.
if resp.status_code != 200 or 'type="password"' in resp.text:
raise RuntimeError('login rejected: HTTP %d %s' % (resp.status_code, resp.text[:120]))
log.info('login accepted: %s', resp.text[:40])Untuk tipe CAPTCHA lain, panggil metode SDK yang sesuai dan ubah nama field di form post. Lihat panduan memecahkan reCAPTCHA v2 di Python untuk pemanggilan yang sama dalam skrip biasa.
Langkah 4: coba ulang di dalam skrip dan keluar dengan kode
Job terjadwal membutuhkan rencana untuk menghadapi kegagalan, dan pengaturan restart milik Task Scheduler sendiri bukan rencana semacam itu. RestartCount dan RestartInterval hanya me-restart task yang gagal dimulai: program yang hilang dimulai lagi sekitar satu dan dua menit kemudian. Skrip yang keluar dengan kode 1 atau 3, atau mati karena exception yang tidak tertangkap, berjalan sekali dan tidak pernah di-restart. Karena itu, percobaan ulang ditempatkan di dalam skrip.
def run():
session = requests.Session() # a fresh session means a fresh CSRF token
csrf, sitekey = fetch_login(session)
log.info('solving reCAPTCHA v2, sitekey %s', sitekey)
submit(session, csrf, solve(sitekey))
def is_retryable(exc):
if isinstance(exc, (NetworkException, TimeoutException, requests.RequestException)):
return True
return isinstance(exc, ApiException) and 'UNSOLVABLE' in str(exc)Empat kegagalan layak mendapat percobaan lagi: CapSkip tidak menjawab, TimeoutException, ERROR_CAPTCHA_UNSOLVABLE (CapSkip tidak bisa memecahkan tugas ini, dan percobaan baru bisa berhasil), serta situs itu sendiri yang tidak menjawab. Yang lainnya, seperti login yang ditolak atau halaman tanpa token CSRF, bersifat fatal, karena percobaan ulang hanya akan mengulangi kegagalan yang sama.
def main():
log.info('start, CapSkip at %s:%s, site %s', HOST, PORT, SITE)
for attempt in range(1, ATTEMPTS + 1):
try:
run()
log.info('done, exit 0')
return 0
except Exception as exc:
retry = is_retryable(exc)
log.warning('attempt %d/%d failed, %s: %s: %s', attempt, ATTEMPTS,
'retryable' if retry else 'fatal', type(exc).__name__, exc,
exc_info=not retry)
if not retry:
return 1
if attempt < ATTEMPTS:
time.sleep(PAUSE)
log.error('giving up after %d attempts, exit 3', ATTEMPTS)
return 3
if __name__ == '__main__':
sys.exit(main())Job melakukan hingga tiga percobaan dengan jeda 30 detik, lalu keluar dengan kode yang ditampilkan Task Scheduler sebagai Last Run Result.
| Kode keluar | Arti |
|---|---|
| 0 | Login berhasil |
| 1 | Kegagalan yang tidak bisa diperbaiki dengan percobaan ulang; log berisi traceback-nya |
| 3 | Setiap percobaan mengalami kegagalan yang mungkin hilang dengan sendirinya |
Kode 2 sengaja dilewatkan. Python sendiri keluar dengan kode 2 saat tidak bisa membuka file skrip, sehingga angka 2 di Last Run Result akan ambigu.
Loop yang sama juga menangani CapSkip yang belum dibuka. Saat CapSkip tertutup, satu percobaan gagal dalam sekitar 2 detik. Dalam pengujian saat pemecah CAPTCHA dan situs sama-sama baru aktif belakangan, percobaan pertama gagal dan percobaan kedua, 30 detik kemudian, berhasil. Jika Anda ingin job dimulai saat masuk ke akun, bukan berdasarkan jadwal, trigger log-on untuk akun Anda sendiri bisa didaftarkan tanpa hak administrator dan menerima jeda; jeda satu menit berhasil didaftarkan.
Langkah 5: daftarkan task
Skrip PowerShell ini mendaftarkan task untuk pengguna saat ini. Tidak ada bagian di dalamnya yang membutuhkan prompt dengan hak administrator.
$python = 'C:\CapSkipJobs\venv\Scripts\python.exe'
$jobDir = 'C:\CapSkipJobs'
$action = New-ScheduledTaskAction -Execute $python `
-Argument ('"{0}\job.py"' -f $jobDir) -WorkingDirectory $jobDir
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(1) `
-RepetitionInterval (New-TimeSpan -Hours 1)
$settings = New-ScheduledTaskSettingsSet `
-ExecutionTimeLimit (New-TimeSpan -Minutes 30) `
-MultipleInstances IgnoreNew `
-StartWhenAvailable -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries
Register-ScheduledTask -TaskName 'CapSkip login job' -Action $action `
-Trigger $trigger -Settings $settings -ForceSetiap bagian ada alasannya.
- Action menjalankan python.exe milik environment secara langsung, dengan skrip sebagai path absolut yang diberi tanda kutip dan folder job sebagai folder kerja. Jangan menaruh cmd /c atau file .bat di depannya. Bagian tentang apa yang sebenarnya dihentikan oleh batas waktu menunjukkan alasannya.
- Trigger aktif satu menit dari sekarang lalu setiap jam, tanpa tanggal berakhir.
- Batas waktunya 30 menit. Nilai default-nya 72 jam, tiga hari. Waktu terlama yang bisa dimakan satu eksekusi mencapai sekitar 18 menit: tiga percobaan yang masing-masing menunggu CapSkip yang diam selama 333 detik, ditambah dua jeda 30 detik. Tiga puluh menit memberi ruang untuk itu dan tetap membebaskan eksekusi yang macet pada pagi yang sama.
- IgnoreNew sudah menjadi nilai default untuk kebijakan multiple instances. Nilai itu tetap ditulis agar pilihannya terlihat.
- Secara default, task tidak dimulai saat PC memakai daya baterai dan berhenti saat PC beralih ke baterai. AllowStartIfOnBatteries dan DontStopIfGoingOnBatteries mematikan keduanya, yang penting di laptop. StartWhenAvailable membuat scheduler memulai eksekusi yang terlewat, misalnya saat PC tertidur, segera setelah memungkinkan. Microsoft mendokumentasikan setiap opsi di referensi New-ScheduledTaskSettingsSet.
- Task berjalan sebagai Anda, hanya saat Anda sedang masuk. Itu cocok untuk CapSkip, yang merupakan aplikasi desktop yang berjalan di sesi Anda.
Satu pilihan lagi adalah python.exe atau pythonw.exe. Di PC Windows 11 yang dipakai untuk pengujian ini, python.exe tidak membuka jendela yang terlihat, hanya console host yang tersembunyi. pythonw.exe sama sekali tidak memiliki konsol, sehingga nilai sys.stdout dan sys.stderr adalah None: print() tidak melakukan apa pun, sys.stderr.write memunculkan AttributeError, dan exception yang tidak tertangkap tidak meninggalkan jejak di mana pun. Job mencatat log ke file, jadi berfungsi dengan keduanya. Beralihlah ke pythonw.exe hanya jika jendela konsol muncul di PC Anda.
Langkah 6: jalankan task dan baca hasilnya
Blok di bawah menjalankan task secara manual, menunggu sampai task tidak lagi berjalan, lalu menampilkan bagaimana task itu berakhir dan apa yang dicatat job.
# Run the task now instead of waiting for the trigger
Start-ScheduledTask -TaskName 'CapSkip login job'
Start-Sleep -Seconds 2
# Wait until it is no longer running
while ((Get-ScheduledTask -TaskName 'CapSkip login job').State -eq 'Running') {
Start-Sleep -Seconds 2
}
# How did it end, and what did the job write?
Get-ScheduledTaskInfo -TaskName 'CapSkip login job' |
Select-Object LastRunTime, LastTaskResult, NextRunTime
Get-Content C:\CapSkipJobs\job.log -Tail 6Last Run Result berupa angka. Berikut angka yang akan Anda temui.
| LastTaskResult | Hex | Arti |
|---|---|---|
| 0 | 0x0 | Job keluar dengan kode 0 |
| 1 | 0x1 | Job keluar dengan kode 1, atau mati karena exception yang tidak tertangkap |
| 3 | 0x3 | Job keluar dengan kode 3 setelah semua percobaannya |
| 267009 | 0x41301 | Task sedang berjalan |
| 267011 | 0x41303 | Task belum pernah berjalan |
| 267014 | 0x41306 | Scheduler menghentikannya, pada batas waktu atau dengan Stop-ScheduledTask |
| 2147946720 | 0x800710E0 | Sebuah trigger diabaikan karena sebuah eksekusi masih berjalan |
| 2147942402 | 0x80070002 | Path program tidak ada |
Mengapa satu eksekusi yang macet menghentikan seluruh jadwal
Inilah kegagalan yang diperparah oleh nilai default. Kebijakan default untuk multiple instances adalah IgnoreNew, sehingga trigger yang aktif saat eksekusi sebelumnya masih berjalan akan dibuang. Batas waktu default-nya 72 jam. Gabungan keduanya berarti satu eksekusi yang tidak pernah berakhir memblokir jadwal selama tiga hari.
Dalam satu pengujian, job dijalankan tanpa patch timeout terhadap CapSkip yang menerima koneksi tetapi tidak pernah menjawab, dengan trigger setiap menit. Task tetap berstatus Running selama lima menit pengamatan. Log job hanya berisi satu baris start dan tidak ada apa pun sesudahnya. Sementara itu, LastRunTime maju setiap menit dan LastTaskResult berubah menjadi 0x800710E0, kode untuk trigger yang diabaikan karena sebuah instance masih berjalan. Task terlihat hidup, dan angka itu menunjuk ke trigger yang dilewati, bukan ke eksekusi yang macet. Log riwayat milik Task Scheduler sendiri dinonaktifkan secara default, jadi log job Anda adalah satu-satunya catatan yang akan Anda miliki.
Tiga lapisan mencegahnya, dan masing-masing menangkap hal yang terlewat oleh yang lain. Timeout SDK mengakhiri pemanggilan CapSkip yang macet dalam 30 sampai 333 detik. Loop percobaan ulang mengubahnya menjadi percobaan lain atau keluar bersih dengan kode 3. Batas waktu adalah jaring pengaman terakhir untuk kemacetan yang tidak terpikirkan oleh Anda. Dengan ketiganya aktif, CapSkip yang tidak pernah menjawab pengiriman tugas membuat job keluar dengan kode 3 setelah sekitar 152 detik: tiga timeout 30 detik dan dua jeda. CapSkip yang tidak pernah menjawab polling hasil memakan waktu hingga 333 detik per percobaan, yang masih tercakup oleh batas 30 menit.
Apa yang sebenarnya dihentikan oleh batas waktu
Batas waktu ini akurat. Batas satu menit mematikan eksekusi pada 60.2 detik, dan Task Scheduler menerima batas 30 detik lalu mematikan pada 30.5. Apa yang dimatikannya bergantung pada bentuk action.
| Tindakan | Dimatikan pada batas waktu | Masih berjalan sesudahnya |
|---|---|---|
| python.exe milik environment | Launcher dan interpreter | Tidak ada |
| cmd /c python job.py | cmd.exe | Launcher dan interpreter, yang masih menahan koneksinya ke CapSkip |
| File .bat yang menjalankan python | cmd.exe | Launcher dan interpreter, yang masih menahan koneksinya ke CapSkip |
Pembagian yang sama muncul pada Stop-ScheduledTask. Hal ini penting untuk job CAPTCHA karena proses yatim (orphan) tetap membuka koneksinya ke CapSkip. Wrapper juga memiliki jebakan yang lebih kecil. Baris cmd /c dengan redirect membutuhkan sepasang tanda kutip luar tambahan, atau job keluar dengan kode 1 tanpa mencatat apa pun, dan target redirect harus berupa path absolut. File .bat yang baris terakhirnya echo melaporkan 0 apa pun yang dikembalikan Python, jadi akhiri dengan exit /b %ERRORLEVEL%. Dan Unregister-ScheduledTask tidak menghentikan eksekusi yang sedang berlangsung, jadi panggil Stop-ScheduledTask lebih dulu.
Job lengkap
Berikut keenam blok job.py digabung menjadi satu. Simpan sebagai C:\CapSkipJobs\job.py, yaitu path yang dituju oleh task.
import functools
import logging
import os
import re
import sys
import time
import types
import requests
import capskip.api
from capskip import ApiException, CapSkip, NetworkException, TimeoutException
HOST = os.getenv('CAPSKIP_HOST', '127.0.0.1')
PORT = int(os.getenv('CAPSKIP_PORT', '8080'))
API_KEY = os.getenv('CAPSKIP_API_KEY', 'YOUR_API_KEY')
SITE = os.getenv('SITE_URL', 'https://example.com').rstrip('/')
USER = os.getenv('SITE_USER', 'YOUR_USERNAME')
PASSWORD = os.getenv('SITE_PASSWORD', 'YOUR_PASSWORD')
LOG_FILE = os.getenv('JOB_LOG', r'C:\CapSkipJobs\job.log')
ATTEMPTS = int(os.getenv('JOB_ATTEMPTS', '3'))
PAUSE = int(os.getenv('JOB_PAUSE', '30'))
os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)
logging.basicConfig(filename=LOG_FILE, level=logging.INFO,
format='%(asctime)s pid=%(process)d %(levelname)s %(message)s')
log = logging.getLogger('job')
# The SDK sets no HTTP timeouts, so give every CapSkip call one: connect 5 s, read 30 s.
# This reaches into the SDK, so the guard fails loudly if a newer version changes it.
if not hasattr(capskip.api, 'requests'):
log.error('capskip.api.requests is gone: check the timeout patch')
sys.exit(1)
capskip.api.requests = types.SimpleNamespace(
RequestException=requests.RequestException,
post=functools.partial(requests.post, timeout=(5, 30)),
get=functools.partial(requests.get, timeout=(5, 30)))
def fetch_login(session):
"""Load the login page: the session cookie, the CSRF token and the sitekey."""
page = session.get(SITE + '/login', timeout=(5, 30))
if page.status_code != 200:
raise RuntimeError('login page returned HTTP %d' % page.status_code)
csrf = re.search(r'name="csrfmiddlewaretoken" value="([^"]+)"', page.text)
key = re.search(r'data-sitekey="([^"]+)"', page.text)
if not csrf or not key:
raise RuntimeError('login page has no CSRF token or no sitekey')
return csrf.group(1), key.group(1)
def solve(sitekey):
solver = CapSkip(apiKey=API_KEY, host=HOST, port=PORT)
return solver.recaptcha(sitekey=sitekey, url=SITE + '/login')['code']
def submit(session, csrf, token):
"""Post the login form, the way the browser would, Referer included."""
resp = session.post(SITE + '/login', timeout=(5, 30),
headers={'Referer': SITE + '/login'},
data={'csrfmiddlewaretoken': csrf, 'username': USER,
'password': PASSWORD, 'g-recaptcha-response': token})
# Many sites answer a failed login with 200 and the form again.
if resp.status_code != 200 or 'type="password"' in resp.text:
raise RuntimeError('login rejected: HTTP %d %s' % (resp.status_code, resp.text[:120]))
log.info('login accepted: %s', resp.text[:40])
def run():
session = requests.Session() # a fresh session means a fresh CSRF token
csrf, sitekey = fetch_login(session)
log.info('solving reCAPTCHA v2, sitekey %s', sitekey)
submit(session, csrf, solve(sitekey))
def is_retryable(exc):
if isinstance(exc, (NetworkException, TimeoutException, requests.RequestException)):
return True
return isinstance(exc, ApiException) and 'UNSOLVABLE' in str(exc)
def main():
log.info('start, CapSkip at %s:%s, site %s', HOST, PORT, SITE)
for attempt in range(1, ATTEMPTS + 1):
try:
run()
log.info('done, exit 0')
return 0
except Exception as exc:
retry = is_retryable(exc)
log.warning('attempt %d/%d failed, %s: %s: %s', attempt, ATTEMPTS,
'retryable' if retry else 'fatal', type(exc).__name__, exc,
exc_info=not retry)
if not retry:
return 1
if attempt < ATTEMPTS:
time.sleep(PAUSE)
log.error('giving up after %d attempts, exit 3', ATTEMPTS)
return 3
if __name__ == '__main__':
sys.exit(main())Menjalankan CapSkip di mesin lain
Task 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 job ke sana. Baris setx di bawah berlaku pada eksekusi berikutnya.
# Only if CapSkip runs in Server mode on another Windows PC setx CAPSKIP_HOST "192.168.1.50" # Only if API key validation is switched on in CapSkip setx CAPSKIP_API_KEY "YOUR_API_KEY"
Gunakan IP publik statis jika rutenya melewati internet, dan aktifkan validasi API key, dengan key yang sama di CAPSKIP_API_KEY. 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 Task Scheduler
| Apa yang Anda lihat | Penyebab | Perbaiki |
|---|---|---|
| Status task tetap Running selama berjam-jam | Sebuah pemanggilan macet dan batas default 72 jam masih sangat jauh | Tambahkan timeout SDK dan batas waktu dalam hitungan menit |
| 2147946720 (0x800710E0) di setiap trigger | Trigger diabaikan selama satu eksekusi masih berjalan | Baca baris terakhir log job, lalu perbaiki kemacetannya |
| 2147942402 (0x80070002) | Path program tidak ada | Gunakan path lengkap ke python.exe milik environment |
| Last Run Result 2 dan log yang kosong | Python tidak bisa membuka job.py, biasanya karena path relatif tanpa folder kerja | Beri action path skrip absolut dan folder kerja |
| PermissionError pada job.log | Nama file relatif di-resolve di dalam C:\Windows\System32 | Gunakan path absolut |
| Keluar dengan kode 3 di setiap eksekusi | CapSkip tidak berjalan, host atau port-nya salah, atau semua pemecahan gagal | Periksa baris pertama log dan alamat di pengaturan koneksi |
| 267014 (0x41306) | Scheduler menghentikan eksekusi pada batas waktu | Cari tempat log berhenti, lalu perbaiki pemanggilan itu |
| Pengaturan tidak ditemukan di dalam job | Variabel hanya disetel di terminal | Setel dengan setx, atau simpan nilai default di file |
| Dua proses python.exe tetap ada setelah penghentian | Action-nya adalah cmd /c atau file .bat | Jalankan python.exe sebagai action |
FAQ
Bisakah task berjalan saat saya sudah keluar dari akun?
Mendaftarkan task yang berjalan baik saat Anda sedang masuk maupun tidak, tanpa kata sandi yang tersimpan, gagal dalam pengujian dengan Access is denied (0x80070005) dari prompt PowerShell yang tidak dijalankan dengan hak administrator. Mendaftarkan task dengan kata sandi tersimpan tidak diuji, begitu juga akun pengguna standar. Bagaimanapun, CapSkip harus terbuka agar bisa menjawab, dan CapSkip adalah aplikasi desktop, jadi penyiapan yang umum adalah PC tempat Anda tetap masuk. Jika Anda membutuhkan pemecah CAPTCHA di mesin yang tidak dipakai siapa pun, jalankan CapSkip di sana dalam mode Server dan arahkan job ke sana.
Bisakah trigger berikutnya menggantikan eksekusi yang macet, bukan diabaikan?
Bisa, dengan kebijakan StopExisting. New-ScheduledTaskSettingsSet hanya menawarkan Parallel, Queue, dan IgnoreNew, jadi setel nilainya pada objek settings secara manual:
# New-ScheduledTaskSettingsSet cannot set this policy, so set it on the # $settings object from Step 5 by hand, then update the task. $settings.CimInstanceProperties['MultipleInstances'].Value = 3 Set-ScheduledTask -TaskName 'CapSkip login job' -Settings $settings
Task yang diekspor lalu menampilkan StopExisting. Dengan python.exe sebagai action, setiap trigger mematikan eksekusi lama dan memulai yang baru. Dengan cmd /c sebagai action, setiap proses yang dimatikan meninggalkan satu proses yatim. Parallel memulai eksekusi baru setiap menit sementara eksekusi yang macet tetap ada, dan Queue terus menunggu di belakangnya.
Apakah ini berfungsi untuk program C# yang dikompilasi?
Sisi scheduler-nya sama. Arahkan action ke exe Anda, tetapkan folder kerja, pertahankan batas waktu, dan gunakan path log absolut. Percobaan ulang dan kode keluar lalu menjadi urusan kode Anda sendiri. Jika program harus berjalan sepanjang hari, bukan dimulai berdasarkan jadwal, panduan memecahkan CAPTCHA di .NET Worker Service membahas pola itu.
Kapan queue lebih cocok daripada Task Scheduler?
Saat kode lain yang membuat pekerjaannya, atau saat setiap pekerjaan harus bertahan setelah crash dan dicoba ulang secara terpisah. Task Scheduler memulai proses baru berdasarkan jadwal dan tidak tahu apa pun tentang job satuan. Queue seperti Huey menyimpan setiap task di sebuah file dan mencoba ulang task itu, dan panduan memecahkan CAPTCHA di task Huey menunjukkan setup yang berjalan di Windows dengan satu file SQLite.
Versi singkatnya
Job CAPTCHA Task Scheduler membutuhkan lebih dari sekadar pemecahan. Jalankan python.exe milik environment secara langsung, dengan folder kerja, path log absolut, dan path skrip absolut. Beri pemanggilan HTTP milik SDK sebuah timeout dan coba ulang di dalam skrip, karena pengaturan restart mengabaikan kode keluar. Setel batas waktu eksekusi dalam hitungan menit, karena nilai default 72 jam membuat satu eksekusi yang macet memblokir setiap trigger berikutnya.
- 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 jam menghasilkan sekitar 720 pemecahan per bulan. Jika semuanya dijalankan melalui sebuah pemecah captcha lokal di mesin Windows Anda sendiri, angka itu tidak pernah berubah menjadi tagihan.
