إذا كان برنامج استخراج بيانات Glassdoor الخاص بك يعمل بشكل ممتاز في 2022 وأصبح الآن لا يُرجع سوى أخطاء 403، فأنت لست وحدك. فالمساحات والمنتديات مليئة بالسؤال نفسه: "هل يعرف أحد لماذا لم يعد هذا الكاشط يعمل؟"
الجواب المختصر: Glassdoor غيّرت كل شيء. فقد ضمّت Recruit Holdings منصة Glassdoor إلى Indeed في يوليو 2025، وتسرب عن ذلك تسريح 1,300 موظف، كما شددت منظومة الحماية ضد البوتات إلى درجة أن أدوات Selenium البسيطة أو أدوات scraping القائمة على requests تُحظر قبل حتى تحميل أول بايت من HTML. وبحلول فبراير 2026، أصبحت عمليات تسجيل الدخول في Glassdoor تتم بالكامل عبر Indeed Login — لذلك فإن أي شرح يعتمد على نموذج تسجيل دخول خاص بـ Glassdoor أصبح معطوبًا من الأساس. وفي الوقت نفسه، ما زالت المنصة تحتفظ بأكثر من 180 مليون مراجعة وبيانات رواتب ورؤى مجمعة عبر 2.5 مليون جهة عمل. هذه البيانات ثمينة للغاية لقياس أداء الموارد البشرية، وتحليل المنافسين، واستهداف العملاء المحتملين — إذا تمكنت فعليًا من الوصول إليها. هذا الدليل هو النسخة التي تعمل بعد كل هذه التغييرات، ويغطي الأنواع الثلاثة من بيانات Glassdoor (الوظائف، والمراجعات، والرواتب) في مكان واحد. سأشرح لك طريقة Python مع كود 2025 يعمل فعليًا، وأوضح لك بالضبط ما الذي يعيقك وكيف تتجاوزه، وأعرض أيضًا حلاً بلا كود لمن يفضّل تجاوز الجانب الهندسي بالكامل.
لماذا تستخرج بيانات Glassdoor باستخدام Python في 2025؟
Glassdoor ليست مجرد لوحة وظائف. إنها واحدة من أغنى قواعد بيانات معلومات أصحاب العمل على الويب — ويستخدمها نحو ثلث شركات Fortune 500 وتجذب حوالي 55 مليون زائر فريد شهريًا. البيانات الموجودة خلف هذه الصفحات تدعم قرارات أعمال حقيقية عبر عدة فرق.
إليك كيف تستخدم الفرق المختلفة بيانات Glassdoor فعليًا:
| حالة الاستخدام | نوع البيانات المطلوبة | الجهات المستفيدة |
|---|---|---|
| مقارنة الرواتب بالسوق | توزيعات الرواتب، أحجام العينات | الموارد البشرية، المكافآت والتعويضات، العمليات |
| تتبع توظيف المنافسين | إعلانات الوظائف، وتيرة النشر | المبيعات، الاستراتيجية، الاستثمار الجريء/تطوير الشركات |
| مراقبة السمعة الوظيفية | نص المراجعات، اتجاهات التقييم، موافقة الرئيس التنفيذي | الموارد البشرية، التسويق، الاتصالات |
| توليد العملاء المحتملين (الشركات النامية) | إعلانات الوظائف + معلومات الشركة | فرق المبيعات، ممثلو تطوير المبيعات |
| أبحاث السوق/الأبحاث الأكاديمية | الأنواع الثلاثة كلها | المحللون، الاستشاريون، الباحثون |

عندما تعذر على مكتب إحصاءات العمل الأمريكي نشر بيانات الوظائف أثناء الإغلاق الحكومي في أكتوبر 2025، نشرت غرفة الأبحاث الاقتصادية التابعة لـ Glassdoor تقريرًا بديلًا عن الوظائف اعتمادًا على بياناتها. هكذا ينظر المحللون المؤسسيون إلى هذه البيانات اليوم.
ولا تزال Python هي اللغة المفضلة لأن منظومتها لا تُضاهى — مثل Playwright لأتمتة المتصفح، وparsel/lxml لتحليل HTML، وcurl_cffi لتجاوز بصمة TLS، ومجتمع ضخم يشارك أنماطًا عملية تعمل بالفعل. المشكلة ليست في Python. المشكلة أن Glassdoor أصبحت أصعب بكثير في الاستخراج.
استخرج بيانات Glassdoor بالذكاء الاصطناعي Get Started Free
إذا كنت تبحث عن بديل بلا كود لاستخراج بيانات Glassdoor، يمكن لـ Thunderbit مساعدتك في استخراج صفحات الوظائف والمراجعات والرواتب من دون بناء وصيانة بنية Python مخصصة.
ما البيانات التي يمكنك استخراجها فعليًا من Glassdoor؟
معظم الشروحات تركز فقط على قوائم الوظائف. لكن الطلب الحقيقي — وفقًا لما تتبعتُه من خيوط النقاش في المنتديات، ومشكلات GitHub، وأسئلة Reddit — يتركز على نوعين لا يشرحهما أحد بشكل كافٍ: المراجعات والرواتب. فيما يلي التفصيل الكامل لما يمكن استخراجه من الفئات الثلاث.
إعلانات الوظائف
هذا هو النوع الأسهل للوصول. يمكنك استخراج: المسمى الوظيفي، اسم الشركة، الموقع، تقدير الراتب، تقييم الشركة، تاريخ النشر، شارة التقديم السهل، ورابط الوظيفة. وتكون الوظائف متاحة جزئيًا حتى من دون تسجيل دخول، رغم أن Glassdoor قد تعرض نافذة تسجيل دخول بعد عدة صفحات.
مراجعات الشركات
هنا تصبح البيانات أكثر قيمة لتحليل السمعة الوظيفية. الحقول القابلة للاستخراج تشمل: التقييم العام، التقييمات الفرعية (التوازن بين العمل والحياة، الثقافة والقيم، التنوع والشمول، فرص النمو المهني، الأجر والمزايا، الإدارة العليا)، نص الإيجابيات، نص السلبيات، المسمى الوظيفي للمراجع، تاريخ المراجعة، وحالة التوظين. أما النص الكامل للمراجعة فهو محمي بتسجيل الدخول — سترى ملخصًا، لكن التفاصيل الكاملة للإيجابيات والسلبيات تتطلب المصادقة.
بيانات الرواتب
هذا هو النوع الأكثر طلبًا والأكثر إزعاجًا في الوقت نفسه. يمكنك استخراج: المسمى الوظيفي، نطاق الراتب الأساسي، نطاق إجمالي التعويضات، عدد تقارير الرواتب، والموقع. لكن صفحات الرواتب محمية بالكامل بتسجيل الدخول، وأحيانًا تضيف Glassdoor خطوة إضافية من نوع "ساهم لفتح المحتوى" حيث تحتاج إلى إدخال راتبك أولًا قبل رؤية بيانات الآخرين. لا يقدم أي شرح منافس كودًا يعمل لهذا الجزء — وسنصلحه هنا.
ما الذي يتطلب تسجيل دخول وما الذي لا يتطلبه؟
هذا الجدول سيوفر عليك تجربة الصفحات الفارغة بالطريقة الصعبة:
| نوع البيانات | متاح بدون تسجيل دخول؟ | ملاحظات |
|---|---|---|
| عناوين الوظائف والمعلومات الأساسية | غالبًا نعم | قد تظهر نافذة منبثقة بعد عدة صفحات |
| أوصاف الوظائف الكاملة | جزئيًا | غالبًا تُحجب بعد 2–3 مشاهدات |
| مراجعات الشركات (النص الكامل) | لا — يتطلب تسجيل دخول | يظهر ملخص فقط، والنص الكامل محمي |
| بيانات الرواتب | لا — يتطلب تسجيل دخول | قد تتطلب أيضًا "المساهمة لفتح المحتوى" |
لماذا تعطل برنامج استخراج Glassdoor القديم لديك على الأرجح

أريد أن أكون واضحًا هنا: إذا كنت تنسخ كودًا من شرح نُشر بين 2021 و2023، فلن يعمل. أشهر مستخرج Glassdoor القديم المبني على Selenium في GitHub (MatthewChatham/glassdoor-review-scraper، حوالي 1.4 ألف نجمة) لديه أكثر من 12 مشكلة مفتوحة بلا حل — منها "Glassdoor new UI design" و"Cloudflare anti-bot protection" و"NoSuchElementException". المستودع مهجور عمليًا. كما أن أداة Apify glassdoor-jobs-scraper actor أصبحت موسومة بأنها DEPRECATED. وتمنح ScrapeOps Glassdoor تقييم صعوبة عام 9/10 وصعوبة تجاوز الحماية 8/10.
إليك ما تغيّر ولماذا يتعطل الكود القديم:
| طبقة الحماية | ما الذي تغيّر | الأثر على الأدوات القديمة |
|---|---|---|
| Cloudflare Bot Management | تشديد بصمات JA3/JA4 منذ 2024 | تُحظر سكربتات requests/Selenium الأساسية مباشرة بأخطاء 403 |
| أسماء CSS الديناميكية | تُعاد عشوائيتها في كل build | محددات CSS القديمة تتعطل بصمت |
| تحديد المعدل + تتبع الجلسة | تشديد حدود كل IP وكل جلسة | تُحظر الأدوات بعد عدد أقل من الصفحات |
| تحديات CAPTCHA (غالبًا Cloudflare Turnstile) | أصبحت أكثر تكرارًا، خاصة مع التصفح الصفحي | المتصفحات غير المرئية تُفعّل التحديات |
| توسيع جدار تسجيل الدخول | أصبحت أنواع صفحات أكثر تتطلب المصادقة | صفحات الرواتب والمراجعات تعود ببيانات فارغة |
| الانتقال إلى Indeed Login (فبراير 2026) | استبدال نموذج تسجيل دخول Glassdoor بالكامل | أي كود يستهدف DOM القديم لتسجيل الدخول انتهى |
دليل Scrapfly لعام 2026 يتضمن تحذيرًا صريحًا: "Glassdoor معروفة بمعدل الحظر المرتفع، لذا إذا حصلت على قيم None أثناء تشغيل كود Python، فغالبًا تم حظرك." كما يوضح منشور DEV.to من مارس 2026 الأمر بشكل مباشر: "طلبات HTTP البسيطة باستخدام requests أو httpx تُحظر فورًا."
وسأعرض لك أيضًا أساليب المواجهة — مثل Patchright (نسخة Playwright متخفية)، ومحددات data-test، والبروكسيات السكنية المتناوبة، والجلسات المستمرة المصادقة — وهي مصممة خصيصًا للتعامل مع كل طبقة من هذه الطبقات.
Glassdoor API أم الاستخراج عبر Python: اختر المسار الصحيح أولًا
تسأل عدة خيوط نقاش: "هل أستخدم Glassdoor API بدلًا من ذلك؟" والإجابة هي: لا يمكنك.
واجهة Glassdoor Partner API القديمة مغلقة أمام المتقدمين الجدد. ولا يزال بوابة المطورين موجودة من الناحية التقنية لكنها تعيد HTTP 403. لم توجد قط نقطة نهاية عامة للمراجعات — وقد تم إنشاء أداة MatthewChatham تحديدًا "لأن Glassdoor لا تملك API للمراجعات." ولا توجد أيضًا أي خطة ترحيل للمراجعات أو الرواتب ضمن Indeed Publisher API.
إليك المقارنة بصراحة:
| العامل | Glassdoor Partner API v1 | الاستخراج عبر Python | Thunderbit (بدون كود) |
|---|---|---|---|
| الوصول | مغلق أمام المتقدمين الجدد | متاح (أنت تنفذه) | إضافة Chrome |
| إعلانات الوظائف | محدود/في طور الإيقاف | متاح مع بعض الجهد | متاح |
| مراجعات الشركات | لم تكن موجودة علنًا | نعم (يتطلب تسجيل دخول) | نعم (عبر Browser Mode) |
| بيانات الرواتب | لم تكن موجودة علنًا | نعم (يتطلب تسجيل دخول) | نعم |
| حدود المعدل | غير موثقة | أنت تتحكم بالإيقاع | بنظام Credits |
| الجهد المطلوب للإعداد | لا يمكنك تسجيل تطبيقات جديدة | من ساعات إلى أيام | حوالي دقيقتين |
| عبء الصيانة | غير منطبق | مرتفع (تغيّر HTML يكسر الكود) | منخفض (الذكاء الاصطناعي يعيد اقتراح الحقول) |
إذا كنت تحتاج إلى المراجعات أو بيانات الرواتب — وهذا ينطبق على معظم من يقرأ هذا المقال — فالاستخراج عبر Python أو أداة بلا كود هو خيارك الواقعي الوحيد.
قبل أن تبدأ
- مستوى الصعوبة: متوسط (يُفضّل أن تكون مرتاحًا مع Python وسطر الأوامر)
- الوقت المطلوب: حوالي 30–60 دقيقة للإعداد الكامل؛ ثم نحو 10 دقائق لكل نوع بيانات
- ما ستحتاجه:
- Python 3.10+ (يُوصى بـ 3.11 أو 3.12)
- متصفح Chrome مثبت
- حساب على Glassdoor (مجاني — مطلوب لبيانات الرواتب والمراجعات)
- بروكسيات سكنية متناوبة (لأكثر من بضع صفحات)
- اختياري: إضافة Thunderbit Chrome Extension إذا كنت تريد المسار بلا كود
الأدوات والمكتبات لاستخراج Glassdoor باستخدام Python في 2025
لقد تغيّر مشهد الأدوات بشكل كبير. إليك ما يعمل فعليًا مع دفاعات Glassdoor الحالية.
لماذا Patchright هو الخيار الأفضل لـ Glassdoor
Patchright هو فرع متخفٍ من Playwright يعالج تسرب Runtime.Enable عبر CDP — وهو السبب التقني المحدد الذي يجعل Playwright العادي يفشل على المواقع المحمية بـ Cloudflare. يستخدم نفس واجهة Playwright تمامًا، لذا إذا كنت تعرف Playwright فأنت تعرف Patchright. الإصدار 1.58.2 (مارس 2026) هو الإصدار الحالي ويجري تطويره بنشاط.
مقارنةً بالبدائل:
- Playwright العادي: يتم اكتشافه على صفحة تسجيل الدخول في Glassdoor بسبب تسرب Runtime.Enable
- Selenium + undetected-chromedriver: آخر إصدار لـ undetected-chromedriver كان في فبراير 2024 — وهو عمليًا حل قديم. ووجد اختبار Scrapfly المرجعي أنه "فشل على كل نطاق في اختبارنا"
- requests + BeautifulSoup: لا يستطيعان تنفيذ JavaScript، ويُحظران فورًا بسبب بصمة TLS من Cloudflare
- curl_cffi: ممتاز للمسار السريع (أسرع 10–20 مرة من المتصفح) عندما ترسل الصفحات
__NEXT_DATA__داخل HTML الأولي، لكنه لا يتعامل مع تسجيل الدخول أو التحديات البينية
المكتبات المساندة
- parsel (1.11.0) أو lxml (6.0.4): لتحليل HTML/XPath بسرعة
- csv أو pandas: لتصدير البيانات
- asyncio: لاستخراج غير متزامن لتصفح الصفحات بشكل أسرع
البروكسيات: سكنية فقط
طبقة Cloudflare في Glassdoor تشدد التحقق من عناوين IP الخاصة بمراكز البيانات بشكل عدواني. وتشير التقارير إلى أن البروكسيات السكنية تخفض معدلات الحظر من 20–30% إلى أقل من 5%. يبدأ التسعير تقريبًا من 1.75 دولار/GB لدى IPRoyal (عروض ترويجية) أو 3.00 دولارات/GB لدى Decodo. وللاستخراج الإنتاجي، خصص ميزانية 3–8 دولارات/GB بحسب الحجم.
ومن الضروري أيضًا إدراج فواصل عشوائية بين الطلبات (3–8 ثوانٍ على الأقل، و5–15 ثانية للتشغيلات الأطول) بغض النظر عن جودة البروكسي.
الخطوة 1: إعداد بيئة Python
أنشئ مجلد المشروع وثبّت الحزمة الموصى بها:
mkdir glassdoor-scraper && cd glassdoor-scraper
python3.11 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
# الحزمة الأساسية
pip install patchright==1.58.2 parsel==1.11.0
# تثبيت ملفات المتصفح
patchright install chromium
# اختياري: المسار السريع لاستخراج __NEXT_DATA__
pip install "curl_cffi==0.15.0"
من المفترض أن ترى Patchright وهو يحمّل نسخة Chromium. إذا فشل patchright install chromium، فتحقق من توفر مساحة كافية على القرص (حوالي 300MB) وأن إصدار Python لديك 3.10 أو أعلى.
الخطوة 2: تشغيل Patchright والانتقال إلى Glassdoor
إليك نمط التشغيل الأساسي الذي ينجح مع طبقة Cloudflare في Glassdoor:
from patchright.sync_api import sync_playwright
import random, time
with sync_playwright() as p:
browser = p.chromium.launch(
headless=False, # الوضع غير المرئي ما يزال أكثر قابلية للاكتشاف
channel="chrome", # استخدم Chrome الحقيقي، وليس Chromium المرفق
)
context = browser.new_context(
viewport={"width": 1440, "height": 900},
locale="en-US",
timezone_id="America/New_York",
user_agent=(
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/134.0.0.0 Safari/537.36"
),
)
page = context.new_page()
page.goto(
"https://www.glassdoor.com/Job/new-york-data-engineer-jobs-"
"SRCH_IL.0,8_IC1132348_KO9,22.htm"
)
# إخفاء طبقة تسجيل الدخول — المحتوى ما يزال موجودًا في DOM
page.add_style_tag(content="""
#HardsellOverlay, .LoginModal { display: none !important; }
body { overflow: auto !important; position: initial !important; }
""")
page.wait_for_selector("[data-test='jobListing']")
print("تم تحميل الصفحة — وإعلانات الوظائف ظاهرة.")
هناك نقطتان مهمتان هنا. الوسيط channel="chrome" يخبر Patchright باستخدام نسخة Chrome المثبتة لديك بدل Chromium المدمج — وهذا ينتج بصمة متصفح أقرب إلى السلوك الحقيقي. كما أن حيلة add_style_tag تُخفي نافذة تسجيل الدخول في Glassdoor (المعروفة باسم #HardsellOverlay) من دون الضغط على أي شيء. وتؤكد Scrapfly أن "كل المحتوى ما يزال موجودًا، لكنه مغطى فقط بالنافذة" — فالبيانات موجودة داخل HTML سواء كانت النافذة ظاهرة أم لا.
من المفترض أن ترى نافذة Chrome تفتح، وتنتقل إلى صفحة بحث الوظائف في Glassdoor، وتعرض بطاقات الوظائف من دون أن تمنعك نافذة تسجيل الدخول من المشاهدة.
الخطوة 3: استخراج إعلانات وظائف Glassdoor
تحديد محددات مستقرة
تقوم Glassdoor بتوليد أسماء CSS عشوائيًا في كل build — لذا فإن المحدد .jobCard_xyz123 من شرح قديم لن يُرجع شيئًا اليوم. بدلًا من ذلك، استخدم سمات data-test، وهي اصطلاح داخلي للاختبار لدى Glassdoor وتبقى ثابتة عبر النشر.
إليك مرجع المحددات لحقول إعلانات الوظائف:
| الحقل | المحدد |
|---|---|
| حاوية بطاقة الوظيفة | [data-test="jobListing"] |
| المسمى الوظيفي | [data-test="job-title"] |
| رابط الوظيفة | a[data-test="job-link"] |
| اسم الشركة | [data-test="employer-name"] |
| الموقع | [data-test="emp-location"] |
| نطاق الراتب | [data-test="detailSalary"] |
| تقييم الشركة | [data-test="rating"] |
| تاريخ النشر | [data-test="job-age"] |
| التالي في الترقيم الصفحي | [data-test="pagination-next"] |
استخراج بيانات الوظائف
from parsel import Selector
import csv, random, time
def scrape_jobs(page, max_pages=5):
all_jobs = []
for page_num in range(1, max_pages + 1):
html = page.content()
sel = Selector(text=html)
cards = sel.css('[data-test="jobListing"]')
if not cards:
print(f"الصفحة {page_num}: لم يتم العثور على بطاقات — احتمال وجود حظر أو تغيّر في المحدد.")
break
for card in cards:
job = {
"title": card.css('[data-test="job-title"]::text').get("").strip(),
"company": card.css('[data-test="employer-name"]::text').get("").strip(),
"location": card.css('[data-test="emp-location"]::text').get("").strip(),
"salary": card.css('[data-test="detailSalary"]::text').get("").strip(),
"rating": card.css('[data-test="rating"]::text').get("").strip(),
"link": card.css('a[data-test="job-link"]::attr(href)').get(""),
"posted": card.css('[data-test="job-age"]::text').get("").strip(),
}
if job["link"] and not job["link"].startswith("http"):
job["link"] = "https://www.glassdoor.com" + job["link"]
all_jobs.append(job)
print(f"الصفحة {page_num}: تم استخراج {len(cards)} وظيفة")
# الترقيم الصفحي
next_btn = page.query_selector('[data-test="pagination-next"]')
if next_btn and page_num < max_pages:
next_btn.click()
time.sleep(random.uniform(3, 8))
page.wait_for_selector("[data-test='jobListing']")
else:
break
return all_jobs
الحفظ إلى CSV
def save_to_csv(jobs, filename="glassdoor_jobs.csv"):
if not jobs:
print("لا توجد وظائف للحفظ.")
return
keys = jobs[0].keys()
with open(filename, "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=keys)
writer.writeheader()
writer.writerows(jobs)
print(f"تم حفظ {len(jobs)} وظيفة في الملف {filename}")
ملاحظة حول حدود الترقيم الصفحي: Glassdoor تحدّ نتائج البحث بحوالي 30 صفحة تقريبًا بغض النظر عن العدد الإجمالي. إذا كنت تحتاج إلى تغطية أوسع، فاستخدم الفلاتر (الموقع، نوع الوظيفة، نطاق الراتب) لتضييق كل بحث بدلًا من محاولة التصفح بعد الحد الأقصى.
في اختباري، استغرق استخراج 5 صفحات من إعلانات الوظائف (حوالي 75 وظيفة) قرابة 45 ثانية مع فواصل عشوائية. أما القيام بذلك يدويًا فسيستغرق ما لا يقل عن 20 دقيقة من النسخ واللصق.
الخطوة 4: استخراج مراجعات شركات Glassdoor
هذا هو القسم الذي لا يقدم أي شرح آخر فيه كودًا يعمل فعليًا. فالمراجعات هي المكان الذي تعيش فيه معلومات أصحاب العمل الحقيقية — تحليل المشاعر، إشارات الثقافة الداخلية، وعلامات الخطر الإدارية.
الانتقال إلى صفحة المراجعات
تسير روابط المراجعات بهذا الشكل: /Reviews/{Company}-Reviews-E{id}.htm. يمكنك العثور على معرف الشركة بالبحث عنها في Glassdoor ثم التحقق من الرابط.
def navigate_to_reviews(page, company_reviews_url):
page.goto(company_reviews_url)
page.add_style_tag(content="""
#HardsellOverlay, .LoginModal { display: none !important; }
body { overflow: auto !important; position: initial !important; }
""")
page.wait_for_selector('[data-test="review"]', timeout=15000)
نقطة النهاية المخفية BFF (المسار الأنظف)
أكبر اكتشاف في بحثي هو أن مراجعات Glassdoor لديها واجهة JSON داخلية تعمل فعليًا وتجاوز الحاجة لتحليل HTML بالكامل. وقد وثّق مستودع Scrapfly الخاص بالـ scrapers هذه النقطة النهائية، وهي أكثر موثوقية بكثير من استخراج DOM.
import json, re, requests
def get_review_ids(page):
"""استخراج employerId و dynamicProfileId من HTML صفحة المراجعات."""
html = page.content()
sel = Selector(text=html)
script_text = sel.xpath(
"//script[contains(text(), 'profileId')]/text()"
).get("")
employer_match = re.search(r'"employer"\s*:\s*(\{[^}]+\})', script_text)
if employer_match:
meta = json.loads(employer_match.group(1))
return meta.get("id"), meta.get("profileId")
return None, None
def fetch_reviews_bff(page, employer_id, profile_id, max_pages=5):
"""استدعاء نقطة BFF الداخلية في Glassdoor للحصول على بيانات مراجعات منظمة."""
all_reviews = []
cookies = {c["name"]: c["value"] for c in page.context.cookies()}
for pg in range(1, max_pages + 1):
payload = {
"applyDefaultCriteria": True,
"employerId": employer_id,
"dynamicProfileId": profile_id,
"employmentStatuses": ["REGULAR", "PART_TIME"],
"language": "eng",
"onlyCurrentEmployees": False,
"page": pg,
"pageSize": 10,
"sort": "DATE",
"textSearch": "",
}
resp = requests.post(
"https://www.glassdoor.com/bff/employer-profile-mono/employer-reviews",
json=payload,
cookies=cookies,
headers={"Content-Type": "application/json"},
)
if resp.status_code != 200:
print(f"أعاد BFF الرمز {resp.status_code} في الصفحة {pg}")
break
data = resp.json()
reviews = data.get("data", {}).get("employerReviews", {}).get("reviews", [])
total_pages = data.get("data", {}).get("employerReviews", {}).get("numberOfPages", 1)
for r in reviews:
all_reviews.append({
"title": r.get("summary", ""),
"rating": r.get("ratingOverall"),
"pros": r.get("pros", ""),
"cons": r.get("cons", ""),
"author_role": r.get("jobTitle", {}).get("text", ""),
"date": r.get("reviewDateTime", ""),
"recommend": r.get("isRecommend"),
})
print(f"صفحة المراجعات {pg}/{total_pages}: تم جلب {len(reviews)} مراجعة")
if pg >= total_pages:
break
time.sleep(random.uniform(3, 6))
return all_reviews
تمنحك نقطة BFF بيانات JSON نظيفة بكل حقول المراجعات — من دون تحليل HTML، ومن دون أن تكسرها محددات CSS. أنت تحتاج إلى ملفات تعريف الارتباط الخاصة بجلسة Playwright/ Patchright المصادق عليها (سنغطي ذلك في الخطوة 6 أدناه)، كما تحتاج أولًا إلى استخراج employerId وdynamicProfileId من HTML صفحة المراجعات.
محددات HTML بديلة للمراجعات
إذا تغيّرت نقطة BFF أو كنت تفضّل تحليل DOM، فإليك المحددات الثابتة data-test:
| الحقل | المحدد |
|---|---|
| حاوية المراجعة | [data-test="review"] |
| العنوان | [data-test="review-title"] |
| التقييم العام | [data-test="overall-rating"] |
| الإيجابيات | [data-test="pros"] |
| السلبيات | [data-test="cons"] |
| التاريخ | [data-test="review-date"] |
| دور صاحب المراجعة | [data-test="author-jobTitle"] |
الخطوة 5: استخراج بيانات رواتب Glassdoor
صفحات الرواتب محمية بالكامل بتسجيل الدخول. يجب أن تكون لديك جلسة مصادقة (الخطوة 6) قبل أن يعيد أي من هذا الكود بيانات حقيقية.
الانتقال إلى صفحة الرواتب
تسير عناوين الرواتب بهذا الشكل: /Salary/{Company}-Salaries-E{id}.htm، مع ترقيم صفحي بالشكل _P{n}.htm.
def scrape_salaries(page, salary_url, max_pages=3):
all_salaries = []
for pg in range(1, max_pages + 1):
url = salary_url if pg == 1 else salary_url.replace(".htm", f"_P{pg}.htm")
page.goto(url)
page.add_style_tag(content="""
#HardsellOverlay { display: none !important; }
body { overflow: auto !important; position: initial !important; }
""")
time.sleep(random.uniform(3, 7))
html = page.content()
sel = Selector(text=html)
items = sel.css('[data-test="salary-item"]')
if not items:
print(f"صفحة الرواتب {pg}: لا توجد عناصر — احتمال وجود حظر أو جدار تسجيل دخول.")
break
for item in items:
salary = {
"job_title": item.css('[class*="SalaryItem_jobTitle__"]::text').get("").strip(),
"salary_range": item.css('[class*="SalaryItem_salaryRange__"]::text').get("").strip(),
"count": item.css('[class*="SalaryItem_salaryCount__"]::text').get("").strip(),
}
all_salaries.append(salary)
print(f"صفحة الرواتب {pg}: تم استخراج {len(items)} سجل")
return all_salaries
لاحظ نمط المطابقة الجزئية [class*="SalaryItem_jobTitle__"]. تستخدم صفحة الرواتب في Glassdoor أسماء CSS Modules مجزأة بالهاش (مثل SalaryItem_jobTitle__XWGpT) حيث يتغير لاحقة الهاش مع كل نشر. يبقى الجزء السابق ثابتًا — أما الهاش فلا. لا تقم أبدًا بكتابة اسم الفئة كاملًا بشكل صلب.
الخطوة 6: تجاوز جدار تسجيل الدخول في Glassdoor
هذه هي القطعة الحاسمة التي تفتح بيانات الرواتب والنص الكامل للمراجعات. الفكرة: سجّل الدخول يدويًا مرة واحدة في متصفح ظاهر، ثم احفظ حالة الجلسة المصادق عليها، وبعدها أعد استخدامها في كل عمليات الاستخراج اللاحقة.
حفظ الجلسة المصادق عليها
شغّل هذا السكربت مرة واحدة. سيقوم بفتح نافذة Chrome، والانتقال إلى صفحة تسجيل الدخول في Glassdoor (التي تعيد التوجيه الآن إلى Indeed Login)، ثم ينتظر منك أن تسجل الدخول يدويًا:
import asyncio
from pathlib import Path
from patchright.async_api import async_playwright
STATE_FILE = Path("glassdoor_state.json")
async def login_and_save():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False, channel="chrome")
context = await browser.new_context(
viewport={"width": 1366, "height": 800},
locale="en-US",
)
page = await context.new_page()
await page.goto("https://www.glassdoor.com/profile/login_input.htm")
print("سجّل الدخول في نافذة المتصفح، ثم اضغط Enter هنا...")
input()
await context.storage_state(path=str(STATE_FILE))
print(f"تم حفظ الجلسة في {STATE_FILE}")
await browser.close()
asyncio.run(login_and_save())
بعد تسجيل الدخول والضغط على Enter، يحفظ Patchright كل ملفات تعريف الارتباط وبيانات local storage في glassdoor_state.json. يحتوي هذا الملف على gdId وGSESSIONID وcf_clearance ورموز المصادقة.
إعادة استخدام الجلسة للاستخراج
كل عملية استخراج لاحقة ستقوم بتحميل الحالة المحفوظة — من دون الحاجة لتسجيل دخول يدوي:
async def scrape_with_auth(target_url):
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True, channel="chrome")
context = await browser.new_context(
storage_state="glassdoor_state.json"
)
page = await context.new_page()
await page.goto(target_url)
await page.add_style_tag(
content="#HardsellOverlay{display:none!important}"
)
await page.wait_for_load_state("networkidle")
html = await page.content()
await browser.close()
return html
تستمر الجلسة المحفوظة عادةً من 20 إلى 30 دقيقة من الاستخدام النشط قبل أن تعيد Glassdoor التحدي مرة أخرى. ولعمليات استخراج أطول، أضف فحصًا بسيطًا: إذا حصلت على صفر نتائج من صفحة يفترض أن تحتوي بيانات، فأعد تشغيل سكربت تسجيل الدخول لتحديث ملف الحالة.
اكتشاف نافذة تسجيل الدخول وإغلاقها
بالنسبة للصفحات المحمية جزئيًا (مثل صفحات الوظائف التي تعرض البيانات لكن تغطيها نافذة منبثقة)، تعمل طريقة إدخال CSS السابقة:
page.add_style_tag(content="""
#HardsellOverlay, .LoginModal { display: none !important; }
body { overflow: auto !important; position: initial !important; }
""")
هذه الطريقة تعمل فقط عندما يكون HTML يحتوي أصلًا على البيانات تحت الطبقة المغطية. أما الصفحات المحمية بالكامل من جهة الخادم (الرواتب وصفحات المراجعات العميقة)، فالجلسة المصادقة من الخطوة 6 هي المسار الوحيد.
نصائح لإبقاء برنامج استخراج Glassdoor يعمل باستمرار
تقوم Glassdoor بتحديث الواجهة الأمامية بشكل متكرر. إليك كيف تبني المرونة في برنامجك.
فضّل سمات data-test على أسماء الفئات
تقوم Glassdoor بعشوائية أسماء CSS، لكنها تميل إلى الإبقاء على سمات data-test ثابتة. فضّل دائمًا [data-test="jobListing"] على .jobCard_abc123. وعندما لا تتوفر data-test (كما في حقول الرواتب)، استخدم نمط المطابقة الجزئية: [class*="SalaryItem_jobTitle__"].
استخدم بروكسيات متناوبة وفواصل زمنية عشوائية
استخدم بروكسيات سكنية متناوبة — فـ IPs الخاصة بمراكز البيانات تتعرض للتحدي تقريبًا فورًا. أضف فواصل عشوائية من 3 إلى 8 ثوانٍ بين تحميل الصفحات (ومن 5 إلى 15 ثانية للتشغيلات الأطول). وتجنب قدر الإمكان الاستخراج خلال ساعات العمل الأمريكية، عندما يكون اكتشاف السلوك بواسطة Cloudflare أكثر عدوانية.
راقب الأعطال مبكرًا
أضف تحققًا بسيطًا داخل برنامجك: إذا كانت الصفحة التي ينبغي أن تحتوي بيانات تُرجع صفر سجلات، فتعامل مع ذلك كفشل في المحددات وليس كعدم وجود نتائج، وأرسل تنبيهًا لنفسك. نفذ اختبار استخراج صغيرًا أسبوعيًا لاكتشاف الأعطال مبكرًا — فـ Glassdoor تنشر تغييرات الواجهة الأمامية من دون إعلان.
استخدم المسار السريع __NEXT_DATA__ عندما يكون متاحًا
Glassdoor مبنية على Next.js + Apollo GraphQL. كثير من الصفحات يرسل وسم <script id="__NEXT_DATA__"> يحتوي على ذاكرة التخزين المؤقت الكاملة لـ GraphQL بصيغة JSON. تحليل هذا المسار أكثر مرونة بكثير من استخراج DOM ويتجاوز طبقة Hardsell بالكامل:
import json
def extract_next_data(html):
sel = Selector(text=html)
raw = sel.css("script#__NEXT_DATA__::text").get()
if raw:
return json.loads(raw)["props"]["pageProps"].get("apolloCache", {})
return None
هذه الدالة تُرجع ذاكرة Apollo المنظمة بكل حقول الوظائف والمراجعات والرواتب — من دون الحاجة إلى محددات CSS. إنها أكثر استراتيجية استخراج متانة متاحة، لأنها تعتمد على نفس البيانات التي تغذي واجهة React في Glassdoor.
تجاوز الكود: استخراج Glassdoor باستخدام Thunderbit (من دون Python)
ليس كل من يقرأ هذا المقال مطورًا. فرق الموارد البشرية، والمجندون، ومحللو عمليات المبيعات، وباحثو السوق يحتاجون إلى بيانات Glassdoor أيضًا — ولا ينبغي أن يضطروا لإدارة سياقات Playwright وتدوير البروكسيات للحصول عليها.
Thunderbit هو إضافة Chrome قائمة على الذكاء الاصطناعي لاستخراج الويب، ويمكنها استخراج البيانات نفسها من الوظائف والمراجعات والرواتب من دون كتابة سطر واحد من الكود. أنا أعمل ضمن فريق Thunderbit، لذا أود أن أكون صريحًا بشأن ذلك — لكن السبب في إدراجه هنا هو أنه يحل بالفعل أصعب مشكلتين في استخراج Glassdoor.
كيف يعمل Thunderbit مع Glassdoor
الطريقة بسيطة وتتم بخطوتين:
- افتح أي صفحة Glassdoor في Chrome (بحث وظائف، صفحة مراجعات شركة، صفحة رواتب)
- اضغط AI Suggest Fields في الشريط الجانبي لـ Thunderbit — سيقرأ الذكاء الاصطناعي DOM ويقترح أعمدة مثل المسمى الوظيفي، الشركة، التقييم، نطاق الراتب، الإيجابيات، السلبيات، إلخ
- اضغط Scrape — وسيتم استخراج البيانات إلى جدول من دون محددات CSS أو كود أتمتة متصفح
يملك Thunderbit قالبًا جاهزًا لاستخراج شركات Glassdoor يستخرج أكثر من 23 حقلًا لكل شركة في تشغيل واحد. أما لإعلانات الوظائف أو المراجعات أو الرواتب، فمسار AI Suggest Fields العام يتعامل مع أي رابط Glassdoor.
التعامل مع جدار تسجيل الدخول من دون كود
هذه هي أفضلية Thunderbit الهيكلية في Glassdoor تحديدًا. وضع المتصفح Browser Mode يعمل داخل جلسة Chrome الخاصة بك — فإذا كنت مسجل الدخول إلى Glassdoor في Chrome، يرث Thunderbit تلك الملفات تلقائيًا. جدار تسجيل الدخول الذي يحجب الرواتب والمراجعات عن الأدوات الخادمة من جهة الخادم لا يطبّق هنا. لا إدارة للكوكيز، ولا سياقات مستمرة، ولا كود جلسات.
الاستخراج من الصفحات الفرعية لإضافة مزيد من البيانات
ابدأ من صفحة قائمة (مثل 30 شركة من نتائج بحث)، ودع Thunderbit يحصر الصفوف، ثم فعّل استخراج الصفحات الفرعية لزيارة صفحة المراجعات أو الرواتب لكل شركة وإثراء الجدول بالأوصاف الكاملة أو نص المراجعات أو تفاصيل الرواتب.
التصدير إلى أدوات الأعمال
بخلاف سكربتات Python التي تُخرج CSV أو JSON، يصدّر Thunderbit مباشرة إلى Google Sheets أو Airtable أو Notion أو Excel — مجانًا في كل خطة. وهذا مفيد جدًا للفرق التي تحتاج إلى مشاركة البيانات وتحليلها بشكل تعاوني.
Python أم Thunderbit: متى تستخدم كل واحد؟
| السيناريو | النهج الموصى به |
|---|---|
| بناء خط بيانات متكرر | Python + Patchright |
| بحث لمرة واحدة أو مشروع صغير لفريق | Thunderbit |
| تحتاج تحكمًا برمجيًا في كل حقل | Python |
| غير مطور ويحتاج بيانات Glassdoor اليوم | Thunderbit |
| استخراج أكثر من 1,000 صفحة في تشغيل واحد | Python + بروكسيات |
| استخراج 30 شركة مع الإثراء | كلاهما يصلح — لكن Thunderbit أسرع في الإعداد |
يبدأ تسعير Thunderbit من الخطة المجانية (6 صفحات/شهر)، مع خطة Pro بسعر 38 دولارًا/شهر مقابل 3,000 نقطة. وباحتساب نقطة واحدة لكل صف ناتج (ونقطتين للاستخراج من الصفحات الفرعية)، فهذا يكفي تقريبًا لـ 33 تشغيلًا شهريًا لاستخراج 30 شركة مع إثرائها.
جرّب Thunderbit لاستخراج Glassdoor
هل استخراج Glassdoor قانوني؟
سأكون مختصرًا وموضوعيًا هنا. شروط استخدام Glassdoor تمنع صراحةً الاستخراج الآلي: "لا يجوز لك استخدام أي روبوت أو عنكبوت أو أداة استخراج... للوصول إلى الخدمات لأي غرض من دون إذن كتابي صريح منا."
لكن المشهد القانوني أكثر تعقيدًا من مجرد بند واحد في الشروط:
- Meta v. Bright Data (المحكمة الفيدرالية، شمال كاليفورنيا، يناير 2024): قضت المحكمة بأنه إذا لم تسجل الدخول أصلًا، فأنت لم توافق على الشروط، والاستخراج من المحتوى العام في وضع عدم تسجيل الدخول لا يخرقها
- hiQ Labs v. LinkedIn (الدائرة التاسعة): قانون CFAA لا ينطبق على جمع البيانات المتاحة علنًا آليًا — لكن الحسابات الوهمية والاستخراج بعد تسجيل الدخول قصة مختلفة
- Van Buren v. United States (المحكمة العليا، 2021): ضيّقت معنى "يتجاوز الوصول المصرح به" ضمن CFAA
الخلاصة العملية: استخراج قوائم الوظائف العامة من دون تسجيل دخول يقع في منطقة قانونية أكثر أمانًا نسبيًا. أما الاستخراج باستخدام جلسة مسجلة الدخول فيعني أنك وافقت على الشروط عند التسجيل، وهي تحظره صراحة. وينطبق هذا على سكربتات Python وعلى وضع Browser Mode في Thunderbit على حد سواء.
ومن الإرشادات الأخلاقية التي يجدر اتباعها بغض النظر عن ذلك:
- حدّد المعدل بما يقل كثيرًا عن سرعة التصفح البشري
- لا تجمع أو تعيد بيع معلومات تعريف شخصية للمراجعين
- احترم تعليمات robots.txt
- اسحب فقط الحقول التي تحتاج إليها فعلًا
الخلاصة: أي طريقة تناسبك؟
غطى هذا الدليل الأنواع الثلاثة من بيانات Glassdoor — الوظائف والمراجعات والرواتب — مع كود 2025 يعمل ويأخذ في الحسبان انتقال تسجيل الدخول إلى Indeed، وCloudflare Bot Management، وتدوير أسماء فئات CSS Modules الذي كسر كل الشروحات القديمة.
إليك إطار القرار:
| وضعك | المسار الأفضل |
|---|---|
| مطور يبني خط بيانات | Python + Patchright (اتبع الخطوات أعلاه) |
| بحث لمرة واحدة أو سحب صغير متكرر | Thunderbit (بدون كود، عبر المتصفح) |
| تحتاج فقط إلى قوائم الوظائف الأساسية وعلى نطاق صغير | تحقّق أولًا مما إذا كان الوصول إلى Glassdoor API ما يزال متاحًا (غالبًا لا) |
| تحتاج بيانات الرواتب أو المراجعات تحديدًا | يجب استخدام Python scraping أو Thunderbit — فالـ API لم يغطي هذه البيانات أبدًا |
| فريق غير تقني يحتاج إلى بيانات مشتركة | Thunderbit → التصدير إلى Google Sheets |
ستستمر دفاعات Glassdoor في التطور. ستتعطل المحددات. ستظهر تحديات جديدة. احفظ هذا الدليل في مفضلتك — وإذا أردت نظرة أعمق على أدوات وتقنيات استخراج الويب، فاطّلع على مقالاتنا حول أفضل أدوات استخراج الويب الآلية، وكيفية استخراج البيانات من موقع باستخدام Python، وأفضل أدوات استخراج وظائف. كما يمكنك مشاهدة الشروحات العملية على قناة Thunderbit على YouTube.
جرّب Thunderbit لاستخراج بيانات Glassdoor Get Started Free
الأسئلة الشائعة
1. هل يمكن استخراج بيانات Glassdoor من دون تسجيل دخول؟
نعم، بالنسبة لمعظم بيانات إعلانات الوظائف وتقييمات الشركات العامة. ولا، بالنسبة للتفاصيل الكاملة للرواتب أو النص الكامل للمراجعات بعد الصفحات الأولى. نافذة #HardsellOverlay هي نافذة CSS فقط — HTML الأساسي ما يزال يحتوي على بيانات الصفحة الأولى — لكن المحتوى الأعمق محمي على مستوى الخادم خلف جدار "المساهمة مقابل الوصول".
2. ما مكتبة Python الأفضل لاستخراج Glassdoor في 2025؟
Patchright (وهو فرع متخفي من Playwright) هو التوصية الافتراضية. فهو يعالج تسرب Runtime.Enable عبر CDP الموجود في Playwright العادي والذي تتحقق منه Cloudflare بوضوح. أما لصفحات القوائم التي ترسل __NEXT_DATA__ في HTML الأولي، فإن curl_cffi مع impersonate="chrome124" أسرع 10–20 مرة، لكنه لا يتعامل مع الصفحات المحمية بتسجيل الدخول.
3. كيف أتجنب الحظر عند استخراج Glassdoor؟
استخدم Patchright أو rebrowser-playwright (وليس Playwright العادي أو Selenium). دوّر البروكسيات السكنية — فـ IPs الخاصة بمراكز البيانات تتعرض للتحدي فورًا. أضف فواصل عشوائية من 3 إلى 8 ثوانٍ بين الصفحات. حافظ على الكوكيز (gdId وcf_clearance وGSESSIONID) عبر الطلبات. وتوقع نافذة جلسة تتراوح بين 20 و30 دقيقة قبل إعادة التحدي.
4. هل توجد Glassdoor API يمكنني استخدامها بدلًا من scraping؟
بشكل عملي، لا. واجهة Partner API القديمة مغلقة أمام المتقدمين الجدد، ولم توجد قط نقطة نهاية عامة للمراجعات، ولا يوجد مسار ترحيل تحت Indeed Publisher API. لذا فإن scraping أو أداة بلا كود مثل Thunderbit هو الخيار العملي الوحيد للمراجعات وبيانات الرواتب.
5. كم مرة تتعطل أدوات استخراج Glassdoor؟
بشكل متكرر. Glassdoor تنشر تغييرات الواجهة الأمامية من دون إعلان، وتتحول بصمات أسماء CSS Modules مع كل build. وأكثر استراتيجيات الاستخراج ثباتًا هي: (1) محددات سمة data-test، (2) كتلة JSON الخاصة بـ __NEXT_DATA__، و(3) نقطة BFF الداخلية للمراجعات. أضف فحصًا لعدم وجود نتائج، وشغّل اختبارًا صغيرًا أسبوعيًا لاكتشاف الأعطال مبكرًا.
معرفة إضافية


