جمع بيانات المنصات الاجتماعية للأبحاث يصمد بأربعة عناصر مجتمعة: وتيرة طلبات قريبة من سلوك مستخدم حقيقي، خادم وسيط مناسب لكل منصة، جلسة ثابتة تحتفظ بالكوكيز، وخدمة حل مثل CaptchaAI ترسل التحدي وتعيد الرمز خلال ثوانٍ فيكمل السكربت من النقطة نفسها. اختلال أي عنصر منها يظهر سريعًا وبالشكل نفسه: صفحة تحقق بدل النتائج بعد بضع عشرات من الطلبات، ودفعة تتوقف عند منتصفها.
الدليل موجّه لفرق البحث السوقي ووكالات مراقبة العلامة التجارية والباحثين الأكاديميين. النطاق محدد: محتوى منشور للعموم أو حسابات تملكها، مع الالتزام بشروط الخدمة وحدود المعدل المعلنة.
لماذا يتوقف جمع بيانات وسائل التواصل الاجتماعي عند CAPTCHA؟
المنصات الاجتماعية من أكثر المواقع استثمارًا في كشف الأنماط الآلية، لأن محتواها هو رأس مالها. التحدي لا يظهر عشوائيًا، بل حين تتقاطع إشارات معروفة:
- وتيرة ثابتة رياضيًا — طلب كل ثانيتين بالضبط أوضح من أي بصمة متصفح.
- عنوان IP من مركز بيانات، أو عنوان سبق استخدامه في حملات جمع مكثفة.
- جلسة بلا تاريخ: لا كوكيز ولا صفحات وسيطة، ودخول مباشر إلى نتائج البحث.
- تعارض بين ترويسة User-Agent وسلوك العميل.
باجتماع إشارتين أو ثلاث تتحول الصفحة إلى reCAPTCHA أو Turnstile. الهدف إذًا مزدوج: تقليل التحديات التي تستدعيها، وحلّ ما يظهر منها آليًا.
خريطة اختبارات CAPTCHA على منصات التواصل الاجتماعي
| المنصة | نوع الاختبار | متى يظهر | السبب |
|---|---|---|---|
| reCAPTCHA v2 | الدخول والبحث وفتح الملفات | كثافة الطلبات | |
| reCAPTCHA v2 | الدخول وعمليات بحث متكررة | نقطة تحقق أمنية | |
| X (Twitter) | Cloudflare Turnstile | الدخول والوصول إلى API | فلترة الطلبات الآلية |
| TikTok | reCAPTCHA v3 | مشاهدة الملفات والبحث | جودة حركة المرور |
| Cloudflare Challenge | تصفّح مكثف للملفات | كشف السلوك الآلي | |
| reCAPTCHA v2 | الدخول والتصفّح المكثف | منع إساءة الاستخدام |
يغطي CaptchaAI هذه العائلات ضمن أنواعه المتاحة عمومًا: reCAPTCHA v2 بنسخه — Invisible وEnterprise — وv3 وCloudflare Turnstile وCloudflare Challenge وGeeTest v3 والصور/OCR وتحديات شبكة الصور وBLS، مع CaptchaFox وFriendly Captcha وLemin في مرحلة beta. في المقابل لا يدعم hCaptcha ولا FunCaptcha، وGeeTest v4 معلن كقادم قريبًا لا أكثر.
حدود التشغيل لكل منصة: الوتيرة والجلسة والخادم الوسيط
الوتيرة أرخص إجراء وقائي لديك: كل تحدٍّ لا يظهر هو ثوانٍ لم تدفعها من زمن الدفعة. ابدأ من هذه الحدود المحافظة ثم عايرها على بياناتك.
| المنصة | معدل طلبات آمن | طول الجلسة | الخادم الوسيط المفضل |
|---|---|---|---|
| طلب كل 10 ثوانٍ | 5 دقائق | جوّال 4G | |
| طلب كل 5 ثوانٍ | 10 دقائق | سكني | |
| X (Twitter) | طلب كل 3 ثوانٍ | 15 دقيقة | سكني |
| TikTok | طلب كل 5 ثوانٍ | 5 دقائق | جوّال 4G |
| طلب كل 10 ثوانٍ | 5 دقائق | سكني عبر مزود خدمة | |
| طلب كل ثانيتين | 30 دقيقة | سكني دوّار |
المنطق وراء العمود الأخير: Instagram وTikTok يتوقعان حركة من أجهزة محمولة، وFacebook وX يضعان علامات مشددة على عناوين مراكز البيانات، وReddit يحسب حدوده لكل عنوان IP. أضف تشويشًا عشوائيًا بين 20% و40% حول كل قيمة، واجعل موقع الخادم مطابقًا للجمهور: الوسوم الرائجة التي يراها زائر من دبي غير التي يراها خادم في فرانكفورت. التفاصيل في الخوادم الوسيطة الجوّالة ومعدلات الحل.
هيكل جامع بيانات يتعامل مع التحدي تلقائيًا
الفكرة بسيطة: جلسة requests واحدة تحمل الكوكيز والترويسات، ودالة solve_captcha ترسل التحدي إلى in.php ثم تستطلع res.php حتى يعود الرمز. الكاشف _has_captcha يبحث في HTML عن data-sitekey أو cf-turnstile، ثم يعيد إرسال الطلب مع g-recaptcha-response أو cf-turnstile-response بحسب النوع. الاحتفاظ بالجلسة بعد الحل هو ما يمنع تكرار التحدي في كل صفحة — التفاصيل في الحفاظ على جلسة المتصفح.
import requests
import time
import re
CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"
def solve_captcha(method, sitekey, pageurl, **kwargs):
data = {
"key": CAPTCHAAI_KEY,
"method": method,
"googlekey": sitekey,
"pageurl": pageurl,
"json": 1,
}
data.update(kwargs)
resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data=data)
task_id = resp.json()["request"]
for _ in range(60):
time.sleep(5)
result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
"key": CAPTCHAAI_KEY, "action": "get",
"id": task_id, "json": 1,
})
r = result.json()
if r["request"] != "CAPCHA_NOT_READY":
return r["request"]
raise TimeoutError("Solve timeout")
class SocialMediaResearcher:
def __init__(self, proxy=None):
self.session = requests.Session()
if proxy:
self.session.proxies = {"http": proxy, "https": proxy}
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) "
"AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 "
"Mobile/15E148 Safari/604.1",
"Accept-Language": "en-US,en;q=0.9",
})
def authenticate(self, login_url, credentials, sitekey):
"""Login with CAPTCHA handling."""
# Load login page
self.session.get(login_url)
# Solve CAPTCHA
token = solve_captcha("userrecaptcha", sitekey, login_url)
# Submit login
resp = self.session.post(login_url, data={
**credentials,
"g-recaptcha-response": token,
})
return resp.status_code == 200
def collect_profiles(self, profile_urls):
"""Collect public profile data with CAPTCHA handling."""
profiles = []
for url in profile_urls:
try:
resp = self.session.get(url, timeout=30)
# Handle CAPTCHA if triggered
if self._has_captcha(resp.text):
resp = self._handle_captcha(resp.text, url)
profiles.append({
"url": url,
"data": self._parse_profile(resp.text),
"status": "success",
})
time.sleep(5) # Slow down between profiles
except Exception as e:
profiles.append({
"url": url,
"error": str(e),
"status": "failed",
})
return profiles
def _has_captcha(self, html):
return any(tag in html.lower() for tag in [
'data-sitekey', 'g-recaptcha', 'cf-turnstile',
'challenge-platform', 'captcha',
])
def _handle_captcha(self, html, url):
match = re.search(r'data-sitekey="([^"]+)"', html)
if not match:
return self.session.get(url)
sitekey = match.group(1)
if 'cf-turnstile' in html:
token = solve_captcha("turnstile", sitekey, url)
return self.session.post(url, data={"cf-turnstile-response": token})
else:
token = solve_captcha("userrecaptcha", sitekey, url)
return self.session.post(url, data={"g-recaptcha-response": token})
def _parse_profile(self, html):
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "html.parser")
return {
"name": self._safe_text(soup, "h1, .profile-name"),
"bio": self._safe_text(soup, ".bio, .profile-bio"),
"followers": self._safe_text(soup, "[data-followers], .followers"),
"posts": self._safe_text(soup, "[data-posts], .posts-count"),
}
def _safe_text(self, soup, selector):
el = soup.select_one(selector)
return el.get_text(strip=True) if el else ""
مثال تطبيقي: رصد وسم حملة في السوق الخليجي
وكالة في الرياض تتابع حملة تجزئة في موسم الجمعة البيضاء تحتاج تقريرًا يوميًا عن الوسم الرسمي: عدد المنشورات، نبرة التعليقات، أكثر الحسابات تفاعلًا. المشروع صغير — خمس صفحات لكل وسم — لكنه يعمل ثلاثة أسابيع، وهنا يظهر الفرق بين سكربت يتوقف عند أول تحدٍّ وآخر يكمل الدفعة.
نقطتان عمليتان هنا: الوسوم العربية تحتاج ترميز URL صحيحًا قبل إرسالها في مسار الطلب، وتوقيت التشغيل يجب أن يقارب ذروة النشاط المحلي مساءً بتوقيت الخليج، وإلا تأخر التقرير دورة كاملة عن الحملة.
def research_hashtag(hashtag, platform_url, pages=5):
"""Collect posts for a specific hashtag."""
researcher = SocialMediaResearcher(
proxy="http://user:[email protected]:5000"
)
all_posts = []
for page in range(pages):
url = f"{platform_url}/explore/tags/{hashtag}?page={page}"
resp = researcher.session.get(url, timeout=30)
if researcher._has_captcha(resp.text):
resp = researcher._handle_captcha(resp.text, url)
from bs4 import BeautifulSoup
soup = BeautifulSoup(resp.text, "html.parser")
posts = soup.select(".post-item, article")
for post in posts:
all_posts.append({
"text": post.get_text(strip=True)[:500],
"hashtag": hashtag,
"page": page,
})
time.sleep(5)
return all_posts
مسح يومي لذكر العلامة التجارية عبر المنصات
الفارق بين بحث لمرة واحدة ومراقبة مستمرة هو الجدولة: المنطق نفسه داخل مهمة يومية تكتب تقريرًا بصيغة JSON يُقارَن بتقرير الأمس. احتفظ بحقل خطأ لكل كلمة مفتاحية بدل إسقاط المسح كله عند فشل واحد.
import json
from datetime import datetime
class BrandMonitor:
def __init__(self, brand_name, keywords, proxy=None):
self.brand = brand_name
self.keywords = keywords
self.researcher = SocialMediaResearcher(proxy=proxy)
def daily_scan(self, platform_urls):
"""Run daily brand mention scan across platforms."""
report = {
"brand": self.brand,
"date": datetime.now().isoformat(),
"platforms": {},
}
for name, url in platform_urls.items():
mentions = []
for keyword in self.keywords:
search_url = f"{url}/search?q={keyword}"
try:
resp = self.researcher.session.get(search_url, timeout=30)
if self.researcher._has_captcha(resp.text):
resp = self.researcher._handle_captcha(
resp.text, search_url,
)
from bs4 import BeautifulSoup
soup = BeautifulSoup(resp.text, "html.parser")
results = soup.select(".search-result, .post")
mentions.append({
"keyword": keyword,
"count": len(results),
})
time.sleep(5)
except Exception as e:
mentions.append({
"keyword": keyword,
"error": str(e),
})
report["platforms"][name] = mentions
return report
# Usage
monitor = BrandMonitor(
brand_name="CaptchaAI",
keywords=["captchaai", "captcha ai", "captcha solver"],
proxy="http://user:[email protected]:5000",
)
report = monitor.daily_scan({
"twitter": "https://twitter-alternative.example.com",
"reddit": "https://www.reddit.com",
})
print(json.dumps(report, indent=2))
كم يكلّف ذلك شهريًا؟ حساب الـ threads لا حساب التحديات
فوترة CaptchaAI قائمة على عدد الـ threads المتزامنة لا على عدد التحديات، وكل خطة تشمل حلولًا غير محدودة ضمن threads الخطة خلال الشهر. السؤال الصحيح إذًا: كم جلسة سأشغّلها في اللحظة نفسها؟
- BASIC بسعر 15 دولارًا شهريًا و5 threads: مشروع رصد واحد بجلستين أو ثلاث بالتوازي.
- STANDARD بسعر 30 دولارًا شهريًا و15 thread: وكالة تتابع عدة علامات ومنصات في تقرير واحد.
- ADVANCE بسعر 90 دولارًا شهريًا و50 thread: دفعات بحث أكاديمي أو مسوح إقليمية متعددة الأسواق.
الأسعار بالدولار الأمريكي، والخطط الأعلى — CORPORATE وENTERPRISE وسلسلة VIP — تتبع المنطق نفسه بعدد أكبر من الـ threads.
معالجة الأعطال المتكررة في مشاريع الرصد
| العطل | السبب الغالب | الإجراء |
|---|---|---|
| تحدٍّ في كل طلب | عنوان IP موسوم | دوّر العناوين وانتقل إلى خادم وسيط جوّال |
| تعليق مؤقت للحساب | إجراءات كثيرة في نافذة قصيرة | خفّض الوتيرة ووزّع المهمة على ساعات أطول |
| صفحة فارغة بلا خطأ | المحتوى خلف تسجيل الدخول | سجّل الدخول بحساب تملكه قبل الجمع |
| حلقة تحدٍّ Cloudflare | تعارض الترويسات مع سلوك العميل | شغّل المسار عبر متصفح حقيقي مثل Playwright |
| محتوى مختلف عن المتصفح | اختلاف الموقع الجغرافي أو الكوكيز | طابق موقع الخادم الوسيط مع جمهور الدراسة |
| مهلة انتهاء عند الاستطلاع | مفتاح موقع خاطئ أو ضغط على الدفعة | تحقق من مفتاح الموقع ووسّع مهلة الاستطلاع |
أسئلة شائعة
كم عدد الـ threads الذي أحتاجه لمشروع رصد يومي؟
احسب الجلسات المتوازية لا عدد التحديات. متابعة ثلاث منصات بجلسة لكل منصة تعمل براحة ضمن BASIC بسعر 15 دولارًا شهريًا و5 threads. عندما يصبح التقرير كل ساعة، انتقل إلى خطة أوسع بدل رفع وتيرة الطلبات.
هل أحتاج خادمًا وسيطًا إذا كان خادمي في المنطقة العربية أصلًا؟
غالبًا نعم. المشكلة نوع العنوان لا المسافة: عناوين مراكز البيانات — ولو كانت مستضافة إقليميًا — تُوسَم سريعًا لدى Facebook وX. ما يفيدك عنوان سكني أو جوّال داخل السوق الذي تدرسه.
ماذا أفعل إذا كانت المنصة تعرض hCaptcha؟
لا يدعم CaptchaAI hCaptcha ولا FunCaptcha حاليًا، وGeeTest v4 معلن كقادم قريبًا فقط. عندها لا تبنِ المشروع على الجمع من الصفحات: اطلب الوصول عبر API الرسمية أو اعتمد مصدر بيانات مرخّصًا.
كيف أوثّق منهجية الجمع في تقرير بحثي؟
سجّل لكل تشغيل: التاريخ والوقت بالتوقيت المحلي، نوع الخادم الوسيط وموقعه، عدد الصفحات لكل وسم، معدل ظهور التحديات، والصفحات التي سقطت. هذه الحقول أول ما يسأل عنه المحكّم الأكاديمي أو مدقّق الامتثال.
اقرأ أيضًا
ابدأ رصدك اليوم دون توقف عند أول تحدٍّ — احصل على مفتاح CaptchaAI وشغّل جامع البيانات حتى نهاية الدفعة.