APScheduler’da Çalıştırmalar Atlanmadan CAPTCHA Nasıl Çözülür

Bir APScheduler CAPTCHA işi, CapSkip’i çağıran ve bir interval tetikleyicisiyle zamanlanan sıradan bir fonksiyondur. Çözümün kendisi tek satırdır. Sorun, etrafındaki varsayılan değerlerdedir. APScheduler bir işin aynı anda yalnızca tek bir örneğini çalıştırır. CapSkip Python SDK’sının senkron istemcisi ise HTTP çağrılarında hiçbir zaman aşımı ayarlamaz. Bu ikisi bir araya geldiğinde, hiç geri dönmeyen tek bir çözüm sonraki tüm çalıştırmaları engeller ve bunun tek işareti on dakikada bir yazılan bir uyarıdır. Bir saniyeden fazla geç başlayan bir çalıştırma düşürülür. Ayrıca Windows’ta Python 3.13 veya daha eski bir sürümle Ctrl+C, bir sonraki çalıştırmanın zamanı gelene kadar hiçbir şey yapmaz. Bu rehber, reCAPTCHA arkasındaki bir siteye on dakikada bir giriş yapan bir işte bu üç sorunun hepsini düzeltir.
Neye ihtiyacınız var
- reCAPTCHA çözücüsü açık hâlde bir Windows makinesinde çalışan CapSkip.
- Python 3.10 veya üzeri. Aşağıdaki kod Python 3.13.7 ve 3.14.0 üzerinde çalıştırıldı.
- Güncel kararlı sürüm hattı olan APScheduler 3.11, ayrıca capskip ve requests paketleri. APScheduler sürümünü 4’ün altına sabitleyin: 4.0 ön sürümlerinin API’si farklıdır ve aşağıdaki import satırları onlarda başarısız olur.
- Çözücü için bir adres. Local modunda CapSkip 127.0.0.1 üzerinden yalnızca o cihaza yanıt verir. Server modunda ise ağ adresinizi veya genel IP’nizi dinler, böylece başka bir makinedeki bir scheduler onu API üzerinden çağırabilir. İkisi de şurada ayarlanır: bağlantı ayarları.
1. Adım: CAPTCHA’yı çözen bir iş
Bir APScheduler işi herhangi bir fonksiyon olabilir. Bu fonksiyon on dakikada bir CapSkip’ten bir reCAPTCHA token’ı ister. localhost yerine 127.0.0.1 yazın: Windows’ta localhost önce IPv6 adresini dener ve bizim çalıştırmalarımızda bu, çalışmayan bir çözücünün bildirilme süresini 2 saniyeden 4 saniyeye çıkararak ikiye katladı.
# 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 ana thread’de çalışır ve her çalıştırmayı 10 worker thread’inden oluşan bir havuza gönderir. İlk çalıştırma başlangıçta değil, başlangıçtan bir aralık sonra gerçekleşir. Bir çözüm sorun çıkarana kadar bu bir sorun değildir; rehberin geri kalanı da tam olarak bununla ilgilidir. Kısa örnekler kısa kalmak için BlockingScheduler kullanır. Windows’ta Python 3.13 veya daha eskisiyle bunun yerine aşağıdaki tam betikteki döngüyü kullanın.
Yavaş bir çözüm bir sonraki çalıştırmayı neden atlatır
Her işin max_instances değeri varsayılan olarak 1’dir. Bir çalıştırmanın zamanı geldiğinde önceki hâlâ çalışıyorsa APScheduler ikinci bir örnek başlatmaz. Bunun yerine apscheduler.scheduler logger’ı altında, WARNING seviyesinde bir uyarı loglar:
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)
Bir CAPTCHA işi için bu varsayılan doğrudur. Aynı giriş için asla aynı anda iki çözüm istemezsiniz. Aralıktan biraz uzun süren bir çözüm, bir çalıştırmanın atlanmasına mal olur ve iş bir sonraki zamanlanmış saatte devam eder. 5 saniyelik aralık ve 12.8 saniyelik çözümle yaptığımız bir testte her çözümde iki çalıştırma atlandı ve sonraki çalıştırma, çözümün hemen ardından değil, bir sonraki zamanlanmış saatte başladı.
Sorun, bir çözüm hiç bitmediğinde başlar. O zaman izin verilen tek örnek sonsuza kadar meşgul kalır ve sonraki her çalıştırma aynı uyarıyla atlanır. İş zamanlanmış görünür, log canlı görünür ve hiçbir şey olmaz.
2. Adım: SDK’ya bir HTTP zaman aşımı verin
CapSkip Python SDK’sı requests.post ve requests.get çağrılarını zaman aşımı olmadan yapar. CapSkip bir bağlantıyı kabul edip hiç yanıt vermezse, örneğin uygulama donduğu için, çağrı sonsuza kadar bekler. SDK’nın varsayılan olarak 300 saniye olan recaptchaTimeout ayarı işe yaramaz, çünkü bu ayar yalnızca yoklamalar arasında kontrol edilir ve takılı kalmış bir yoklama hiç bitmez. Testimizde bu şekilde takılan bir iş, çözücü düzeldikten sonra da takılı kaldı ve yalnızca atlama uyarıları logladı.
Akla ilk gelen iki düzeltme işe yaramaz. socket.setdefaulttimeout hiçbir etki yapmaz, çünkü requests, değer None olsa bile her zaman kendi timeout değerini aşağıya iletir. SDK da yapılandırabileceğiniz bir session nesnesi kabul etmez. İşe yarayan şey, SDK’nın modülüne requests paketinin yerine geçen ve post ile get çağrılarında her zaman bir timeout ileten küçük bir nesne vermektir.
# 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)Bu kod, capskip 1.3.0’da SDK’nın isteklerini CapSkip’e gönderen modül olan capskip.api içindeki requests adını değiştirir. SDK’yı yükselttikten sonra bunu yeniden kontrol edin. Kodu ilk çözümden önce bir kez çalıştırın; böylece her çağrıya bağlanmak için 5 saniye, yanıt vermek için 30 saniye tanınır.
Bu durumda iki tür takılma farklı şekilde sona erer. CapSkip görev gönderilirken yanıt vermeyi keserse iş 30 saniye sonra read timed out diyen bir NetworkException ile başarısız olur. SDK sonuç için yoklama yaparken yanıt vermeyi keserse SDK zaman aşımını henüz hazır değil olarak yorumlar ve yoklamaya devam eder; bu yüzden iş recaptchaTimeout noktasında bir TimeoutException ile sona erer. Varsayılan değerlerle bu, testimizde 333 saniye sürdü. Dolayısıyla en kötü durum yaklaşık beş buçuk dakikadır; bu da on dakikalık bir aralığın içine sığar ve bir sonraki çalıştırma normal şekilde çözer.
3. Adım: geç kalan çalıştırmalara ne olacağını seçin
İkinci varsayılan misfire_grace_time ayarıdır ve değeri 1 saniyedir. Zamanlanmış saatinden bir saniyeden fazla sonra başlayan bir çalıştırma düşürülür ve APScheduler, gecikme süresiyle birlikte çalıştırma zamanının kaçırıldığını bildiren bir uyarı loglar. Çalıştırmalar sandığınızdan daha sık geç başlar. Tüm thread’leri çözümle meşgul bir havuz ya da bir çalıştırmayı uykuda geçiren bir dizüstü bilgisayar bunun için yeterlidir.
# 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()misfire_grace_time değerini None yapın; geç kalan bir çalıştırma yine de, geç de olsa, gerçekleşir. coalesce seçeneğini varsayılan değeri olan True olarak bırakın; böylece uzun bir duraklamadan sonra kaçırılan birkaç çalıştırma art arda çalışmak yerine tek bir çalıştırmada birleşir. Uyku modundaki bir bilgisayarı taklit etmek için 4 saniyelik aralıkla çalışan bir scheduler’ı 14 saniye duraklattık. Varsayılan değerlerle telafi çalıştırması düşürüldü. misfire_grace_time None olduğunda bir kez çalıştı. coalesce seçeneği de False yapıldığında art arda üç kez çalıştı: tek bir giriş için üç CAPTCHA çözümü.
Başlangıçta işi hemen çalıştırmak için next_run_time verin. jitter seçeneği her çalıştırmaya o kadar saniyeye kadar rastgele bir gecikme ekler ve bu da istekleri zamana yayar. Her gecikme, zaten bir gecikme içeren önceki çalıştırma zamanına eklenir; bu yüzden ortalama periyot, aralık artı jitter’ın yarısı olur.
4. Adım: hataları oldukları anda görün
Bir işin içinde fırlatılan bir istisna scheduler’ı durdurmaz. APScheduler bunu, işin bir istisna fırlattığını söyleyen bir mesaj ve tam traceback ile ERROR seviyesinde loglar; iş de zamanlamasını korur. Bir dinleyici aynı olayları nesneler olarak alır; böylece onları sayabilir, onlar için uyarı gönderebilir ya da istediğiniz yere yazabilirsiniz.
# 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()Bir CAPTCHA işi için üç olay yeterlidir. EVENT_JOB_ERROR istisnanın kendisini taşır, örneğin mesajı ERROR_CAPTCHA_UNSOLVABLE olan bir ApiException. EVENT_JOB_MAX_INSTANCES atlanan her çalıştırma için bir kez tetiklenir; bu da takılı kalmış bir çözümü artan bir sayı olarak görünür kılar. EVENT_JOB_MISSED ise düşürülen her geç çalıştırma için tetiklenir.
Tam APScheduler CAPTCHA işi
Bu betik giriş sayfasını bir requests oturumuyla çeker, sitekey’i ve CSRF alanını okur, reCAPTCHA’yı CapSkip ile çözer ve formu token ile gönderir. CapSkip’in hatalarını işin içinde yakalar; böylece başarısız bir çözüm tek bir uyarıdan ibaret kalır ve bir sonraki çalıştırma yeniden dener.
# 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()Yalnızca Windows’ta ortaya çıkan bir nedenle BlockingScheduler yerine BackgroundScheduler ve bir uyku döngüsü kullanır. Python 3.13 veya daha eskisinde BlockingScheduler ile ana thread, Ctrl+C’nin kesemediği bir kilit üzerinde bekler; bu yüzden KeyboardInterrupt ancak bir sonraki zamanlanmış uyanmada gelir. On dakikalık bir aralıkla bu on dakika sürebilir. Python 3.14 bunu Windows’ta düzeltti, ancak döngü her sürümde çalışır: Ctrl+C, time.sleep’i hemen keser.
Durdurma işlemi yine de süren bir çözümü bekler. Süreç çıkmadan önce Python havuzun worker thread’lerinin bitmesini bekler, bu yüzden çalışan bir çözüm önce tamamlanır. Bu, scheduler.shutdown() çağırsanız da çağırmasanız da olur ve 2. adımdaki zaman aşımıyla bu bekleme en fazla yaklaşık beş buçuk dakika sürer. İkinci bir Ctrl+C bunu kısaltmaz.
Oturum formu bir Referer başlığıyla gönderir, çünkü requests kendiliğinden bu başlığı göndermez ve Django gibi framework’ler Referer başlığı olmayan bir HTTPS form gönderimini reddeder. Oturum ayrıca CSRF alanıyla eşleşen çerezi de saklar. Göndermeden hemen önce çözün: bir reCAPTCHA token’ının süresi, verildikten iki dakika sonra dolar. Görünmez widget’lar, Enterprise anahtarları ve diğer varyantlar şurada ele alınıyor: Python ile reCAPTCHA v2 çözme rehberi.
Tek bir zamanlamada çok sayıda hesap
Her hesap için bir iş ve paylaşılan tek bir CapSkip istemcisi iyi çalışır; bu istemciyi birden fazla thread’den kullanmak güvenlidir. Thread havuzunu hesap sayısı kadar büyük yapın.
# 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()Varsayılan havuzda 10 thread vardır. Aynı anda zamanı gelen 20 işle 10 çalıştırma bir thread bekledi, 7.8 saniye geç kaldı ve varsayılan 1 saniyelik tolerans süresi nedeniyle düşürüldü. Hesapların yarısı hiç giriş yapmadı ve bunu yalnızca kaçırılan çalıştırma uyarıları gösterdi. 20 thread’lik bir havuz ya da None yapılmış bir misfire_grace_time bu sorunu düzeltir.
CapSkip’in de kendi sınırı vardır. reCAPTCHA ayarları varsayılan olarak Max. Threads altında aynı anda 10 çözüme izin verir ve sonraki görevler boş bir thread bekler. 20 thread ile yaptığımız testte 10 çözüm 7.8 saniye, diğer 10 çözüm ise 12.8 saniye sürdü, çünkü bunlar CapSkip için 5 saniye beklediler. Makinenizin kapasitesi varsa CapSkip’te Max. Threads değerini yükseltin, yoksa hesapları jitter ile zamana yayın.
Thread yerine asyncio ile
Kodunuzun geri kalanı async ise AsyncIOScheduler’ı, SDK’nın yerleşik async istemcisi olan AsyncCapSkip ile birlikte kullanın. Coroutine işleri event loop üzerinde çalışır ve max_instances tam olarak önceki gibi çalışır.
# 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())İki şey farklıdır. AsyncCapSkip, varsayılan zaman aşımı 5 saniye olan httpx üzerine kuruludur; bu yüzden takılı kalan bir CapSkip, 2. adımdaki yama olmadan da bir istisnayla sonuçlanır: görev gönderimi takılırsa 5 saniye sonra, bir yoklama takılırsa recaptchaTimeout noktasında. Bundan gelen bir NetworkException’ın mesajı boş olabilir, bu yüzden istisna türünü de loglayın. Ayrıca durdurma işlemi süren bir çözümü beklemek yerine iptal eder: iş bu durumda istisna olarak bir CancelledError loglar. Traceback onun üstünde bir NetworkException da gösterir; bu bir ağ hatası değil, yalnızca SDK’nın hazır değil sinyalidir. Ctrl+C saniyenin küçük bir kesrinde çıkar.
CapSkip’i başka bir makinede çalıştırmak
Scheduler ile çözücünün aynı bilgisayarı paylaşması gerekmez. Bağlantı ayarlarından CapSkip’i Server moduna alın; ağ adresinizi veya genel IP’nizi dinlemeye başlar. Ardından istemciyi oraya yönlendirin.
# 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)
Rota internetten geçiyorsa statik bir genel IP kullanın ve API anahtarı doğrulamasını açıp aynı anahtarı istemcide de kullanın. CapSkip, Server modu başladığında portunu her adrese açar; bu yüzden erişimi beklediğiniz makinelerle sınırlamak için diğerlerine yönelik bir Windows Firewall engelleme kuralı ekleyin. Çözücü hâlâ sizin kendi Windows makinenizdir ve çözüm başına ücretlendirme hâlâ yoktur.
Sık görülen APScheduler CAPTCHA hataları
| Gördüğünüz | Neden | Düzeltme |
|---|---|---|
| Skipped: maximum number of running instances reached (1), arada bir | Bir çözüm aralıktan uzun sürdü | Hiçbir şey ya da daha uzun bir aralık |
| Her çalıştırmada aynı skipped uyarısı ve hiç çözüm yok | Bir çözüm, zaman aşımı olmayan bir HTTP çağrısında takılı kaldı | 2. adımdaki gibi SDK’ya bir zaman aşımı verin |
| Run time of job was missed by uyarısı (birkaç saniye) | Çalıştırma 1 saniyeden fazla geç başladı ve düşürüldü | misfire_grace_time değerini None yapın |
| Hesapların yarısı hiç çalışmıyor | Zamanı gelen iş sayısı, varsayılan havuzun 10 thread’inden fazlaydı | Havuzu iş sayısına göre boyutlandırın |
| Ctrl+C dakikalarca hiçbir şey yapmıyor | Windows’ta Python 3.13 veya daha eskisiyle BlockingScheduler | Bir uyku döngüsüyle BackgroundScheduler ya da Python 3.14 kullanın |
| İş bir istisna fırlattı: ApiException ERROR_CAPTCHA_UNSOLVABLE | CapSkip bu görevi çözemedi | CapSkipError’ı işin içinde yakalayın; bir sonraki çalıştırma yeniden dener |
| NetworkException: Read timed out. (read timeout=30) | CapSkip görevi kabul etti ve yanıt vermeyi kesti | CapSkip’in yanıt verdiğini kontrol edin; bir sonraki çalıştırma yeniden dener |
| TimeoutException: timeout 300.0 exceeded | SDK yoklama yaparken CapSkip yanıt vermeyi kesti ya da kapatıldı | CapSkip’in çalıştığını kontrol edin; bir sonraki çalıştırma yeniden dener |
| NetworkException: hedef makine bağlantıyı etkin olarak reddetti | CapSkip çalışmıyor ya da host veya port yanlış | CapSkip’i başlatın ve adresi bağlantı ayarlarıyla karşılaştırın |
| ModuleNotFoundError: No module named apscheduler.schedulers | APScheduler 4 kurulu, örneğin bir ön sürüm | 4’ten eski bir APScheduler sürümü kurun |
| Site token’ı reddediyor | Token’ın süresi doldu ya da gönderimde bir çerez, gizli bir alan veya Referer eksikti | Göndermeden hemen önce, sayfayı çeken oturumda çözün |
FAQ
Bu işleri bir veritabanında saklayabilir miyim?
Evet, SQLAlchemyJobStore ile; ancak neyin kaydedildiğine dikkat edin. İşin fonksiyonu referans olarak saklanır, bu yüzden import edilebilir bir modülde bulunmalıdır: bir lambda ValueError ile başarısız olur, __main__ olarak çalıştırdığınız betikteki bir fonksiyon ise iş deposunu (job store) başka bir program yüklediğinde kaldırılır. CapSkip istemcisini işin args değeri yerine bir modül değişkeni üzerinden verin. args içindeki bir istemci host, port ve API anahtarıyla birlikte pickle ile veritabanına yazılır ve kaydedilen iş, siz işi aynı id ve True yapılmış replace_existing ile yeniden ekleyene kadar o adresi korur. Her durumda işe bir id verin: id olmadan programın her başlatılışı bir kopya daha ekler.
Zaman aşımını neden doğrudan recaptcha çağrısının kendisine vermiyoruz?
Çünkü SDK orada zaman aşımı kabul etmez. capskip 1.3.0’da solver.recaptcha’ya timeout argümanı vermek bir TypeError fırlatır; istemcideki recaptchaTimeout ayarı ise yalnızca yoklama döngüsünü sınırlar ve yalnızca istekler arasında kontrol edilir. İkisi de tek bir HTTP çağrısını sınırlamaz; 2. adımın requests çağrılarının kendisini yamamasının nedeni de budur.
Ne zaman bir görev kuyruğu APScheduler’dan daha uygundur?
İşi başka kodlar oluşturduğunda ya da her iş parçasının saklanması ve süreç çökerse yeniden denenmesi gerektiğinde. APScheduler işleri bir zamanlayıcıya bağlı olarak kendi programınızın içinde çalıştırır. RQ gibi bir kuyruk ise her işi Redis’te saklar ve ayrı worker’larda çalıştırır; ayrıca hesaba katmanız gereken kendi iş zaman aşımı vardır. Bu konu şurada açıklanıyor: RQ işlerinde CAPTCHA çözme rehberi.
Scheduler, CapSkip’ten farklı bir makinede çalışabilir mi?
Evet. Bağlantı ayarlarından CapSkip’i Server moduna alın; böylece loopback yerine bir ağ adresini dinler. Ardından bu adresi istemcinin host değeri olarak verin. Scheduler bundan sonra porta ulaşabilen her makineden onu aynı HTTP API üzerinden çağırır. Porta ulaşmaması gereken adresler için bir Windows Firewall engelleme kuralı ekleyin. Çözücü yine sizin sahip olduğunuz donanımda çalışır ve hiçbir çözüm üçüncü taraf bir hizmetten geçmez.
Kısa özet
Bir APScheduler CAPTCHA işi, çözümün kendisinden fazlasına ihtiyaç duyar. SDK’nın HTTP çağrılarına bir zaman aşımı verin, çünkü max_instances 1 iken takılı kalan tek bir çözüm sonraki tüm çalıştırmaları atlatır. misfire_grace_time değerini None yapın ve coalesce seçeneğini açık tutun; böylece geç kalan çalıştırmalar düşürülmek yerine bir kez gerçekleşir. Thread havuzunu işlerinize göre boyutlandırın, CapSkipError’ı işin içinde yakalayın ve Windows’ta Python 3.13 veya daha eskisinde scheduler’ı Ctrl+C ile durduruyorsanız bir uyku döngüsüyle BackgroundScheduler kullanın. APScheduler 3.x kullanıcı rehberi burada kullanılan her seçeneği belgeliyor.
- Python paketinin desteklediği tüm CAPTCHA türleri: Python CAPTCHA çözücü sayfası.
- Onay kutulu reCAPTCHA’nın nasıl çalıştığı ve çözücünün neleri kapsadığı: reCAPTCHA v2 çözücü sayfası.
On dakikada bir çalışan bir iş, ayda dört binden fazla çözüm yapar. Bunları kendi Windows makinenizde çalışan bir captcha çözücü üzerinden yürütmek, bu sayının asla bir faturaya dönüşmemesi demektir.
