تضم Yelp 330 مليون مراجعة تراكمية موزعة على 8.4 مليون صفحة نشاط تجاري نشطة — ولم يكن تحويل هذه البيانات إلى صيغة قابلة للاستخدام أصعب مما هو عليه اليوم. فحملة Yelp الصارمة ضد الروبوتات في 2024–2025 عطّلت بصمت معظم شروحات استخراج البيانات بـ Python التي ما زال الناس يعتمدون عليها.
إذا جرّبت مؤخرًا تشغيل أداة استخراج بيانات من Yelp وواجهت سيلًا من أخطاء 403، أو استجابات HTML فارغة، أو CAPTCHAs لم تكن موجودة قبل ستة أشهر، فأنت لست تتخيل ذلك. Yelp تستخدم الآن بصمة TLS/JA3، وأسماء CSS متغيرة ومموّهة، وتقييمًا صارمًا لسمعة عنوان IP — وهذا يعني أن أسلوب requests + BeautifulSoup القديم الذي لا تزال كل الشروحات توصي به يتعطل من أول طلب. قضيت أسابيع أختبر طرقًا مختلفة على البنية الحالية لـ Yelp، وهذا الدليل يجمع كل ما يعمل فعلاً في 2025: واجهة Fusion API الرسمية (ولماذا قد لا تكفي)، وسير عمل كامل لاستخراج البيانات بـ Python مع استراتيجية متعددة الطبقات لتجاوز الحظر، وبديلًا بدون كود بخطوتين فقط عبر Thunderbit لمن يريد البيانات مباشرة من دون معركة تصحيح الأخطاء الطويلة.
جرّب Thunderbit لاستخراج بيانات Yelp
لماذا تستخرج بيانات Yelp باستخدام Python؟ ومن المستفيد فعلاً؟
قبل كتابة أي سطر برمجي، ما هي الفائدة التجارية الحقيقية من بيانات Yelp؟ المنصة ليست مجرد موقع لمراجعات المطاعم — بل هي عمليًا قاعدة بيانات حيّة للشركات المحلية، تحتوي على معلومات اتصال منظمة، وتقييمات، وتصنيفات، وساعات العمل، ومئات الملايين من مراجعات العملاء.

إليك من يستفيد أكثر، وما الذي يستخرجه:
| حالة الاستخدام | حقول البيانات الأساسية | لماذا هذا مهم |
|---|---|---|
| المبيعات وتوليد العملاء المحتملين | اسم النشاط التجاري، الهاتف، الموقع الإلكتروني، العنوان، الفئة، التقييم | بناء قوائم استهداف للشركات المحلية الصغيرة والمتوسطة — 4 من كل 5 مستخدمي Yelp جاهزون للشراء عند الدخول |
| استخبارات تنافسية | المراجعات، النجوم، حجم المراجعات، المشاعر | مراقبة سمعة المنافسين، اكتشاف الثغرات في الخدمة، وتتبع الاتجاهات |
| أبحاث السوق وNLP | النص الكامل للمراجعات، التواريخ، بيانات المراجعين | تحليل المشاعر، ونمذجة الموضوعات — وتُعد مراجعات Yelp من أكثر corpora استخدامًا في NLP في البحث الأكاديمي |
| العقار واختيار المواقع | كثافة الأنشطة التجارية، مزيج الفئات، جودة المراجعات حسب المنطقة | اختيار مواقع الفروع والمتاجر — وتبيع Yelp Location Intelligence كمنتج B2B مرخّص لهذا الغرض تحديدًا |
| التجارة الإلكترونية والعمليات | إشارات التسعير، شكاوى العملاء، ساعات الخدمة | تتبع كيف يتم تقييم المنافسين، واكتشاف الأنماط التشغيلية |
القاسم المشترك هنا: الهدف الحقيقي هو البيانات المنظمة، وPython مجرد وسيلة للوصول إليها. بعض القراء يحتاجون تحكمًا برمجيًا كاملًا. وآخرون يريدون فقط جدولًا بسيطًا ببيانات التواصل الخاصة بالسبّاكين في أوستن. هذا المقال يغطي المسارين.
Yelp Fusion API أم استخراج البيانات بـ Python: أيهما تختار؟
تتجاهل معظم الأدلة هذا القرار بالكامل وتنتقل مباشرة إلى الكود من دون تقييم ما إذا كانت Yelp Fusion API الرسمية — والتي أعيدت تسميتها الآن إلى "Yelp Places API" — كانت ستكفي أصلًا. من تجربتي، هذا التقييم يوفر ساعات من الجهد الضائع — لأن الـ API ممتازة لبعض الاستخدامات، لكنها غير مناسبة تمامًا لاستخدامات أخرى.
ماذا تمنحك Fusion API فعليًا؟
توفر Fusion API بحثًا منظمًا عن الأنشطة التجارية، وتفاصيل النشاط، والإكمال التلقائي، ونقطة نهاية للمراجعات. وهي مصرح بها، ومشروحة جيدًا، ولا تحتاج إلى حيل معقدة لتجاوز أنظمة الحظر.
لكن المشكلة تظهر عند نقطة المراجعات. وقد أكد موظفو Yelp ذلك على GitHub:
"واجهة Yelp API لا تُرجع النص الكامل للمراجعات. يتم توفير ثلاث مقتطفات فقط بطول 160 حرفًا افتراضيًا." — رد أحد موظفي Yelp، GitHub Issue #163
وهذا ليس خللًا، بل تصميم مقصود. فالواجهة تقتصر فعليًا على 3 مقتطفات مراجعات (7 في Premium)، وكل مقتطف مبتور إلى نحو 160 حرفًا. لا توجد بيانات وصفية للمراجعة (مثل useful/funny/cool)، ولا سجل للمراجع، ولا ردود المالك. كما أن الحد اليومي للعملاء الجدد انخفض إلى 300–500 طلب/يوم بعد مايو 2023 — بدلًا من 5,000. وتبدأ الأسعار من $29 شهريًا.
إطار اتخاذ القرار
| العامل | Yelp Fusion API | استخراج البيانات بـ Python | Thunderbit (بدون كود) |
|---|---|---|---|
| النص الكامل للمراجعات | ❌ 3 مقتطفات فقط (~160 حرفًا لكل منها) | ✅ كل المراجعات عبر GraphQL | ✅ كل المراجعات الظاهرة |
| حدود الطلبات | 300–500/يوم (للجدد)؛ 5,000 (القدامى) | تديرها بنفسك (وبميزانية البروكسي) | بنظام الرصيد |
| جهد الإعداد | ~15 دقيقة (مفتاح API + SDK) | من ساعات إلى أيام | ~دقيقتان |
| حقول الأعمال | ~20 حقلًا منظمًا | غير محدود (تحليل HTML/JSON) | حقول تقترحها الذكاء الاصطناعي |
| التعامل مع الحظر | غير مطلوب (مصرّح) | يجب بناؤه بنفسك | يُدار تلقائيًا |
| المخاطر القانونية | ✅ مصرح | ⚠️ منطقة رمادية في الشروط | ⚠️ مثل أي عملية استخراج |
| التكلفة | يبدأ من $29/شهر | مجاني (+ تكاليف بروكسي $0.75–$4/GB) | توجد خطة مجانية |
| الصيانة | منخفضة (الـ API مستقرة) | مرتفعة (العناصر تتغير والحظر يتصاعد) | منخفضة (الذكاء يعيد التكيّف) |
استخدم Fusion API إذا: كنت تحتاج معلومات أساسية عن النشاط التجاري، أو عمليات بحث صغيرة النطاق، أو تكاملًا مصرحًا — وكانت 3 مقتطفات من المراجعات لكل نشاط كافية لك.
استخدم استخراج Python إذا: كنت تحتاج النص الكامل للمراجعات، أو كل مراجعات نشاط معين، أو بيانات وصفية للمراجعات، أو أكثر من 240 نتيجة لكل بحث، أو كانت ميزانيتك أقل من $29 شهريًا.
استخدم Thunderbit إذا: أردت البيانات بسرعة من دون كتابة الكود أو صيانته. مزيد عن ذلك في قسم الحل بدون كود أدناه.
الاختصار بدون كود: استخرج بيانات Yelp عبر Thunderbit من دون Python
قبل التعمق في Python، إليك أسرع طريق لمن هدفه البيانات لا التمرين البرمجي. معظم الأدلة المنافسة تفترض أنك تجيد Python، لكن في عملي داخل Thunderbit، رأيت أن جزءًا كبيرًا ممن يبحثون عن "scrape Yelp" هم مندوبي مبيعات، ومديري العمليات، وأصحاب الأعمال الصغيرة الذين يريدون فقط ملف Excel فيه بيانات الشركات المحلية — لا دورة مكثفة في TLS fingerprinting.
Thunderbit يوفر أصلًا قوالب Yelp جاهزة:
- Yelp Business Web Scraper — يستخرج اسم النشاط، التقييم، بيانات التواصل، العنوان، ساعات العمل، والفئة
- Yelp Review Scraper — يستخرج اسم المستخدم للمراجع، محتوى المراجعة، التقييم، التاريخ، وموقع المراجع
كيف يعمل عمليًا؟
- افتح صفحة نتائج بحث Yelp أو صفحة نشاط تجاري في Chrome
- اضغط AI Suggest Fields في إضافة Thunderbit — سيقرأ الذكاء الاصطناعي الصفحة ويقترح الأعمدة (اسم النشاط، التقييم، عدد المراجعات، نطاق السعر، الفئة، العنوان، الهاتف، الرابط)
- اضغط Scrape — وانتهى الأمر
أما مع قوالب Yelp الجاهزة، فالأمر أبسط: افتح القالب ثم اضغط Scrape.
الاستخراج من الصفحات الفرعية يتكفل تلقائيًا بدورة الإثراء — ابدأ من صفحة نتائج البحث في Yelp، فعّل استخراج الصفحات الفرعية، وسيتنقل Thunderbit إلى كل صفحة نشاط لاستخراج ساعات العمل، والمراجعات الكاملة، والموقع الإلكتروني، والصور، والمزايا. من دون إعداد إضافي.
الترقيم الصفحي تلقائي — سواء كان بالنقر أو بالتمرير، فهو مدعوم مباشرة. (لمزيد من التفاصيل، راجع دليل الترقيم الصفحي.)
التصدير مجاني في كل الخطط — Excel، Google Sheets، Airtable، Notion، CSV، JSON. لا حاجة إلى pandas ولا إلى كتابة ملفات CSV.
مقارنة الوقت
| الوقت | أداة Python | Thunderbit |
|---|---|---|
| التشغيل الأول | من ساعات إلى أيام (كتابة المحددات، التعامل مع الترقيم، البروكسي، ومنطق إعادة المحاولة) | نحو 30 ثانية مع قالب Yelp الجاهز |
| عند تغيّر بنية Yelp | إعادة كتابة المحددات يدويًا | اضغط AI Suggest Fields مرة أخرى — يتكيف تلقائيًا |
| عند حظر الـ IP | تصحيح الأخطاء، تدوير مجموعات البروكسي، وإعادة الاختبار | وضع Cloud يتولى تدوير الـ IP |
| التصدير إلى Google Sheets | كتابة OAuth وطبقة ربط pandas | نقرة واحدة، مجانًا |
إذا جرّبت Thunderbit أولًا ووجدت أنه يغطي احتياجاتك، يمكنك تخطي بقية المقال. أما إذا كنت تحتاج تحكمًا برمجيًا كاملًا، أو حقولًا مخصصة، أو نطاقًا يتجاوز بضعة آلاف سجل شهريًا — فتابع القراءة.
مكتبات Python لاستخراج بيانات Yelp: أيها تختار؟
"هل أستخدم Scrapy أم BS4+requests أم Selenium؟" من أكثر الأسئلة شيوعًا في نقاشات r/webscraping حول Yelp. ومع ذلك، يختار كل دليل المكتبة التي يفضلها ثم يمضي دون تفسير. إليك التفصيل الصريح.
واقع 2025: requests + BeautifulSoup لا يعمل مع Yelp
المزيج الذي توصي به كل الشروحات الكلاسيكية عن Yelp — pip install requests beautifulsoup4 — سيُحظر من أول طلب في 2025. ليس من الطلب الخمسين. من الأول.
السبب: مكتبة requests في Python ترسل بصمة TLS/JA3 لا تطابق أي متصفح حقيقي. طبقة الحظر في Yelp تكتشف ذلك عند مستوى مصافحة TLS قبل أن تقرأ حتى User-Agent. اختبرت هذا مرارًا — عنوان IP جديد، Headers واقعية، تأخيرات عشوائية — ومع ذلك أحصل مباشرة على 403 Forbidden عند استخدام requests العادي.
مصفوفة اختيار المكتبة
| المكتبة | الأفضل لـ | تتعامل مع JS؟ | تجاوز الحظر؟ | منحنى التعلم | السرعة |
|---|---|---|---|---|---|
requests + BeautifulSoup | ❌ | ❌ | منخفض جدًا | سريع (حتى يتم الحظر) | |
httpx async + parsel | استخراج متزامن واسع النطاق | ❌ | ❌ | منخفض | سريع جدًا |
curl_cffi + parsel | Yelp تحديدًا: انتحال بصمة TLS | ❌ | ✅ TLS/JA3/HTTP2 | منخفض | سريع جدًا |
Scrapy 2.14 | خطوط زحف كاملة مع الترقيم الصفحي | جزئيًا (عبر scrapy-playwright) | AutoThrottle، وretry middleware | متوسط إلى مرتفع | سريع |
Selenium 4.43 / Playwright 1.58 | الصفحات الثقيلة بالـ JS، وحلول CAPTCHA | ✅ | جزئيًا | متوسط | بطيء (~10–30 صفحة/دقيقة) |
| Thunderbit | لغير المبرمجين، واستخراج سريع | ✅ (عبر المتصفح) | مدمج (وضع Cloud) | منخفض جدًا | سريع |
سرّ curl_cffi
المكتبة التي غيّرت طريقة عملي مع Yelp هي curl_cffi — وهي ربط Python لـ curl-impersonate. فهي تُصدر نفس بصمة TLS/JA3 + HTTP/2 بالضبط مثل Chrome الحقيقي، وواجهتها بديل مباشر لـ requests:
from curl_cffi import requests
r = requests.get(
"https://www.yelp.com/biz/some-restaurant",
impersonate="chrome131",
)
print(r.status_code, len(r.text))
هذا التغيير الوحيد — from curl_cffi import requests مع impersonate="chrome131" — يتجاوز أكبر طبقات الحظر في Yelp من دون تشغيل متصفح. في اختباراتنا، الفرق كان بين 403 فوري واستجابة 200 نظيفة.
المكدس الذي أوصي به لـ Yelp في 2025: curl_cffi + parsel + jmespath + بروكسيات سكنية. وإذا كنت تحتاج خط زحف كاملًا مع الجدولة، فلفّه داخل Scrapy 2.14 مع middleware للتحميل يعتمد على curl_cffi.
إعداد بيئة Python لاستخراج بيانات Yelp
- مستوى الصعوبة: متوسط
- الوقت المطلوب: نحو 15 دقيقة للإعداد، و1–2 ساعة لبناء أداة تعمل
- ما ستحتاجه: Python 3.10+ (ويُفضَّل 3.12)، طرفية أو Terminal، واختياريًا مزود بروكسيات سكنية
الخطوة 1: أنشئ بيئة افتراضية وثبّت الحزم
python3.12 -m venv .venv
source .venv/bin/activate # على Windows: .venv\Scripts\activate
pip install "curl_cffi>=0.11" "parsel>=1.9" "jmespath>=1.0" pandas
وظيفة كل حزمة:
curl_cffi— لإجراء طلبات HTTP ببصمة TLS الخاصة بـ Chrome (وهو أسلوب تجاوز الحظر)parsel— لانتقاء CSS/XPath وتحليل HTML (وهو نفس المحرك الذي يستخدمه Scrapy، لكنه أخف)jmespath— للاستعلام عن JSON بشكل تصريحي (أوضح من الوصول المتداخل إلى القواميس في JSON المضمّن لدى Yelp)pandas— لتصدير البيانات إلى CSV/Excel
اختياري لكنه مفيد:
pip install fake-useragent # ملاحظة: المستودع مؤرشف في أبريل 2026 لكنه لا يزال قابلًا للتثبيت
خطوة بخطوة: كيف تستخرج بيانات Yelp باستخدام Python
هذا هو الدرس الأساسي. الفكرة الأهم التي تجعل كل شيء أكثر صلابة: تجاوز محددات CSS واستخرج JSON المخفي بدلًا منها. Yelp تغيّر أسماء CSS class عشوائيًا وقت البناء (y-css-14xwok2 هذا الأسبوع، وy-css-hcq7b9 في الأسبوع التالي)، لذا فإن أي أداة استخراج تعتمد عليها ستتعطل خلال أسابيع. أما الحمولات المضمّنة بصيغة JSON — مثل application/ld+json وreact-root-props — فهي ثابتة.
الخطوة 2: استخراج نتائج بحث Yelp
روابط بحث Yelp تتبع نمطًا متوقعًا: https://www.yelp.com/search?find_desc={term}&find_loc={location}. وبيانات النتائج تكون مضمّنة داخل وسم <script data-id="react-root-props"> كـ JSON — وليس ضمن فوضى class names في CSS.
import re, json, jmespath
from curl_cffi import requests
from parsel import Selector
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": "text/html,application/xhtml+xml,application/xml;q=0.9,"
"image/avif,image/webp,image/apng,*/*;q=0.8",
"accept-language": "en-US,en;q=0.9",
"accept-encoding": "gzip, deflate, br",
"cookie": "intl_splash=false",
}
def scrape_search(term: str, location: str, max_pages: int = 3):
results = []
for page in range(max_pages):
url = (f"https://www.yelp.com/search?"
f"find_desc={term}&find_loc={location}&start={page * 10}")
r = requests.get(url, headers=HEADERS, impersonate="chrome131")
if r.status_code != 200:
print(f"تم الحظر في الصفحة {page}: {r.status_code}")
break
sel = Selector(text=r.text)
script = sel.xpath(
"//script[@data-id='react-root-props']/text()"
).get() or ""
m = re.search(r"react_root_props\s*=\s*(\{.*?\});", script, re.S)
if not m:
print(f"لم يتم العثور على react-root-props في الصفحة {page} — قد يكون حظرًا خفيًا")
break
data = json.loads(m.group(1))
businesses = jmespath.search(
"legacyProps.searchAppProps.searchPageProps"
".mainContentComponentsListProps"
"[?searchResultBusiness].searchResultBusiness.{"
"name: name, url: businessUrl, rating: rating, "
"reviews: reviewCount, phone: phone, "
"neighborhoods: neighborhoods}",
data,
) or []
results.extend(businesses)
import time, random
time.sleep(random.uniform(3, 7))
return results
ينبغي أن تحصل على قائمة من القواميس تحتوي على أسماء الأنشطة، وروابطها، والتقييمات، وأعداد المراجعات. إذا كان react-root-props مفقودًا من الاستجابة، فهذا يعني أنك تلقيت صفحة حظر مخففة — بدّل عنوان الـ IP وأعد المحاولة.
الهيدر Cookie: intl_splash=false هو حل قياسي لتجاوز تحويل Yelp إلى صفحة البلد. من دونه، قد يواجه عنوان IP غير الأمريكي صفحة تمهيدية تبدو كحظر خفيف، لكنها ليست كذلك.
الخطوة 3: استخراج صفحات الأنشطة التجارية في Yelp
كل رابط نشاط تجاري من نتائج البحث يقود إلى صفحة تفاصيل تحتوي على بيانات أغنى. وأكثر هدف استخراج ثابت هو كتلة <script type="application/ld+json"> — لأنها تحتوي على بيانات schema.org منظمة، وتحافظ عليها Yelp لأغراض SEO ولا تُشوّهها.
def scrape_business(biz_url: str) -> dict:
url = f"https://www.yelp.com{biz_url}" if biz_url.startswith("/") else biz_url
r = requests.get(url, headers=HEADERS, impersonate="chrome131")
if r.status_code != 200:
return {"url": url, "error": r.status_code}
sel = Selector(text=r.text)
biz_id = sel.css('meta[name="yelp-biz-id"]::attr(content)').get()
for raw in sel.css('script[type="application/ld+json"]::text').getall():
try:
data = json.loads(raw)
except json.JSONDecodeError:
continue
for node in (data if isinstance(data, list) else [data]):
if node.get("@type") in (
"Restaurant", "LocalBusiness", "FoodEstablishment",
"HealthAndBeautyBusiness", "HomeAndConstructionBusiness",
):
return {
"biz_id": biz_id,
"name": node.get("name"),
"rating": (node.get("aggregateRating") or {}).get("ratingValue"),
"review_count": (node.get("aggregateRating") or {}).get("reviewCount"),
"address": node.get("address"),
"telephone": node.get("telephone"),
"price_range": node.get("priceRange"),
"hours": node.get("openingHours"),
"url": url,
}
return {"biz_id": biz_id, "url": url}
قيمة meta[name="yelp-biz-id"] هي معرّف النشاط المشفّر الذي ستحتاجه لنقطة نهاية المراجعات. خذها من هنا — ستستخدمها في الخطوة التالية.
الخطوة 4: استخراج مراجعات Yelp مع الترقيم الصفحي
هنا بالضبط تتفوق عملية الاستخراج على Fusion API. فواجهة GraphQL الداخلية لدى Yelp تُرجع النص الكامل للمراجعات، ومعلومات المراجع، والتواريخ، والتقييمات، وعدّادات الأصوات — أي كل ما تحجبه الـ API.
نقطة النهاية هي https://www.yelp.com/gql/batch, وتستخدم documentId ثابتًا لعملية GetBusinessReviewFeed. ويعمل الترقيم الصفحي عبر cursor مشفّر بـ base64.
import base64
GQL_URL = "https://www.yelp.com/gql/batch"
DOC_ID = "ef51f33d1b0eccc958dddbf6cde15739c48b34637a00ebe316441031d4bf7681"
def fetch_reviews(enc_biz_id: str, num_pages: int = 5):
all_reviews = []
for page in range(num_pages):
offset = page * 10
cursor = base64.b64encode(
json.dumps({"version": 1, "offset": offset}).encode()
).decode()
payload = [{
"operationName": "GetBusinessReviewFeed",
"variables": {
"encBizId": enc_biz_id,
"reviewsPerPage": 10,
"after": cursor,
"sortBy": "DATE_DESC",
"language": "en",
},
"extensions": {
"operationType": "query",
"documentId": DOC_ID,
},
}]
r = requests.post(
GQL_URL,
json=payload,
headers={
**HEADERS,
"content-type": "application/json",
"x-apollo-operation-name": "GetBusinessReviewFeed",
"apollographql-client-name": "yelp-main-frontend",
},
impersonate="chrome131",
)
if r.status_code != 200:
print(f"فشل جلب المراجعات عند offset {offset}: {r.status_code}")
break
data = r.json()
# التنقل داخل الاستجابة لاستخراج المراجعات
try:
reviews = data[0]["data"]["business"]["reviews"]["edges"]
for edge in reviews:
node = edge.get("node", {})
all_reviews.append({
"reviewer": node.get("author", {}).get("displayName"),
"rating": node.get("rating"),
"date": node.get("localizedDate"),
"text": node.get("text", {}).get("full"),
})
except (KeyError, IndexError, TypeError):
break
import time, random
time.sleep(random.uniform(3, 7))
return all_reviews
كل صفحة تُرجع 10 مراجعات. زد قيمة offset داخل cursor المشفّر بـ base64 للانتقال إلى الصفحة التالية. ويدعم sortBy قيمًا مثل DATE_DESC (الأحدث أولًا)، وRATING_ASC، وRATING_DESC، وغيرها.
الخطوة 5: تصدير بيانات Yelp التي استخرجتها
import pandas as pd
# بافتراض أنك جمعت بيانات الأنشطة والمراجعات
df_businesses = pd.DataFrame(businesses)
df_businesses.to_csv("yelp_businesses.csv", index=False)
df_reviews = pd.DataFrame(all_reviews)
df_reviews.to_csv("yelp_reviews.csv", index=False)
# أو احفظها بصيغة JSON لمرونة أكبر
import json
with open("yelp_data.json", "w") as f:
json.dump({"businesses": businesses, "reviews": all_reviews}, f, indent=2)
ولمن يسلكون طريق no-code، يصدّر Thunderbit البيانات نفسها مباشرة إلى Excel أو Google Sheets أو Airtable أو Notion — من دون pandas أو أي كود لكتابة الملفات.
خطة تجنب الحظر: كيف تستخرج بيانات Yelp من دون أن يتم حظرك
هذا القسم هو السبب الحقيقي لوجود المقال. فإجراءات Yelp ضد الروبوتات أصبحت أشد بكثير منذ أواخر 2024 — بصمة TLS، وفحص سمعة عنوان IP، وCAPTCHA، والتحليل السلوكي كلها باتت في المشهد. معظم الأدلة الموجودة قديمة لأنها كُتبت قبل هذه الحملة.

الاستراتيجية هنا متعددة الطبقات. كل طبقة تقلل معدل الحظر؛ ومعًا تجعل الاستخراج المستمر ممكنًا.
الطبقة 1: Headers واقعية للطلبات
Headers الافتراضية في requests ترسل User-Agent: python-requests/2.x — وهذا يُحظر فورًا. لكن حتى User-Agent واقعي لا يكفي. Yelp تتحقق من مجموعة Client Hints كاملة للتأكد من الاتساق.
FULL_HEADERS = {
"authority": "www.yelp.com",
"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": "text/html,application/xhtml+xml,application/xml;q=0.9,"
"image/avif,image/webp,image/apng,*/*;q=0.8",
"accept-language": "en-US,en;q=0.9",
"accept-encoding": "gzip, deflate, br",
"sec-ch-ua": '"Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"',
"sec-fetch-dest": "document",
"sec-fetch-mode": "navigate",
"sec-fetch-site": "same-origin",
"sec-fetch-user": "?1",
"upgrade-insecure-requests": "1",
"referer": "https://www.yelp.com/",
"cookie": "intl_splash=false",
}
ثلاثة أخطاء تجعلك مكشوفًا:
- يقول الـ UA إنه Chrome لكن
sec-ch-uaمفقود أو يناقض إصدار المتصفح sec-ch-ua-platformيقول "Windows" بينما سلسلة UA تقول macOS- نفس User-Agent تمامًا عبر آلاف الطلبات من عنوان IP واحد — بدّل بين مجموعة من 10–20 سلسلة حديثة لـ Chrome/Firefox/Safari
الطبقة 2: تحديد السرعة وتأخيرات عشوائية
أنماط التوقيت المتوقعة تُعد إشارة خطر. أضف فواصل نوم عشوائية وطبّق backoff تصاعديًا عند ظهور الأخطاء.
import random, time
def polite_get(client_get, url, attempt=0):
r = client_get(url, headers=FULL_HEADERS, impersonate="chrome131")
if r.status_code in (403, 429, 503):
if attempt >= 4:
raise RuntimeError(f"تم الحظر بعد {attempt + 1} محاولات على {url}")
backoff = 2 ** (attempt + 1) + random.random()
print(f" تم تلقي {r.status_code}، الرجوع للخلف {backoff:.1f} ثانية (المحاولة {attempt + 1})")
time.sleep(backoff)
return polite_get(client_get, url, attempt + 1)
time.sleep(random.uniform(3, 7))
return r
| المعامل | القيمة الموصى بها |
|---|---|
| النوم العشوائي بين الطلبات | random.uniform(3, 7) ثوانٍ |
| backoff عند 429/403/503 | 2 → 4 → 8 → 16 ثانية، بحد أقصى 5 محاولات |
| عدد العمال المتزامنين لكل IP | 1 (نفّذ التسلسل لكل IP؛ واستخدم البروكسي للتوازي) |
| الحد المستدام التقريبي لكل IP سكني | نحو طلب واحد كل 5 ثوانٍ (~12 طلب/دقيقة) |
الطبقة 3: تدوير User-Agent والجلسات
بدّل بين مجموعة من سلاسل User-Agent الحقيقية للمتصفحات. واحفظ الجلسات والكوكيز لمحاكاة سلوك التصفح الحقيقي — Yelp تعتمد على الكشف عبر الكوكيز، لذا فإن إنشاء جلسة جديدة لكل طلب أمر مريب بحد ذاته.
UA_POOL = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 14_4_1) AppleWebKit/537.36 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",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 14.4; rv:125.0) Gecko/20100101 Firefox/125.0",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 14_4_1) AppleWebKit/605.1.15 Safari/17.4.1",
# أضف 5–10 سلاسل حديثة أخرى
]
الطبقة 4: تدوير البروكسيات
عند أي حجم حقيقي، ستحتاج إلى بروكسيات سكنية. البروكسيات السحابية ومجانية الاستخدام لا تعمل مع Yelp — فطبقة سمعة IP في Yelp تحظر مسبقًا نطاقات AWS وGCP وDigitalOcean.
| المزوّد | السعر الابتدائي لكل GB | ملاحظات |
|---|---|---|
| IPRoyal | $1.75/GB | الأرخص؛ ويشغّل أكثر شروحات Yelp تداولًا |
| Decodo (ex-Smartproxy) | $3.20–$3.50 | أفضل نسبة GB/$ عند التوسع |
| Bright Data | $4.00 (PAYG) | مجموعة IP ضخمة تتجاوز 150 مليونًا؛ وصفحة مخصصة لـ Yelp Proxies |
| Oxylabs | $6.00–$8.00 | ممتاز؛ أكثر من 10 ملايين IP |
| Aluvia (SIM mobile) | $3.00 | عناوين IP حقيقية من شبكات US carrier، ومصممة لـ Yelp |
البروكسيات السكنية الدوّارة (IP جديد لكل طلب) هي الأفضل للزحف الكبير على نتائج البحث. أما الجلسات الثابتة (الإبقاء على IP واحد لمدة 10 دقائق) فهي أفضل عندما تريد الحفاظ على الكوكيز أثناء التدفق من صفحة النشاط → المراجعات → الترقيم الصفحي.
الطبقة 5: اكتشاف الحظر والتعامل معه
ليس كل حظر يبدو بالشكل نفسه. Yelp كثيرًا ما تعرض غلافًا عامًا من نوع "page not available" بدل CAPTCHA، ولهذا يظن الناس أن أدواتهم تعمل بينما هي في الحقيقة تتلقى استجابات فارغة.
BLOCK_MARKERS = (
"captcha", "px-captcha", "page not available",
"access denied", "unusual traffic",
)
def is_blocked(resp):
if resp.status_code in (401, 403, 429, 503):
return True
body = resp.text.lower()
if any(m in body for m in BLOCK_MARKERS):
return True
# إذا كانت هذه صفحة بحث/نشاط لكن react-root-props مفقودة،
# فهذا يعني أن Yelp أرسلت رد حظر مخفف
if "react-root-props" not in body and "/biz/" in str(resp.url):
return True
return False
| الإشارة | المعنى |
|---|---|
| HTTP 403 | حظر صريح — تم حرق الـ IP/الـ headers/بصمة TLS |
| HTTP 429 | تجاوزت المعدل — غالبًا يمكن التعافي عبر backoff |
| HTTP 503 | حظر عام أو تخفيف حمل |
إعادة توجيه إلى /error أو جسم يحتوي "page not available" | حظر خفيف |
| فارغ ويحتوي فقط على | صفحة تحدي تنتظر JavaScript |
وجود captcha / g-recaptcha / px-captcha في الجسم | تصعيد — مطلوب CAPTCHA |
غياب react-root-props في صفحة قائمة | استجابة حظر مخففة |
الطبقة 6: حيلة التحليل الأكثر صلابة — JSON المخفي بدل محددات CSS
أعيدها لأن الفكرة مهمة: Yelp تغيّر أسماء CSS class وقت البناء. وأي أداة استخراج تعتمد على h3.y-css-14xwok2 ستتعطل خلال أسابيع عندما تعيد Yelp النشر مع h3.y-css-hcq7b9.
الحمولات التي لا تتغير:
<script type="application/ld+json">— بيانات schema.org المنظمة (الاسم، العنوان، الهاتف، التقييم، ساعات العمل)<script data-id="react-root-props">— بيانات نتائج البحث الكاملة بصيغة JSONhttps://www.yelp.com/gql/batch— نقطة نهاية GraphQL للمراجعات معdocumentIdثابت
إذا كنت تحلل CSS classes، فأنت تبني على الرمل. حلّل JSON بدلًا من ذلك.
الطبقة 7: بديل المتصفح الخفي
انتقل إلى متصفح headless فقط عندما يفشل curl_cffi مع البروكسيات السكنية — عادة عندما تعرض Yelp صفحة تحدي JavaScript أو CAPTCHA.
في 95% من حالات استخراج بيانات الشركات/البحث/المراجعات، يكون curl_cffi + JSON المخفي + البروكسيات السكنية أسرع وأرخص وأكثر موثوقية من المتصفح. لكن عندما تحتاج إلى متصفح فعلاً:
| الأداة | الحالة (2025) | ملاحظات |
|---|---|---|
| rebrowser-playwright | نقطة انطلاق موصى بها | نسخة Playwright معدّلة لتقليل تسرب CDP |
| nodriver | الأفضل في تخفي Chrome | خليفة undetected-chromedriver؛ يتجنب بروتوكول WebDriver بالكامل |
| patchright | فرع Playwright نشط الصيانة | ينجح في اختبارات الكشف الحديثة |
| playwright-stealth | ناضجة | تصحح navigator.webdriver، وتحذف HeadlessChrome من الـ UA |
تجاوز Selenium العادي مع Yelp. من السهل جدًا كشفه.
مقارنة كاملة: Yelp Fusion API مقابل Python Scraping مقابل Thunderbit
| البُعد | Yelp Fusion API | استخراج Python | Thunderbit |
|---|---|---|---|
| النص الكامل للمراجعات | ❌ 3 مقتطفات × ~160 حرفًا | ✅ غير محدود (GraphQL) | ✅ قالب مراجعات مدمج |
| البيانات الوصفية للمراجعات (الأصوات، ردود المالك) | ❌ | ✅ | ✅ عبر الحقول المقترحة بالذكاء الاصطناعي |
| الصور | ❌ (0 في الخطة الأساسية) | ✅ غير محدود | ✅ |
| أقصى عدد نتائج لكل بحث | 240 (كان 1,000 قبل 2024) | غير محدود (مع الترقيم الصفحي) | غير محدود |
| الحد اليومي | 300–500 (للجدد) / 5,000 (للقدامى) | ميزانية البروكسي فقط | بنظام الرصيد (3,000/شهر في Pro) |
| جهد الإعداد | نحو 15 دقيقة | من ساعات إلى أيام | نحو دقيقتين |
| التعامل مع الحظر | غير مطلوب | مشكلتك | مُدار (وضع Cloud) |
| المخاطر القانونية | منخفضة (مصرح) | متوسطة (منطقة رمادية في الشروط) | متوسطة (مثل أي استخراج) |
| التكلفة (المدخل) | 29$/شهر | نحو $0.75–$4/GB للبروكسيات + وقت التطوير | خطة مجانية |
| التكلفة عند الاستخدام الكثيف | $643+/شهر | $50–$500/شهر للبروكسيات + وقت التطوير | $38–$49/شهر |
| تصدير البيانات | JSON | CSV/JSON (أنت تكتبه) | Excel / Sheets / Airtable / Notion — مجانًا |
| الصيانة | منخفضة | مرتفعة (العناصر تتغير والحظر يتصاعد) | منخفضة (الذكاء يعيد التكيّف) |
نصائح قانونية وأخلاقية لاستخراج بيانات Yelp
لست محاميًا، وهذا ليس استشارة قانونية. لكن المشهد القانوني تغيّر بما يكفي خلال العامين الماضيين بحيث يجب أن تعرف الأساسيات قبل استثمار وقتك في مشروع استخراج بيانات من Yelp.
ما تقوله شروط Yelp: تحديث شروط الاستخدام في أكتوبر 2025 يحظر صراحة استخدام "أي روبوت أو spider... أو أي جهاز آلي آخر" من أجل "الوصول إلى أي جزء من الخدمة أو استرجاعه أو نسخه أو استخراجه أو فهرسته". كما أضاف لغة تتعلقتضم Yelp 330 مليون مراجعة تراكمية موزعة على 8.4 مليون صفحة نشاط تجاري نشطة — ولم يعد تحويل هذه البيانات إلى صيغة قابلة للاستخدام سهلًا كما كان. فحملة Yelp الصارمة ضد الروبوتات في 2024–2025 عطّلت بصمت معظم شروحات استخراج البيانات بـ Python التي ما زال الناس يعتمدون عليها.
إذا جرّبت مؤخرًا تشغيل أداة استخراج بيانات من Yelp وواجهت سيلًا من أخطاء 403، أو استجابات HTML فارغة، أو CAPTCHAs لم تكن موجودة قبل ستة أشهر، فأنت لا تتوهم. Yelp تستخدم الآن بصمة TLS/JA3، وأسماء CSS متغيرة ومموّهة، وتقييمًا صارمًا لسمعة عنوان IP — وهذا يعني أن أسلوب requests + BeautifulSoup القديم الذي لا تزال كل الشروحات توصي به يتعطل من أول طلب. قضيت أسابيع أختبر طرقًا مختلفة على البنية الحالية لـ Yelp، وهذا الدليل يجمع كل ما يعمل فعلاً في 2025: واجهة Fusion API الرسمية (ولماذا قد لا تكفي)، وسير عمل كامل لاستخراج البيانات بـ Python مع استراتيجية متعددة الطبقات لتجاوز الحظر، وبديلًا بدون كود بخطوتين فقط عبر Thunderbit لمن يريد البيانات مباشرة من دون معركة تصحيح الأخطاء الطويلة.
جرّب Thunderbit لاستخراج بيانات Yelp
لماذا تستخرج بيانات Yelp باستخدام Python؟ ومن المستفيد فعلاً؟
قبل كتابة أي سطر برمجي، ما هي الفائدة التجارية الحقيقية من بيانات Yelp؟ المنصة ليست مجرد موقع لمراجعات المطاعم — بل هي عمليًا قاعدة بيانات حيّة للشركات المحلية، تحتوي على معلومات اتصال منظمة، وتقييمات، وتصنيفات، وساعات العمل، ومئات الملايين من مراجعات العملاء.

إليك من يستفيد أكثر، وما الذي يستخرجه:
| حالة الاستخدام | حقول البيانات الأساسية | لماذا هذا مهم |
|---|---|---|
| المبيعات وتوليد العملاء المحتملين | اسم النشاط التجاري، الهاتف، الموقع الإلكتروني، العنوان، الفئة، التقييم | بناء قوائم استهداف للشركات المحلية الصغيرة والمتوسطة — 4 من كل 5 مستخدمي Yelp جاهزون للشراء عند الدخول |
| استخبارات تنافسية | المراجعات، النجوم، حجم المراجعات، المشاعر | مراقبة سمعة المنافسين، اكتشاف الثغرات في الخدمة، وتتبع الاتجاهات |
| أبحاث السوق وNLP | النص الكامل للمراجعات، التواريخ، بيانات المراجعين | تحليل المشاعر، ونمذجة الموضوعات — وتُعد مراجعات Yelp من أكثر corpora استخدامًا في NLP في البحث الأكاديمي |
| العقار واختيار المواقع | كثافة الأنشطة التجارية، مزيج الفئات، جودة المراجعات حسب المنطقة | اختيار مواقع الفروع والمتاجر — وتبيع Yelp Location Intelligence كمنتج B2B مرخّص لهذا الغرض تحديدًا |
| التجارة الإلكترونية والعمليات | إشارات التسعير، شكاوى العملاء، ساعات الخدمة | تتبع كيف يتم تقييم المنافسين، واكتشاف الأنماط التشغيلية |
القاسم المشترك هنا: الهدف الحقيقي هو البيانات المنظمة، وPython مجرد وسيلة للوصول إليها. بعض القراء يحتاجون تحكمًا برمجيًا كاملًا. وآخرون يريدون فقط جدولًا بسيطًا ببيانات التواصل الخاصة بالسبّاكين في أوستن. هذا المقال يغطي المسارين.
Yelp Fusion API أم استخراج البيانات بـ Python: أيهما تختار؟
تتجاهل معظم الأدلة هذا القرار بالكامل وتنتقل مباشرة إلى الكود من دون تقييم ما إذا كانت Yelp Fusion API الرسمية — والتي أعيدت تسميتها الآن إلى "Yelp Places API" — كانت ستكفي أصلًا. من تجربتي، هذا التقييم يوفر ساعات من الجهد الضائع — لأن الـ API ممتازة لبعض الاستخدامات، لكنها غير مناسبة تمامًا لاستخدامات أخرى.
ماذا تمنحك Fusion API فعليًا؟
توفر Fusion API بحثًا منظمًا عن الأنشطة التجارية، وتفاصيل النشاط، والإكمال التلقائي، ونقطة نهاية للمراجعات. وهي مصرح بها، ومشروحة جيدًا، ولا تحتاج إلى حيل معقدة لتجاوز أنظمة الحظر.
لكن المشكلة تظهر عند نقطة المراجعات. وقد أكد موظفو Yelp ذلك على GitHub:
"واجهة Yelp API لا تُرجع النص الكامل للمراجعات. يتم توفير ثلاث مقتطفات فقط بطول 160 حرفًا افتراضيًا." — رد أحد موظفي Yelp، GitHub Issue #163
وهذا ليس خللًا، بل تصميم مقصود. فالواجهة تقتصر فعليًا على 3 مقتطفات مراجعات (7 في Premium)، وكل مقتطف مبتور إلى نحو 160 حرفًا. لا توجد بيانات وصفية للمراجعة (مثل useful/funny/cool)، ولا سجل للمراجع، ولا ردود المالك. كما أن الحد اليومي للعملاء الجدد انخفض إلى 300–500 طلب/يوم بعد مايو 2023 — بدلًا من 5,000. وتبدأ الأسعار من $29 شهريًا.
إطار اتخاذ القرار
| العامل | Yelp Fusion API | استخراج البيانات بـ Python | Thunderbit (بدون كود) |
|---|---|---|---|
| النص الكامل للمراجعات | ❌ 3 مقتطفات فقط (~160 حرفًا لكل منها) | ✅ كل المراجعات عبر GraphQL | ✅ كل المراجعات الظاهرة |
| حدود الطلبات | 300–500/يوم (للجدد)؛ 5,000 (القدامى) | تديرها بنفسك (وبميزانية البروكسي) | بنظام الرصيد |
| جهد الإعداد | ~15 دقيقة (مفتاح API + SDK) | من ساعات إلى أيام | ~دقيقتان |
| حقول الأعمال | ~20 حقلًا منظمًا | غير محدود (تحليل HTML/JSON) | حقول تقترحها الذكاء الاصطناعي |
| التعامل مع الحظر | غير مطلوب (مصرّح) | يجب بناؤه بنفسك | يُدار تلقائيًا |
| المخاطر القانونية | ✅ مصرح | ⚠️ منطقة رمادية في الشروط | ⚠️ مثل أي عملية استخراج |
| التكلفة | يبدأ من $29/شهر | مجاني (+ تكاليف بروكسي $0.75–$4/GB) | توجد خطة مجانية |
| الصيانة | منخفضة (الـ API مستقرة) | مرتفعة (العناصر تتغير والحظر يتصاعد) | منخفضة (الذكاء يعيد التكيّف) |
استخدم Fusion API إذا: كنت تحتاج معلومات أساسية عن النشاط التجاري، أو عمليات بحث صغيرة النطاق، أو تكاملًا مصرحًا — وكانت 3 مقتطفات من المراجعات لكل نشاط كافية لك.
استخدم استخراج Python إذا: كنت تحتاج النص الكامل للمراجعات، أو كل مراجعات نشاط معين، أو بيانات وصفية للمراجعات، أو أكثر من 240 نتيجة لكل بحث، أو كانت ميزانيتك أقل من $29 شهريًا.
استخدم Thunderbit إذا: أردت البيانات بسرعة من دون كتابة الكود أو صيانته. مزيد عن ذلك في قسم الحل بدون كود أدناه.
الاختصار بدون كود: استخرج بيانات Yelp عبر Thunderbit من دون Python
قبل التعمق في Python، إليك أسرع طريق لمن هدفه البيانات لا التمرين البرمجي. معظم الأدلة المنافسة تفترض أنك تجيد Python، لكن في عملي داخل Thunderbit، رأيت أن جزءًا كبيرًا ممن يبحثون عن "scrape Yelp" هم مندوبي مبيعات، ومديري العمليات، وأصحاب الأعمال الصغيرة الذين يريدون فقط ملف Excel فيه بيانات الشركات المحلية — لا دورة مكثفة في TLS fingerprinting.
Thunderbit يوفر أصلًا قوالب Yelp جاهزة:
- Yelp Business Web Scraper — يستخرج اسم النشاط، التقييم، بيانات التواصل، العنوان، ساعات العمل، والفئة
- Yelp Review Scraper — يستخرج اسم المستخدم للمراجع، محتوى المراجعة، التقييم، التاريخ، وموقع المراجع
كيف يعمل عمليًا؟
- افتح صفحة نتائج بحث Yelp أو صفحة نشاط تجاري في Chrome
- اضغط AI Suggest Fields في إضافة Thunderbit — سيقرأ الذكاء الاصطناعي الصفحة ويقترح الأعمدة (اسم النشاط، التقييم، عدد المراجعات، نطاق السعر، الفئة، العنوان، الهاتف، الرابط)
- اضغط Scrape — وانتهى الأمر
أما مع قوالب Yelp الجاهزة، فالأمر أبسط: افتح القالب ثم اضغط Scrape.
الاستخراج من الصفحات الفرعية يتكفل تلقائيًا بدورة الإثراء — ابدأ من صفحة نتائج البحث في Yelp، فعّل استخراج الصفحات الفرعية، وسيتنقل Thunderbit إلى كل صفحة نشاط لاستخراج ساعات العمل، والمراجعات الكاملة، والموقع الإلكتروني، والصور، والمزايا. من دون إعداد إضافي.
الترقيم الصفحي تلقائي — سواء كان بالنقر أو بالتمرير، فهو مدعوم مباشرة. (لمزيد من التفاصيل، راجع دليل الترقيم الصفحي.)
التصدير مجاني في كل الخطط — Excel، Google Sheets، Airtable، Notion، CSV، JSON. لا حاجة إلى pandas ولا إلى كتابة ملفات CSV.
مقارنة الوقت
| الوقت | أداة Python | Thunderbit |
|---|---|---|
| التشغيل الأول | من ساعات إلى أيام (كتابة المحددات، التعامل مع الترقيم، البروكسي، ومنطق إعادة المحاولة) | نحو 30 ثانية مع قالب Yelp الجاهز |
| عند تغيّر بنية Yelp | إعادة كتابة المحددات يدويًا | اضغط AI Suggest Fields مرة أخرى — يتكيف تلقائيًا |
| عند حظر الـ IP | تصحيح الأخطاء، تدوير مجموعات البروكسي، وإعادة الاختبار | وضع Cloud يتولى تدوير الـ IP |
| التصدير إلى Google Sheets | كتابة OAuth وطبقة ربط pandas | نقرة واحدة، مجانًا |
إذا جرّبت Thunderbit أولًا ووجدت أنه يغطي احتياجاتك، يمكنك تخطي بقية المقال. أما إذا كنت تحتاج تحكمًا برمجيًا كاملًا، أو حقولًا مخصصة، أو نطاقًا يتجاوز بضعة آلاف سجل شهريًا — فتابع القراءة.
مكتبات Python لاستخراج بيانات Yelp: أيها تختار؟
"هل أستخدم Scrapy أم BS4+requests أم Selenium؟" من أكثر الأسئلة شيوعًا في نقاشات r/webscraping حول Yelp. ومع ذلك، يختار كل دليل المكتبة التي يفضلها ثم يمضي دون تفسير. إليك التفصيل الصريح.
واقع 2025: requests + BeautifulSoup لا يعمل مع Yelp
المزيج الذي توصي به كل الشروحات الكلاسيكية عن Yelp — pip install requests beautifulsoup4 — سيُحظر من أول طلب في 2025. ليس من الطلب الخمسين. من الأول.
السبب: مكتبة requests في Python ترسل بصمة TLS/JA3 لا تطابق أي متصفح حقيقي. طبقة الحظر في Yelp تكتشف ذلك عند مستوى مصافحة TLS قبل أن تقرأ حتى User-Agent. اختبرت هذا مرارًا — عنوان IP جديد، Headers واقعية، تأخيرات عشوائية — ومع ذلك أحصل مباشرة على 403 Forbidden عند استخدام requests العادي.
مصفوفة اختيار المكتبة
| المكتبة | الأفضل لـ | تتعامل مع JS؟ | تجاوز الحظر؟ | منحنى التعلم | السرعة |
|---|---|---|---|---|---|
requests + BeautifulSoup | ❌ | ❌ | منخفض جدًا | سريع (حتى يتم الحظر) | |
httpx async + parsel | استخراج متزامن واسع النطاق | ❌ | ❌ | منخفض | سريع جدًا |
curl_cffi + parsel | Yelp تحديدًا: انتحال بصمة TLS | ❌ | ✅ TLS/JA3/HTTP2 | منخفض | سريع جدًا |
Scrapy 2.14 | خطوط زحف كاملة مع الترقيم الصفحي | جزئيًا (عبر scrapy-playwright) | AutoThrottle، وretry middleware | متوسط إلى مرتفع | سريع |
Selenium 4.43 / Playwright 1.58 | الصفحات الثقيلة بالـ JS، وحلول CAPTCHA | ✅ | جزئيًا | متوسط | بطيء (~10–30 صفحة/دقيقة) |
| Thunderbit | لغير المبرمجين، واستخراج سريع | ✅ (عبر المتصفح) | مدمج (وضع Cloud) | منخفض جدًا | سريع |
سرّ curl_cffi
المكتبة التي غيّرت طريقة عملي مع Yelp هي curl_cffi — وهي ربط Python لـ curl-impersonate. فهي تُصدر نفس بصمة TLS/JA3 + HTTP/2 بالضبط مثل Chrome الحقيقي، وواجهتها بديل مباشر لـ requests:
from curl_cffi import requests
r = requests.get(
"https://www.yelp.com/biz/some-restaurant",
impersonate="chrome131",
)
print(r.status_code, len(r.text))
هذا التغيير الوحيد — from curl_cffi import requests مع impersonate="chrome131" — يتجاوز أكبر طبقات الحظر في Yelp من دون تشغيل متصفح. في اختباراتنا، الفرق كان بين 403 فوري واستجابة 200 نظيفة.
المكدس الذي أوصي به لـ Yelp في 2025: curl_cffi + parsel + jmespath + بروكسيات سكنية. وإذا كنت تحتاج خط زحف كاملًا مع الجدولة، فلفّه داخل Scrapy 2.14 مع middleware للتحميل يعتمد على curl_cffi.
إعداد بيئة Python لاستخراج بيانات Yelp
- مستوى الصعوبة: متوسط
- الوقت المطلوب: نحو 15 دقيقة للإعداد، و1–2 ساعة لبناء أداة تعمل
- ما ستحتاجه: Python 3.10+ (ويُفضَّل 3.12)، طرفية أو Terminal، واختياريًا مزود بروكسيات سكنية
الخطوة 1: أنشئ بيئة افتراضية وثبّت الحزم
python3.12 -m venv .venv
source .venv/bin/activate # على Windows: .venv\Scripts\activate
pip install "curl_cffi>=0.11" "parsel>=1.9" "jmespath>=1.0" pandas
وظيفة كل حزمة:
curl_cffi— لإجراء طلبات HTTP ببصمة TLS الخاصة بـ Chrome (وهو أسلوب تجاوز الحظر)parsel— لانتقاء CSS/XPath وتحليل HTML (وهو نفس المحرك الذي يستخدمه Scrapy، لكنه أخف)jmespath— للاستعلام عن JSON بشكل تصريحي (أوضح من الوصول المتداخل إلى القواميس في JSON المضمّن لدى Yelp)pandas— لتصدير البيانات إلى CSV/Excel
اختياري لكنه مفيد:
pip install fake-useragent # ملاحظة: المستودع مؤرشف في أبريل 2026 لكنه لا يزال قابلًا للتثبيت
خطوة بخطوة: كيف تستخرج بيانات Yelp باستخدام Python
هذا هو الدرس الأساسي. الفكرة الأهم التي تجعل كل شيء أكثر صلابة: تجاوز محددات CSS واستخرج JSON المخفي بدلًا منها. Yelp تغيّر أسماء CSS class عشوائيًا وقت البناء (y-css-14xwok2 هذا الأسبوع، وy-css-hcq7b9 في الأسبوع التالي)، لذا فإن أي أداة استخراج تعتمد عليها ستتعطل خلال أسابيع. أما الحمولات المضمّنة بصيغة JSON — مثل application/ld+json وreact-root-props — فهي ثابتة.
الخطوة 2: استخراج نتائج بحث Yelp
روابط بحث Yelp تتبع نمطًا متوقعًا: https://www.yelp.com/search?find_desc={term}&find_loc={location}. وبيانات النتائج تكون مضمّنة داخل وسم <script data-id="react-root-props"> كـ JSON — وليس ضمن فوضى class names في CSS.
import re, json, jmespath
from curl_cffi import requests
from parsel import Selector
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": "text/html,application/xhtml+xml,application/xml;q=0.9,"
"image/avif,image/webp,image/apng,*/*;q=0.8",
"accept-language": "en-US,en;q=0.9",
"accept-encoding": "gzip, deflate, br",
"cookie": "intl_splash=false",
}
def scrape_search(term: str, location: str, max_pages: int = 3):
results = []
for page in range(max_pages):
url = (f"https://www.yelp.com/search?"
f"find_desc={term}&find_loc={location}&start={page * 10}")
r = requests.get(url, headers=HEADERS, impersonate="chrome131")
if r.status_code != 200:
print(f"تم الحظر في الصفحة {page}: {r.status_code}")
break
sel = Selector(text=r.text)
script = sel.xpath(
"//script[@data-id='react-root-props']/text()"
).get() or ""
m = re.search(r"react_root_props\s*=\s*(\{.*?\});", script, re.S)
if not m:
print(f"لم يتم العثور على react-root-props في الصفحة {page} — قد يكون حظرًا خفيًا")
break
data = json.loads(m.group(1))
businesses = jmespath.search(
"legacyProps.searchAppProps.searchPageProps"
".mainContentComponentsListProps"
"[?searchResultBusiness].searchResultBusiness.{"
"name: name, url: businessUrl, rating: rating, "
"reviews: reviewCount, phone: phone, "
"neighborhoods: neighborhoods}",
data,
) or []
results.extend(businesses)
import time, random
time.sleep(random.uniform(3, 7))
return results
ينبغي أن تحصل على قائمة من القواميس تحتوي على أسماء الأنشطة، وروابطها، والتقييمات، وأعداد المراجعات. إذا كان react-root-props مفقودًا من الاستجابة، فهذا يعني أنك تلقيت صفحة حظر مخففة — بدّل عنوان الـ IP وأعد المحاولة.
الهيدر Cookie: intl_splash=false هو حل قياسي لتجاوز تحويل Yelp إلى صفحة البلد. من دونه، قد يواجه عنوان IP غير الأمريكي صفحة تمهيدية تبدو كحظر خفيف، لكنها ليست كذلك.
الخطوة 3: استخراج صفحات الأنشطة التجارية في Yelp
كل رابط نشاط تجاري من نتائج البحث يقود إلى صفحة تفاصيل تحتوي على بيانات أغنى. وأكثر هدف استخراج ثابت هو كتلة <script type="application/ld+json"> — لأنها تحتوي على بيانات schema.org منظمة، وتحافظ عليها Yelp لأغراض SEO ولا تُشوّهها.
def scrape_business(biz_url: str) -> dict:
url = f"https://www.yelp.com{biz_url}" if biz_url.startswith("/") else biz_url
r = requests.get(url, headers=HEADERS, impersonate="chrome131")
if r.status_code != 200:
return {"url": url, "error": r.status_code}
sel = Selector(text=r.text)
biz_id = sel.css('meta[name="yelp-biz-id"]::attr(content)').get()
for raw in sel.css('script[type="application/ld+json"]::text').getall():
try:
data = json.loads(raw)
except json.JSONDecodeError:
continue
for node in (data if isinstance(data, list) else [data]):
if node.get("@type") in (
"Restaurant", "LocalBusiness", "FoodEstablishment",
"HealthAndBeautyBusiness", "HomeAndConstructionBusiness",
):
return {
"biz_id": biz_id,
"name": node.get("name"),
"rating": (node.get("aggregateRating") or {}).get("ratingValue"),
"review_count": (node.get("aggregateRating") or {}).get("reviewCount"),
"address": node.get("address"),
"telephone": node.get("telephone"),
"price_range": node.get("priceRange"),
"hours": node.get("openingHours"),
"url": url,
}
return {"biz_id": biz_id, "url": url}
قيمة meta[name="yelp-biz-id"] هي معرّف النشاط المشفّر الذي ستحتاجه لنقطة نهاية المراجعات. خذها من هنا — ستستخدمها في الخطوة التالية.
الخطوة 4: استخراج مراجعات Yelp مع الترقيم الصفحي
هنا بالضبط تتفوق عملية الاستخراج على Fusion API. فواجهة GraphQL الداخلية لدى Yelp تُرجع النص الكامل للمراجعات، ومعلومات المراجع، والتواريخ، والتقييمات، وعدّادات الأصوات — أي كل ما تحجبه الـ API.
نقطة النهاية هي https://www.yelp.com/gql/batch، وتستخدم documentId ثابتًا لعملية GetBusinessReviewFeed. ويعمل الترقيم الصفحي عبر cursor مشفّر بـ base64.
import base64
GQL_URL = "https://www.yelp.com/gql/batch"
DOC_ID = "ef51f33d1b0eccc958dddbf6cde15739c48b34637a00ebe316441031d4bf7681"
def fetch_reviews(enc_biz_id: str, num_pages: int = 5):
all_reviews = []
for page in range(num_pages):
offset = page * 10
cursor = base64.b64encode(
json.dumps({"version": 1, "offset": offset}).encode()
).decode()
payload = [{
"operationName": "GetBusinessReviewFeed",
"variables": {
"encBizId": enc_biz_id,
"reviewsPerPage": 10,
"after": cursor,
"sortBy": "DATE_DESC",
"language": "en",
},
"extensions": {
"operationType": "query",
"documentId": DOC_ID,
},
}]
r = requests.post(
GQL_URL,
json=payload,
headers={
**HEADERS,
"content-type": "application/json",
"x-apollo-operation-name": "GetBusinessReviewFeed",
"apollographql-client-name": "yelp-main-frontend",
},
impersonate="chrome131",
)
if r.status_code != 200:
print(f"فشل جلب المراجعات عند offset {offset}: {r.status_code}")
break
data = r.json()
# التنقل داخل الاستجابة لاستخراج المراجعات
try:
reviews = data[0]["data"]["business"]["reviews"]["edges"]
for edge in reviews:
node = edge.get("node", {})
all_reviews.append({
"reviewer": node.get("author", {}).get("displayName"),
"rating": node.get("rating"),
"date": node.get("localizedDate"),
"text": node.get("text", {}).get("full"),
})
except (KeyError, IndexError, TypeError):
break
import time, random
time.sleep(random.uniform(3, 7))
return all_reviews
كل صفحة تُرجع 10 مراجعات. زد قيمة offset داخل cursor المشفّر بـ base64 للانتقال إلى الصفحة التالية. ويدعم sortBy قيمًا مثل DATE_DESC (الأحدث أولًا)، وRATING_ASC، وRATING_DESC، وغيرها.
الخطوة 5: تصدير بيانات Yelp التي استخرجتها
import pandas as pd
# بافتراض أنك جمعت بيانات الأنشطة والمراجعات
df_businesses = pd.DataFrame(businesses)
df_businesses.to_csv("yelp_businesses.csv", index=False)
df_reviews = pd.DataFrame(all_reviews)
df_reviews.to_csv("yelp_reviews.csv", index=False)
# أو احفظها بصيغة JSON لمرونة أكبر
import json
with open("yelp_data.json", "w") as f:
json.dump({"businesses": businesses, "reviews": all_reviews}, f, indent=2)
ولمن يسلكون طريق no-code، يصدّر Thunderbit البيانات نفسها مباشرة إلى Excel أو Google Sheets أو Airtable أو Notion — من دون pandas أو أي كود لكتابة الملفات.
خطة تجنب الحظر: كيف تستخرج بيانات Yelp من دون أن يتم حظرك
هذا القسم هو السبب الحقيقي لوجود المقال. فإجراءات Yelp ضد الروبوتات أصبحت أشد بكثير منذ أواخر 2024 — بصمة TLS، وفحص سمعة عنوان IP، وCAPTCHA، والتحليل السلوكي كلها باتت في المشهد. معظم الأدلة الموجودة قديمة لأنها كُتبت قبل هذه الحملة.

الاستراتيجية هنا متعددة الطبقات. كل طبقة تقلل معدل الحظر؛ ومعًا تجعل الاستخراج المستمر ممكنًا.
الطبقة 1: Headers واقعية للطلبات
Headers الافتراضية في requests ترسل User-Agent: python-requests/2.x — وهذا يُحظر فورًا. لكن حتى User-Agent واقعي لا يكفي. Yelp تتحقق من مجموعة Client Hints كاملة للتأكد من الاتساق.
FULL_HEADERS = {
"authority": "www.yelp.com",
"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": "text/html,application/xhtml+xml,application/xml;q=0.9,"
"image/avif,image/webp,image/apng,*/*;q=0.8",
"accept-language": "en-US,en;q=0.9",
"accept-encoding": "gzip, deflate, br",
"sec-ch-ua": '"Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"',
"sec-fetch-dest": "document",
"sec-fetch-mode": "navigate",
"sec-fetch-site": "same-origin",
"sec-fetch-user": "?1",
"upgrade-insecure-requests": "1",
"referer": "https://www.yelp.com/",
"cookie": "intl_splash=false",
}
ثلاثة أخطاء تجعلك مكشوفًا:
- يقول الـ UA إنه Chrome لكن
sec-ch-uaمفقود أو يناقض إصدار المتصفح sec-ch-ua-platformيقول "Windows" بينما سلسلة UA تقول macOS- نفس User-Agent تمامًا عبر آلاف الطلبات من عنوان IP واحد — بدّل بين مجموعة من 10–20 سلسلة حديثة لـ Chrome/Firefox/Safari
الطبقة 2: تحديد السرعة وتأخيرات عشوائية
أنماط التوقيت المتوقعة تُعد إشارة خطر. أضف فواصل نوم عشوائية وطبّق backoff تصاعديًا عند ظهور الأخطاء.
import random, time
def polite_get(client_get, url, attempt=0):
r = client_get(url, headers=FULL_HEADERS, impersonate="chrome131")
if r.status_code in (403, 429, 503):
if attempt >= 4:
raise RuntimeError(f"تم الحظر بعد {attempt + 1} محاولات على {url}")
backoff = 2 ** (attempt + 1) + random.random()
print(f" تم تلقي {r.status_code}، الرجوع للخلف {backoff:.1f} ثانية (المحاولة {attempt + 1})")
time.sleep(backoff)
return polite_get(client_get, url, attempt + 1)
time.sleep(random.uniform(3, 7))
return r
| المعامل | القيمة الموصى بها |
|---|---|
| النوم العشوائي بين الطلبات | random.uniform(3, 7) ثوانٍ |
| backoff عند 429/403/503 | 2 → 4 → 8 → 16 ثانية، بحد أقصى 5 محاولات |
| عدد العمال المتزامنين لكل IP | 1 (نفّذ التسلسل لكل IP؛ واستخدم البروكسي للتوازي) |
| الحد المستدام التقريبي لكل IP سكني | نحو طلب واحد كل 5 ثوانٍ (~12 طلب/دقيقة) |
الطبقة 3: تدوير User-Agent والجلسات
بدّل بين مجموعة من سلاسل User-Agent الحقيقية للمتصفحات. واحفظ الجلسات والكوكيز لمحاكاة سلوك التصفح الحقيقي — Yelp تعتمد على الكشف عبر الكوكيز، لذا فإن إنشاء جلسة جديدة لكل طلب أمر مريب بحد ذاته.
UA_POOL = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 14_4_1) AppleWebKit/537.36 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",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 14.4; rv:125.0) Gecko/20100101 Firefox/125.0",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 14_4_1) AppleWebKit/605.1.15 Safari/17.4.1",
# أضف 5–10 سلاسل حديثة أخرى
]
الطبقة 4: تدوير البروكسيات
عند أي حجم حقيقي، ستحتاج إلى بروكسيات سكنية. البروكسيات السحابية ومجانية الاستخدام لا تعمل مع Yelp — فطبقة سمعة IP في Yelp تحظر مسبقًا نطاقات AWS وGCP وDigitalOcean.
| المزوّد | السعر الابتدائي لكل GB | ملاحظات |
|---|---|---|
| IPRoyal | $1.75/GB | الأرخص؛ ويشغّل أكثر شروحات Yelp تداولًا |
| Decodo (ex-Smartproxy) | $3.20–$3.50 | أفضل نسبة GB/$ عند التوسع |
| Bright Data | $4.00 (PAYG) | مجموعة IP ضخمة تتجاوز 150 مليونًا؛ وصفحة مخصصة لـ Yelp Proxies |
| Oxylabs | $6.00–$8.00 | ممتاز؛ أكثر من 10 ملايين IP |
| Aluvia (SIM mobile) | $3.00 | عناوين IP حقيقية من شبكات US carrier، ومصممة لـ Yelp |
البروكسيات السكنية الدوّارة (IP جديد لكل طلب) هي الأفضل للزحف الكبير على نتائج البحث. أما الجلسات الثابتة (الإبقاء على IP واحد لمدة 10 دقائق) فهي أفضل عندما تريد الحفاظ على الكوكيز أثناء التدفق من صفحة النشاط → المراجعات → الترقيم الصفحي.
الطبقة 5: اكتشاف الحظر والتعامل معه
ليس كل حظر يبدو بالشكل نفسه. Yelp كثيرًا ما تعرض غلافًا عامًا من نوع "page not available" بدل CAPTCHA، ولهذا يظن الناس أن أدواتهم تعمل بينما هي في الحقيقة تتلقى استجابات فارغة.
BLOCK_MARKERS = (
"captcha", "px-captcha", "page not available",
"access denied", "unusual traffic",
)
def is_blocked(resp):
if resp.status_code in (401, 403, 429, 503):
return True
body = resp.text.lower()
if any(m in body for m in BLOCK_MARKERS):
return True
# إذا كانت هذه صفحة بحث/نشاط لكن react-root-props مفقودة،
# فهذا يعني أن Yelp أرسلت رد حظر مخفف
if "react-root-props" not in body and "/biz/" in str(resp.url):
return True
return False
| الإشارة | المعنى |
|---|---|
| HTTP 403 | حظر صريح — تم حرق الـ IP/الـ headers/بصمة TLS |
| HTTP 429 | تجاوزت المعدل — غالبًا يمكن التعافي عبر backoff |
| HTTP 503 | حظر عام أو تخفيف حمل |
إعادة توجيه إلى /error أو جسم يحتوي "page not available" | حظر خفيف |
| فارغ ويحتوي فقط على | صفحة تحدي تنتظر JavaScript |
وجود captcha / g-recaptcha / px-captcha في الجسم | تصعيد — مطلوب CAPTCHA |
غياب react-root-props في صفحة قائمة | استجابة حظر مخففة |
الطبقة 6: حيلة التحليل الأكثر صلابة — JSON المخفي بدل محددات CSS
أعيدها لأن الفكرة مهمة: Yelp تغيّر أسماء CSS class وقت البناء. وأي أداة استخراج تعتمد على h3.y-css-14xwok2 ستتعطل خلال أسابيع عندما تعيد Yelp النشر مع h3.y-css-hcq7b9.
الحمولات التي لا تتغير:
<script type="application/ld+json">— بيانات schema.org المنظمة (الاسم، العنوان، الهاتف، التقييم، ساعات العمل)<script data-id="react-root-props">— بيانات نتائج البحث الكاملة بصيغة JSONhttps://www.yelp.com/gql/batch— نقطة نهاية GraphQL للمراجعات معdocumentIdثابت
إذا كنت تحلل CSS classes، فأنت تبني على الرمل. حلّل JSON بدلًا من ذلك.
الطبقة 7: بديل المتصفح الخفي
انتقل إلى متصفح headless فقط عندما يفشل curl_cffi مع البروكسيات السكنية — عادة عندما تعرض Yelp صفحة تحدي JavaScript أو CAPTCHA.
في 95% من حالات استخراج بيانات الشركات/البحث/المراجعات، يكون curl_cffi + JSON المخفي + البروكسيات السكنية أسرع وأرخص وأكثر موثوقية من المتصفح. لكن عندما تحتاج إلى متصفح فعلاً:
| الأداة | الحالة (2025) | ملاحظات |
|---|---|---|
| rebrowser-playwright | نقطة انطلاق موصى بها | نسخة Playwright معدّلة لتقليل تسرب CDP |
| nodriver | الأفضل في تخفي Chrome | خليفة undetected-chromedriver؛ يتجنب بروتوكول WebDriver بالكامل |
| patchright | فرع Playwright نشط الصيانة | ينجح في اختبارات الكشف الحديثة |
| playwright-stealth | ناضجة | تصحح navigator.webdriver، وتحذف HeadlessChrome من الـ UA |
تجاوز Selenium العادي مع Yelp. من السهل جدًا كشفه.
مقارنة كاملة: Yelp Fusion API مقابل Python Scraping مقابل Thunderbit
| البُعد | Yelp Fusion API | استخراج Python | Thunderbit |
|---|---|---|---|
| النص الكامل للمراجعات | ❌ 3 مقتطفات × ~160 حرفًا | ✅ غير محدود (GraphQL) | ✅ قالب مراجعات مدمج |
| البيانات الوصفية للمراجعات (الأصوات، ردود المالك) | ❌ | ✅ | ✅ عبر الحقول المقترحة بالذكاء الاصطناعي |
| الصور | ❌ (0 في الخطة الأساسية) | ✅ غير محدود | ✅ |
| أقصى عدد نتائج لكل بحث | 240 (كان 1,000 قبل 2024) | غير محدود (مع الترقيم الصفحي) | غير محدود |
| الحد اليومي | 300–500 (للجدد) / 5,000 (للقدامى) | ميزانية البروكسي فقط | بنظام الرصيد (3,000/شهر في Pro) |
| جهد الإعداد | نحو 15 دقيقة | من ساعات إلى أيام | نحو دقيقتين |
| التعامل مع الحظر | غير مطلوب | مشكلتك | مُدار (وضع Cloud) |
| المخاطر القانونية | منخفضة (مصرح) | متوسطة (منطقة رمادية في الشروط) | متوسطة (مثل أي استخراج) |
| التكلفة (المدخل) | 29$/شهر | نحو $0.75–$4/GB للبروكسيات + وقت التطوير | خطة مجانية |
| التكلفة عند الاستخدام الكثيف | $643+/شهر | $50–$500/شهر للبروكسيات + وقت التطوير | $38–$49/شهر |
| تصدير البيانات | JSON | CSV/JSON (أنت تكتبه) | Excel / Sheets / Airtable / Notion — مجانًا |
| الصيانة | منخفضة | مرتفعة (العناصر تتغير والحظر يتصاعد) | منخفضة (الذكاء يعيد التكيّف) |
نصائح قانونية وأخلاقية لاستخراج بيانات Yelp
لست محاميًا، وهذا ليس استشارة قانونية. لكن المشهد القانوني تغيّر بما يكفي خلال العامين الماضيين بحيث يجب أن تعرف الأساسيات قبل استثمار وقتك في مشروع استخراج بيانات من Yelp.
ما تقوله شروط Yelp: تحديث شروط الاستخدام في أكتوبر 2025 يحظر صراحة استخدام "أي روبوت أو spider... أو أي جهاز آلي آخر" من أجل "الوصول إلى أي جزء من الخدمة أو استرجاعه أو نسخه أو استخراجه أو فهرسته". كما أضاف لغة تتعلق بـ "AI Technologies and/or other automated tools".
وتؤكد Yelp Support: "Yelp لا تسمح بأي عملية استخراج من الموقع."
ما يقوله robots.txt: يحتوي robots.txt لدى Yelp على User-agent: * / Disallow: / شامل، ويمنع أيضًا GPTBot وClaudeBot وPerplexityBot وCCBot وMeta-ExternalAgent. ولا يُسمح إلا لـ Googlebot وBingbot وبعض أدوات الزحف الخاصة بمنصات التواصل.
السابقة القانونية الأهم: في قضية Meta v. Bright Data (المحكمة الجزئية الشمالية في كاليفورنيا، يناير 2024)، حكمت المحكمة بأن استخراج البيانات المتاحة للعامة، من دون تسجيل دخول، لا ينتهك شروط Meta. والتمييز الأساسي هنا هو: بيانات عامة من دون تسجيل دخول مقابل بيانات تتطلب تسجيل دخول. كما أن قضية hiQ v. LinkedIn قررت أن استخراج البيانات العامة لا ينتهك على الأرجح CFAA، لكن hiQ خسرت مع ذلك في دعاوى المسؤولية المدنية على مستوى الولاية (التعدي على المنقولات، والاستيلاء غير المشروع)، وصدر ضدها حكم بقيمة $500,000.
إرشادات عملية:
- استخرج فقط الصفحات العامة المتاحة من دون تسجيل دخول
- حد من سرعة طلباتك (التأخيرات في هذا الدليل تؤدي أيضًا وظيفة أخلاقية كحدود معدل)
- لا تعِد بيع النص الخام للمراجعات منسوبًا إلى مستخدمين بأسمائهم — احترم خصوصية المراجعين
- التزم بقوانين حماية البيانات المحلية (CCPA، GDPR)
- لا تسجّل الدخول من أجل الاستخراج — فهذا يتجاوز حدود التصريح
- تعامل مع معلومات النشاط التجاري (الاسم/العنوان/الهاتف/التقييم) كحقائق عامة، ومع نص المراجعات كبيانات أكثر حساسية
استشر مختصًا قانونيًا بشأن حالتك الخاصة.
الخلاصة
ثلاثة مسارات، وهدف واحد.
واجهة Yelp Fusion API هي الخيار المصرح والمنخفض الصيانة — لكنها تقتصر على 3 مقتطفات مراجعات وتبدأ من $29 شهريًا. أما استخراج البيانات بـ Python فيمنحك تحكمًا كاملًا في كل نقطة بيانات داخل Yelp، لكنه يحتاج استثمارًا حقيقيًا: curl_cffi لانتحال بصمة TLS، وبروكسيات سكنية، وتأخيرات عشوائية، وتحليل JSON المخفي، وصيانة مستمرة مع تطور دفاعات Yelp. أما Thunderbit فيوصلك من "أحتاج بيانات Yelp" إلى "هذا ملفي الجدولي" في نحو 30 ثانية، من دون كود ومن دون إعداد بروكسي.
المتطلبات الأساسية لتجاوز الحظر التي تعمل فعلًا في 2025: Headers واقعية مع Client Hints كاملة، وcurl_cffi لانتحال بصمة TLS، وتأخيرات عشوائية مع exponential backoff، وتدوير البروكسيات السكنية، وفوق كل ذلك تحليل JSON المخفي (application/ld+json وreact-root-props) بدلًا من الاعتماد على محددات CSS الهشة.
لست متأكدًا أي طريق يناسبك؟ جرّب الخطة المجانية في Thunderbit أولًا. إذا لبّت احتياجاتك، فقد وفّرت على نفسك ساعات. وإن كنت تحتاج مزيدًا من التحكم — خطوط معالجة برمجية كاملة، وحقولًا مخصصة، وتكاملًا محكمًا مع CRM — فالدليل أعلاه يغطي ذلك. ولإلقاء نظرة أوسع على مشهد أدوات الاستخراج، اطلع على تجميعنا لأفضل إضافات Chrome لاستخراج البيانات أو دليلنا حول استخراج البيانات من المواقع إلى Excel.
جرّب Thunderbit لاستخراج بيانات Yelp Get Started Free
الأسئلة الشائعة
هل يمكنني استخراج بيانات Yelp مجانًا باستخدام Python؟
نعم — باستخدام مكتبات مجانية مثل curl_cffi وparsel وjmespath. لكن عند أي حجم حقيقي (أكثر من بضع عشرات من الصفحات)، ستحتاج إلى بروكسيات سكنية مدفوعة، وتبدأ أسعارها من حوالي $1.75/GB مع IPRoyal. كما يوفر Thunderbit خطة مجانية مع 6 صفحات شهريًا لاستخراج سريع من دون كود.
هل Yelp تحظر أدوات الاستخراج؟
نعم، وبشكل صارم. تستخدم Yelp بصمة TLS/JA3، وتقييم سمعة IP، وCAPTCHA، والتحليل السلوكي، وCSS classes متغيرة ومموّهة. وrequests العادية تُحظر من أول محاولة. الاستراتيجية متعددة الطبقات في هذا الدليل — curl_cffi لانتحال TLS، وHeaders واقعية، وتأخيرات عشوائية، وبروكسيات سكنية — هي ما يعمل في 2025.
هل Yelp Fusion API أفضل من الاستخراج؟
يعتمد ذلك على احتياجاتك. فالـ API مصرح بها ومنخفضة المخاطر، لكنها لا تُرجع سوى 3 مقتطفات مراجعات بطول يقارب 160 حرفًا لكل منها، وتحد النتائج بـ 240، وتبدأ من $29 شهريًا. إذا كنت تحتاج النص الكامل للمراجعات، أو بياناتها الوصفية، أو أكثر من بضع مئات من السجلات يوميًا، فالاستخراج هو الخيار الوحيد.
كيف أستخرج مراجعات Yelp باستخدام Python؟
استخدم curl_cffi مع impersonate="chrome131" لجلب صفحة النشاط، ثم استخرج معرّف النشاط المشفّر من <meta name="yelp-biz-id">، ثم أرسل POST إلى https://www.yelp.com/gql/batch مع عملية GetBusinessReviewFeed واستخدم cursor مشفرًا بـ base64 في الحقل after للتنقل بين الصفحات. الكود خطوة بخطوة موجود في قسم الشرح أعلاه. كما أن مستودع Scrapfly Yelp scraper مرجع تطبيقي جيد أيضًا.
هل يمكنني استخراج بيانات Yelp من دون كتابة كود؟
نعم — AI Web Scraper من Thunderbit يأتي بقوالب جاهزة لـ Yelp business وreview. افتح صفحة Yelp، واضغط AI Suggest Fields، ثم Scrape. التصدير إلى Google Sheets وExcel وAirtable وNotion مجاني في كل الخطط، بما فيها الخطة المجانية.
اعرف المزيد


