chromedp के साथ Go SDK का उपयोग करें
पहले सॉल्व करें, फिर उसी प्रॉक्सी और लौटाई गई ब्राउज़र पहचान के साथ Chrome शुरू करें। टोकन को एप्लिकेशन के फ़ॉर्म में डालें, उसे सबमिट करें और एप्लिकेशन के परिणाम का इंतज़ार करें। टास्क तैयार होने का मतलब है कि आपके पास समाधान है—यह नहीं कि वेबसाइट ने उसे स्वीकार कर लिया है।
इस पेज पर
मॉड्यूल, प्रोफ़ाइल और प्रॉक्सी सेट अप करें
go get से solvethree.com/[email protected] और github.com/chromedp/[email protected] इंस्टॉल करें। SDK के लिए Go 1.22+ आवश्यक है, लेकिन chromedp के इस संस्करण के लिए Go 1.25+ आवश्यक है, इसलिए संयुक्त उदाहरण के लिए उसी का इस्तेमाल करें। इसका टाइप्ड API पुराने chromedp उदाहरणों से अलग है।
प्रोग्राम चलाने से पहले अपने वर्कस्पेस में लक्षित होस्टनाम के लिए एक सक्रिय साइट प्रोफ़ाइल बनाएँ। होस्टनाम और ऐक्शन भेजने से प्रोफ़ाइल नहीं बनती।
TARGET_URL: आपके फ़ॉर्म वाले पेज का पूरा HTTPS URL। टास्क उसके होस्टनाम कोSiteके रूप में इस्तेमाल करता है; Chrome पूरे URL पर जाता है।SOLVETHREE_PROXY: एक HTTP या HTTPS प्रॉक्सी URL। इस उदाहरण के लिए IP-अनुमति सूची वाला प्रॉक्सी चाहिए, जिसके URL में क्रेडेंशियल न हों।SOLVETHREE_API_KEY: आपके वर्कस्पेस की API कुंजी। इसे Go प्रोसेस में रखें, पेज की JavaScript में नहीं।
यह उदाहरण login ऐक्शन का अनुरोध करता है और डिफ़ॉल्ट Enterprise v3 reCAPTCHA मोड इस्तेमाल करता है। ऐक्शन को उस मान में बदलें जिसकी आपका एप्लिकेशन अपेक्षा करता है।
सॉल्व करें, Chrome शुरू करें और सबमिट करें
प्रोग्राम Chrome का एलोकेटर बनाने से पहले SDK का सॉल्व पूरा होने का इंतज़ार करता है। यह Chrome को उसी एक प्रॉक्सी और result.Solution.UserAgent के साथ कॉन्फ़िगर करता है, फिर नेविगेशन से पहले लौटाए गए SecChUA को sec-ch-ua हेडर के रूप में सेट करता है। किसी असंबंधित ब्राउज़र पहचान का इस्तेमाल न करें और सॉल्विंग व सबमिशन के बीच प्रॉक्सी न बदलें।
// 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
}यह उदाहरण जानबूझकर एक प्रॉक्सी इस्तेमाल करता है, इसलिए किसी कैंडिडेट का चयन तय करने की ज़रूरत नहीं है। यदि बाद में आप ProxyCandidates इस्तेमाल करें, तो SuccessfulProxy(originalTask, readyResult) से सफल प्रॉक्सी प्राप्त करें और Chrome के लिए उसी प्रॉक्सी का इस्तेमाल करें।
डेमो फ़ॉर्म से जुड़ी धारणाएँ बदलें
टोकन डालते समय JavaScript एक्सप्रेशन बनाने से पहले json.Marshal इस्तेमाल किया जाता है। एस्केप करने का यह चरण बनाए रखें: यह बिना एस्केप किए गए टेक्स्ट को निष्पादन योग्य कोड में जोड़ने के बजाय टोकन को JavaScript स्ट्रिंग मान के रूप में पास करता है।
[name="g-recaptcha-response"]को उस फ़ील्ड से बदलें जिसे आपका एप्लिकेशन वास्तव में सबमिट करता है। नमूना उसका मान सेट करता है और एक input इवेंट डिस्पैच करता है; यदि आपके एप्लिकेशन को सबमिशन का कोई अलग तरीका चाहिए, तो इसे अनुकूलित करें।button[type="submit"]को इच्छित सबमिट कंट्रोल से बदलें। क्लिक करने से पहले सभी आवश्यक फ़ॉर्म मान, CSRF फ़ील्ड और सेशन स्टेट शामिल करें।#successको ऐसे परिणाम से बदलें जो आपके एप्लिकेशन में वास्तव में स्वीकृति दर्शाता हो। क्लिक पूरा होना या टोकन फ़ील्ड भरा होना ऐसा परिणाम नहीं है।
SDK टोकन को लक्ष्य पर सबमिट नहीं करता। यदि लक्ष्य अनुरोध अस्वीकार करे, तो पहले भेजे जा रहे फ़ॉर्म की जाँच करें: पुष्टि करें कि उसमें result.Solution.Token है, न कि टास्क ID या फ़ील्ड का पुराना मान, और जाँचें कि प्रॉक्सी व ब्राउज़र पहचान अब भी मेल खाते हैं।
डुप्लिकेट सॉल्व बनाए बिना समय-सीमाएँ संभालें
सॉल्व के कॉन्टेक्स्ट की समय-सीमा 180-सेकंड है। सॉल्विंग के बाद Chrome को अलग से 60-सेकंड की समय-सीमा मिलती है। run फ़ंक्शन त्रुटियाँ लौटाता है, ताकि main के त्रुटि लॉग करने से पहले उसका स्थगित कॉन्टेक्स्ट रद्दीकरण और ब्राउज़र क्लीनअप चल सके।
सॉल्व कॉन्टेक्स्ट रद्द करने से इंतज़ार बंद होता है, रिमोट काम नहीं। SDK एक बार बनाता है और केवल पोलिंग की अस्थायी विफलताओं पर फिर कोशिश करता है; यह निर्माण वाले POST को कभी दोबारा नहीं भेजता। इसलिए टाइमआउट तुरंत नया टास्क सबमिट करने का कारण नहीं है।
- रद्दीकरण या समय-सीमा समाप्त होने पर, कॉन्टेक्स्ट त्रुटि पहचानने के लिए
errors.Isइस्तेमाल करें।errors.Asसे*solvethree.Errorनिकालें और उसकाTaskIDवRequestIDसहेजकर रखें। - यदि आपके पास टास्क ID है, तो उसे
GetTaskसे प्राप्त करें। अन्यथा, उसी अनुरोध ID के साथ मूल टास्क के हूबहू समान इनपुट दोबारा भेजकर उसे पुनः प्राप्त करें। उस ID के बिना फिर कॉल करने से नया लॉजिकल अनुरोध बनता है; उसी ID का दोबारा इस्तेमाल करते हुए इनपुट बदलने से टकराव होता है। *TaskFailedErrorके लिएErrorCodeजाँचें और त्रुटि का टेक्स्ट पाने के लिए विफल टास्क प्राप्त करें। वह टास्क अंतिम स्थिति में है: उसकी पोलिंग बंद करें और अपरिवर्तित इनपुट से दोबारा कोशिश करने के बजाय कारण ठीक करें।- HTTP API त्रुटि के लिए,
StatusCodeऔरRetryAfterजाँचने हेतु नेस्टेड*APIErrorनिकालें। HTTP विफलता को अंतिम रूप से विफल टास्क न समझें।
स्रोत और API संदर्भ
अपना पहला टास्क चलाएँ।
$5 वर्कस्पेस क्रेडिट के साथ शुरुआत करें।