حل reCAPTCHA Enterprise باستخدام Ruby

بقلم solvethreeمدة القراءة: 3 دقيقة

استخدم Net::HTTP في Ruby لإنشاء مهمة reCAPTCHA Enterprise والاستعلام عنها دوريًا حتى تصبح جاهزة أو تفشل. يستدعي المثال أدناه واجهة REST API الخاصة بـ solvethree مباشرةً؛ ولا يتطلب Ruby SDK.

في هذه الصفحة

اضبط الموقع والبيئة

  1. 1.

    تفعيل ملف تعريف الموقع

    اضبط اسم المضيف المستهدف في وحدة تحكم solvethree وتأكد من أن ملفه التعريفي نشط لمساحة عملك. إرسال اسم مضيف وإجراء لا يُنشئ ملفًا تعريفيًا. راجع إعداد الملف التعريفي للموقع.

  2. 2.

    تعيين متغيرات البيئة

    اضبط SOLVETHREE_API_KEY على مفتاح API لمساحة عملك، وSOLVETHREE_PROXY على عنوان URL لوكيل HTTP أو HTTPS الذي ستستخدمه أيضًا عند إرسال الرمز إلى الهدف. احتفظ بالمفتاح على الخادم.

  3. 3.

    غيّر مدخلات المثال

    استبدل accounts.example.com باسم المضيف المستهدف، وليس بعنوان URL كامل، واستبدل login بالإجراء الذي يتطلبه ذلك الهدف. يستخدم الطلب proxy واحدًا؛ فلا تُضف proxyCandidates أيضًا. لا تُدرج type وurl. يؤدي إغفال recaptchaType إلى اختيار القيمة الافتراضية، enterprise-v3.

احفظ المثال باسم solve.rb وشغّله باستخدام Ruby بعد ضبط تلك المتغيرات. يحمّل المثال net/http وjson وsecurerandom؛ وتتولى JSON معالجة جسم الطلب واستجابات API.

أنشئ المهمة مرة واحدة، ثم استعلم دوريًا باستخدام معرّفها

Ruby · إنشاء مرة واحدة واستعلام دوري محدود
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 لمعرفة الخطوة التشخيصية التالية.

شغّل مهمتك الأولى.

ابدأ برصيد قدره $5 في مساحة العمل.

إنشاء مساحة عمل
حل reCAPTCHA Enterprise باستخدام Ruby · solvethree