تنبيه قانوني: قبل البدء، يجب احترام شروط خدمة Yelp والقوانين المعمول بها مثل قانون الاحتيال وإساءة استخدام الكمبيوتر (CFAA) في الولايات المتحدة واللائحة العامة لحماية البيانات (GDPR) في الاتحاد الأوروبي. هذا الدليل يغطي البيانات العامة المتاحة دون تسجيل دخول فقط، ولا يشجع على تجاوز جدران الدفع أو استخراج بيانات شخصية بشكل غير قانوني.
إذا كنت مطوّراً يبني مجموعات بيانات للأعمال المحلية والمراجعات، فمن المرجّح أنك واجهت حظر IP أو تحديات CAPTCHA بعد عدد قليل من الطلبات إلى Yelp. في هذا الدليل سنشرح كيفية استخراج قوائم الأعمال والمراجعات من Yelp في 2026 بطريقة عملية ومسؤولة، مع التركيز على البيانات العامة واستخدام البروكسي السكني الدوّار لتجاوز دفاعات PerimeterX/HUMAN.
ما هي البيانات العامة المتاحة على Yelp دون تسجيل دخول؟
صفحات الأعمال في Yelp متاحة علناً على مسار /biz/<slug> دون الحاجة إلى حساب. كل صفحة عمل تحتوي على:
- الاسم والعنوان ورقم الهاتف — متاح في كائن JSON مضمّن يُسمى
__INITIAL_STATE__. - التقييم وعدد المراجعات — يظهر في أعلى الصفحة وفي البيانات المنظمة.
- الفئات وساعات العمل — متاحة في نفس الكائن المضمّن.
- نصوص المراجعات — تُحمّل المراجعات الأولى مع الصفحة، بينما تُجلَب المراجعات الإضافية عبر نقطة
review_feedبصيغة JSON.
يقدّم Yelp أيضاً واجهة Fusion API الرسمية، لكنها تفرض قيوداً صارمة: تُعيد البحث عن الأعمال حتى 50 نتيجة لكل طلب، وتقتصر المراجعات على 3 مراجعات فقط لكل نشاط تجاري. هذا الحد غير كافٍ لمعظم حالات استخدام تحليل المشاعر أو مراقبة السمعة على نطاق واسع، ممّا يدفع المطورين إلى استخراج البيانات من الصفحات العامة.
| المصدر | عدد المراجعات | يتطلب مفتاح API | بيانات الساعات | معدل التحديث |
|---|---|---|---|---|
| Fusion API | 3 كحد أقصى | نعم | نعم | في الوقت الفعلي تقريباً |
| صفحة /biz/ العامة | حتى 20+ لكل صفحة | لا | نعم | فوري |
| review_feed JSON | 10 لكل طلب | لا | لا | فوري |
لماذا يصعب استخراج بيانات Yelp؟ دفاعات PerimeterX/HUMAN
يستخدم Yelp منصة PerimeterX (التي أصبحت جزءاً من HUMAN Security) كطبقة حماية من البوتات. تعمل هذه الطبقة على عدة مستويات:
ملف تعريف ارتباط _px3 وتحدي المستشعر
عند زيارة أي صفحة على Yelp، يُحقن سكربت PerimeterX ملف تعريف ارتباط يُسمى _px3 مشفّر. يتضمن هذا الملف توقيعاً يعتمد على بصمة المتصفح، ومسار الماوس، وسرعة الكتابة، وغيرها من إشارات السلوك. إذا فشل المتصفح في حل "تحدي المستشعر" خلال نحو 200 مللي ثانية، يُعاد توجيه الطلب إلى صفحة CAPTCHA أو يُحظر الـ IP مباشرة.
بصمة TLS (JA3/JA4)
يقوم PerimeterX بفحص بصمة TLS 1.3 للعميل. مكتبات مثل requests أو urllib في Python تنتج بصمة TLS مختلفة جذرياً عن متصفح Chrome الحقيقي، ممّا يكشفها فوراً حتى قبل فحص أي ملف تعريف ارتباط.
سمعة IP وحظر مراكز البيانات
بعد 3–5 طلبات فقط من عنوان IP ينتمي إلى مركز بيانات معروف (مثل AWS أو DigitalOcean)، يُفعّل PerimeterX حظراً مؤقتاً مدته 24 ساعة أو تحدي CAPTCHA دائم. هذا هو السبب الرئيسي لفشل أدوات الاستخراج البسيطة.
لماذا تحتاج إلى بروكسي سكني دوّار مع استهداف جغرافي للولايات المتحدة؟
نتائج Yelp تتأثر بالموقع الجغرافي للزائر. إذا طلبت صفحة عمل من IP في ألمانيا، فقد ترى ساعات عمل مختلفة أو فروعاً بديلة. لذلك، من الضروري استخدام بروكسي سكني بـ IP من الولايات المتحدة، ويفضّل استهداف مدينة محددة:
- البروكسي السكني يمنحك IP حقيقي من مزود إنترنت منزلي، بسمعة عالية لدى PerimeterX.
- الدوران لكل طلب يوزّع الطلبات عبر آلاف الـ IP، ممّا يقلل احتمال الحظر.
- الجلسات الثابتة (Sticky) تحافظ على نفس الـ IP لمدة محددة، ممّا يبقي ملفات تعريف الارتباط صالحة.
- استهداف المدينة يضمن نتائج محلية دقيقة، مثل
-country-US-city-austin.
يمكنك الاطلاع على المواقع المتاحة لدعم استهداف المدن في ProxyHat.
إعداد ProxyHat: البوابة والمنافذ
تستخدم جميع الأمثلة في هذا الدليل بوابة ProxyHat التالية:
- HTTP:
http://USERNAME:PASSWORD@gate.proxyhat.com:8080 - SOCKS5:
socks5://USERNAME:PASSWORD@gate.proxyhat.com:1080
تُمرّر أعلام الاستهداف الجغرافي والجلسة في اسم المستخدم. مثال:
http://user-country-US-city-austin-session-abc123:pass@gate.proxyhat.com:8080
راجع وثائق ProxyHat للتفاصيل الكاملة، وصفحة الأسعار لخطط البروكسي السكني.
مثال عملي 1: استخراج المراجعات باستخدام Python وrequests
في هذا المثال نستخرج كائن __INITIAL_STATE__ المضمّن من صفحة عمل، ثم نضرب نقطة review_feed لجلب المزيد من المراجعات. نستخدم بروكسي سكني دوّار مع جلسة ثابتة:
import requests
import re
import json
import time
import random
PROXY = "http://user-country-US-city-austin-session-sess01:pass@gate.proxyhat.com:8080"
PROXIES = {"http": PROXY, "https": PROXY}
HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Accept-Language": "en-US,en;q=0.9",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
}
biz_slug = "the-french-laundry-yountville"
url = f"https://www.yelp.com/biz/{biz_slug}"
resp = requests.get(url, headers=HEADERS, proxies=PROXIES, timeout=30)
if resp.status_code != 200:
print(f"Blocked or error: {resp.status_code}")
exit(1)
# استخراج __INITIAL_STATE__ المضمّن
match = re.search(r'<script[^>]*>window\.__INITIAL_STATE__\s*=\s*({.*?});</script>',
resp.text, re.DOTALL)
if match:
state = json.loads(match.group(1))
biz = state.get("biz", {}).get(biz_slug, {})
name = biz.get("name", "N/A")
rating = biz.get("rating", "N/A")
review_count = biz.get("reviewCount", 0)
print(f"Business: {name} | Rating: {rating} | Reviews: {review_count}")
# استخراج أول مراجعة مضمّنة (مقتطعة)
reviews = biz.get("reviews", [])
if reviews:
first = reviews[0]
print(f"Review by {first.get('author', {}).get('name', 'N/A')}:")
print(f" Rating: {first.get('rating', 'N/A')}")
print(f" Text: {first.get('comment', {}).get('text', '')[:200]}...")
# جلب المزيد من المراجعات عبر review_feed
feed_url = f"https://www.yelp.com/biz/{biz_slug}/review_feed?rl=en&sort_by=date_desc&start=20"
time.sleep(random.uniform(2, 5)) # تباطؤ عشوائي
feed_resp = requests.get(feed_url, headers=HEADERS, proxies=PROXIES, timeout=30)
if feed_resp.status_code == 200:
feed_data = feed_resp.json()
for r in feed_data.get("reviews", [])[:3]:
author = r.get("author", {}).get("name", "N/A")
text = r.get("comment", {}).get("text", "")[:150]
print(f" - {author}: {text}...")
else:
print(f"Feed blocked: {feed_resp.status_code}")
النقاط الرئيسية في هذا الكود:
- استخدمنا جلسة ثابتة
session-sess01للحفاظ على نفس الـ IP وملف تعريف الارتباط_px3. - أضفنا تأخيراً عشوائياً بين 2 و5 ثوانٍ بين الطلبات لتقليل خطر الكشف.
- استخرجنا فقط أول 200 حرف من نص المراجعة لأغراض العرض.
مثال عملي 2: استخراج بيانات Yelp باستخدام Node.js وSOCKS5
في هذا المثال نستخدم Node.js مع مكتبة socks-proxy-agent للاتصال عبر منفذ SOCKS5 الخاص بـ ProxyHat:
const { SocksProxyAgent } = require('socks-proxy-agent');
const fetch = require('node-fetch');
const SOCKS_PROXY = 'socks5://user-country-US-city-austin-session-sess02:pass@gate.proxyhat.com:1080';
const agent = new SocksProxyAgent(SOCKS_PROXY);
const HEADERS = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 '
+ '(KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
'Accept-Language': 'en-US,en;q=0.9',
};
async function scrapeYelpBiz(slug) {
const url = `https://www.yelp.com/biz/${slug}`;
const resp = await fetch(url, { agent, headers: HEADERS, timeout: 30000 });
if (!resp.ok) {
console.error(`Blocked: ${resp.status}`);
return null;
}
const html = await resp.text();
const match = html.match(/window\.__INITIAL_STATE__\s*=\s*({.*?});<\/script>/s);
if (!match) return null;
const state = JSON.parse(match[1]);
const biz = state.biz?.[slug];
if (!biz) return null;
return {
name: biz.name,
rating: biz.rating,
reviewCount: biz.reviewCount,
categories: (biz.categories || []).map(c => c.title),
hours: (biz.hours || []).map(h => ({ days: h.days, hours: h.open })),
};
}
(async () => {
const data = await scrapeYelpBiz('the-french-laundry-yountville');
console.log(JSON.stringify(data, null, 2));
})();
الترقيم الصفحي وإدارة معدل الطلبات والجلسات الثابتة
الترقيم الصفحي للمراجعات
نقطة review_feed تدعم معامل start للترقيم الصفحي، بقفزات بمقدار 10 مراجعات لكل طلب. للوصول إلى جميع مراجعات نشاط تجاري بـ 500 مراجعة، ستحتاج إلى نحو 50 طلباً. وزّع هذه الطلبات عبر جلسات بروكسي مختلفة:
for start in range(0, review_count, 10):
session_id = f"sess-{start // 10:03d}"
proxy = f"http://user-country-US-city-austin-session-{session_id}:pass@gate.proxyhat.com:8080"
# ... إجراء الطلب ...
time.sleep(random.uniform(3, 7))
إدارة معدل الطلبات
يُوصى بعدم تجاوز 1–2 طلب لكل ثانية لكل عنوان IP. مع دوران البروكسي، يمكنك زيادة الإنتاجية الإجمالية، لكن حافظ على تباطؤ معقول لكل IP:
- تأخير عشوائي: 2–7 ثوانٍ بين الطلبات لكل جلسة.
- حد التزامن: لا تتجاوز 10 جلسات متزامنة لتفادي إثارة أنماط حركة المرور.
- فترات راحة: أوقف الاستخراج لمدة 30 دقيقة بعد كل 500 طلب.
تدوير User-Agent
استخدم مجموعة من User-Agents حقيقية لمتصفحات Chrome وFirefox على أنظمة تشغيل مختلفة. لا تستخدم User-Agents قديمة أو غير شائعة لأن PerimeterX يتعرف عليها بسهولة:
USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0",
]
headers = {"User-Agent": random.choice(USER_AGENTS)}
أخطاء شائعة وحالات حدية
1. الاعتماد على بروكسي مركز البيانات
كما ذكرنا، يتم حظر IP مراكز البيانات بعد 3–5 طلبات. استثمر في بروكسي سكني من البداية.
2. تجاهل ملفات تعريف الارتباط
ملف تعريف الارتباط _px3 ضروري لاجتياز تحدي PerimeterX. استخدم requests.Session() في Python للحفاظ على ملفات تعريف الارتباط عبر الطلبات:
session = requests.Session()
session.proxies = PROXIES
session.headers.update(HEADERS)
# جميع الطلبات اللاحقة ستحمل نفس ملفات تعريف الارتباط
resp = session.get(url)
3. طلب صفحات محمية بتسجيل الدخول
بعض البيانات على Yelp تتطلب تسجيل الدخول، مثل المراسلات الخاصة أو بعض المراجعات المحذوفة. لا تحاول تجاوز جدار تسجيل الدخول — هذا ينتهك شروط الخدمة وقد يخالف CFAA.
4. عدم التحقق من حالة الاستجابة
قد يعيد PerimeterX كود 403 أو 429 بدلاً من صفحة العمل. تحقق دائماً من status_code قبل معالجة المحتوى، وأعد المحاولة مع جلسة بروكسي جديدة.
الاستخراج الأخلاقي ومتى تستخدم واجهة API الرسمية
الاستخراج المسؤول ليس مجرد التزام قانوني — بل هو أيضاً استراتيجية استدامة. إليك المبادئ الأساسية:
- احترام robots.txt: تحقق من ملف robots.txt الخاص بـ Yelp قبل الاستخراج. قد تكون بعض المسارات محظورة.
- تجنب البيانات الشخصية: أسماء المراجعين وصورهم هي بيانات شخصية تخضع لـ GDPR في الاتحاد الأوروبي. إذا كانت مجموعة بياناتك ستُستخدم في الاتحاد الأوروبي، فكّر في إخفاء هوية المراجعين.
- لا تتجاوز جدار تسجيل الدخول: البيانات المتاحة دون حساب فقط هي التي يجب استخراجها.
- استخدم Fusion API حيث يكفي: إذا كنت تحتاج فقط إلى بيانات الأعمال الأساسية (الاسم، العنوان، الهاتف، التقييم، 3 مراجعات)، فإن Fusion API هو الخيار الأنسب والأكثر استدامة.
- حدد معدل طلباتك: لا تضغط على خوادم Yelp بحركة مرور مفرطة. التأخيرات العشوائية ليست فقط لتجنّب الحظر، بل أيضاً لإظهار الاحترام.
قاعدة أساسية: إذا كانت واجهة API الرسمية تغطي 80% من احتياجاتك، استخدمها لـ 80% واستخرج الصفحات العامة لـ 20% المتبقية فقط. هذا يقلل المخاطر القانونية والتقنية.
النقاط الرئيسية
- البيانات العامة على صفحات
/biz/<slug>تشمل الاسم، التقييم، الفئات، الساعات، ونصوص المراجعات — دون تسجيل دخول. - Fusion API الرسمية يقتصر على 3 مراجعات لكل نشاط، ممّا يجعل الاستخراج من الصفحات ضرورياً للمجموعات الأكبر.
- PerimeterX/HUMAN يحظر IP مراكز البيانات بعد 3–5 طلبات ويستخدم بصمة TLS وتحدي المستشعر للكشف عن البوتات.
- البروكسي السكني الدوّار مع استهداف الولايات المتحدة (
-country-US-city-austin) يقلل خطر الحظر ويضمن نتائج محلية دقيقة. - استخدم جلسات ثابتة للحفاظ على ملفات تعريف الارتباط، وتأخيرات عشوائية بين 2–7 ثوانٍ، وتدوير User-Agents.
- احترم شروط الخدمة وGDPR وCFAA، وفضّل Fusion API حيث يغطي احتياجاتك.
لمزيد من الأدلة العملية، راجع حالة استخدام استخراج الويب وتتبع نتائج محركات البحث.






