مع إطلاق إيلون ماسك لطبقات API المدفوعة وإزالة البحث المجاني، وجد العديد من المطورين وفرق النمو أنفسهم أمام خيار صعب: دفع مئات الدولارات شهرياً للوصول إلى البيانات، أو اللجوء إلى كشط الويب. هذا الدليل يشرح كيفية الوصول إلى البيانات العامة على منصة X بطريقة مسؤولة، مع استخدام البروكسي السكنية لتجنب الحظر.
تنبيه قانوني: هذا الدليل مخصص للوصول إلى البيانات العامة فقط. يجب عليك احترام شروط خدمة كل منصة والقوانين المعمول بها (CFAA في الولايات المتحدة، GDPR في الاتحاد الأوروبي). الكشط غير المصرح به للبيانات الخاصة أو المحمية بتسجيل الدخول قد يكون غير قانوني.
مشهد ما بعد قيود API على تويتر/إكس
في عام 2023، أجرت منصة X تغييرات جذرية على واجهة برمجة التطبيقات الخاصة بها:
- إزالة المستوى المجاني: لم يعد الوصول المجاني إلى API متاحاً للبحث أو قراءة التغريدات
- Basic Tier بمبلغ 100$/شهر: يسمح بـ 10,000 طلب قراءة شهرياً فقط
- Pro Tier بمبلغ 5,000$/شهر: يسمح بـ 1 مليون طلب شهرياً
- Enterprise Tier: أسعار مخصصة للشركات الكبرى
لهذه التغييرات، انتقلت العديد من الفرق التي كانت تعتمد على API المجاني إلى كشط الويب كبديل عملي. لكن X قامت بتشديد إجراءات مكافحة الكشط بشكل كبير.
لماذا تفرض X قيوداً صارمة على الكشط؟
تستخدم X عدة طبقات من الحماية:
- كشف نطاقات IP مراكز البيانات: نطاقات AWS وAzure وGoogle Cloud وغيرها مفلترة بشكل نشط
- تحليل بصمة المتصفح: تفحص X بصمة TLS وبصمة JavaScript للمتصفح
- حدود معدل صارمة للجلسات غير المسجلة: المستخدمون غير المسجلين يواجهون حدوداً أقل بكثير
- تحديات CAPTCHA المتكررة: تظهر للمستخدمين المشبوه بهم
البيانات المتاحة publicly مقابل المحمية بتسجيل الدخول
قبل البدء، من المهم فهم ما يمكن الوصول إليه بدون تسجيل دخول:
بيانات متاحة بدون تسجيل دخول
- الملفات الشخصية العامة (الاسم، الوصف، عدد المتابعين)
- التغريدات العامة الفردية (عبر رابط مباشر)
- الردود على التغريدات
- المواضيع الرائجة (Trending) حسب المنطقة
- بعض نتائج البحث المحدودة
بيانات تتطلب تسجيل دخول
- البحث المتقدم مع فلاتر متعددة
- جداول زمنية كاملة للمستخدمين
- قوائم المتابعين والمتابَعين
- الإشارات والرسائل المباشرة
- التغريدات من الحسابات المحمية
هذا الدليل يركز فقط على البيانات العامة المتاحة بدون تسجيل دخول، لأن الكشط بعد تسجيل الدخول ينتهك شروط الخدمة بشكل صريح.
لماذا البروكسي السكنية ضرورية لكشط X
تفرض X تمييزاً صارماً بين أنواع عناوين IP:
| نوع IP | السلوك المتوقع | معدل الحظر |
|---|---|---|
| سكني حقيقي (ISP) | يعامل كمستخدم عادي | منخفض جداً |
| مركز بيانات (DC) | مفلتر بشكل نشط | مرتفع جداً |
| موبايل (4G/5G) | أعلى ثقة | d>منخفض للغاية |
| بروكسي مجانية | محظورة مسبقاً | شبه مؤكد |
آليات كشف مركز البيانات
تستخدم X عدة تقنيات لتحديد IPs مركز البيانات:
- قواعد WHOIS: التحقق من ملكية IP (شركة اتصالات vs مركز بيانات)
- قواعد ASN: تصفية نطاقات ASN المعروفة للخدمات السحابية
- السلوك التاريخي: IPs التي أظهرت سلوك كشط سابقاً
- تحليل حركة المرور: أنماط الطلب غير البشرية
البروكسي السكنية توفر IPs من مزودي خدمة إنترنت حقيقيين (ISPs)، مما يجعل طلباتك تبدو كأنها من مستخدمين عاديين.
تنفيذ Python مع Playwright والبروكسي السكنية
X تستخدم بنية Single Page Application (SPA) تعتمد على GraphQL. البيانات مضمنة في استجابات JSON داخل الصفحة. إليك كيفية استخراجها:
إعداد المشروع
# تثبيت المتطلبات
# pip install playwright proxyhat-python
# playwright install chromium
import asyncio
import json
import re
from playwright.async_api import async_playwright
class XScraper:
def __init__(self, proxy_config):
self.proxy = proxy_config
self.base_url = "https://x.com"
async def create_browser_context(self, playwright):
browser = await playwright.chromium.launch(
proxy={
"server": f"http://{self.proxy['host']}:{self.proxy['port']}",
"username": self.proxy['username'],
"password": self.proxy['password']
},
headless=True
)
context = await browser.new_context(
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
viewport={"width": 1920, "height": 1080}
)
return browser, context
كشف ملف تعريف المستخدم
async def scrape_profile(self, username):
"""كشف ملف تعريف مستخدم عام"""
async with async_playwright() as p:
browser, context = await self.create_browser_context(p)
page = await context.new_page()
# اعتراض طلبات GraphQL
graphql_responses = []
async def capture_response(response):
if "graphql" in response.url:
try:
data = await response.json()
graphql_responses.append(data)
except:
pass
page.on("response", capture_response)
# التنقل إلى الصفحة
await page.goto(f"{self.base_url}/{username}", wait_until="networkidle")
await asyncio.sleep(2) # انتظار تحميل JavaScript
# استخراج البيانات من استجابات GraphQL
profile_data = self.extract_profile_data(graphql_responses)
await browser.close()
return profile_data
def extract_profile_data(self, responses):
"""استخراج بيانات الملف الشخصي من استجابات GraphQL"""
for response in responses:
if "user" in response.get("data", {}):
user = response["data"]["user"]
return {
"id": user.get("id"),
"name": user.get("legacy", {}).get("name"),
"screen_name": user.get("legacy", {}).get("screen_name"),
"description": user.get("legacy", {}).get("description"),
"followers_count": user.get("legacy", {}).get("followers_count"),
"friends_count": user.get("legacy", {}).get("friends_count"),
"statuses_count": user.get("legacy", {}).get("statuses_count"),
"created_at": user.get("legacy", {}).get("created_at"),
"verified": user.get("legacy", {}).get("verified"),
}
return None
استخدام البروكسي السكنية من ProxyHat
# تكوين البروكسي السكنية مع التدوير
proxy_config = {
"host": "gate.proxyhat.com",
"port": 8080,
"username": "user-country-US-session-" + str(int(time.time())),
"password": "your_password"
}
# تشغيل الكشف
scraper = XScraper(proxy_config)
profile = asyncio.run(scraper.scrape_profile("elonmusk"))
print(json.dumps(profile, indent=2))
كشف التغريدات والردود
async def scrape_tweet_with_replies(self, tweet_id):
"""كشف تغريدة مع ردودها"""
async with async_playwright() as p:
browser, context = await self.create_browser_context(p)
page = await context.new_page()
tweet_data = []
async def capture_response(response):
if "TweetDetail" in response.url or "Tweet" in response.url:
try:
data = await response.json()
tweet_data.append(data)
except:
pass
page.on("response", capture_response)
await page.goto(f"{self.base_url}/i/status/{tweet_id}")
await asyncio.sleep(3)
# التمرير لتحميل المزيد من الردود
for _ in range(3):
await page.evaluate("window.scrollBy(0, 1000)")
await asyncio.sleep(1)
await browser.close()
return self.parse_tweet_data(tweet_data)
مثال Node.js مع بروكسي سكنية
const { chromium } = require('playwright');
async function scrapeXProfile(username, proxyConfig) {
const browser = await chromium.launch({
proxy: {
server: `http://${proxyConfig.host}:${proxyConfig.port}`,
username: proxyConfig.username,
password: proxyConfig.password
},
headless: true
});
const context = await browser.newContext({
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
});
const page = await context.newPage();
// اعتراض استجابات GraphQL
const graphqlData = [];
page.on('response', async (response) => {
if (response.url().includes('graphql')) {
try {
const data = await response.json();
graphqlData.push(data);
} catch (e) {}
}
});
await page.goto(`https://x.com/${username}`);
await page.waitForTimeout(3000);
await browser.close();
return extractProfileFromGraphQL(graphqlData);
}
// تكوين ProxyHat
const proxyConfig = {
host: 'gate.proxyhat.com',
port: 8080,
username: 'user-country-US-session-' + Date.now(),
password: 'your_password'
};
scrapeXProfile('elonmusk', proxyConfig).then(console.log);
التعامل مع حدود المعدل و429 Errors
تستخدم X نظام حدود معدل متعدد الطبقات:
أنواع الحدود
- حدود مستوى IP: عدد الطلبات من عنوان IP واحد في فترة زمنية
- حدود مستوى الجلسة: مرتبطة بملفات تعريف الارتباط والرموز المميزة
- حدود مستوى الحساب: للمستخدمين المسجلين (لا ينطبق على الكشط العام)
- نوافذ منزلقة: حدود تُعاد حسابها باستمرار
استراتيجيات التخفيف
import time
import random
from functools import wraps
def rate_limit_handler(max_retries=3, backoff_base=60):
"""مزين للتعامل مع حدود المعدل"""
def decorator(func):
@wraps(func)
async def wrapper(*args, **kwargs):
for attempt in range(max_retries):
try:
result = await func(*args, **kwargs)
return result
except Exception as e:
if "429" in str(e) or "rate" in str(e).lower():
wait_time = backoff_base * (2 ** attempt) + random.randint(1, 10)
print(f"Rate limited. Waiting {wait_time}s...")
await asyncio.sleep(wait_time)
# تدوير جلسة البروكسي
kwargs['session_id'] = f"session-{int(time.time())}"
else:
raise e
raise Exception("Max retries exceeded")
return wrapper
return decorator
class ProxyRotator:
"""تدوير البروكسي تلقائياً"""
def __init__(self, base_username, password):
self.base_username = base_username
self.password = password
self.request_count = 0
self.max_requests_per_session = 50
def get_proxy_config(self):
"""الحصول على تكوين بروكسي مع جلسة جديدة عند الحاجة"""
if self.request_count >= self.max_requests_per_session:
self.request_count = 0
session_id = f"session-{int(time.time())}-{random.randint(1000, 9999)}"
self.request_count += 1
return {
"host": "gate.proxyhat.com",
"port": 8080,
"username": f"{self.base_username}-session-{session_id}",
"password": self.password
}
أفضل الممارسات للحدود
- حدد سرعة الطلبات: لا تتجاوز 1-2 طلب في الثانية لكل جلسة
- استخدم جلسات لاصقة: حافظ على نفس IP للطلبات المرتبطة
- راقب استجابات 429: استخدم backoff أسي
- وزع على IPs متعددة: استخدم بروكسي سكنية متعددة
- قلد السلوك البشري: أضف تأخيرات عشوائية
الإطار القانوني ووعي شروط الخدمة
القضايا القانونية الأخيرة
شهدت السنوات الأخيرة عدة قضايا مهمة:
- hiQ Labs v. LinkedIn: أكدت محكمة الاستئناف أن البيانات العامة يمكن كشطها، لكن مع قيود
- Meta v. Bright Data: تسوية حول كشط Facebook
- X Corp v. Various Scrapers: X تستهدف نشطاً مزودي أدوات الكشط
الاستنتاج العام: كشط البيانات العامة قد يكون قانونياً، لكن انتهاك شروط الخدمة قد يعرضك لمسؤولية قانونية.
ما يجب تجنبه
- كشط بيانات المستخدمين المحمية (حسابات خاصة)
- استخدام بيانات الاعتماد المسروقة أو المسجلة
- تجاوز CAPTCHA تلقائياً بشكل متكرر
- بيع البيانات المكدوشة لمنافسين
- إرسال حجم طلبات يؤثر على أداء المنصة
ما هو مقبول عموماً
- كشف البيانات العامة المتاحة بدون تسجيل دخول
- مراقبة الاتجاهات والمواضيع الرائجة
- تحليل المشاعر للأغراض البحثية
- أرشفة المحتوى العام
متى تستخدم API الرسمية بدلاً من الكشط
في بعض الحالات، API الرسمية هو الخيار الأفضل:
| المعيار | API الرسمية | كشط الويب |
|---|---|---|
| الحجم | مناسب للكميات الكبيرة | مناسب للكميات الصغيرة-المتوسطة |
| الاستقرار | عقود SLA واضحة | قد يتغير هيكل الصفحة |
| التكلفة | 100$-5000$/شهر | تكلفة البروكسي فقط |
| البيانات | بيانات منظمة وموثوقة | قد تكون غير مكتملة |
| المخاطر القانونية | لا توجد | مخاطر محتملة |
استخدم API الرسمية عندما:
- تحتاج إلى أكثر من 100,000 طلب شهرياً
- تبني منتجاً تجارياً يعتمد على البيانات
- تحتاج إلى بيانات تاريخية
- تتطلب بيانات الوقت الحقيقي
- الامتثال القانوني ضروري
استخدم الكشط عندما:
- تحتاج إلى بيانات محدودة (أقل من 10,000 طلب/شهر)
- الميزانية محدودة
- تجري بحثاً أكاديمياً
- تحتاج فقط لملفات تعريف عامة
- تختبر نموذجاً قبل الالتزام بـ API
النقاط الرئيسية
- بعد قيود API الجديدة، أصبح كشط الويب حلاً للوصول إلى البيانات العامة
- البروكسي السكنية ضرورية لأن X تحظر نطاقات مركز البيانات بشكل نشط
- ركز فقط على البيانات العامة المتاحة بدون تسجيل دخول
- استخدم تدوير الجلسات والحدود المعدلة لتجنب الحظر
- احترم شروط الخدمة والقوانين المعمول بها
- فكر في API الرسمية للمشاريع التجارية الكبيرة
للبدء مع البروكسي السكنية الموثوقة، يمكنك زيارة صفحة التسعير أو استكشاف حالات استخدام كشط الويب الأخرى.






