chromedp ile Go SDK'sını kullanın
Önce çözüm alın, ardından Chrome'u aynı proxy ve döndürülen tarayıcı kimliğiyle başlatın. Token'ı uygulamanın formuna yerleştirin, formu gönderin ve uygulamanın sonucunu bekleyin. Hazır bir görev, bir çözümünüz olduğu anlamına gelir; web sitesinin bunu kabul ettiği anlamına gelmez.
Bu sayfada
Modülleri, profili ve proxy'yi ayarlayın
solvethree.com/[email protected] ve github.com/chromedp/[email protected] modüllerini go get ile yükleyin. SDK, Go 1.22+ gerektirir; ancak bu chromedp sürümü Go 1.25+ gerektirir. Bu nedenle birleşik örnek için bu sürümü kullanın. Tür tanımlı API'si eski chromedp örneklerindekinden farklıdır.
Programı çalıştırmadan önce çalışma alanınızda hedef ana makine adı için etkin bir site profili oluşturun. Ana makine adı ve eylem göndermek profil oluşturmaz.
TARGET_URL: formunuzu içeren sayfanın tam HTTPS URL'si. Görev, bu URL'nin ana makine adınıSiteolarak kullanır; Chrome ise tam URL'ye gider.SOLVETHREE_PROXY: tek bir HTTP veya HTTPS proxy URL'si. Bu örnek, URL'sinde kimlik bilgileri bulunmayan ve IP adresinin izin listesinde olduğu bir proxy gerektirir.SOLVETHREE_API_KEY: çalışma alanınızın API anahtarı. Bunu sayfanın JavaScript kodunda değil, Go sürecinde tutun.
Örnek, login eylemini ister ve varsayılan Enterprise v3 reCAPTCHA modunu kullanır. Eylemi, uygulamanızın beklediği değerle değiştirin.
Çözün, Chrome'u başlatın ve gönderin
Program, Chrome'un allocator'ını oluşturmadan önce SDK çözümünü bekler. Chrome'u aynı tek proxy ve result.Solution.UserAgent ile yapılandırır, ardından gezinmeden önce döndürülen SecChUA değerini sec-ch-ua başlığı olarak ayarlar. İlgisiz bir tarayıcı kimliği kullanmayın veya çözüm ile gönderim arasında proxy değiştirmeyin.
// go get github.com/chromedp/[email protected] (requires Go 1.25+)
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"net/url"
"os"
"time"
"github.com/chromedp/cdproto/network"
"github.com/chromedp/chromedp"
solvethree "solvethree.com/sdk"
)
func main() { if err := run(); err != nil { log.Fatal(err) } }
func run() error {
target,err:=url.Parse(os.Getenv("TARGET_URL"));if err!=nil||target.Scheme!="https"||target.Hostname()=="" { return fmt.Errorf("set an HTTPS TARGET_URL") }
proxy,err:=url.Parse(os.Getenv("SOLVETHREE_PROXY"));if err!=nil||proxy.User!=nil { return fmt.Errorf("use an IP-allowlisted proxy without URL credentials") }
client,err:=solvethree.NewClient(os.Getenv("SOLVETHREE_API_KEY"),nil);if err!=nil { return err }
ctx,cancel:=context.WithTimeout(context.Background(),180*time.Second);defer cancel()
result,err:=client.Solve(ctx,solvethree.TaskRequest{Site:target.Hostname(),Action:"login",Proxy:proxy.String()},solvethree.SolveOptions{})
if err!=nil { return err }
options:=append(chromedp.DefaultExecAllocatorOptions[:],chromedp.ProxyServer(proxy.String()),chromedp.UserAgent(result.Solution.UserAgent))
allocator,closeAllocator:=chromedp.NewExecAllocator(context.Background(),options...);defer closeAllocator()
browser,closeBrowser:=chromedp.NewContext(allocator);defer closeBrowser()
browser,stop:=context.WithTimeout(browser,60*time.Second);defer stop()
tokenJSON,err:=json.Marshal(result.Solution.Token);if err!=nil { return err }
script:=`(token => {const field=document.querySelector('[name="g-recaptcha-response"]'); field.value=token; field.dispatchEvent(new Event('input',{bubbles:true}));})(`+string(tokenJSON)+`)`
_,err=chromedp.Call(browser,network.SetExtraHTTPHeaders,network.SetExtraHTTPHeadersParams{Headers:network.Headers{"sec-ch-ua":result.Solution.SecChUA}})
if err!=nil { return err }
err=chromedp.Do(browser,
chromedp.Navigate(target.String()),chromedp.WaitReady(chromedp.CSS(`[name="g-recaptcha-response"]`)),
chromedp.Evaluate[chromedp.Void](script),chromedp.Click(chromedp.CSS(`button[type="submit"]`)),
chromedp.WaitVisible(chromedp.ID("success")))
if err!=nil { return err }
// #success is this owned demo form's outcome. Adapt its selectors, token
// parameter and success check to your application, including CSRF/session fields.
return nil
}Bu örnek bilerek tek bir proxy kullanır; dolayısıyla adaylar arasından seçim yapmaya gerek yoktur. Daha sonra ProxyCandidates kullanırsanız başarılı proxy'yi SuccessfulProxy(originalTask, readyResult) ile alın ve Chrome için bu proxy'yi kullanın.
Demo formuna ilişkin varsayımları değiştirin
Token yerleştirme işlemi, JavaScript ifadesini oluşturmadan önce json.Marshal kullanır. Bu kaçış adımını koruyun: token'ı, kaçış uygulanmamış metni yürütülebilir koda yerleştirmek yerine bir JavaScript dize değeri olarak aktarır.
[name="g-recaptcha-response"]yerine uygulamanızın gerçekten gönderdiği alanı kullanın. Örnek, bu alanın değerini ayarlar ve bir input olayı tetikler; uygulamanız farklı bir gönderim yolu gerektiriyorsa bunu uyarlayın.button[type="submit"]yerine amaçlanan gönderme denetimini kullanın. Tıklamadan önce gerekli tüm form değerlerini, CSRF alanlarını ve oturum durumunu ekleyin.#successyerine uygulamanızda kabul edildiğini gerçekten gösteren bir sonuç kullanın. Tıklamanın tamamlanması veya token alanının doldurulması böyle bir sonuç değildir.
SDK, token'ı hedefe göndermez. Hedef isteği reddederse önce giden formu inceleyin: görev kimliğini veya alanın eski değerini değil, result.Solution.Token içerdiğini doğrulayın ve proxy ile tarayıcı kimliğinin hâlâ eşleştiğini kontrol edin.
Yinelenen çözüm istekleri oluşturmadan süre sınırlarını yönetin
Çözüm işleminin bağlam süresi sınırı 180 saniyedir. Çözümden sonra Chrome'a ayrı bir 60 saniyelik süre sınırı verilir. run fonksiyonu hataları döndürür; böylece ertelenmiş bağlam iptali ve tarayıcı temizliği, main bir hata kaydetmeden önce çalışır.
Çözüm bağlamını iptal etmek, uzaktaki işlemi değil, beklemeyi durdurur. SDK yalnızca bir kez oluşturur ve sadece geçici durum sorgulama hatalarını yeniden dener; oluşturma POST isteğini asla yeniden denemez. Bu nedenle zaman aşımı, hemen yeni bir görev göndermek için gerekçe değildir.
- İptal veya süre sınırı durumunda bağlam hatasını belirlemek için
errors.Iskullanın.errors.Asile*solvethree.Errordeğerini çıkarın veTaskIDileRequestIDdeğerlerini saklayın. - Görev kimliğiniz varsa görevi
GetTaskile alın. Yoksa özgün görev girdilerini aynı istek kimliğiyle birebir yeniden göndererek kurtarın. Bu kimlik olmadan tekrar çağrı yapmak yeni bir mantıksal istek oluşturur; aynı kimliği yeniden kullanırken girdileri değiştirmek çakışmaya neden olur. *TaskFailedErroriçinErrorCodealanını inceleyin ve hata metnini almak üzere başarısız görevi getirin. Bu görev son duruma ulaşmıştır: durumunu sorgulamayı bırakın ve aynı girdilerle yeniden denemek yerine nedeni düzeltin.- Bir HTTP API hatasında,
StatusCodeveRetryAfteralanlarını incelemek için iç içe geçmiş*APIErrordeğerini çıkarın. HTTP hatasını, son duruma ulaşmış başarısız bir görevle karıştırmayın.
Kaynaklar ve API referansı
İlk görevinizi çalıştırın.
$5 çalışma alanı kredisiyle başlayın.