
payscale 网站采用动态渲染与反爬机制,直接使用 requests + beautifulsoup 会返回空表格;需改用 undetected_chromedriver 模拟真实浏览器行为,并精准定位动态加载的表格结构。
payscale 网站采用动态渲染与反爬机制,直接使用 requests + beautifulsoup 会返回空表格;需改用 undetected_chromedriver 模拟真实浏览器行为,并精准定位动态加载的表格结构。
Payscale 的「College Salary Report」页面(如 majors-that-pay-you-back/bachelors/)并非纯静态 HTML,其核心表格内容由 JavaScript 动态注入,且服务器会检测请求头、User-Agent、JavaScript 执行环境等特征。因此,requests.get() 获取的响应中不包含实际表格 DOM 节点,导致 soup.find_all('table', class_='data-table') 返回空列表——这不是选择器错误,而是内容根本未加载。
✅ 正确方案:使用 undetected_chromedriver(UC)替代常规 Selenium 或 requests。UC 专为绕过 Cloudflare、Distil、PerimeterX 等主流反爬系统设计,能自动规避指纹检测,无需手动配置 headless 参数或 User-Agent。
以下是完整、可运行的爬取教程代码(支持单页解析,可轻松扩展为多页循环):
import time
import pandas as pd
from bs4 import BeautifulSoup
import undetected_chromedriver as uc
# ✅ 关键配置:启用可视化(便于调试),禁用自动化提示
options = uc.ChromeOptions()
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
# 可选:添加 --headless=new 实现无界面运行(生产环境推荐)
driver = uc.Chrome(options=options, headless=False)
url = "https://www.php.cn/link/6312c07423889fb5ff005880166214b1"
try:
driver.get(url)
# ⚠️ 必须等待 JS 渲染完成(建议用 WebDriverWait 显式等待更稳健)
time.sleep(5)
soup = BeautifulSoup(driver.page_source, "lxml")
# ? 精准定位:表格在 <tbody> 内,每行 <tr> 包含 5 列关键字段
rows = soup.select("table.data-table > tbody > tr")
data = []
for row in rows:
try:
data.append({
"rank": row.select_one("td.csr-col--rank .data-table__value").get_text(strip=True),
"major": row.select_one("td.csr-col--school-name .data-table__value").get_text(strip=True),
"degree": row.select_one("td.csr-col--school-type .data-table__value").get_text(strip=True),
"early_career_pay": row.select_one("td:nth-of-type(4) .data-table__value").get_text(strip=True),
"mid_career_pay": row.select_one("td:nth-of-type(5) .data-table__value").get_text(strip=True),
})
except AttributeError:
# 跳过缺失字段的异常行(如广告位、分隔行)
continue
df = pd.DataFrame(data)
print(f"✅ 成功提取 {len(df)} 条专业薪资数据:")
print(df.head(10))
finally:
driver.quit() # ? 务必关闭驱动,避免残留进程<p>? <strong>关键注意事项:</strong> </p>
<ul>
<li>
<strong>安装依赖</strong>:执行 <code>pip install undetected-chromedriver pandas beautifulsoup4 lxml</code>;注意 UC v3+ 需配合 Chrome 114+,推荐使用 <code>pip install "undetected-chromedriver==3.5.5"</code> 锁定稳定版本。 </li>
<li>
<strong>反爬应对</strong>:切勿使用普通 <code>selenium.webdriver.Chrome</code> —— Payscale 会识别 <code>navigator.webdriver === true</code> 并拒绝响应。UC 自动修复该指纹。 </li>
<li>
<strong>稳定性增强</strong>:生产环境中应替换 <code>time.sleep(5)</code> 为显式等待,例如: <pre class="brush:php;toolbar:false;">from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.CSS_SELECTOR, "table.data-table tbody tr")))
f"https://.../bachelors/page/{page}",外层加 for page in range(1, 35) 循环,并合并各页 df 即可(注意添加 time.sleep(1–2) 防触发限速)。 robots.txt(Payscale 允许 /college-salary-report/ 路径抓取),仅用于个人学习或非商业分析,禁止高频请求或数据转售。通过以上方法,你将稳定获取结构化薪资数据,为后续分析(如专业薪酬趋势、学位回报率建模)奠定可靠基础。










