2026年如何抓取Glassdoor公司评论与薪资数据:BFF GraphQL、DataDome与代理实战指南

本指南面向HR分析与劳动力市场数据工程师,详解如何利用住宅代理与curl_cffi绕过Glassdoor的DataDome和Cloudflare反爬栈,合规抓取公开评论与薪资数据。

How to Scrape Glassdoor Company Reviews and Salaries in 2026: BFF GraphQL, DataDome, and Proxy Workarounds
本文目录

免责声明:本文仅讨论对公开可访问数据的合规采集。在抓取任何平台之前,请仔细阅读其服务条款(ToS)。在美国,《计算机欺诈和滥用法》(CFAA)可能限制未授权的自动化访问;在欧盟,GDPR对涉及欧盟雇员的个人数据处理有严格要求。ProxyHat不鼓励任何违反平台条款或适用法律的行为。

如果你正在为HR分析平台或劳动力市场报告构建数据管道,抓取Glassdoor(scrape Glassdoor)几乎是绕不开的话题。Glassdoor拥有超过1亿条公司评论和薪资数据点,但它的反爬栈——DataDome加Cloudflare Bot Management——也是业内最复杂的之一。本指南将带你从公开评论页面走到BFF GraphQL端点,用可运行的Python代码和住宅代理完成一次完整的采集流程。

一、Glassdoor上哪些数据公开、哪些需要登录

Glassdoor的数据可访问性分为三层:

  • 完全公开(无需登录):公司概览页面(/Overview/<company>-EI_IE<id>.htm)和评论列表页(/Reviews/<company>-Reviews-E<id>.htm)。评论列表会展示截断的评论节点,包含 ratingOverallprosconsjobTitle 等字段。
  • 软墙(需免费注册):完整评论正文、部分评论的详细子评分。Glassdoor会弹出“注册以继续阅读”的模态框,技术上属于登录墙后的内容。
  • 硬墙(需登录):完整的薪资明细页面(/Salary/<company>-Salaries-E<id>.htm)中按岗位、地点、年限拆分的薪资分布表。

本指南仅聚焦第一层——公开评论列表页和BFF GraphQL端点返回的结构化截断评论。不要尝试用自动化脚本登录后抓取薪资明细,这几乎必然违反ToS,且DataDome会在登录态下更激进地检测异常行为。

二、Glassdoor反爬技术栈:DataDome + Cloudflare + TLS指纹

Glassdoor的反爬体系由三层构成:

  1. DataDome——基于IP信誉、行为特征和设备指纹的实时反爬服务。DataDome会在首次请求时下发 datadome Cookie,后续请求需携带该Cookie并通过其JS挑战刷新。
  2. Cloudflare Bot Management——在边缘节点执行JS挑战和TLS指纹检测。Cloudflare会检查客户端的JA3/JA4指纹是否匹配已知浏览器。
  3. 自定义请求头校验——BFF GraphQL端点要求 gd-csrf-token 头,该token由前端JS在页面加载时生成。

为什么普通的 requestscurl 会失败?因为Python的 requests 库底层使用OpenSSL,其TLS ClientHello与Chrome浏览器差异巨大,Cloudflare的JA3指纹检测会在TCP握手阶段就拒绝连接。解决方案是使用 curl_cffi——一个基于curl-impersonate的Python库,能够模拟Chrome的TLS指纹。

工具TLS指纹模拟JS挑战处理Cookie管理推荐场景
requests手动不推荐
curl_cffi是(Chrome)部分(需配合)自动首选
Playwright自动高并发成本高

三、BFF GraphQL端点:结构化评论的捷径

Glassdoor前端使用BFF(Backend-for-Frontend)架构,页面数据通过未公开的GraphQL端点获取:

  • https://www.glassdoor.com/bff/graphql——主要评论查询端点
  • https://www.glassdoor.com/graph——备用GraphQL端点

这些端点返回JSON而非HTML,省去了解析复杂DOM的步骤。关键要求:

  • 必须携带 gd-csrf-token 头,token值可从评论列表页的HTML中提取(通常在 <script> 标签内的JSON配置中)。
  • 必须携带从首次页面请求获取的 datadome Cookie。
  • 请求体是标准GraphQL query + variables 结构。

为什么住宅代理比数据中心代理更适合对抗DataDome?DataDome的IP信誉库会标记已知的云服务商IP段(AWS、GCP、Azure等),数据中心IP通常在3-5个请求后即被拦截。住宅IP来自真实ISP,信誉评分高,配合sticky session可在单个IP上维持50-100个请求的会话窗口。

四、Python实战:通过ProxyHat抓取一条评论

以下示例使用 curl_cffi 通过ProxyHat住宅代理抓取Glassdoor BFF GraphQL端点,解析一条截断评论节点。

import re, json, time
from curl_cffi import requests as cffi_requests

# ProxyHat 住宅代理配置(sticky session)
PROXY_URL = "http://user-session-glassdoor01:pass@gate.proxyhat.com:8080"

HEADERS = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                 "AppleWebKit/537.36 (KHTML, like Gecko) "
                 "Chrome/120.0.0.0 Safari/537.36",
    "Accept": "application/json",
    "Content-Type": "application/json",
    "Origin": "https://www.glassdoor.com",
    "Referer": "https://www.glassdoor.com/",
}

# 第一步:访问评论列表页,获取 csrf token 和 datadome cookie
listings_url = "https://www.glassdoor.com/Reviews/Microsoft-Reviews-EI_IE1621.htm"
resp = cffi_requests.get(
    listings_url,
    headers=HEADERS,
    proxies={"http": PROXY_URL, "https": PROXY_URL},
    impersonate="chrome120",
    timeout=30,
)

# 从 HTML 中提取 gd-csrf-token
csrf_match = re.search(r'"csrfToken":"([^"]+)"', resp.text)
csrf_token = csrf_match.group(1) if csrf_match else ""

# datadome cookie 由 curl_cffi 自动保存
cookies = resp.cookies

# 第二步:POST 到 BFF GraphQL 端点
graphql_url = "https://www.glassdoor.com/bff/graphql"
query = """
query EmployerReviews($input: ReviewsInput!) {
  employerReviews(input: $input) {
    reviews {
      reviewId
      ratingOverall
      pros
      cons
      jobTitle
      date
    }
    pageInfo { nextCursor }
  }
}
"""
variables = {
    "input": {
        "employerId": 1621,
        "cursor": None,
        "limit": 10
    }
}

headers = {
    **HEADERS,
    "gd-csrf-token": csrf_token,
}

graphql_resp = cffi_requests.post(
    graphql_url,
    headers=headers,
    json={"query": query, "variables": variables},
    cookies=cookies,
    proxies={"http": PROXY_URL, "https": PROXY_URL},
    impersonate="chrome120",
    timeout=30,
)

data = graphql_resp.json()
reviews = data.get("data", {}).get("employerReviews", {}).get("reviews", [])

for r in reviews[:1]:
    print(f"评分: {r['ratingOverall']}")
    print(f"职位: {r['jobTitle']}")
    print(f"优点: {r['pros'][:100]}...")
    print(f"缺点: {r['cons'][:100]}...")

Node.js 版本(使用 undici + ProxyAgent)

import { request } from 'undici';
import { ProxyAgent } from 'undici';

const proxyAgent = new ProxyAgent('http://user-session-glassdoor01:pass@gate.proxyhat.com:8080');

const resp = await request('https://www.glassdoor.com/bff/graphql', {
  method: 'POST',
  dispatcher: proxyAgent,
  headers: {
    'Content-Type': 'application/json',
    'gd-csrf-token': csrfToken,
    'User-Agent': 'Mozilla/5.0 ... Chrome/120.0.0.0',
  },
  body: JSON.stringify({ query, variables }),
});

const data = await resp.body.json();
console.log(data.data.employerReviews.reviews[0]);

五、分页、会话管理与重试策略

分页游标(Pagination Cursors)

BFF GraphQL端点使用游标分页。响应中的 pageInfo.nextCursor 字段包含下一页的游标值。将此值传入 variables.input.cursor 即可获取下一批评论。当 nextCursornull 时,表示已到末尾。

DataDome的 datadome Cookie与IP绑定。如果在请求过程中切换IP,Cookie会立即失效并触发JS挑战。因此,整个分页流程必须使用同一个住宅IP。在ProxyHat中,通过用户名中的 session- 标志实现sticky session:

# 同一会话保持同一出口IP
PROXY_URL = "http://user-session-glassdoor-batch01:pass@gate.proxyhat.com:8080"

一个sticky session建议在50-80个请求后轮换,避免DataDome行为分析触发拦截。

请求间隔与重试

import random, time

def fetch_with_retry(cursor, max_retries=3):
    for attempt in range(max_retries):
        try:
            resp = cffi_requests.post(
                graphql_url,
                headers=headers,
                json=build_query(cursor),
                cookies=cookies,
                proxies={"http": PROXY_URL, "https": PROXY_URL},
                impersonate="chrome120",
                timeout=30,
            )
            if resp.status_code == 200:
                return resp.json()
            elif resp.status_code == 403:
                # DataDome 拦截 — 轮换 session
                print(f"403 拦截,轮换 session...")
                time.sleep(random.uniform(5, 10))
                # 重新初始化 session
                return None
            else:
                time.sleep(random.uniform(2, 5))
        except Exception as e:
            print(f"请求失败: {e}")
            time.sleep(random.uniform(3, 8))
    return None

# 主循环:每页间隔 3-7 秒
cursor = None
while True:
    data = fetch_with_retry(cursor)
    if not data:
        break
    reviews = extract_reviews(data)
    save_to_db(reviews)
    cursor = get_next_cursor(data)
    if not cursor:
        break
    time.sleep(random.uniform(3, 7))  # 人性化延迟

六、常见错误与边缘情况

  • JA3指纹不匹配:即使使用curl_cffi,如果 impersonate 版本与你的User-Agent声明不一致,Cloudflare仍会拦截。确保 chrome120 对应的UA字符串匹配。
  • CSRF Token过期:gd-csrf-token 有时效性,通常在30-60分钟后失效。长时间运行的采集任务需定期重新访问列表页刷新token。
  • DataDome JS挑战:当收到HTTP 403且响应体包含 _dd_ 前缀的JSON时,说明触发了JS挑战。此时必须轮换IP和session,重新初始化整个流程。
  • 地理限制:部分公司评论仅在特定地区可见。使用ProxyHat的地理定位功能:user-country-US-session-abc:pass@gate.proxyhat.com:8080

七、ProxyHat配置详解

ProxyHat住宅代理通过 gate.proxyhat.com:8080(HTTP)或 gate.proxyhat.com:1080(SOCKS5)提供接入。所有控制参数通过用户名字段传递:

参数示例说明
国家定位user-country-US出口IP位于美国
城市定位user-country-US-city-seattle精确到城市
Sticky Sessionuser-session-abc123保持同一出口IP
组合使用user-country-US-session-gd01美国IP + 固定会话

完整接入文档请参考 ProxyHat官方文档。定价信息见 ProxyHat定价页。如需了解更多抓取场景,可查看我们的 网页抓取用例SERP追踪用例。支持的国家和地区列表见 ProxyHat位置页

八、伦理抓取与何时使用官方API

抓取Glassdoor数据时,请遵循以下原则:

  1. 仅采集聚合、非个人数据。评论本身由用户自愿发布在公开平台,但评论中可能包含可识别个人的信息(如特定经理姓名)。在存储和分析时应做脱敏处理。
  2. 不抓取登录墙后的内容。完整薪资明细、个人资料页等需要登录才能访问的内容,不应通过自动化手段获取。这不仅违反ToS,还可能触及CFAA的“超出授权访问”条款。
  3. GDPR合规。如果分析对象包含欧盟雇员的评论,需注意GDPR对个人数据处理的要求。评论虽然公开,但系统化收集并存储仍可能构成数据处理行为。建议仅存储聚合统计(如平均评分、评论数量),而非原始评论文本。
  4. 尊重robots.txt。Glassdoor的 robots.txt 明确限制了部分路径的爬取。在开始前请检查并遵守。
  5. 考虑官方数据许可。如果你的产品面向商业客户或需要大规模数据,Glassdoor提供 官方API和数据许可方案。对于企业级HR分析产品,这是最合规且可持续的选择。

关键要点:公开评论列表页可合规抓取,但需对抗DataDome和Cloudflare反爬栈。使用curl_cffi模拟Chrome TLS指纹,配合ProxyHat住宅代理的sticky session维持会话。BFF GraphQL端点提供结构化JSON输出,比HTML解析更可靠。始终遵守平台ToS和适用法律,优先考虑官方API。

九、总结

Glassdoor评论抓取器(Glassdoor reviews scraper)的构建核心在于三层:TLS指纹模拟(curl_cffi)、IP信誉管理(住宅代理 + sticky session)、和端点选择(BFF GraphQL优于HTML解析)。对于 Glassdoor薪资数据(Glassdoor salary data),由于完整薪资明细位于登录墙后,建议通过官方渠道获取或仅使用公开评论中的薪资提及做估算。

ProxyHat住宅代理提供195+国家覆盖、99.9%正常运行时间和灵活的sticky session控制,适合需要稳定大规模采集的数据工程团队。开始你的第一个采集任务前,请务必完成法律合规审查。

常见问题

如何抓取Glassdoor公司评论和薪资数据?

公开评论列表页(/Reviews/-Reviews-E.htm)无需登录即可访问。使用curl_cffi模拟Chrome的TLS指纹绕过Cloudflare检测,通过ProxyHat住宅代理维持sticky session以保持DataDome Cookie有效,然后POST到Glassdoor的BFF GraphQL端点(/bff/graphql)获取结构化JSON评论数据。完整薪资明细位于登录墙后,不建议自动化抓取。

为什么抓取Glassdoor时需要使用代理?

Glassdoor使用DataDome和Cloudflare Bot Management进行反爬检测。DataDome会根据IP信誉评分拦截数据中心IP,通常3-5个请求后即被封禁。住宅代理提供来自真实ISP的IP地址,信誉评分高,配合sticky session可在单个IP上维持50-100个请求的会话窗口,大幅降低被拦截的概率。

哪种代理类型最适合抓取Glassdoor?

住宅代理是最佳选择。数据中心IP会被DataDome快速识别并拦截,移动代理虽然信誉高但速度较慢且成本更高。住宅代理在速度、信誉和成本之间取得最佳平衡,配合ProxyHat的sticky session功能(user-session-xxx参数)可以保持同一出口IP,确保DataDome Cookie在整个分页流程中持续有效。

如何避免抓取Glassdoor时被封禁?

关键策略包括:使用curl_cffi模拟Chrome TLS指纹避免JA3检测、通过ProxyHat住宅代理的sticky session保持IP一致、每页请求间隔3-7秒模拟人类行为、在50-80个请求后轮换session、正确携带gd-csrf-token和datadome Cookie、以及实现403状态码的自动重试和session轮换逻辑。

抓取Glassdoor数据是否合法?

抓取公开可访问的数据在技术上可行,但需注意:在美国CFAA可能限制未授权的自动化访问;在欧盟GDPR对涉及雇员个人数据的处理有严格要求。建议仅采集聚合和非个人数据,不抓取登录墙后内容,遵守robots.txt和平台ToS。对于商业用途,建议考虑Glassdoor的官方数据许可方案。

准备开始了吗?

通过AI过滤访问148多个国家的5000多万个住宅IP。

查看价格住宅代理
← 返回博客