Görsel CAPTCHA gönderirken ERROR_UPLOAD nasıl düzeltilir

ERROR_UPLOAD, çözücüye kullanılabilir hiçbir görsel verisinin ulaşmadığı anlamına gelir. İsteğin kendisi sorunsuzdu ve API anahtarı da sorunsuzdu, ancak resmi taşıması gereken kısım boş geldi ya da hiç gelmedi. Girişte ters gidebilecek her şeyi kapsayan dört koddan biridir ve dördü de sizin tarafınızdan bakıldığında aynı göründüğü için birbirine karıştırılması kolaydır. Bu yazı bunları birbirinden ayırır, gerçek sınırları verir ve bunların hiçbirine takılmayan yükleme kodunu gösterir.
Neye ihtiyacınız var
- CapSkip'in çalışıyor olması gerekir; loopback adresinde Local modda ya da kodunuzun ulaşabileceği bir makinede Server modda. Her ikisi de bağlantı ayarları altında anlatılır ve seçim aşağıdaki hatalar konusunda hiçbir şeyi değiştirmez.
- SDK'sı kurulu Python 3.10 veya daha yenisi, ya da uç noktaya doğrudan istek atmayı tercih ediyorsanız curl.
- Diske kaydedilmiş gerçek bir CAPTCHA görseli. Tüm sayfanın ekran görüntüsü yanlış bir test senaryosudur ve sizi hatayı değil boyut sınırını kovalamaya iter.
Her görsel hata kodu ne anlama gelir
Bunlar, görsel gönderimleri için API'nin döndürdüğü kodlardır; doğrudan CapSkip API dokümantasyonundan alınmıştır. Önce anlam sütununu okuyun, çünkü bunları birbirinden ayıran şey ne kadar kötü olduğu değil, hatanın nerede gerçekleştiğidir.
| Kod | Ne anlama geldiği | Sorunun nerede olduğu |
|---|---|---|
| ERROR_UPLOAD | Görsel verisi sağlanmadı ya da yükleme başarısız oldu | İstek gövdesi. Kullanılabilir hiçbir şey ulaşmadı |
| ERROR_INVALID_IMAGE | Geçersiz görsel biçimi ya da bozuk görsel verisi | Baytlar ulaştı ama görsel olarak çözülmüyor |
| ERROR_INVALID_BASE64 | Geçersiz base64 kodlaması | Dize baytlara hiç dönüştürülemedi |
| ERROR_TOO_BIG_CAPTCHA_FILESIZE | 600 kB'nin üzerinde ya da bir boyutta 1000px'in üzerinde | Görsel gerçek ve geçerli, sadece çok büyük |
| ERROR_BAD_PARAMETERS | Eksik ya da geçersiz zorunlu parametreler | Görselin çevresindeki form alanları |
API'ye hiç ulaşmayan beşinci bir hata türü de vardır. SDK'ya var olmayan bir yol verirseniz, istek bile göndermeden dosyanın adını belirten bir ValidationException fırlatır. Bu ayrımı erkenden kavramakta fayda var: bir Python istisnası kendi makinenizin isteği durdurduğu, ERROR ile başlayan bir kod ise çözücünün durdurduğu anlamına gelir.
1. adım: görseli API'nin kabul ettiği biçimde gönderin
SDK üç girdi biçimini kabul eder ve hepsini aynı gönderime dönüştürür: yerel bir yol, uzak bir URL ya da görseli satır içinde taşıyan bir data URI.
# pip install capskip
from capskip import CapSkip
solver = CapSkip(host="127.0.0.1", port=8080)
# All three of these are accepted by the same method.
result = solver.normal("captcha.png")
result = solver.normal("https://example.com/captcha.jpg")
result = solver.normal("data:image/png;base64,iVBORw0KGgo...")
print(result["code"]) # the recognized textGöreli bir yol yerine mutlak bir yol kullanın. Göreli bir yol, sürecin çalışma dizinine göre çözümlenir; bu da nadiren kodu yazdığınız dizindir ve editörünüzde çalışan bir betiğin bir zamanlayıcı ya da servis altında başarısız olmasının en yaygın nedeni budur.
Ham HTTP API'sinde görseli taşımanın iki yolu vardır ve ERROR_UPLOAD'ı en sık üreten şey yanlış alanı seçmektir. Multipart dosyanın kendisini gönderir, base64 ise onu bir dize olarak gönderir.
# no install needed, curl only # method=post carries the file as multipart/form-data curl -X POST "http://127.0.0.1:8080/in.php" \ -F "key=capskip" \ -F "method=post" \ -F "[email protected]" # method=base64 carries the same image as a string curl -X POST "http://127.0.0.1:8080/in.php" \ -d "key=capskip" \ -d "method=base64" \ --data-urlencode "body=BASE64_STRING_HERE"
Alan adlarına dikkat edin. Multipart yönteminde görsel file adlı alana, base64 yönteminde ise body adlı alana gider. Dosyayı body alanına göndermek ya da curl'e dosyayı okumasını söyleyen @ işaretini düşürüp adını düz metin olarak göndermek, ikisi de içinde görsel olmayan bir yükleme üretir.
2. adım: ERROR_INVALID_BASE64 hatasını düzeltin
Base64 hataları neredeyse her zaman satır kaydırmadan kaynaklanır. GNU coreutils çıktısını varsayılan olarak 76 karakterde kaydırır ve bu satır sonları isteğe kadar hayatta kalır; bu yüzden komut satırında kodlarken kaydırma genişliğini sıfır verin. Kodlayıcılar bu konuda birbirinden ayrılır, bazıları hiç kaydırma yapmaz, bu da kodlamayı komut satırında değil kod içinde yapmanın gerekçesidir.
SDK ile ham API arasında geçiş yapanları yakalayan bir ayrım daha var. SDK, öneki dahil tam bir data URI kabul eder. Ham uç noktadaki body parametresi ise önünde önek olmadan yalnız başına base64 verisini ister.
# pip install capskip
import base64
with open("captcha.png", "rb") as fh:
raw = base64.b64encode(fh.read()).decode()
# One continuous string. No newlines, no spaces, no truncation.
assert "\n" not in raw and len(raw) > 50
# The SDK wants the prefix, the raw body parameter does not.
result = solver.normal("data:image/png;base64," + raw)Bu uzunluk kontrolü göründüğünden daha önemlidir. Yaklaşık elli karakterden kısa bir base64 dizesi görsel verisi değil dosya yolu olarak okunur; bu yüzden kesilmiş bir veri hiç bozuk base64 hatası olarak başarısız olmaz. Eksik dosya hatası olarak başarısız olur ve bu da sizi yanlış yere baktırır.
3. adım: ERROR_TOO_BIG_CAPTCHA_FILESIZE hatasını düzeltin
Bu hata belirsiz bir kural yerine yayınlanmış rakamlara dayanır. API, 600 kB'nin üzerindeki bir görseli reddeder ve herhangi bir boyutta 1000px'i aşan bir görseli de reddeder. Her iki sınır da gerçek bir CAPTCHA için gayet cömerttir; bu yüzden ikisinden birine takılmak genellikle widget yerine tam sayfa ekran görüntüsünün gönderildiği anlamına gelir.
CAPTCHA'ya kırpmak daha iyi bir çözümdür, çünkü aynı zamanda doğruluğu da artırır. Güvenilir şekilde kırpamadığınız durumlar için küçültme yedek çözümdür.
# pip install capskip pillow
from PIL import Image
img = Image.open("captcha.png")
# Bring the longest side under the documented 1000px ceiling.
if max(img.size) > 1000:
img.thumbnail((1000, 1000))
# optimize=True usually clears the 600 kB limit on its own.
img.save("captcha-ready.png", optimize=True)4. adım: ERROR_INVALID_IMAGE hatasını düzeltin
Bu kod, baytların sağlam şekilde ulaştığı ama bir görsel olmadığı anlamına gelir. Uygulamada bunun baskın tek bir nedeni vardır. CAPTCHA'yı bir HTTP istemcisiyle indirdiniz, sunucu bir hata sayfası ya da yönlendirmeyle yanıt verdi ve kodunuz içine hiç bakmadan yanıt gövdesini .png ile biten bir dosyaya kaydetti. Dosya gerçek, boyutu makul görünüyor ve ilk dört bayt HTML.
# no install needed, standard library only
SIGNATURES = (b"\x89PNG", b"\xff\xd8\xff", b"GIF8", b"RIFF")
with open("captcha.png", "rb") as fh:
head = fh.read(4)
# An error page saved as .png starts with <!DO or <htm instead.
print(any(head.startswith(sig) for sig in SIGNATURES))Bu kontrolü çözüm anında değil indirme anında çalıştırın. Dört baytlık bir okuma bedavadır ve kafa karıştıran bir çözücü hatasını, ağ hatasının gerçekten meydana geldiği noktada bariz bir ağ hatasına dönüştürür.
Tam çalışan örnek
Dört düzeltmeyi bir araya getirmek, göndermeden önce doğrulama yapan ve makinenizin fırlattığı hataları çözücünün döndürdüğü hatalardan ayrı tutan bir fonksiyon ortaya çıkarır.
# pip install capskip pillow
from PIL import Image
from capskip import CapSkip, ApiException, ValidationException
solver = CapSkip(host="127.0.0.1", port=8080, defaultTimeout=120)
def solve_image(path):
"""Return the CAPTCHA text, or None with a reason printed."""
img = Image.open(path) # raises if it is not an image
if max(img.size) > 1000:
img.thumbnail((1000, 1000))
img.save(path, optimize=True)
try:
return solver.normal(path)["code"]
except ValidationException as exc:
print("never left this machine:", exc)
except ApiException as exc:
print("the solver rejected it:", exc)
return NoneGörseli önce Pillow ile açmak dört koddan ikisini tek bir yerel istisnada birleştirir, çünkü burada açılamayan bir dosya zaten orada da çözülemeyecekti. Bundan sonra API'ye ulaşan şey, bilinen iyi bir boyutta bilinen iyi bir görseldir.
Eklenmemesi gereken bir şey: proxy. Proxy'ler reCAPTCHA, Turnstile, GeeTest ve CaptchaFox için desteklenir, görsel CAPTCHA'lar için desteklenmez. Bir proxy göndermek sessizce yok sayılmaz, bir parametre hatasıdır; bu yüzden çağrıyı doğrudan başarısız kılar.
Çözücüyü onun yerine bir sunucuda çalıştırmak
Görsel yüklemeleri, isteğin gerçek bir veri yükü taşıdığı tek CAPTCHA türüdür; bu yüzden bu verinin nereye gittiğini bilmekte fayda var. CapSkip iki düzenleme sunar:
| Mod | Dinlediği adres | Ne zaman kullanılır |
|---|---|---|
| Yerel | 127.0.0.1, yalnızca o cihaz | Betiğiniz ve çözücü tek bir makinede çalışır |
| Sunucu | Ağ adresiniz veya genel IP'niz | Worker'lar, bir VPS veya barındırılan bir platform API üzerinden çağrı yapar |
Server modunda SDK'nın adresini çözücü makineye yöneltirsiniz ve kodunuzda başka hiçbir şey değişmez; böylece bir işçi havuzu tek bir örneği paylaşabilir. Çağıranlar kendi ağınızın dışında yer alıyorsa statik bir genel IP önerilir. Ayrıntılar bağlantı ayarları altında yer alır ve Server modu yine sizin donanımınızdır, yine ölçümsüzdür: çözücünün nerede çalıştığını değiştirir, ama onu kimin sahiplendiğini ya da nasıl faturalandığını asla değiştirmez.
FAQ
CapSkip'in kabul ettiği maksimum görsel boyutu nedir?
600 kB ve her iki boyutta da 1000px. İkisinden birini aşarsanız kısmi bir çözüm yerine ERROR_TOO_BIG_CAPTCHA_FILESIZE alırsınız. Her iki sayı da API referans sayfasında yayınlanmıştır ve ikisi de gerçek bir CAPTCHA görselinin epey üzerindedir; bu yüzden bunlara takılmayı, sayfadan istediğinizden fazlasını gönderdiğinizin işareti olarak görün.
Aynı görsel neden yerelde çalışıyor ama sunucumda başarısız oluyor?
Genellikle sorun görsel değil yoldur. Göreli bir yol, sürecin başlatıldığı çalışma dizinine göre çözümlenir ve bir servis ya da zamanlanmış görev nadiren düşündüğünüz yerde başlar. Mutlak bir yol kullanın, ardından dosyanın sürecin çalıştığı hesap tarafından okunabilir olduğunu kontrol edin. Çözücünün kendisi başka bir makinedeyse, host ve portun loopback yerine gerçekten ona işaret ettiğini doğrulayın.
Görsel CAPTCHA'ları çözerken proxy kullanabilir miyim?
Hayır. Proxy desteği, çözücünün sayfayı kendisinin yüklediği türler olan reCAPTCHA, Turnstile, GeeTest ve CaptchaFox'u kapsar. Görsel CAPTCHA ise zaten elinizde bulunan baytlardır; bu yüzden proxy'nin yapabileceği bir şey yoktur ve parametre yok sayılmak yerine reddedilir.
Bir görsel CAPTCHA ne kadar sürmeli?
Normal işleyişte bir saniyenin epey altında. Görsel işler için polling zaman aşımı varsayılan olarak 120 saniyedir; bu bir beklenti değil bir güvenlik ağıdır ve SDK, polling işlemine çeyrek saniyede başlayıp oradan yavaşlar. Milisaniyeler yerine saniyelerce bekliyorsanız, asıl merak edilmesi gereken şey çözücünün ne yaptığıdır, zaman aşımınızın yeterince uzun olup olmadığı değil.
En kısa hâli
Herhangi bir şeyi değiştirmeden önce hangi tarafın başarısız olduğunu belirleyin. Bir Python istisnası, görselin hiç makinenizden çıkmadığı anlamına gelir; ERROR ile başlayan bir kod ise görselin ulaştığı ve reddedildiği anlamına gelir. Ardından kodu eşleştirin: hiçbir şey ulaşmadıysa ERROR_UPLOAD'dır, ulaştı ama çözülmüyorsa ERROR_INVALID_IMAGE'dir, dize çözülmüyorsa ERROR_INVALID_BASE64'tür ve çok büyükse 600 kB'yi ya da 1000px'i aşmış demektir. Baytları indirme anında doğrulayın, bunların çoğu böylece hiç yaşanmaz. Temiz bir yüklemeden sonra başarısız bir çözüm ise farklı bir sorundur; bu konu ERROR_CAPTCHA_UNSOLVABLE rehberinde ele alınır. Parametrelerin kendisi için ise görsel CAPTCHA çözücü sayfası referanstır, Python'a özgü ayrıntılar ise Python CAPTCHA çözücü sayfasında yer alır. Ekonomi de burada yardımcı oluyor: sınırsız captcha çözücü kapasitesinin kendi donanımınızda olması, kötü bir yüklemeden sonraki bir yeniden denemenin yalnızca yeniden denemenin kendisi kadar maliyete mal olduğu anlamına gelir.
