Go में CAPTCHA टास्क समवर्ती रूप से हल करें
एक साझा Go SDK क्लाइंट और निश्चित आकार का वर्कर पूल इस्तेमाल करें। हर जॉब को उसका अपना कॉन्टेक्स्ट दें, फिर टोकन को बाद के बैच के लिए इकट्ठा करने के बजाय हर तैयार समाधान तुरंत सबमिट करें।
इस पेज पर
क्लाइंट और लक्ष्य तैयार करें
- Go 1.22 या नया संस्करण और आधिकारिक
solvethree.com/sdkमॉड्यूल का संस्करणv0.1.0इस्तेमाल करें। इंस्टॉलेशन का विवरण Go इंटीग्रेशन दस्तावेज़ में है। - सर्वर एनवायरनमेंट में
SOLVETHREE_API_KEYऔरSOLVETHREE_PROXYसेट करें। API कुंजी को ब्राउज़र कोड से बाहर रखें। accounts.example.comऔरloginकी जगह अपना लक्ष्य होस्टनाम और ऐक्शन डालें। वर्कस्पेस में उस साइट की सक्रिय प्रोफ़ाइल होनी चाहिए; होस्टनाम सबमिट करने से प्रोफ़ाइल नहीं बनती। साइट प्रोफ़ाइल सेटअप देखें।
यह उदाहरण reCAPTCHA Enterprise का अनुरोध करता है, जो डिफ़ॉल्ट है। इसमें एक प्रॉक्सी दी जाती है और जानबूझकर Type और URL सेट नहीं किए जाते: reCAPTCHA अनुरोध इन फ़ील्ड के बजाय साइट होस्टनाम और ऐक्शन इस्तेमाल करते हैं।
काम की सीमा तय करें, क्लाइंट की संख्या की नहीं
क्लाइंट का समवर्ती इस्तेमाल सुरक्षित है। यह उदाहरण चार वर्कर शुरू करता है और बिना बफ़र वाले चैनल से उन्हें आठ जॉब देता है। हर जॉब के लिए goroutine शुरू करने के बजाय, सभी वर्कर व्यस्त होने पर प्रोड्यूसर इंतज़ार करता है। चार केवल उदाहरण के लिए चुनी गई एप्लिकेशन सेटिंग है, solvethree सेवा की सीमा नहीं।
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()
}हर वर्कर हर जॉब के लिए अलग 180-सेकंड का कॉन्टेक्स्ट बनाता है। Solve टास्क एक बार बनाता है और उसके नतीजे का इंतज़ार करता है। उदाहरण में RequestID नहीं दिया गया है, इसलिए SDK टास्क बनाते समय एक ID जनरेट करता है। विफल कॉल लॉग की जाती है और continue केवल उस वर्कर को उसके अगले जॉब पर ले जाता है; इससे बैच नहीं रुकता।
जैसा दिखाया गया है, कैंसलेशन को लूप के अंदर रखें, ताकि हर जॉब अपने कॉन्टेक्स्ट संसाधन तुरंत रिलीज़ करे। कैंसलेशन स्थानीय इंतज़ार रोकता है; यह रिमोट काम रद्द नहीं करता।
अगला जॉब लेने से पहले समाधान संभालें
उदाहरण तैयार टास्क की ID प्रिंट करता है; यह लक्ष्य पर कुछ सबमिट नहीं करता। टिप्पणी की जगह अपना लक्ष्य अनुरोध डालें, फिर वर्कर के अगला जॉब लेने से पहले उस जॉब के सबमिशन का नतीजा रिपोर्ट करें। workers.Wait के बाद इस्तेमाल करने के लिए टोकन किसी स्लाइस में न जोड़ें।
result.Solution.Tokenसबमिट करें,result.IDनहीं।- सफल प्रॉक्सी पहचानने के लिए मूल टास्क और तैयार नतीजे के साथ
SuccessfulProxyइस्तेमाल करें। लौटाई गईUserAgentऔरSecChUAब्राउज़र पहचान के साथ उसी प्रॉक्सी से सबमिट करें। - सबमिशन को जॉब के कॉन्टेक्स्ट के अंदर,
cancel()से पहले रखें। तब 180-सेकंड की समय-सीमा समाधान निकालने और सबमिशन, दोनों पर लागू होगी; अलग समय बजट चाहिए तो सबमिशन के लिए अलग कॉन्टेक्स्ट इस्तेमाल करें।
समाधान निकालने और लक्ष्य पर सबमिशन के नतीजे अलग-अलग रिपोर्ट करें। तैयार टास्क इस्तेमाल योग्य समाधान देता है, लेकिन केवल लक्ष्य का रिस्पॉन्स बताता है कि उसने एप्लिकेशन अनुरोध स्वीकार किया या नहीं।
बैच दोबारा शुरू किए बिना बाधित जॉब रिकवर करें
इस छोटे उदाहरण के लिए त्रुटि लॉग करना पर्याप्त है, लेकिन रिकवर किए जा सकने वाले इंटीग्रेशन को हर जॉब के बिल्कुल वही टास्क इनपुट और उपलब्ध अनुरोध व टास्क ID सुरक्षित रखने चाहिए। टाइमआउट से यह साबित नहीं होता कि टास्क बनाना विफल हुआ।
RequestIDऔरTaskIDपाने के लिए*solvethree.Errorनिकालें। टास्क ID पता हो तो नए कॉन्टेक्स्ट मेंGetTaskसे नतीजा प्राप्त करना फिर शुरू करें।- अगर टास्क बना या नहीं, यह स्पष्ट नहीं है और आपके पास अनुरोध ID है, तो उसी
RequestIDके साथ मूल इनपुट दोबारा भेजें। वही अनुरोध मौजूदा टास्क लौटाता है; ID दोबारा इस्तेमाल करते हुए इनपुट बदलने से कॉन्फ़्लिक्ट होता है। *TaskFailedErrorके लिएErrorCodeदर्ज करें और उसकाErrorटेक्स्ट चाहिए तो विफल टास्क प्राप्त करें। उस टास्क की पोलिंग रोकें और बिना सोचे वही अमान्य इनपुट दोबारा सबमिट करने के बजाय कारण ठीक करें।
HTTP त्रुटियों को टास्क की अंतिम विफलताओं से अलग रखें। errors.As, StatusCode और RetryAfter वाला नेस्टेड *APIError निकाल सकता है। Solve पहले से ही HTTP 429, 502, 503 या 504 वाले अस्थायी पोलिंग रिस्पॉन्स पर दोबारा प्रयास करता है और कॉन्टेक्स्ट की समय-सीमा के भीतर Retry-After का पालन करता है। टास्क बनाने का प्रयास कभी अपने-आप दोहराया नहीं जाता।
स्रोत और API संदर्भ
अपना पहला टास्क चलाएँ।
$5 वर्कस्पेस क्रेडिट के साथ शुरुआत करें।