פתרון reCAPTCHA Enterprise באמצעות Ruby
השתמשו ב-Net::HTTP של Ruby כדי ליצור משימת reCAPTCHA Enterprise ולתשאל אותה עד שתהיה מוכנה או תיכשל. הדוגמה הבאה קוראת ישירות ל-REST API של solvethree; אין צורך ב-SDK ל-Ruby.
בדף הזה
הגדירו את האתר והסביבה
- 1.
הפעלת פרופיל האתר
הגדירו את שם מארח היעד במסוף של solvethree וודאו שהפרופיל שלו פעיל בסביבת העבודה שלכם. שליחת שם מארח ופעולה אינה יוצרת פרופיל. ראו הגדרת פרופיל אתר.
- 2.
הגדרת משתני הסביבה
הגדירו את
SOLVETHREE_API_KEYלמפתח ה-API של סביבת העבודה שלכם ואתSOLVETHREE_PROXYלכתובת ה-URL של פרוקסי HTTP או HTTPS שבו תשתמשו גם לשליחת הטוקן ליעד. שמרו את המפתח בשרת. - 3.
שנו את הקלטים שבדוגמה
החליפו את
accounts.example.comבשם מארח היעד — לא בכתובת URL מלאה — ואתloginבפעולה שהיעד דורש. הבקשה משתמשת ב-proxyאחד; אל תוסיפו גםproxyCandidates. אל תכללו אתtypeואתurl. השמטתrecaptchaTypeבוחרת בברירת המחדל,enterprise-v3.
שמרו את הדוגמה בשם solve.rb והריצו אותה באמצעות Ruby לאחר הגדרת המשתנים האלה. היא טוענת את net/http, את json ואת securerandom; JSON מטפל בגוף הבקשה ובתגובות ה-API.
צרו פעם אחת, ואז תשאלו לפי מזהה המשימה
require 'net/http'
require 'json'
require 'securerandom'
api = 'https://api.solvethree.com/v1'
input = {site: 'accounts.example.com', action: 'login', proxy: ENV.fetch('SOLVETHREE_PROXY'), requestId: SecureRandom.uuid}
deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + 180
call = lambda do |method, path, body = nil|
remaining = deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC)
raise 'Local deadline reached' if remaining <= 0
uri = URI(api + path)
request = method == :post ? Net::HTTP::Post.new(uri) : Net::HTTP::Get.new(uri)
request['Authorization'] = 'Bearer ' + ENV.fetch('SOLVETHREE_API_KEY')
request['Accept'] = 'application/json'
if body
request['Content-Type'] = 'application/json'
request.body = JSON.generate(body)
end
# Net::HTTP's own proxy configuration is separate from input[:proxy].
http = Net::HTTP.new(uri.hostname, uri.port, nil)
http.use_ssl = uri.scheme == 'https'
http.open_timeout = [10, remaining].min
http.read_timeout = [25, remaining].min
http.write_timeout = [25, remaining].min
http.max_retries = 0
response = http.request(request)
raise "API HTTP #{response.code}" unless response.is_a?(Net::HTTPSuccess)
JSON.parse(response.body)
end
task_id = nil
begin
result = call.call(:post, '/tasks?waitMs=0', input)
task_id = result.fetch('id')
while %w[pending solving].include?(result.fetch('status'))
result = call.call(:get, '/tasks/' + URI.encode_www_form_component(task_id) + '?waitMs=15000')
sleep(1) if %w[pending solving].include?(result.fetch('status'))
end
raise "Task failed: #{result['errorCode']}" unless result['status'] == 'ready'
puts "Ready task: #{task_id}"
# Submit result['solution']['token'] with its userAgent/secChUa and original proxy.
rescue StandardError => error
warn "Recovery requestId=#{input[:requestId]} taskId=#{task_id || 'unknown'}"
raise error
endהסקריפט שולח בקשת יצירה אחת, שומר את מזהה המשימה שהוחזר ומאחזר את המשימה הזו כל עוד הסטטוס שלה הוא pending או solving. רק ready מספק פתרון שמיש. לכל תגובה חייב להיות סטטוס HTTP מוצלח לפני שמפענחים את הגוף שלה כמטען נתוני הצלחה.
HTTPS מופעל במפורש. ניסיונות חוזרים אוטומטיים מושבתים, והפניות נדחות בבדיקת סטטוס ה-HTTP במקום לעקוב אחריהן. הפרוקסי בגוף המשימה מיועד לפתרון; הוא אינו מגדיר את החיבור מ-Ruby ל-API של solvethree.
המועד האחרון המשותף, המבוסס על שעון מונוטוני, מקצה לתשאול מסגרת זמן מקומית של 180 שניות. זמני הקצוב לחיבור, לקריאה ולכתיבה מוגבלים לפי הזמן שנותר בתחילת כל בקשה. התייחסו למסגרת הזו כמגבלת תשאול, לא כטיימר ביטול קשיח לבקשה שכבר מתבצעת. התיעוד של Ruby Net::HTTP מתאר את הגדרות הזמן הקצוב הנפרדות.
שלחו את הטוקן עם זהות הדפדפן שלו
הדוגמה מדפיסה את מזהה המשימה המוכנה, לא את הטוקן. קראו את solution.token מהתוצאה המוכנה והציבו אותו בשדה הטוקן שהבקשה ליעד מצפה לו. אל תשלחו במקומו את מזהה המשימה.
השתמשו ב-solution.userAgent שהוחזר עבור הכותרת User-Agent וב-solution.secChUa עבור Sec-CH-UA. שלחו ליעד המיועד דרך אותו פרוקסי שסופק למשימה הזו. אל תחליפו את הזהות שהוחזרה בכותרות של דפדפן לא קשור.
משימה מוכנה פירושה ש-solvethree יצר פתרון. בדקו את תגובת היעד בנפרד כדי לקבוע אם הוא קיבל את בקשת היישום שלכם.
טפלו בכשלים בלי ליצור משימות כפולות
- הסקריפט מעלה שגיאת HTTP של ה-API.
בדקו את תגובת ה-HTTP שאינה מציינת הצלחה. זו שגיאה ברמת הבקשה, לא תוצאה סופית של המשימה.
כדאי לנסות: אבחנו את התגובה הזו לפני ניסיון חוזר. אל תשלחו שוב ושוב קלטים לא תקינים ללא שינוי.
- המשימה מגיעה לסטטוס
failed. בדקו גם את
errorCodeוגם אתerrorבתוצאה. הודעת החריגה שבדוגמה כוללת רק אתerrorCode.כדאי לנסות: הפסיקו לתשאל את המשימה הזו וטפלו בגורם שדווח. על פתרונות שנכשלו ניתן החזר כספי; כישלון אינו מעיד בהכרח על יתרה לא מספקת.
- הזמן הקצוב ליצירה פג לפני שהתקבל מזהה משימה.
שמרו את
requestIdלשחזור שנכתב לפלט השגיאות הסטנדרטי. פקיעת הזמן הקצוב אינה מוכיחה שהיצירה נכשלה.כדאי לנסות: שחזרו באמצעות שליחת בקשת משימה זהה עם אותו מזהה בקשה. אל תריצו פשוט את הסקריפט מחדש: הרצה חדשה מייצרת מזהה חדש ועלולה ליצור משימה נוספת.
- התשאול מגיע למועד האחרון המקומי או מאבד את החיבור.
שמרו את מזהה המשימה ומזהה הבקשה שנרשמו ביומן.
כדאי לנסות: אחזרו את המשימה לפי המזהה הידוע לפני יצירת משימה נוספת. חריגה מקומית אינה סטטוס סופי של המשימה.
כדי לאפשר שחזור לאחר הפעלה מחדש של התהליך, שמרו את מזהה הבקשה ואת קלטי המשימה המקוריים לפני שליחת ה-POST, ואז שמרו את מזהה המשימה ברגע שהוא מוחזר. שימוש חוזר במזהה בקשה עם קלטים זהים מחזיר את המשימה הקיימת; שינוי הקלטים תוך שמירה על אותו מזהה גורם להתנגשות. ראו טיפול בשגיאות API לשלב האבחון הבא.
מקורות ותיעוד API
הפעלת המשימה הראשונה שלך.
התחילו עם $5 בקרדיט לסביבת העבודה.