Go'da CAPTCHA görevlerini eşzamanlı çözün

solvethree tarafından3 dk okuma

Tek bir paylaşılan Go SDK istemcisi ve sabit bir işçi havuzu kullanın. Her işe kendi bağlamını verin; ardından token'ları sonraki bir toplu işlem için biriktirmek yerine hazır olan her çözümü hemen gönderin.

Bu sayfada

İstemciyi ve hedefi hazırlayın

  • Go 1.22 veya üzerini ve resmi solvethree.com/sdk modülünün v0.1.0 sürümünü kullanın. Kurulum ayrıntıları Go entegrasyon belgelerinde yer alır.
  • Sunucu ortamında SOLVETHREE_API_KEY ve SOLVETHREE_PROXY değişkenlerini ayarlayın. API anahtarını tarayıcı koduna dahil etmeyin.
  • accounts.example.com ve login değerlerini hedef ana makine adınız ve eyleminizle değiştirin. Çalışma alanında bu site için etkin bir profil bulunmalıdır; ana makine adını göndermek profil oluşturmaz. Site profili kurulumuna bakın.

Örnek, varsayılan olan reCAPTCHA Enterprise'ı talep eder. Tek bir proxy sağlar ve Type ile URL alanlarını bilerek ayarlamaz: reCAPTCHA istekleri bu alanları değil, sitenin ana makine adını ve eylemi kullanır.

İstemci sayısını değil, iş yükünü sınırlayın

İstemci eşzamanlı kullanım için güvenlidir. Bu örnek dört işçi başlatır ve tamponlanmamış bir kanal üzerinden onlara sekiz iş iletir. Üretici, her iş için bir goroutine başlatmak yerine tüm işçiler meşgulken bekler. Dört, örnek bir uygulama ayarıdır; solvethree hizmet sınırı değildir.

Go · dört işçi ve her işi anında işleme
package main

import (
    "context"
    "fmt"
    "log"
    "os"
    "sync"
    "time"
    solvethree "solvethree.com/sdk"
)

func main() {
    client, err := solvethree.NewClient(os.Getenv("SOLVETHREE_API_KEY"), nil)
    if err != nil { log.Fatal(err) }
    jobs := make(chan int)
    var workers sync.WaitGroup
    for worker := 0; worker < 4; worker++ {
        workers.Add(1)
        go func() {
            defer workers.Done()
            for job := range jobs {
                ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
                input := solvethree.TaskRequest{Site: "accounts.example.com", Action: "login", Proxy: os.Getenv("SOLVETHREE_PROXY")}
                result, err := client.Solve(ctx, input, solvethree.SolveOptions{})
                if err != nil { cancel(); log.Printf("Job %d: %v", job, err); continue }
                fmt.Println("Ready task:", result.ID)
                // Submit this solution now, with its proxy and browser identity.
                cancel()
            }
        }()
    }
    for job := 0; job < 8; job++ { jobs <- job }
    close(jobs)
    workers.Wait()
}

Her işçi, her iş için ayrı bir 180 saniyelik bağlam oluşturur. Solve, görevi bir kez oluşturur ve sonucunu bekler. Örnekte RequestID belirtilmediğinden SDK, bu oluşturma işlemi için bir kimlik üretir. Başarısız çağrı günlüğe kaydedilir ve continue yalnızca ilgili işçiyi bir sonraki işine geçirir; toplu işlemi durdurmaz.

Her işin bağlam kaynaklarını gecikmeden serbest bırakması için iptal işlemini gösterildiği gibi döngünün içinde tutun. İptal, yerel beklemeyi durdurur; uzaktaki işi iptal etmez.

Başka bir iş almadan önce çözümü işleyin

Örnek, hazır görevin kimliğini yazdırır; hedefe hiçbir şey göndermez. Yorumun yerine hedef isteğinizi ekleyin, ardından işçi başka bir iş almadan önce bu işin gönderim sonucunu raporlayın. Token'ları workers.Wait sonrasında kullanmak üzere bir dilime eklemeyin.

  • result.ID değil, result.Solution.Token gönderin.
  • Başarılı proxy'yi belirlemek için özgün görev ve hazır sonuçla birlikte SuccessfulProxy kullanın. Döndürülen UserAgent ve SecChUA tarayıcı kimliğiyle bu proxy üzerinden gönderim yapın.
  • Gönderimi işin bağlamı içinde, cancel() çağrısından önce yapın. Böylece 180 saniyelik son süre hem çözümü hem de gönderimi kapsar; ayrı bir süre bütçesine ihtiyacınız varsa ayrı bir gönderim bağlamı kullanın.

Çözüm ve hedefe gönderim sonuçlarını ayrı ayrı raporlayın. Hazır bir görev kullanılabilir bir çözüm sağlar, ancak uygulama isteğini kabul edip etmediğini yalnızca hedefin yanıtı gösterir.

Toplu işlemi yeniden başlatmadan kesintiye uğrayan bir işi kurtarın

Bu küçük örnek için hatayı günlüğe kaydetmek yeterlidir, ancak kurtarma desteği olan bir entegrasyon her işin görev girdilerini eksiksiz olarak ve mevcut istek ve görev kimliklerini saklamalıdır. Zaman aşımı, görev oluşturmanın başarısız olduğunu kanıtlamaz.

  • RequestID ve TaskID değerlerini almak için *solvethree.Error türünü çıkarın. Görev kimliği biliniyorsa yeni bir bağlam altında GetTask ile sonucu almayı sürdürün.
  • Oluşturma işleminin sonucu belirsizse ve istek kimliği elinizdeyse özgün girdileri aynı RequestID ile yeniden gönderin. Aynı istek mevcut görevi döndürür; kimliği yeniden kullanırken girdileri değiştirmek çakışmaya yol açar.
  • *TaskFailedError için ErrorCode değerini kaydedin ve Error metnine ihtiyacınız varsa başarısız görevi alın. Bu görevi sorgulamayı bırakın ve aynı geçersiz girdileri körü körüne yeniden göndermek yerine sorunun nedenini giderin.

HTTP hatalarını görevin nihai başarısızlığından ayrı tutun. errors.As, StatusCode ve RetryAfter içeren iç içe bir *APIError çıkarabilir. Solve, HTTP 429, 502, 503 veya 504 içeren geçici sorgulama yanıtlarını zaten yeniden dener ve bağlamın son süresi içinde Retry-After değerine uyar. Görev oluşturma hiçbir zaman otomatik olarak yeniden denenmez.

İlk görevinizi çalıştırın.

$5 çalışma alanı kredisiyle başlayın.

Çalışma alanı oluşturun
Go'da CAPTCHA görevlerini eşzamanlı çözün · solvethree