Captcha solver hata yönetimi - yeniden deneme, backoff ve asla tekrarlanmaması gerekenler
Captcha çözme, değiştirme gücünüz olmayan bir sisteme, önceden haber vermeden değişebilen bir doğrulama için yapılan bir ağ çağrısıdır. Hataları iyi yönetmek, zarifçe bozulan bir pipeline ile bir yeniden deneme fırtınasında zaman kaybeden bir pipeline arasındaki farktır.
Scarnox ile ekonomi size yardım eder: başarısız çözümler ücretlendirilmez; yani bir yeniden deneme yalnızca zaman harcatır, başka bir şey değil. Ama yanlış hatayı tekrar denemek yine de o zamanı boşa harcar ve yeterince sert tekrar denemek kendi başına sorunlar yaratabilir. Bu rehber, bir Python işine yapıştırabileceğiniz bir yeniden deneme politikası verir.
Scarnox bugün PopularCaptcha'yı çözer. Aynı hata yönetimi herhangi bir captcha solver için geçerlidir; dolayısıyla aşağıdaki politika captcha türüne bağlı değildir.
Her zaman önce errorId'yi kontrol edin
Bir çözüm yanıtında errorId alanı bulunur. 0 başarıyı gösterir ve token solution.token altındadır. Başka her değer çözümün başarısız olduğu anlamına gelir. Başarısız bir yanıt ayrıca bir errorCode ve bir errorDescription taşır. İkisini de loglayın: kodu sonra aramak isteyeceksiniz, açıklamayı ise bir çalıştırma ters gittiğinde okuyacaksınız.
{"errorId": 1, "errorCode": "...", "errorDescription": "..."}
HTTP durumu 200 olduğu için bir yanıtın başarılı olduğunu varsaymayın. errorId değerini her seferinde kontrol edin.
Tekrar denenmesi gereken hatalar
Bazı hatalar geçicidir. Bunları üstel backoff ve küçük rastgele bir gecikme ile tekrar deneyin:
- Ağ hataları: bağlantı sıfırlamaları, DNS sorunları, sizin tarafınızdaki okuma zaman aşımları.
- Sunucu hataları: HTTP 5xx yanıtları; bunlar servis tarafındaki bir sorunu gösterir.
- Hız sınırlaması: HTTP 429; çok hızlı istek gönderdiğinizi gösterir. Yavaşlayın.
- Zaman aşımları: çözüm, istemcinizin beklediğinden uzun sürdü. Henüz ayarlamadıysanız daha uzun bir zaman aşımıyla tekrar deneyin.
Bu hatalar tekrar denemeye değer, çünkü bir sonraki deneme, sizin tarafınızda bir değişiklik olmadan başarılı olabilir.
Tekrar denemeden önce düzeltilmesi gereken hatalar
Diğer hatalar beklemekle geçmez. Aynı girdiyle yeniden denemek aynı şekilde başarısız olur. Önce bunları düzeltin:
- Geçersiz görev türü.
captcha_typedeğerinin dokümandaki yazımıyla birebir aynı olduğunu kontrol edin. - Yanlış ya da eksik sitekey. Sitekey'i sayfadan yeniden okuyun. Eski bir deploy'dan kalma sitekey yaygın bir sebeptir.
- Yanlış sayfa URL'si.
site_url, widget'ı gösteren sayfa olmalıdır. - Proxy sorunları. Ölü, yanlış yazılmış ya da engellenmiş bir proxy her denemeyi başarısız kılar. Proxy'yi önce tek başına test edin. Bkz. proxy mi proxysiz mi.
- Hesap sorunları. Geçersiz bir anahtar ya da gerekli bakiyesi olmayan bir hesap, biri onu düzeltene kadar her denemeyi başarısız kılar. Bir kişiyi uyarın; döngüde tekrar denemeyin.
Her iki listede de olmayan bir hata ile karşılaştığınızda, onu düzeltilmesi gereken bir hata olarak ele alın. Hata metnine bakın, karar verin ve kodu doğru listeye ekleyin. Listeleri kısa ve gözden geçirilmiş tutun.
Yapıştırabileceğiniz bir politika
import os
import random
import time
import requests
API_URL = "https://api.scarnox.com/api/tasks/create"
HEADERS = {"Authorization": f"Bearer {os.environ['SCARNOX_KEY']}"}
MAX_ATTEMPTS = 4
class SolveError(Exception):
def __init__(self, code: str, description: str, retryable: bool):
super().__init__(f"{code}: {description}")
self.code = code
self.retryable = retryable
def solve_once(payload: dict) -> str:
try:
r = requests.post(API_URL, headers=HEADERS, json=payload, timeout=185)
except requests.RequestException as exc:
# Bizim tarafımızda ağ hatası ya da zaman aşımı: yeniden denemek güvenli.
raise SolveError("NETWORK", str(exc), retryable=True)
if r.status_code == 429 or r.status_code >= 500:
raise SolveError(f"HTTP_{r.status_code}", r.text[:200], retryable=True)
try:
data = r.json()
except ValueError:
raise SolveError(f"HTTP_{r.status_code}", r.text[:200], retryable=False)
if data.get("errorId") == 0:
return data["solution"]["token"]
# API bir hata bildirdi. Yalnızca geçici olduğunu gördüğünüz kodları yeniden deneyin.
code = data.get("errorCode", "UNKNOWN")
retryable = code in TRANSIENT_CODES
raise SolveError(code, data.get("errorDescription", ""), retryable=retryable)
# API hata kodlarını yalnızca loglarınızda geçici olduklarını gördükten sonra buraya ekleyin.
TRANSIENT_CODES: set[str] = set()
def solve(payload: dict) -> str:
for attempt in range(MAX_ATTEMPTS):
try:
return solve_once(payload)
except SolveError as err:
last_attempt = attempt == MAX_ATTEMPTS - 1
if not err.retryable or last_attempt:
raise
delay = min(30, 2 ** attempt) + random.random() # bekleme süresi + rastgele gecikme (jitter)
print(f"attempt {attempt + 1} failed ({err.code}), retrying in {delay:.1f}s")
time.sleep(delay)
raise RuntimeError("unreachable")
Politika, düzeltilmesi gereken bir hatayı asla tekrar denemez ve sabit sayıda denemeden sonra durur. TRANSIENT_CODES kümesi bilerek boş başlar: bir kodu yalnızca loglarınız geçici olduğunu gösterdikten sonra ekleyin.
Neden jitter önemlidir
Elli işçi aynı anda başarısız olur ve hepsi tam iki saniye uyursa, birlikte tekrar dener ve birlikte yeniden başarısız olurlar. Rastgele bir saniye kesri onları dağıtır. Bu, büyük API sağlayıcılarının kendi istemcileri için verdiği tavsiyenin aynısıdır.
Zaman aşımları
HTTP zaman aşımınızı tipik çözme süresinin çok üzerinde, yaklaşık 185 saniyeye ayarlayın. İstek token hazır olana kadar bloke olur; bu yüzden kısa bir istemci zaman aşımı, yavaş bir başarıyı boşuna tekrar denediğiniz bir başarısızlığa çevirebilir. Çözümden uzun bir istemci zaman aşımı güvenli ayardır.
Token'lar önbelleğe alınamaz
Token yaklaşık iki dakika içinde süresi dolar. Token'ları çalıştırmalar arasında önbelleğe almayın ve ikinci bir gönderim için yeniden kullanmayın. Token kullanıldıktan sonra bir gönderim başarısız olursa, eski token'ı tekrar göndermek yerine yeniden çözün. Zamanlama ayrıntıları için token süresi rehberi bölümüne bakın.
Birden çok işçi arasında eşzamanlılık ve backoff
Birçok işçi tek bir anahtarı paylaşıyorsa, bir işçideki backoff diğerlerini yavaşlatmaz. Eşzamanlı çözümler için bir semafor ya da kuyruk gibi ortak bir sınır ekleyin; böylece yeniden denemelerin patlaması bir istek patlamasına dönüşmez. Basit bir eşzamanlılık sınırı, hız sınırı hatalarının çoğunu başlamadan önce çözer.
Yardımcı olan loglama
Başarısız her denemede errorCode değerini, deneme numarasını, sitekey'i, sayfa host'unu ve hatanın yeniden denenip denenmediğini loglayın. API anahtarını ya da proxy şifresini loglamayın. Saat başına kodları sayan bir pano, sorunun kodunuzda, proxy'de mi yoksa serviste mi olduğunu size hızla söyler.
Sonraki adımlar
- Python ile PopularCaptcha nasıl çözülür
- Proxy mi proxysiz mi: hangi görev türüne ihtiyacınız var?
- CI'yi yeşil tutmak: captcha varken
- Ücretsiz captcha solver denemesi
Yeniden denemelerinizi ücretsiz bir denemeyle test edin: hesap oluşturun ve kredi kartı gerekmeden ücretsiz deneme kredisiyle başlayın.