عندما تُطرح تذاكر حفلة مطلوبة أو مباراة نهائية، تنفد المقاعد خلال دقائق، ويصبح تحديث الصفحة يدوياً بلا جدوى. الحل العملي هو برنامج مراقبة يفحص صفحة التذاكر تلقائياً على فترات منتظمة، ويحل اختبار CAPTCHA الذي يعترضه، ثم ينبّهك في اللحظة التي تتغيّر فيها حالة التوفر. في هذا الدليل نبني هذا البرنامج بلغة Python خطوة بخطوة، ونترك مهمة حل reCAPTCHA v2 وCloudflare Turnstile لخدمة CaptchaAI حتى يستمر الفحص دون أن يتوقف عند أول تحدٍّ.
تعتمد منصات التذاكر على اختبارات CAPTCHA وحدود المعدل (rate limiting) لكبح الوصول الآلي المكثّف، لذا فإن أي أداة مراقبة تعمل بشكل مباشر ستصطدم بهذه الحواجز سريعاً. الهدف هنا ليس التحايل على أي موقع، بل بناء مراقبة موثوقة تعمل ضمن سير عمل مصرّح به، على مواقع تملك صلاحية اختبارها أو متابعتها، مع احترام سياسات كل منصة.
سيناريو واقعي من السوق
تخيّل أن حفلة ضمن موسم الرياض أو مباراة قوية في دوري روشن السعودي قد نفدت تذاكرها، لكن المنصة تعيد أحياناً طرح مقاعد مُلغاة قبل موعد الحدث. متابعة ذلك يدوياً تعني البقاء أمام الشاشة ساعات طويلة دون ضمان. بدلاً من ذلك، يفحص برنامج المراقبة صفحة الحدث كل بضع دقائق، ويحل أي اختبار reCAPTCHA أو Turnstile يظهر، ثم يرسل تنبيهاً فورياً إلى بريدك أو قناة فريقك عند عودة المقاعد للتوفر. النتيجة: تتحرّك في الثواني الأولى بدل أن تكتشف الأمر بعد فوات الأوان.
هذا النمط نفسه ينطبق على فرق تجربة المستخدم التي تختبر مسارات الشراء على منصاتها الخاصة، أو على مشغّلي البيانات الذين يتابعون توفر التذاكر عبر عدة مواقع في وقت واحد.
كيف يعمل سير عمل المراقبة
يمر كل فحص بمسار واضح: نضبط قائمة الأحداث، نفحص التوفر، فإن ظهر اختبار CAPTCHA نحلّه عبر CaptchaAI ثم نعيد الطلب، وإلا ننتقل مباشرة إلى قراءة حالة التوفر. عند اكتشاف أي تغيّر عن الحالة السابقة يُرسَل تنبيه:
Configure events → Check availability → CAPTCHA?
↓ Yes
Solve via CaptchaAI → Retry
↓ No
Parse availability → Changed?
↓ Yes
Send alert
يعني هذا أن حل CAPTCHA ليس هدفاً بذاته، بل خطوة وسيطة تمكّن البرنامج من الوصول إلى محتوى الصفحة الحقيقي وقراءة حالة المقاعد.
المتطلبات الأساسية
قبل كتابة أي سطر، جهّز العناصر الثلاثة التالية:
| المتطلب | التفاصيل |
|---|---|
| مفتاح CaptchaAI API | أنشئ حسابك على captchaai.com |
| Python 3.8+ | مع مكتبة requests |
| الخادم الوسيط | يُنصح باستخدام وكيل سكني |
الوكيل السكني ليس رفاهية هنا؛ فمواقع التذاكر تحظر عناوين IP الخاصة بمراكز البيانات بصرامة، واستخدام عنوان سكني يقلّل تكرار ظهور اختبار CAPTCHA من الأساس. ثبّت المكتبة المطلوبة:
pip install requests
دالة حل اختبار CAPTCHA
نبدأ بدالة عامة واحدة تتعامل مع أي نوع مدعوم عبر CaptchaAI. تُرسل الدالة الطلب إلى نقطة النهاية in.php، ثم تنتظر مهلة أولية، وبعدها تستطلع النتيجة من res.php بشكل دوري حتى يعود الرمز المحلول. لاحظ أن المهلة الأولية أقصر لـ Turnstile (10 ثوانٍ) منها لبقية الأنواع (20 ثانية)، لأن وقت الحل يختلف بحسب النوع:
import requests
import time
API_KEY = "YOUR_API_KEY"
def solve_captcha(method, params):
"""Generic CaptchaAI solver for any supported method."""
params["key"] = API_KEY
params["json"] = 1
submit = requests.post("https://ocr.captchaai.com/in.php", data=params).json()
if submit.get("status") != 1:
raise RuntimeError(f"Submit error: {submit.get('request')}")
task_id = submit["request"]
initial_wait = 10 if method == "turnstile" else 20
time.sleep(initial_wait)
for _ in range(30):
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 RuntimeError(f"Solve error: {result['request']}")
time.sleep(5)
raise TimeoutError("Solve timed out")
الرسالة CAPCHA_NOT_READY تعني ببساطة أن الحل ما زال قيد المعالجة، فتُعيد الدالة الاستطلاع بعد خمس ثوانٍ. أي رمز خطأ آخر يوقف المحاولة فوراً بدل إهدار الوقت.
بناء مراقب التذاكر
الآن نبني الكلاس المسؤول عن الفحص. يحتفظ TicketMonitor بجلسة requests.Session واحدة لتثبيت ملفات تعريف الارتباط وترويسة User-Agent، ويكتشف نوع الحماية في محتوى الصفحة: إن وجد g-recaptcha يرسل الطلب بطريقة userrecaptcha مع مفتاح الموقع، وإن وجد cf-turnstile يستخدم طريقة turnstile. بعد الحصول على الرمز يعيد إرسال الطلب حاملاً حقل الاستجابة الصحيح، ثم يقارن حالة التوفر الجديدة بالحالة المخزّنة سابقاً ليقرر إرسال التنبيه:
from datetime import datetime
import json
class TicketMonitor:
def __init__(self, proxy=None):
self.session = requests.Session()
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
})
if proxy:
self.session.proxies = {
"http": f"http://{proxy}",
"https": f"http://{proxy}"
}
self.last_status = {}
def check_event(self, event):
"""Check ticket availability for an event, solving CAPTCHAs if needed."""
url = event["url"]
response = self.session.get(url)
# Handle CAPTCHA if detected
if "g-recaptcha" in response.text or "recaptcha" in response.text:
sitekey = self._extract_sitekey(response.text)
if sitekey:
token = solve_captcha("userrecaptcha", {
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": url
})
response = self.session.post(url, data={
"g-recaptcha-response": token
})
elif "cf-turnstile" in response.text:
sitekey = self._extract_turnstile_key(response.text)
if sitekey:
token = solve_captcha("turnstile", {
"method": "turnstile",
"sitekey": sitekey,
"pageurl": url
})
response = self.session.post(url, data={
"cf-turnstile-response": token
})
# Parse availability
availability = self._parse_availability(response.text, event)
# Check for changes
event_key = event["name"]
if event_key in self.last_status:
if availability != self.last_status[event_key]:
self._send_alert(event, availability)
self.last_status[event_key] = availability
return availability
def _extract_sitekey(self, html):
if 'data-sitekey="' in html:
start = html.index('data-sitekey="') + 14
end = html.index('"', start)
return html[start:end]
return None
def _extract_turnstile_key(self, html):
if 'data-sitekey="' in html:
start = html.index('data-sitekey="') + 14
end = html.index('"', start)
return html[start:end]
return None
def _parse_availability(self, html, event):
"""Parse ticket availability. Customize per ticketing site."""
available = "sold out" not in html.lower()
return {
"event": event["name"],
"available": available,
"checked_at": datetime.now().isoformat()
}
def _send_alert(self, event, availability):
"""Send availability change notification."""
status = "AVAILABLE" if availability["available"] else "SOLD OUT"
print(f"[ALERT] {event['name']}: {status}")
def monitor_all(self, events):
"""Check all events and return results."""
results = []
for event in events:
try:
result = self.check_event(event)
results.append(result)
print(f"[OK] {event['name']}: {'available' if result['available'] else 'sold out'}")
except Exception as e:
print(f"[ERROR] {event['name']}: {e}")
return results
# Usage
events = [
{
"name": "Concert - Madison Square Garden - Aug 15",
"url": "https://example-tickets.com/event/12345"
},
{
"name": "Basketball Finals - Game 7",
"url": "https://example-tickets.com/event/67890"
}
]
monitor = TicketMonitor(proxy="user:pass@proxy.example.com:8080")
results = monitor.monitor_all(events)
for r in results:
print(json.dumps(r, indent=2))
الدالة _parse_availability هي الجزء الوحيد الذي تحتاج غالباً إلى تخصيصه لكل منصة، لأن كل موقع يعبّر عن نفاد المقاعد بطريقة مختلفة في شيفرة HTML. المنطق هنا مبسّط للتوضيح فقط: أي وجود لعبارة «sold out» يعني نفاد التذاكر.
الناتج المتوقع:
[OK] Concert - Madison Square Garden - Aug 15: available
[OK] Basketball Finals - Game 7: sold out
جدولة الفحص الدوري
تشغيل السكربت يدوياً يفقده الفائدة؛ الأفضل جدولته ليعمل تلقائياً على فترات ثابتة. على أنظمة Linux وmacOS استخدم cron لتشغيله كل 15 دقيقة وتوجيه المخرجات إلى ملف سجل يمكنك مراجعته لاحقاً:
# Check every 15 minutes
*/15 * * * * cd /path/to/project && python ticket_monitor.py >> /var/log/tickets.log 2>&1
اختر الفترة بحسب أهمية الحدث: 15 دقيقة كافية للمتابعة العامة، بينما تحتاج الأحداث شديدة الطلب إلى فترات أقصر مع تقبّل ظهور اختبارات CAPTCHA أكثر تكراراً.
نصائح لتقليل تكرار اختبارات CAPTCHA
كلما قلّ عدد الاختبارات التي يواجهها البرنامج، أصبح أسرع وأقل تكلفة. تساعدك الممارسات التالية على إبقاء التكرار منخفضاً:
- ثبّت الجلسة: أعِد استخدام كائن
requests.Sessionنفسه للحفاظ على ملفات تعريف الارتباط بين الطلبات بدل بدء جلسة جديدة كل مرة. - دوّر الوكلاء السكنيين: وزّع الطلبات على مجموعة عناوين IP سكنية لتخفيف الضغط على أي عنوان واحد وتقليل حظر المعدل.
- باعِد بين الفحوصات: فترة أطول قليلاً بين كل فحص وآخر تقلّل احتمال التصنيف كحركة آلية مكثّفة.
- استخدم ترويسات واقعية: حافظ على
User-Agentوترويسات متسقة تشبه متصفحاً حقيقياً.
معالجة المشكلات الشائعة
| المشكلة | السبب المحتمل | الحل |
|---|---|---|
| ظهور اختبار CAPTCHA عند كل فحص | ثبات عنوان IP وغياب استمرارية الجلسة | فعّل ملفات تعريف الارتباط ودوّر الوكلاء السكنيين |
| الحظر بعد عدة فحوصات | تجاوز حدّ المعدل | زد الفترة بين الفحوصات واعتمد تدوير الوكلاء |
| حالة توفر غير صحيحة | تغيّر بنية الصفحة | حدّث دالة _parse_availability لتطابق بنية HTML الجديدة |
| بطء حل اختبار CAPTCHA | ضغط عالٍ على الخدمة | أضف منطق إعادة المحاولة مع التراجع الأسي |
الأسئلة الشائعة
هل مراقبة توفر التذاكر بهذه الطريقة مسموحة؟
المراقبة الآلية مشروعة حين تتم ضمن سير عمل مصرّح به وعلى مواقع تملك صلاحية متابعتها أو اختبارها، مع الالتزام بشروط استخدام كل منصة ومعدلات الطلبات المعقولة. استخدم النمط لأغراض اختبار الجودة ومتابعة التوفر المعلنة علناً، لا لأي نشاط يخالف سياسات الموقع.
كيف أستقبل التنبيهات على البريد أو Telegram؟
في المثال أعلاه تكتفي الدالة _send_alert بطباعة رسالة. لإرسال تنبيه حقيقي، عدّلها لتنفّذ طلب POST إلى Webhook خاص بـ Telegram أو خدمة بريد، أو أرسلها إلى قناة الفريق. المنطق نفسه لا يتغيّر؛ فقط تستبدل سطر الطباعة بنداء الإرسال.
ما الفرق بين مراقبة التوفر وشراء التذاكر آلياً؟
المراقبة تكتفي بقراءة حالة المقاعد وإخطارك بالتغيّر، بينما الشراء الآلي ينفّذ خطوات إتمام الشراء. هذا الدليل يغطي المراقبة فقط. لمسار الشراء المصرّح به راجع اختبار غرف الانتظار ومسارات الدفع في منصات التذاكر المملوكة.
هل تؤثر زيادة تكرار الفحص على عدد اختبارات CAPTCHA؟
نعم. كلما قصُرت الفترة بين الفحوصات ارتفع احتمال ظهور اختبار CAPTCHA وحدود المعدل، لأن حركة الطلبات تبدو أكثر كثافة. وازِن بين سرعة رصد التغيّر وبين عدد الاختبارات التي ستحلّها، واعتمد على الوكلاء السكنيين والجلسات الثابتة لتخفيف الأثر.
كيف أتعامل مع صفحات غرف الانتظار؟
غرف الانتظار الافتراضية منفصلة عن اختبارات CAPTCHA؛ على البرنامج أن يكتشف صفحة قائمة الانتظار وينتظر دوره أو يعيد المحاولة لاحقاً. تتولى CaptchaAI حل اختبار CAPTCHA الذي قد يظهر بعد اجتياز قائمة الانتظار، لا إدارة الانتظار نفسه.
احصل على مفتاح CaptchaAI API الخاص بك
جهّز مراقب التذاكر وابدأ متابعة التوفر عبر captchaai.com، ودع حل reCAPTCHA v2 وCloudflare Turnstile يجري تلقائياً داخل سير عمل مراقبة الأحداث.