פתרון משימות CAPTCHA במקביל ב-Go
השתמשו בלקוח Go SDK משותף אחד ובמאגר קבוע של workers. הקצו לכל עבודה context משלה, ושלחו כל פתרון מיד כשהוא מוכן במקום לאסוף טוקנים לאצווה מאוחרת יותר.
בדף הזה
הכנת הלקוח והיעד
- השתמשו ב-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 משתמשות בשם המארח של האתר ובפעולה, ולא בשדות האלה.
הגבילו את העבודה, לא את מספר הלקוחות
הלקוח בטוח לשימוש מקבילי. הדוגמה מפעילה ארבעה workers ומעבירה להם שמונה עבודות דרך ערוץ ללא חוצץ. כשכל ה-workers עסוקים, היצרן ממתין במקום להפעיל 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()
}כל worker יוצר context נפרד של 180 שניות לכל עבודה. Solve יוצר את המשימה פעם אחת וממתין לתוצאה שלה. מכיוון שהדוגמה אינה מציינת RequestID, ה-SDK מייצר מזהה עבור היצירה הזו. קריאה שנכשלה נרשמת ביומן, ו-continue מעביר רק את אותו worker לעבודה הבאה שלו; הוא אינו עוצר את האצווה.
השאירו את הביטול בתוך הלולאה, כפי שמוצג, כדי שכל עבודה תשחרר בהקדם את משאבי ה-context שלה. הביטול מפסיק את ההמתנה המקומית; הוא אינו מבטל עבודה מרוחקת.
טפלו בפתרון לפני קבלת עבודה נוספת
הדוגמה מדפיסה את מזהה המשימה המוכנה; היא אינה שולחת דבר ליעד. החליפו את ההערה בבקשה ליעד שלכם, ואז דווחו על תוצאת השליחה של אותה עבודה לפני שה-worker מקבל עבודה נוספת. אל תוסיפו טוקנים ל-slice לשימוש לאחר workers.Wait.
- שלחו את
result.Solution.Token, לא אתresult.ID. - השתמשו ב-
SuccessfulProxyעם המשימה המקורית ועם התוצאה המוכנה כדי לזהות את הפרוקסי שהצליח. שלחו דרך הפרוקסי הזה עם זהות הדפדפן שהוחזרה ב-UserAgentוב-SecChUA. - בצעו את השליחה במסגרת ה-context של העבודה, לפני
cancel(). כך מגבלת הזמן של 180 שניות מכסה גם את הפתרון וגם את השליחה; השתמשו ב-context נפרד לשליחה אם דרוש לכם תקציב זמן נפרד.
דווחו בנפרד על הפתרון ועל השליחה ליעד. משימה מוכנה מספקת פתרון שמיש, אבל רק תגובת היעד מעידה אם הוא קיבל את בקשת היישום.
שחזור עבודה שנקטעה בלי להפעיל מחדש את האצווה
רישום שגיאה ביומן מספיק לדוגמה הקטנה הזו, אבל אינטגרציה שתומכת בשחזור צריכה לשמור את קלטי המשימה המדויקים של כל עבודה ואת מזהי הבקשה והמשימה הזמינים. חריגה ממגבלת הזמן אינה מוכיחה שיצירת המשימה נכשלה.
- חלצו את
*solvethree.Errorכדי לקבל אתRequestIDואתTaskID. אם מזהה המשימה ידוע, חדשו את אחזור המשימה באמצעותGetTaskעם context חדש. - אם לא ברור אם המשימה נוצרה ויש לכם את מזהה הבקשה, שלחו שוב את הקלטים המקוריים עם אותו
RequestID. אותה בקשה מחזירה את המשימה הקיימת; שינוי הקלטים תוך שימוש חוזר במזהה גורם להתנגשות. - במקרה של
*TaskFailedError, שמרו אתErrorCodeואחזרו את המשימה שנכשלה אם אתם זקוקים לטקסט שב-Errorשלה. הפסיקו לתשאל את המשימה הזו וטפלו בגורם לכישלון במקום לשלוח שוב באופן עיוור את אותם קלטים לא תקינים.
הבחינו בין שגיאות HTTP לבין כישלונות סופיים של משימות. errors.As יכול לחלץ *APIError מקונן עם StatusCode ו-RetryAfter. Solve כבר מנסה מחדש תשאולים שהחזירו תגובות זמניות עם HTTP 429, 502, 503 או 504, תוך כיבוד Retry-After במסגרת מגבלת הזמן של ה-context. יצירת משימה לעולם אינה מתבצעת שוב אוטומטית.
מקורות ותיעוד API
הפעלת המשימה הראשונה שלך.
התחילו עם $5 בקרדיט לסביבת העבודה.