
本文介绍当Selenium无法获取完整HTML时,如何通过解析页面内嵌的JSON数据(如Next.js的__NEXT_DATA__)高效、准确地提取动态渲染网站的全部结构化信息,避免因JavaScript延迟加载导致的数据丢失。
本文介绍当selenium无法获取完整html时,如何通过解析页面内嵌的json数据(如next.js的`__next_data__`)高效、准确地提取动态渲染网站的全部结构化信息,避免因javascript延迟加载导致的数据丢失。
在Web爬虫实践中,一个常见却易被忽视的陷阱是:看似“成功加载”的页面,其HTML源码可能并不包含你所见的全部内容。尤其在使用React、Next.js等现代前端框架构建的网站(如 kununu.com)中,关键数据往往并非直接写入DOM,而是以序列化JSON形式嵌入 <script id="__NEXT_DATA__"> 标签中,再由客户端JavaScript动态渲染。此时,即使Selenium已等待元素可见、甚至模拟了“展开更多评论”等交互,driver.execute_script("return document.documentElement.innerHTML") 返回的仍是<em>渲染中途或未完全挂载的DOM快照——导致你观察到的“HTML缺失”(如评分星级、子维度ID等字段凭空消失)。</script>
根本解法不是更激进地等待或滚动,而是跳过DOM渲染层,直取原始数据源。以 kununu 为例,其真实评论与评分数据全部预置在页面初始HTML的 <script id="__NEXT_DATA__"> 中:</script>
import json
import requests
from bs4 import BeautifulSoup
url = "https://www.kununu.com/de/adidas/kommentare"
response = requests.get(url)
response.raise_for_status() # 确保请求成功
soup = BeautifulSoup(response.content, "html.parser")
# 定位并提取 Next.js 的初始化数据脚本
script_tag = soup.select_one("#__NEXT_DATA__")
if not script_tag:
raise ValueError("无法找到 __NEXT_DATA__ 脚本标签,请检查页面结构是否变更")
data = json.loads(script_tag.string)
# 数据路径示例(依Next.js服务端渲染结构而定)
reviews = data["props"]["initialReduxState"]["reviews"]["reviews"]
for review in reviews[:3]: # 仅展示前3条
print(f"标题: {review['title']}")
print(f"总分: {review['score']}")
for rating in review.get("ratings", []):
print(f" - {rating['id']}: {rating['score']} 分 | {rating['text']}")
print("-" * 50)✅ 优势显著:
- 完整性:100%覆盖服务端注入的原始数据,无渲染时序问题;
- 高性能:单次HTTP请求 + 本地JSON解析,远快于启动浏览器+等待JS执行;
- 稳定性:不依赖CSS选择器或DOM结构变动(__NEXT_DATA__ 是Next.js标准锚点,变更频率极低)。
⚠️ 注意事项:
立即学习“前端免费学习笔记(深入)”;
- 并非所有网站都使用Next.js;需先检查源码是否存在 id="__NEXT_DATA__" 或类似命名的 <script> 标签(如Gatsby的 window.___gatsby、Vue SSR的 window.__INITIAL_STATE__); </script>
- 若目标网站采用纯客户端渲染(CSR)且无服务端数据注入,则仍需Selenium配合显式等待(WebDriverWait + presence_of_element_located),但应优先尝试网络面板(Network Tab)中XHR/Fetch请求,直接调用API;
- 使用 requests 时注意处理反爬:添加 User-Agent、管理会话Cookie、必要时集成代理或验证码服务。
总结而言,面对“HTML提取不全”的难题,工程师的第一反应不应是优化等待逻辑,而应打开浏览器开发者工具的 Elements 面板搜索 __NEXT_DATA__ 或 Network 面板筛选 XHR 请求——真正的数据,往往藏在最安静的地方。











