دروس API

حل GeeTest v3 باستخدام CaptchaAI API

يُحَل GeeTest v3 عبر CaptchaAI في أربع خطوات مترابطة:

  1. استخرج المعلمات الثلاث من الصفحة (gt وchallenge وapi_server).
  2. أرسل المهمة إلى CaptchaAI عبر in.php.
  3. استطلع النتيجة حتى تجهز ثلاثية الحل.
  4. مرّر challenge وvalidate وseccode إلى نقطة التحقق في الموقع.

أصعب ما في العملية ليس الحل نفسه، بل أن GeeTest — بخلاف reCAPTCHA — لا يضع مفتاحاً جاهزاً في الصفحة، وإنما يعتمد تدفق تحقق مخصصاً يفرض عليك التقاط ثلاث معلمات ديناميكية قبل إرسال أي طلب.

الخبر الجيد أن GeeTest v3 من الأنواع المدعومة بالكامل في CaptchaAI، ويُحَل عادةً في أقل من 12 ثانية بمعدل نجاح مرتفع على مختلف أنماط التحدي. في هذا الدليل نمرّ على التدفق كاملاً بأمثلة Python وNode.js جاهزة للنسخ، ثم نغطي معالجة الأخطاء وسيناريو عملياً قريباً من واقع فرق الأتمتة في المنطقة.


كيف يعمل تدفق التحقق في GeeTest v3

قبل كتابة أي سطر، من المفيد فهم ما يميّز GeeTest عن غيره. أنواع مثل reCAPTCHA وCloudflare Turnstile تضع sitekey واحداً ثابتاً في الصفحة، فتقرأه وترسله. أما GeeTest v3 فيبدأ بطلب تهيئة يعيد زوجاً من القيم: gt وهو معرّف ثابت مرتبط بالموقع، وchallenge وهو رمز جلسة قصير العمر يُصرف مرة واحدة فقط. بعد حل التحدي التفاعلي (الشريحة أو النقر على الأيقونات أو مطابقة الكلمات) تعيد الخدمة ثلاث قيم يتحقق منها الموقع في الخطوة الأخيرة:

  • challenge: رمز الجلسة بعد اكتمال الحل.
  • validate: قيمة التحقق المرتبطة بذلك الحل.
  • seccode: الرمز الأمني الذي يؤكده الموقع نهائياً.

فهم هذه الدورة يفسّر لاحقاً لماذا لا يمكن إعادة استخدام قيمة challenge، ولماذا قد يرفض الموقع حلاً صحيحاً تقنياً إذا استُخرجت المعلمات من جلسة قديمة.


المتطلبات قبل البدء

البند القيمة
مفتاح CaptchaAI API منcaptchaai.com
قيمة GeeTest gt معرف ثابت لكل موقع
GeeTest challenge القيمة الديناميكية لكل جلسة
عنوان URL للصفحة عنوان URL الذي يظهر فيه GeeTest
اللغة بايثون 3.7+ أو Node.js 14+

الخطوة 1: استخراج معلمات GeeTest الثلاث

يعتمد GeeTest على ثلاث معلمات: gt ثابت لا يتغير بين الطلبات، وchallenge يتجدد مع كل جلسة، وapi_server الاختياري الذي يحدد خادم التحقق. أمامك ثلاث طرق للحصول عليها، اختر الأنسب لبنية الموقع الذي تعمل عليه.

الطريقة الأولى: علامة تبويب الشبكة

  1. افتح علامة التبويب DevTools → الشبكة
  2. التصفية حسب register-slide أو gettype.php أو get.php
  3. شغّل رمز التحقق وابحث عن طلب التهيئة
  4. يحتوي الرد على gt وchallenge وأحيانا api_server
{
  "success": 1,
  "gt": "019924a82c70bb123aae90d483087f94",
  "challenge": "12345678abc90def12345678abc90def",
  "new_captcha": true
}

هذه الطريقة هي الأدق لأنها تلتقط القيمة الفعلية التي أرسلها الموقع للمتصفح لحظة تحميل التحدي.

الطريقة الثانية: مصدر الصفحة

عندما تكون المعلمات مضمّنة مباشرة داخل وسوم <script>، يمكنك البحث عنها في مصدر الصفحة عبر استدعاء initGeetest:

// Search page source for initGeetest or gt value
document.querySelectorAll('script').forEach(s => {
  if (s.textContent.includes('initGeetest')) {
    console.log(s.textContent);
  }
});

الطريقة الثالثة: نقطة نهاية واجهة برمجة التطبيقات

تقوم العديد من المواقع بجلب معلمات GeeTest من واجهة برمجة التطبيقات الخاصة بها، وهي الطريقة الأنسب للأتمتة لأنها تعطيك قيمة challenge طازجة في كل تشغيل:

# The site's registration endpoint
params_response = requests.get("https://example.com/api/captcha/register")
data = params_response.json()
gt = data["gt"]
challenge = data["challenge"]

الخطوة 2: أرسل المهمة إلى CaptchaAI

بعد التقاط gt وchallenge، أرسلهما إلى نقطة النهاية in.php مع تحديد method بقيمة geetest. الاستجابة تعيد لك معرّف المهمة (task_id) الذي ستستخدمه في خطوة الاستطلاع.

بايثون

import requests
import time

API_KEY = "YOUR_API_KEY"

response = requests.get("https://ocr.captchaai.com/in.php", params={
    "key": API_KEY,
    "method": "geetest",
    "gt": "019924a82c70bb123aae90d483087f94",
    "challenge": "12345678abc90def12345678abc90def",
    "api_server": "api.geetest.com",  # Optional, use if site specifies
    "pageurl": "https://example.com/login",
    "json": 1
})

data = response.json()
if data.get("status") != 1:
    raise Exception(f"Submit error: {data.get('request')}")

task_id = data["request"]
print(f"Task submitted: {task_id}")

Node.js

const axios = require('axios');

const API_KEY = 'YOUR_API_KEY';

async function submitGeeTest(gt, challenge, pageurl) {
  const { data } = await axios.get('https://ocr.captchaai.com/in.php', {
    params: {
      key: API_KEY,
      method: 'geetest',
      gt,
      challenge,
      api_server: 'api.geetest.com',
      pageurl,
      json: 1
    }
  });

  if (data.status !== 1) throw new Error(`Submit error: ${data.request}`);
  return data.request;
}

انتبه إلى تمرير pageurl مطابقاً تماماً للصفحة التي يظهر فيها التحدي، فأي اختلاف في المسار قد يجعل الحل غير مقبول لدى الموقع لاحقاً.


الخطوة 3: استطلاع نتيجة الحل

حل GeeTest غير فوري؛ استخدم نقطة النهاية res.php للاستطلاع الدوري حتى تجهز النتيجة. القيمة العائدة عند النجاح ثلاثية: challenge وvalidate وseccode. فاصل خمس ثوانٍ بين المحاولات كافٍ لتجنّب الطلبات الزائدة مع بقاء زمن الانتظار قصيراً.

بايثون

def get_geetest_solution(task_id):
    for attempt in range(30):
        time.sleep(5)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY,
            "action": "get",
            "id": task_id,
            "json": 1
        }).json()

        if result.get("status") == 1:
            return result["request"]
        if result.get("request") != "CAPCHA_NOT_READY":
            raise Exception(f"Error: {result.get('request')}")

    raise Exception("Timeout")

solution = get_geetest_solution(task_id)
# solution = {
#   "geetest_challenge": "12345678abc90def12345678abc90def1a",
#   "geetest_validate": "abcdef1234567890abcdef1234567890",
#   "geetest_seccode": "abcdef1234567890abcdef1234567890|jordan"
# }

Node.js

async function getGeeTestSolution(taskId) {
  for (let i = 0; i < 30; i++) {
    await new Promise(r => setTimeout(r, 5000));
    const { data } = await axios.get('https://ocr.captchaai.com/res.php', {
      params: { key: API_KEY, action: 'get', id: taskId, json: 1 }
    });
    if (data.status === 1) return data.request;
    if (data.request !== 'CAPCHA_NOT_READY') throw new Error(data.request);
  }
  throw new Error('Timeout');
}

لاحظ أن الرد CAPCHA_NOT_READY ليس خطأً، بل يعني أن الحل ما زال قيد المعالجة؛ استمر في الاستطلاع حتى تصل status إلى القيمة 1 أو ينفد عدد المحاولات.


الخطوة 4: إرسال الحل إلى الموقع المستهدف

أرسل القيم الثلاث إلى نقطة نهاية التحقق الخاصة بالموقع، مرفقة ببقية بيانات النموذج كاسم المستخدم وكلمة المرور. هنا تُختبر صلاحية الحل فعلياً:

# Submit the GeeTest solution with the form data
verify_response = requests.post("https://example.com/api/login", data={
    "username": "user@example.com",
    "password": "password123",
    "geetest_challenge": solution["geetest_challenge"],
    "geetest_validate": solution["geetest_validate"],
    "geetest_seccode": solution["geetest_seccode"]
})

print(f"Login status: {verify_response.status_code}")

أسماء الحقول (geetest_challenge وgeetest_validate وgeetest_seccode) قد تختلف قليلاً من موقع لآخر؛ تحقق من الحقول التي يتوقعها النموذج الأصلي وطابقها.


مثال بايثون الكامل

يجمع المثال التالي الخطوات الأربع في سكربت واحد قابل لإعادة الاستخدام:

import requests
import time

API_KEY = "YOUR_API_KEY"
SITE_URL = "https://example.com/login"

# 1. Get GeeTest parameters from the site
params = requests.get("https://example.com/api/captcha/register").json()

# 2. Submit to CaptchaAI
submit = requests.get("https://ocr.captchaai.com/in.php", params={
    "key": API_KEY,
    "method": "geetest",
    "gt": params["gt"],
    "challenge": params["challenge"],
    "pageurl": SITE_URL,
    "json": 1
}).json()
task_id = submit["request"]

# 3. Poll for solution
for _ in range(30):
    time.sleep(5)
    result = requests.get("https://ocr.captchaai.com/res.php", params={
        "key": API_KEY, "action": "get", "id": task_id, "json": 1
    }).json()
    if result.get("status") == 1:
        solution = result["request"]
        break

# 4. Submit to site
login = requests.post(SITE_URL, data={
    "username": "user@example.com",
    "password": "pass",
    "geetest_challenge": solution["geetest_challenge"],
    "geetest_validate": solution["geetest_validate"],
    "geetest_seccode": solution["geetest_seccode"]
})
print(f"Result: {login.status_code}")

سيناريو عملي: أتمتة اختبار تسجيل الدخول

لنفترض أن فريق ضمان الجودة في متجر إلكتروني بالرياض يشغّل اختباراً يومياً يتحقق من مسار تسجيل الدخول على بوابة يحميها GeeTest v3. بدل تعطّل الاختبارات عند كل ظهور للتحدي، يستدعي السكربت CaptchaAI للحصول على ثلاثية الحل، ثم يكمل تسجيل الدخول ويؤكد تحميل الصفحة التالية. ولأن CaptchaAI يعتمد تسعيراً قائماً على الـ Threads المتزامنة — لا الدفع لكل عملية حل — يستطيع الفريق تشغيل عدة اختبارات متوازية ضمن الخطة نفسها دون رسوم لكل تحدي.

الفكرة المهمة هنا أن هذا الاستخدام موجّه لاختبار موثوقية سير العمل على موقعك أنت أو موقع لديك إذن باختباره، لا لتجاوز حماية أطراف أخرى. مع زمن حل يقل عادةً عن 12 ثانية للتحدي الواحد، يبقى أثر GeeTest على زمن الاختبار الكلي محدوداً حتى في الدفعات الكبيرة.


معالجة الأخطاء الشائعة

خطأ السبب إصلاح
ERROR_BAD_PARAMETERS مفقود GT أو التحدي كلاهما مطلوب – مقتطف من الصفحة
ERROR_CAPTCHA_UNSOLVABLE التحدي منتهي الصلاحية أو غير صالح أعد جلب تحدي جديد من الموقع
الحل مرفوض من قبل الموقع قيمة التحدي التي لا معنى لها التحدي هو الاستخدام الفردي. احصل على واحدة جديدة لكل محاولة
geetest_validate فارغ فشل الحل داخليا أعد المحاولة بتحدي جديد

القاعدة العملية في أغلب هذه الحالات واحدة: ابدأ دائماً من معلمات طازجة. معظم حالات الرفض لا تعود إلى خطأ في الحل، بل إلى قيمة challenge استُهلكت أو انتهت صلاحيتها قبل الوصول إلى خطوة التحقق.


مثال كامل قابل للتشغيل

هل تحتاج إلى مشروع عمل كامل مع إعداد البيئة والاستقصاء وإعادة المحاولة ومعالجة الأخطاء؟

راجع المثال الكامل القابل للتشغيل على GitHub →


الأسئلة الشائعة

كم تبلغ تكلفة حل GeeTest v3 عبر CaptchaAI؟

يعتمد CaptchaAI على تسعير قائم على الـ Threads المتزامنة مع عدد غير محدود من عمليات الحل شهرياً لكل Thread، لا على الدفع لكل عملية. تبدأ الخطط من BASIC بسعر 15 دولاراً شهرياً (5 Threads) وترتفع حتى الخطط المؤسسية، فتصبح تكلفة حل GeeTest v3 مرتبطة بعدد الطلبات المتزامنة التي تحتاجها لا بحجم الحلول نفسه.

هل تنطبق هذه الطريقة على GeeTest v4؟

لا، هذا الدليل مخصص للإصدار v3 فقط. أما GeeTest v4 فيستخدم بروتوكولاً مختلفاً، وهو غير متاح حالياً في CaptchaAI ومدرج على قائمة "قريباً"، لذا لا تعتمد الخطوات أعلاه للإصدار v4.

كم عدد طلبات GeeTest التي يمكن معالجتها في آن واحد؟

يتحكم عدد الـ Threads في خطتك بسقف الطلبات المتزامنة:

  • خطة بخمسة Threads تعالج خمس مهام GeeTest في اللحظة نفسها.
  • بمجرد اكتمال حل، يتحرر الـ Thread ليلتقط الطلب التالي، فتكون ترقية الخطة هي المسار المباشر لرفع الإنتاجية.

لماذا يرفض الموقع الحل رغم نجاح الاستجابة من CaptchaAI؟

في الغالب لأن أحد هذه العناصر اختلّ:

  • قيمة challenge استُهلكت أو صارت من جلسة سابقة.
  • seccode لم تصل كاملة كما وردت من الخدمة.
  • pageurl لا يطابق تماماً الصفحة الأصلية.

هل أحتاج إلى بروكسي عند حل GeeTest v3؟

ليس شرطاً في معظم الحالات، إذ تعيد الخدمة ثلاثية حل صالحة اعتماداً على gt وchallenge. لكن إذا كان الموقع يربط الجلسة بعنوان IP معيّن أو يطبّق تحديد معدل صارماً، فقد يساعد استخدام خادم وسيط ثابت للحفاظ على اتساق الجلسة بين الاستخراج والتحقق.


أدلة ذات صلة

التعليقات غير مفعّلة لهذا المقال.