Windows’ta SQLite ile Huey Görevlerinde CAPTCHA Nasıl Çözülür

huey captcha - How to Solve CAPTCHAs in Huey Tasks With SQLite on Windows

Huey’de CAPTCHA çözmek için kuyruğu görev modülünüzün yanındaki bir SqliteHuey dosyasında tutun, CapSkip’i yeniden denemeleri olan bir görevin içinde çağırın ve consumer’ı thread worker’larıyla başlatın. Windows’ta bütün yığın bundan ibarettir: tek bir SQLite dosyası, Redis sunucusu yok ve aynı bilgisayarda çözücü. Bu huey captcha kurulumunun dört tuzağı var ve bu rehber her birini ele alıyor. Consumer, huey_consumer.py değil, bir exe dosyasıdır. Huey’in timeout seçeneği thread worker’larında hiçbir şey yapmaz, bu yüzden takılı kalan tek bir çözüm bir worker’ı sonsuza kadar meşgul eder. Varsayılan ayarlarla bir sonucu okumak, Huey hâlâ yeniden denerken ilk başarısız denemeyi bildirir. Ayrıca CancelExecution ilk argüman olarak retry alır; bu yüzden yeniden denemeyi durdurmanın akla gelen ilk yolu, bunun yerine sonsuza kadar yeniden denemeye yol açabilir.

Neye ihtiyacınız var

  • reCAPTCHA çözücüsü açık hâlde bir Windows makinesinde çalışan CapSkip.
  • Python 3.10 veya üzeri; CapSkip SDK’sının alt sınırı budur. Huey 3.4.0 kendisi için bir minimum sürüm belirtmez. Aşağıdaki her şey huey 3.4.0 ve capskip 1.3.0 ile Python 3.13.7 ve 3.14.0 üzerinde çalıştırıldı.
  • Redis gerekmez. SqliteHuey kuyruğu, zamanlamayı, kilitleri ve sonuçları tek bir SQLite dosyasında tutar.
  • Çö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 consumer onu API üzerinden çağırabilir. İkisi de şurada ayarlanır: bağlantı ayarları.

1. Adım: Huey’i ve CapSkip SDK’sını kurun

Proje klasörünüzde bir sanal ortam oluşturun ve üç paket kurun. requests paketi, tam örnekte giriş sayfasını çekmek ve formu göndermek için, ilerideki zaman aşımı düzeltmesinde de kullanılır.

# Windows, in PowerShell or cmd: a virtual environment in your project folder
python -m venv .venv
.venv\Scripts\python -m pip install huey capskip requests

2. Adım: kuyruğu ve çözücü istemcisini oluşturun

Huey’in ihtiyaç duyduğu her şey tasks.py dosyasında bulunur. Consumer görevleri bulmak için bu dosyayı import eder; kuyruğa iş ekleyen her betik de onu import eder.

# tasks.py
import os
from pathlib import Path

from capskip import CapSkip
from huey import SqliteHuey

# The whole queue is one SQLite file. Keep it next to this module, so the
# consumer and every script that imports tasks use the same file, whatever
# folder they are started from.
huey = SqliteHuey(
    "captcha",
    filename=str(Path(__file__).with_name("huey.db")),
    store_intermediate_errors=False,  # get() waits for the last retry
)

# Local mode: CapSkip on this PC. Server mode: set CAPSKIP_HOST (and
# CAPSKIP_API_KEY if key validation is on) to reach it on another machine.
solver = CapSkip(
    apiKey=os.environ.get("CAPSKIP_API_KEY", "capskip"),
    host=os.environ.get("CAPSKIP_HOST", "127.0.0.1"),
    port=int(os.environ.get("CAPSKIP_PORT", "8080")),
)

Veritabanı dosyasını yukarıdaki gibi tam bir yolla adlandırın. Varsayılan dosya adı, süreç hangi klasörden başlatıldıysa oradaki huey.db dosyasıdır. Bu durumda başka bir klasörden başlatılan bir betik kendi boş huey.db dosyasını oluşturur, görevini oraya ekler ve hiç gelmeyecek bir sonucu bekler. Dosyayı tasks.py dosyasının yanına sabitlemek her sürece aynı kuyruğu verir. Consumer çalışırken yanında huey.db-wal ve huey.db-shm adlı iki yardımcı dosya durur. Bunlar SQLite’ın write-ahead log’una (WAL) aittir, normaldir ve sert bir durdurmadan sonra yerinde kalabilir.

SQLite yükü hatasız kaldırdı. On iki worker ve aralarında 600 görevi kuyruğa ekleyen üç betik, veritabanının kilitli olduğunu söyleyen tek bir hata bile almadı. Her sürecin içinde Huey tek bir bağlantıyı bir kilidin arkasında paylaşır; süreçler arasında ise SQLite dosya için 5 saniyeye kadar bekler. Dosya hakkında bilinmesi gereken bir şey var: görev argümanları ve sonuçlar pickle ile düz bayt olarak dosyaya yazılır. Argüman olarak verilen bir parola tabloda okunabiliyordu; bu yüzden gizli bilgileri görev argümanlarında değil, ortamda ya da tasks.py içinde tutun.

3. Adım: Huey CAPTCHA görevini yazın ve neyin yeniden deneneceğini seçin

Bir Huey görevinin fırlattığı her istisna bir yeniden deneme hakkını tüketir. Bu, bazı CapSkip hataları için doğru, bazıları için ise israftır; bu yüzden görev onları ayırır.

from capskip import ApiException, ValidationException
from huey import CancelExecution


# Any exception uses one of the two retries, 15 s apart: NetworkException
# when CapSkip is not running, TimeoutException, an unsolvable task.
@huey.task(retries=2, retry_delay=15)
def solve_recaptcha(sitekey, page_url):
    try:
        return solver.recaptcha(sitekey=sitekey, url=page_url)["code"]
    except (ApiException, ValidationException) as exc:
        if "ERROR_CAPTCHA_UNSOLVABLE" in str(exc):
            raise  # this attempt failed; a fresh one may not
        # ERROR_GOOGLEKEY, ERROR_PAGEURL, ERROR_BAD_PARAMETERS and
        # ERROR_KEY_DOES_NOT_EXIST fail the same way on every attempt.
        # CancelExecution's first argument is retry: False ends the task now.
        raise CancelExecution(False, f"{type(exc).__name__}: {exc}") from exc

Üç hata yeni bir denemeye değer: CapSkip henüz çalışmıyorken gelen bir NetworkException, bir TimeoutException ve CapSkip’in bu sefer işe yaramayan bir çözümü bildirme biçimi olan ERROR_CAPTCHA_UNSOLVABLE. Consumer hatayı traceback’iyle birlikte loglar, ardından görevi kalan yeniden deneme sayısıyla birlikte yeniden kuyruğa aldığını söyleyen bir satır yazar. Bizim çalıştırmalarımızda 15 saniyelik bir retry_delay ile bir sonraki deneme, hatadan 16.1 saniye sonra başladı.

Hatalı biçimlendirilmiş bir sitekey, http ya da https içermeyen bir sayfa URL’si veya (anahtar doğrulaması açıkken) yanlış bir API anahtarı, herhangi bir çözüm başlamadan ERROR_GOOGLEKEY, ERROR_PAGEURL ya da ERROR_KEY_DOES_NOT_EXIST ile reddedilir. Boş bir sitekey ya da sayfa URL’si ERROR_BAD_PARAMETERS alır. Bunlar her seferinde aynı şekilde başarısız olur, bu yüzden yeniden denemek yalnızca zaman kaybettirir. Huey’in CancelExecution istisnası bir görevi yalnızca retry False olduğunda yeniden denemeden sonlandırır. Argümansız fırlatıldığında, görevin yeniden deneme hakkı kaldıkça yine yeniden dener. İmzasını da okuyun: ilk konumsal argümanı mesaj değil, retry’dır. Yalnızca bir mesajla CancelExecution şeklinde yazıldığında mesaj retry değeri olur ve true sayılır. Log bu durumda görevin yeniden deneneceğini söyler ve görev, siz consumer’ı durdurana kadar tekrar tekrar çalışır. Mesajı retry=False ile birlikte vermek bir TypeError fırlatır, çünkü retry bu durumda iki değer almış olur. Koddaki gibi önce False verin. Consumer bu durumda görevin CancelExecution fırlattığını ve yeniden denenmeyeceğini söyleyen bir WARNING loglar.

Bu ayrımın bir sınırı var: Google’ın kendisinin reddettiği bir sitekey size yine ERROR_CAPTCHA_UNSOLVABLE olarak ulaşır, çünkü CapSkip başarısız her çözümü bu şekilde bildirir. Bu durum, başarısız olmadan önce üç denemeye mal olur. Bir sayfa her seferinde başarısız oluyorsa önce sitekey’ini kontrol edin.

4. Adım: consumer’ı Windows’ta başlatın

Consumer’ı tasks.py dosyasının bulunduğu klasörden çalıştırın. Exe dosyasını yoluyla çağırdığınızda sanal ortamı etkinleştirmeniz gerekmez.

# In the folder that holds tasks.py, in PowerShell or cmd
.venv\Scripts\huey_consumer tasks.huey -w 4

Eski rehberler ve consumer’ın kendi kullanım ipucu huey_consumer.py der. Huey 3 yalnızca huey_consumer.exe kurar, bu yüzden o ad hem PowerShell’de hem de cmd’de tanınmadığını söyleyen bir mesajla başarısız olur. Yukarıdaki komut ikisinde de çalışır, .venv\Scripts\python -m huey.bin.huey_consumer tasks.huey de öyle. Başka bir klasörden başlatılan consumer, Error importing tasks.huey hatası ve ModuleNotFoundError: No module named tasks ile durur, çünkü arama yoluna yalnızca geçerli klasörü ekler.

Windows’ta tek gerçek seçenek thread worker’larıdır. -k process ile consumer, huey cannot be run in process-mode on Windows diyen bir hatayla hemen çıkar, çünkü process worker’ları Windows’ta bulunmayan fork() çağrısına ihtiyaç duyar. Greenlet worker’ları için gevent’in kurulu olması gerekir. Thread’ler zaten bu işe uygundur, çünkü bir worker bir çözümün neredeyse tamamını CapSkip’i bekleyerek geçirir.

Her worker kendi isteğini gönderir, bu yüzden worker sayısı aynı zamanda CapSkip’in aynı anda aldığı çözüm sayısıdır. 12 worker ve kuyrukta bekleyen 12 görevle 12 isteğin tamamı 30 milisaniye içinde CapSkip’e ulaştı. CapSkip’in reCAPTCHA bölümü varsayılan olarak aynı anda 10 çözüm çalıştırır (Max. Threads ayarı) ve geri kalanını sıraya alır. Birkaç giriş için dört worker yeterlidir. Kuyruk uzun olduğunda -w değerini bu sınıra doğru yükseltin.

5. Adım: bir çözümü kuyruğa ekleyin ve sonucu bir kez okuyun

Görevi çağırmak onu çalıştırmaz. Çağrı görevi kuyruğa yazar ve üzerinde bekleyebileceğiniz bir Result tanıtıcısı (handle) döndürür.

# enqueue.py, next to tasks.py: .venv\Scripts\python enqueue.py
from huey.exceptions import ResultTimeout, TaskException

from tasks import huey, solve_recaptcha

result = solve_recaptcha("YOUR_SITEKEY", "https://example.com/login")
try:
    # Three attempts of up to about 5.5 minutes each, plus two 15 s delays.
    token = result.get(blocking=True, timeout=1100)
except TaskException as exc:
    print("solve failed:", exc)
except ResultTimeout:
    print("no result yet: is the consumer running?")
else:
    print("token:", token[:30], "...")
    # Reading the result deleted it from huey.db. This handle keeps its
    # copy, but a new handle for the same task id finds nothing.
    print("read again:", huey.result(result.id))  # None

1100 saniyelik bekleme en kötü durumu kapsar: her biri SDK’nın sınırına kadar süren üç deneme ve iki yeniden deneme gecikmesi. Başarısız bir görev, mesajı son hata olan ve meta verisinde kalan yeniden deneme sayısıyla traceback’i tutan bir TaskException fırlatır. Zamanında hiçbir şey yanıt vermezse ResultTimeout alırsınız; bu genellikle consumer’ın çalışmadığı ya da başka bir veritabanı dosyası kullandığı anlamına gelir.

2. adımdaki store_intermediate_errors satırı burada önemlidir. Huey’in varsayılan ayarıyla her başarısız deneme sonuç olarak saklanır. Testimizde get(), Huey yeniden denemeyi çalıştırırken ilk hatadan sonra TaskException fırlattı. Yeniden denemenin sonucu ancak tanıtıcı üzerinde reset() çağrıldıktan sonra görünür oldu. Bu ayar kapatıldığında get() son denemeyi bekler.

Bir sonuç yalnızca bir kez okunabilir. Onu okumak, CapSkip’in kendi yanıtlarıyla yaptığı gibi, sonucu dosyadan siler. Onu okuyan tanıtıcı kendi kopyasını saklar, ancak aynı görev kimliğiyle çağrılan huey.result() bundan sonra None döndürür. Kodunuzun iki farklı kısmı bu değere ihtiyaç duyuyorsa get() çağrısına preserve=True verin. None döndüren bir görev hiçbir şey saklamaz, bu yüzden onu beklemek ResultTimeout ile sona erer.

Takılı kalan bir çözüm neden kendi zaman aşımına ihtiyaç duyar

Huey 3 bir görevde timeout seçeneğini kabul eder, ancak thread worker’larında bu seçenek hiçbir şey yapmaz. Bir thread dışarıdan kesilemez, bu yüzden Huey bu süreyi ancak görevin kendisi task.check_timeout() çağırırsa kontrol eder. timeout=2 ayarlı ve beş saniye uyuyan bir görev normal şekilde tamamlandı. Zaman aşımının uygulanabileceği process worker’ları ise Windows’ta reddedilir.

Bu önemlidir, çünkü CapSkip SDK’sı isteklerinde hiçbir HTTP zaman aşımı ayarlamaz. CapSkip bir bağlantıyı kabul edip hiç yanıt vermezse çağrı sonsuza kadar bekler. Testimizde iki worker tek bir log satırı bile yazmadan bu durumda kaldı ve arkalarında kuyrukta bekleyen görevler hiç başlamadı. Çözücü düzeldikten 45 saniye sonra da hâlâ takılıydılar. Düzeltme, SDK’nın HTTP çağrılarına bir zaman aşımı vermektir. Bunu tasks.py dosyasına, modül düzeyinde koyun; böylece herhangi bir çözümden önce çalışır.

import functools
import types

import requests
import capskip.api

# capskip 1.3.0 calls requests.post/get with no timeout, and Huey cannot stop
# a thread worker that is stuck in one. Give every SDK call 5 s to connect
# and 30 s to answer. Module level in tasks.py, so it runs before any solve.
capskip.api.requests = types.SimpleNamespace(
    RequestException=requests.RequestException,
    post=functools.partial(requests.post, timeout=(5, 30)),
    get=functools.partial(requests.get, timeout=(5, 30)),
)

Bu kodla birlikte takılan bir gönderim 30.0 saniye sonra NetworkException fırlattı ve görev yeniden denendi. Takılan bir durum kontrolü daha uzun sürer, çünkü SDK başarısız bir yoklamayı henüz hazır değil olarak yorumlar ve kendi 300 saniyelik recaptchaTimeout süresi dolana kadar yoklamaya devam eder. O deneme yaklaşık 333 saniye sonra TimeoutException ile sona erdi ve yeniden denemede çözüm başarılı oldu. Her iki durumda da worker yeniden boşa çıkar. Düzeltme, SDK’nın iç parçalarından biri olan capskip.api içindeki requests referansını değiştirir, bu yüzden capskip’i yükselttiğinizde onu yeniden kontrol edin.

Kendisiyle çakışamayan zamanlanmış bir çözüm

Periyodik bir görev, örneğin bir girişi taze tutmak için, bir çözümü bir zamanlayıcıyla tekrarlayabilir. Aşağıdaki tam örnek gerçek girişi yapar. Periyodik görevler argüman almaz, bu yüzden sitekey ve URL fonksiyonun içinde durur.

from huey import crontab


# Every 15 minutes. The lock goes under periodic_task: when a run is due
# while the previous one is still solving, another worker skips it instead
# of starting a second solve for the same login.
@huey.periodic_task(crontab(minute="*/15"))
@huey.lock_task("login")
def refresh_login():
    result = solver.recaptcha(sitekey="YOUR_SITEKEY", url="https://example.com/login")
    print("new token:", result["code"][:30], "...")

Consumer periyodik görevlerini başlarken bir kez, ardından bu başlangıçtan itibaren sayılan her 60 saniyede bir kontrol eder. Dolayısıyla içinde bulunulan dakikada zamanı gelen bir çalıştırma hemen başlar. Bir çözüm aralıktan uzun sürerse Huey yine de sonraki çalıştırmayı kuyruğa ekler. Birkaç worker varsa boşta olan bir worker, ilk çalıştırma hâlâ çözerken onu başlatırdı. Kilit bunu engeller: yeni çalıştırma, kilidi alamadığı için çalıştırılmadığını söyleyen bir WARNING loglar ve atlanır. Tek worker ile hiçbir şey çakışmaz, ancak geç kalan çalıştırmalar kuyrukta birikir ve sonra art arda yürütülür. Çok uzun bekleyen çalıştırmaları düşürmek için periodic_task dekoratörüne saniye cinsinden bir expires argümanı ekleyin, örneğin expires=600.

Kilitler veritabanı dosyasında durur, bu yüzden bir çökmeden sağ çıkarlar. Sert bir durdurmadan sonra geride kalan bir kilit, sonraki her çalıştırmanın atlanmasına yol açar. Dekoratör kilitlerini temizlemek için consumer’ı -f ile başlatın; consumer eskimiş kilitler bulduğunu loglar. Huey 3.4, lock_task dekoratörüne bir ttl seçeneği de ekledi, ancak SqliteHuey bunu desteklemez ve kilit alındığında NotImplementedError fırlatır.

Tam Huey CAPTCHA görev dosyası

Bu sürüm giriş sayfasını çeker, sitekey’i ve CSRF token’ını okur, CAPTCHA’yı gönderimden hemen önce çözer ve formu bir Referer başlığıyla gönderir. Girişi talep üzerine log_in olarak, zamanlanmış şekilde de scheduled_login olarak sunar. İkisi tek bir kilidi paylaşır, bu yüzden aynı hesap için asla aynı anda çözüm yapmazlar. URL’yi ve kimlik bilgilerini değiştirin, ardından consumer’ı -f ile başlatın.

# tasks.py: pip install huey capskip requests
# Start: .venv\Scripts\huey_consumer tasks.huey -w 4 -f
import functools
import logging
import os
import re
import types
from pathlib import Path

import requests
import capskip.api
from capskip import ApiException, CapSkip, ValidationException
from huey import CancelExecution, SqliteHuey, crontab

LOGIN_URL = "https://example.com/login"
USERNAME, PASSWORD = "YOUR_USERNAME", "YOUR_PASSWORD"

huey = SqliteHuey(
    "captcha",
    filename=str(Path(__file__).with_name("huey.db")),  # same file from any folder
    store_intermediate_errors=False,  # get() waits for the last retry
)
log = logging.getLogger("huey.captcha")  # printed by the consumer

# The SDK's HTTP calls have no timeout; give them one so a stuck CapSkip
# cannot hold a worker thread forever.
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(
    apiKey=os.environ.get("CAPSKIP_API_KEY", "capskip"),
    host=os.environ.get("CAPSKIP_HOST", "127.0.0.1"),
    port=int(os.environ.get("CAPSKIP_PORT", "8080")),
)


def solve(sitekey, page_url):
    try:
        return solver.recaptcha(sitekey=sitekey, url=page_url)["code"]
    except (ApiException, ValidationException) as exc:
        if "ERROR_CAPTCHA_UNSOLVABLE" in str(exc):
            raise  # worth another attempt
        # A refused sitekey, page URL or API key fails the same way every time.
        log.error("not retrying: %s: %s", type(exc).__name__, exc)
        raise CancelExecution(False, f"{type(exc).__name__}: {exc}") from exc


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="([^"]+)"')
        csrf = field(page.text, r'name="csrfmiddlewaretoken" value="([^"]+)"')
        token = solve(sitekey, LOGIN_URL)  # solve right before the post
        reply = session.post(LOGIN_URL, timeout=30, headers={"Referer": LOGIN_URL}, data={
            "csrfmiddlewaretoken": csrf,
            "username": USERNAME,
            "password": PASSWORD,
            "g-recaptcha-response": token,
        })
        reply.raise_for_status()  # a refused login fails the attempt
        log.info("logged in (HTTP %s)", reply.status_code)
        return reply.status_code


# Both tasks take the same lock, so an on-demand login never runs while a
# scheduled one is solving, and the other way round.

# On demand: from tasks import log_in; log_in().get(blocking=True, timeout=1100)
@huey.task(retries=2, retry_delay=15)  # a locked attempt uses a retry
@huey.lock_task("login")
def log_in():
    return login()


# On a schedule; a run that comes due while the lock is held is skipped.
@huey.periodic_task(crontab(minute="*/15"))
@huey.lock_task("login")
def scheduled_login():
    login()

Çözüm, gönderimle aynı deneme içinde gerçekleşir; bu yüzden bir yeniden deneme her zaman taze bir sayfa çeker ve yeniden çözer. Başarısız bir denemeden asla bir token devralınmaz; bu önemlidir, çünkü Google bir reCAPTCHA token’ının iki dakika geçerli kalmasına izin verir. 403 gibi bir HTTP hatası döndüren reddedilmiş bir giriş, raise_for_status() ile denemeyi başarısız kılar ve her seferinde yeni bir sayfa ve yeni bir çözümle iki kez yeniden denenir. CapSkip çözüm başına ücret almaz, bu yüzden bunun zamandan başka bir maliyeti yoktur. Birçok site yanlış bir parolaya 200 koduyla ve formu yeniden göstererek yanıt verir; bu yüzden sitenize özgü bir kontrol ekleyin, örneğin gönderimden sonraki URL. Kilidi zamanlanmış çalıştırmanın elinde bulan talep üzerine bir log_in aynı WARNING ile atlanır ve o deneme bir yeniden deneme hakkı harcar. Aralarında 15 saniye olan iki yeniden deneme, ona toplamda yaklaşık 30 saniyelik bir bekleme süresi verir. Zamanlanmış çözüm daha uzun sürerse üç denemenin üçü de atlanır ve get(), mesajında TaskLockedException bulunan bir TaskException fırlatır. Çözümleriniz genellikle bundan uzun sürüyorsa log_in üzerindeki retry_delay değerini yükseltin.

Başka bir betikten talep üzerine giriş yapmak için log_in’i tasks modülünden import edin, çağırın ve 5. adımdaki gibi sonucu get(blocking=True, timeout=1100) ile bekleyin. Dönüş değeri, gönderimden sonraki son HTTP durumudur. Görevin log satırları, consumer’ın penceresinde Huey’in kendi satırlarının yanında görünür.

Consumer’ı temiz bir şekilde durdurmak

Consumer’ın penceresinde Ctrl+C tuşlarına bir kez basın. Huey yeni görev almayı bırakır, çalışanları bekler ve çıkar. Bizim çalıştırmalarımızda bir çözümün ortasında durdurulan bir consumer, o çözüm biter bitmez, 18 saniye sonra çıktı. Boştaki bir consumer saniyenin onda birinden kısa sürede çıktı. İkinci bir Ctrl+C sürüme göre farklı davranır: Python 3.14 hemen çıkar, 3.13 ise çalışan görevi yine bekler; bu yüzden yukarıdaki zaman aşımı olmadan takılı kalan bir çözüm ancak süreç öldürülerek durdurulabilirdi.

Düzgün bir durdurmadan daha hızlı olan her yol, çalışmakta olan görevi kaybettirir. 3.14’te ikinci bir Ctrl+C, Ctrl+Break ve düzgün kapanma beklemesine üst sınır koyan -t seçeneği de buna dahildir: -t 5 ile consumer, Ctrl+C’den yaklaşık 5.1 saniye sonra çıktı. Kaybolan görev kuyruktan zaten çıkmıştı, bu yüzden yeniden çalışmaz ve kilidi geride kalır. Tam örneğin -f ile başlamasının nedeni budur.

CapSkip’i başka bir makinede çalıştırmak

Consumer 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. tasks.py dosyanız adresi zaten ortamdan okur, bu yüzden consumer’ı başlatmadan önce değişkenleri ayarlayın.

# PowerShell, before starting the consumer: CapSkip runs in Server mode
# on another Windows machine on your network
$env:CAPSKIP_HOST = "192.168.1.50"
$env:CAPSKIP_API_KEY = "YOUR_API_KEY"
# $env:CAPSKIP_PORT = "8080"   only if you changed the port
.venv\Scripts\huey_consumer tasks.huey -w 4 -f

Rota internetten geçiyorsa statik bir genel IP kullanın ve API anahtarı doğrulamasını açıp aynı anahtarı CAPSKIP_API_KEY içinde de verin. CapSkip, Server modu başladığında portunu her adrese açar; portu yalnızca beklediğiniz makinelere açık tutmak için diğerlerine yönelik bir Windows Firewall engelleme kuralı ekleyin. Bundan sonra consumer porta ulaşabilen herhangi bir makinede çalışabilir; çözücü ise yine çözüm başına ücretlendirme olmayan kendi Windows makinenizdir.

Sık görülen Huey CAPTCHA hataları

GördüğünüzNedenDüzeltme
huey_consumer.py tanınmıyorHuey 3 yalnızca huey_consumer.exe kurarKomutu .venv\Scripts\huey_consumer olarak çalıştırın
huey cannot be run in process-mode on WindowsProcess worker’ları fork() gerektirirVarsayılan thread worker’larını kullanın
ModuleNotFoundError: No module named tasksConsumer, tasks.py dosyasının bulunduğu klasörün dışında başlatıldıOnu o klasörden başlatın
Consumer çalıştığı hâlde ResultTimeoutBetik ve consumer farklı huey.db dosyaları kullanıyorSqliteHuey’e dosyanın tam yolunu verin
get() bir hata bildiriyor, ardından görev başarılı oluyorstore_intermediate_errors açık, bu yüzden her başarısız deneme saklanıyorstore_intermediate_errors=False ayarlayın
Durması gereken bir görev yeniden denemeye devam ediyorCancelExecution, mesajı retry argümanı olarak aldıCancelExecution(False, message) fırlatın
Worker’lar görev almayı bırakıyor ve hiçbir şey loglamıyorBir çözüm, zaman aşımı olmayan bir HTTP çağrısında takılı kaldıSDK’nın isteklerine bir zaman aşımı verin
Zamanlanmış her çalıştırma atlanıyorÖldürülen bir consumer’dan kalan eskimiş bir kilitConsumer’ı -f ile yeniden başlatın

FAQ

SqliteHuey yerine RedisHuey kullanabilir miyim?

Evet. Bu rehberdeki görevler, yeniden denemeler ve kilitler aynı şekilde çalışır. redis paketini de kurun, ardından kuyruğu SqliteHuey yerine RedisHuey ile oluşturun. Ancak RedisHuey bir Redis sunucusuna ihtiyaç duyar ve Windows bununla birlikte gelmez. CapSkip’i zaten çalıştıran bilgisayarda SQLite dosyası sizi ikinci bir servis çalıştırmaktan kurtarır. Birçok makineye yayılmış bir kuyruk içinse Redis daha uygundur; bunun bir örneğini şurada bulabilirsiniz: Celery görevlerinde CAPTCHA çözme rehberi.

Boşta geçen bir süreden sonraki ilk görev neden geç başlıyor?

Boştaki bir consumer veritabanını giderek daha seyrek kontrol eder; varsayılan olarak bu aralık 10 saniyeye kadar çıkar. Bizim çalıştırmalarımızda dört worker ile boşta geçen bir sürenin ardından gelen ilk görev 3 ile 7 saniye bekledi. Bu beklemeyi bir saniyeyle sınırlamak için consumer’ı -m 1 ile başlatın; bu durumda bekleme bir saniyenin altında kaldı.

Bu bir Django projesinde çalışır mı?

Evet, huey.contrib.djhuey üzerinden. HUEY ayarında huey_class değerini huey.SqliteHuey yapın ve bir filename belirtin, ardından consumer’ı manage.py run_huey ile başlatın. Bir varsayılan ayar insanları şaşırtır: DEBUG açıkken djhuey görevleri isteğin içinde hemen çalıştırır, bu yüzden bir çözüm CapSkip yanıt verene kadar sayfayı bekletir. Gerçek kuyruğu test etmek için HUEY ayarında immediate değerini False yapın.

Consumer, 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 consumer başlamadan önce CAPSKIP_HOST değerini bu adrese ayarlayın. Görevler 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

Windows’ta bir Huey CAPTCHA görevi için SqliteHuey dosyasını tasks.py dosyasının yanına sabitleyin, store_intermediate_errors ayarını kapatın ve yalnızca yeni bir denemenin düzeltebileceği CapSkip hatalarını yeniden deneyin; geri kalanını CancelExecution(False, message) ile sonlandırın. .venv\Scripts\huey_consumer komutunu tasks.py dosyasının bulunduğu klasörden thread worker’larıyla başlatın, SDK’nın HTTP çağrılarına bir zaman aşımı verin, her sonucu yalnızca bir kez okuyabileceğinizi unutmayın ve zamanlanmış çözümlere bir kilit koyun. Huey consumer belgeleri burada kullanılan her consumer seçeneğini listeler.

Tek bir dosyadaki kuyruk ve aynı bilgisayardaki çözücü, işin tamamını sizin kontrol ettiğiniz donanımda tutar. Yerel bir captcha atlatma yönteminin asıl amacı da budur: her yeniden deneme ücretsizdir, bu yüzden görev yeniden denemeyi göze alabilir.