إنشاء ترويسات Kasada باستخدام cURL
أنشئ KasadaTask، وانتظر ready، ثم أرسل كائن solution.headers بأكمله مع هوية المتصفح المُعادة عبر الوكيل نفسه. يدعم Kasada المستقل حالياً أهداف HTTPS على www.ticketmaster.com.
في هذه الصفحة
الإنشاء والاستعلام الدوري والإرسال باستخدام cURL
يتطلب السكربت Bash وcURL 7.76 أو أحدث وjq وopenssl. اضبط SOLVETHREE_API_KEY على مفتاح API لمساحة عملك، وSOLVETHREE_PROXY على عنوان URL لوكيل HTTP أو HTTPS لديك. احتفظ بمفتاح API على جانب الخادم وأبقِ تتبّع الصدفة معطّلاً.
يستخدم هذا المثال وكيلاً واحداً طوال العملية. يتطلب طلب Kasada الحقلين type وurl وواحداً فقط من proxy أو proxyCandidates؛ ويجب ألا يتضمن حقول reCAPTCHA مثل site أو action، أو session، أو حقول هوية متصفح مخصصة. راجع مواصفات طلب Kasada.
#!/usr/bin/env bash
set -euo pipefail
: "${SOLVETHREE_API_KEY:?Set the API key}" "${SOLVETHREE_PROXY:?Set the proxy}"
# Requires bash, curl, jq and openssl. Do not enable shell tracing.
work=$(mktemp -d)
chmod 700 "$work"
trap 'rm -rf "$work"' EXIT
request_id=$(openssl rand -hex 16)
printf 'Recovery requestId=%s\n' "$request_id"
printf 'Authorization: Bearer %s\n' "$SOLVETHREE_API_KEY" > "$work/auth"
jq -n --arg proxy "$SOLVETHREE_PROXY" --arg id "$request_id" '{"type":"KasadaTask","url":"https://www.ticketmaster.com/","proxy":$proxy,"requestId":$id}' > "$work/input.json"
api='https://api.solvethree.com/v1'
curl --fail-with-body --silent --show-error --max-time 30 \
--header @"$work/auth" --header 'Content-Type: application/json' \
--data-binary @"$work/input.json" --output "$work/result.json" "$api/tasks?waitMs=0"
task_id=$(jq -er '.id' "$work/result.json")
encoded_id=$(jq -nr --arg id "$task_id" '$id|@uri')
printf 'Recovery taskId=%s\n' "$task_id"
deadline=$((SECONDS + 180))
while [[ $(jq -r '.status' "$work/result.json") =~ ^(pending|solving)$ ]]; do
remaining=$((deadline - SECONDS))
(( remaining > 0 )) || { echo 'Local deadline reached; resume the saved task ID' >&2; exit 1; }
timeout=$((remaining < 25 ? remaining : 25))
curl --fail-with-body --silent --show-error --max-time "$timeout" \
--header @"$work/auth" --output "$work/result.json" "$api/tasks/$encoded_id?waitMs=15000"
[[ $(jq -r '.status' "$work/result.json") =~ ^(pending|solving)$ ]] && sleep 1 || true
done
[[ $(jq -r '.status' "$work/result.json") == ready ]] || { echo 'Solver task failed' >&2; exit 1; }
user_agent=$(jq -er '.solution.userAgent' "$work/result.json")
client_hints=$(jq -er '.solution.secChUa' "$work/result.json")
jq -r '.solution.headers | to_entries[] | "\(.key): \(.value)"' "$work/result.json" > "$work/target-headers"
curl --silent --show-error --max-time 30 --proxy "$SOLVETHREE_PROXY" \
--header @"$work/target-headers" --user-agent "$user_agent" \
--header "sec-ch-ua: $client_hints" --output "$work/target-response" \
--write-out 'Target HTTP %{http_code}\n' 'https://www.ticketmaster.com/'
# Inspect the application's response before treating the operation as successful.
# Replace the example target path with the actual supported workflow URL.استبدل عنوان URL المستهدف في المثال، في كلٍّ من متن المهمة واستدعاء cURL النهائي، بعنوان URL المقصود لسير العمل المدعوم. لا تنفّذ الحل لعنوان URL ثم ترسل النتيجة إلى هدف غير ذي صلة.
يجري السكربت المصادقة باستخدام ترويسة Bearer، وينشئ مهمة واحدة، ويستعلم دورياً عن معرّفها المُعاد فقط. لإنشاء المهمة مهلة طلب تبلغ 30 ثانية؛ ويستخدم الاستعلام الدوري مهلة محلية تبلغ 180 ثانية وطلبات GET محدودة المدة. هذه حدود للسكربت، وليست ضمانات لمدة الحل. لا تُفعَّل إعادة المحاولة التلقائية ولا متابعة إعادة التوجيه.
تطبيق كائن الترويسات بأكمله
تعني pending وsolving مواصلة الاستعلام الدوري. تحتوي ready وحدها على حل قابل للاستخدام. يقرأ السكربت كائن solution.headers الخام باستخدام jq ويحوّل كل إدخال إلى سطر في ملف الترويسات؛ ولا يختار ترويسة واحدة أو يعامل معرّف المهمة على أنه الحل.
يحمّل الطلب النهائي ملف الترويسات هذا، ويضبط solution.userAgent وsolution.secChUa، ويستخدم الوكيل الأصلي. احتفظ بهذه القيم معاً بدلاً من استبدالها بترويسات متصفحك المعتادة.
تبقى استجابات API والترويسات المُنشأة واستجابة الهدف في مجلد مؤقت خاص بدلاً من طباعتها. أبقِها خارج السجلات الاعتيادية، ولا تفعّل تتبّع الصدفة.
استرداد المهمة بدلاً من إنشاء أخرى
احفظ معرّفات الاسترداد المطبوعة. تؤدي إعادة تشغيل السكربت إلى إنشاء requestId جديد؛ وليست محاولة استرداد. لاسترداد عملية الإنشاء، أعد استخدام معرّف الطلب المحفوظ مع مدخلات المهمة الأصلية نفسها تماماً. يحذف السكربت ملف المدخلات عند الخروج، لذا احتفظ بتلك المدخلات بأمان إذا احتجت إلى إعادة بناء الطلب.
- تنتهي مهلة POST قبل إرجاع معرّف المهمة.
لا يثبت انتهاء مهلة الاتصال أن إنشاء المهمة قد فشل.
جرّب هذا: أرسل طلب المهمة نفسه باستخدام requestId المحفوظ. تسترد المدخلات المتطابقة المهمة الموجودة؛ أما تغيير المدخلات مع إعادة استخدام ذلك المعرّف فيؤدي إلى تعارض.
- تنتهي المهلة المحلية للاستعلام الدوري.
استخدم معرّف المهمة المطبوع للتحقق مما إذا كانت المهمة الموجودة لا تزال قيد الانتظار أو الحل.
جرّب هذا: استأنف الاستعلام الدوري عبر GET لذلك المعرّف بمهلة محدودة أخرى. لا تنشئ مهمة بديلة لمجرد انتهاء الانتظار المحلي.
- يعيد طلب API استجابة HTTP غير ناجحة.
تستخدم استدعاءات API الخيار --fail-with-body، لذا ينتهي cURL قبل أن يقرأ السكربت حمولة نجاح.
جرّب هذا: للتشخيص، أضف معالج أخطاء HTTP يفحص متن الاستجابة المحفوظ بشكل خاص قبل التنظيف. صحّح مشكلة الطلب المُبلَّغ عنها بدلاً من إعادة المحاولة عشوائياً بالمدخلات نفسها دون تغيير.
- تصل المهمة إلى الحالة failed.
يطبع المثال رسالة فشل عامة؛ وتحتوي الاستجابة أيضاً على errorCode وerror.
جرّب هذا: افحص هذين الحقلين في فرع الفشل قبل التنظيف، ثم أوقف الاستعلام الدوري عن تلك المهمة. استند إلى السبب المُبلَّغ عنه لتحديد ما يجب تغييره. تُردّ رسوم عمليات الحل الفاشلة.
المصادر ومرجع API
شغّل مهمتك الأولى.
ابدأ برصيد قدره $5 في مساحة العمل.