
本文详解为何传统 BeautifulSoup 解析无法获取被 Cloudflare 邮箱保护机制混淆的 email,以及如何通过解析嵌入页面的 __NEXT_DATA__ JSON 数据精准提取真实邮箱、姓名、位置等结构化信息。
本文详解为何传统 beautifulsoup 解析无法获取被 cloudflare 邮箱保护机制混淆的 email,以及如何通过解析嵌入页面的 `__next_data__` json 数据精准提取真实邮箱、姓名、位置等结构化信息。
在使用 requests + BeautifulSoup 抓取现代前端框架(如 Next.js)构建的网站时,常会遇到“元素存在但内容为空”或“邮箱显示为 /cdn-cgi/l/email-protection#...”等现象。这并非代码错误,而是网站主动采用的反爬与隐私保护策略:邮箱被 JavaScript 动态解密渲染,原始 HTML 中仅含混淆后的 data-cfemail 属性值,且真实数据实际内嵌于页面的 __NEXT_DATA__ 脚本块中。
以凯利·威廉姆斯(KW)经纪人页面为例(如 https://www.kw.com/agent/UPA-6587385179144187908-1),其邮箱字段看似不可见,实则完整存在于 <script id="__NEXT_DATA__" type="application/json"></script> 标签内——这是 Next.js 服务端渲染(SSR)生成的初始状态快照,包含全部结构化代理数据。
✅ 正确做法是:跳过 DOM 渲染层,直接解析该 JSON 脚本:
import requests
from bs4 import BeautifulSoup
import json
url = 'https://www.kw.com/agent/UPA-6587385179144187908-1'
response = requests.get(url)
response.raise_for_status() # 确保请求成功
soup = BeautifulSoup(response.text, 'lxml')
script_tag = soup.find('script', {'id': '__NEXT_DATA__'})
if not script_tag:
raise ValueError("无法找到 __NEXT_DATA__ 脚本块")
json_data = json.loads(script_tag.string)
agent = json_data['props']['pageProps']['agentData']
name = agent['name']['full']
city = agent['location']['city']
state = agent['location']['state']
email = agent['email'] # ✅ 直接获取明文邮箱字符串(如 "heidi@heidiabelerealtor.com")
website = agent.get('website', 'N/A')
print(f"姓名: {name}")
print(f"城市/州: {city}, {state}")
print(f"邮箱: {email}")
print(f"个人网站: {website}")⚠️ 注意事项:
-
不要依赖
class或href文本匹配:Cloudflare 的邮箱保护会将<a></a>标签的href替换为/cdn-cgi/l/email-protection,且data-cfemail值需额外解密(不推荐手动实现,易出错且非必要); -
务必检查脚本是否存在:部分页面可能因加载策略缺失
__NEXT_DATA__,应添加异常处理; -
User-Agent 头建议设置:某些网站对无头请求返回简化 HTML,可添加
headers={'User-Agent': 'Mozilla/5.0...'}提高兼容性; -
JSON 路径可能变更:Next.js 版本升级可能导致
agentData结构微调,建议先print(json.dumps(json_data, indent=2)[:500])快速探查结构。
总结:面对现代 SSR 应用,优先挖掘页面内嵌 JSON 数据源,远比逆向 JS 解密或模拟浏览器更高效、稳定、可维护。掌握 __NEXT_DATA__ 解析技巧,是突破动态渲染网站数据抓取瓶颈的关键能力。


















