正则匹配 window.xxx 失效主因是变量被压缩、换行、注释包裹或动态生成;应优先确认其存在于 HTML 源码中,再用 re.DOTALL、括号层级匹配、ast.literal_eval 安全解析,或 js2py 执行 JS 获取值。

为什么正则匹配 window.xxx 变量经常失效
直接用 re.search(r'window\.data\s*=\s*(.*?);', html) 匹配 JS 变量,大概率拿不到值——不是正则写错了,而是变量可能被压缩、换行、注释包裹,或根本不在 HTML 字符串里(比如由后续 JS 动态生成)。更常见的是,window.data 实际赋值语句被拆成多行,或中间插入了 /* comment */ 或空格缩进,导致懒惰匹配 .*? 提前截断。
实操建议:
- 先用
re.DOTALL让.匹配换行符 - 避免依赖分号结尾:有些变量是
window.data = {...},也有是window.data = [...]或window.data = "xxx",统一用括号层级匹配更稳 - 优先查源码中是否真有该变量:打开浏览器开发者工具 → Elements 标签页搜索
window.data,确认它确实以文本形式存在于 HTML 中(而非通过fetch()后续加载)
用 ast.literal_eval 安全解析 JS 对象字面量
很多人用 json.loads() 解析从 JS 中提取的 {...},但 JS 对象和 JSON 不等价:JS 允许单引号、末尾逗号、无引号键名(如 {id: 123}),而 json.loads() 会直接报 JSONDecodeError。
更稳妥的做法是把提取出的 JS 字面量字符串(如 "{id: 123, name: '张三'}")转成 Python 字典,用 ast.literal_eval():
import ast
js_str = "{id: 123, name: '张三', tags: ['a', 'b']}"
try:
data = ast.literal_eval(js_str.replace('undefined', 'None').replace('null', 'None'))
except (ValueError, SyntaxError):
pass # 解析失败,跳过
注意点:
-
ast.literal_eval()只允许基本 Python 字面量,不执行代码,比eval()安全得多 - JS 的
undefined和null需手动替换为None,否则解析失败 - 如果 JS 中有函数、正则字面量(
/abc/g)或注释,ast.literal_eval()仍会报错,说明该内容不适合直接提取
绕过压缩与混淆:用 js2py 执行小段 JS 获取变量值
当目标变量是多步计算结果(例如 window.data = getInitData();),或 JS 被压缩成一行且含闭包逻辑时,纯正则基本失效。这时可借助 js2py 在 Python 中模拟 JS 运行环境:
import js2py
js_code = '''
var config = {api: 'https://api.example.com'};
var token = 'abc123';
window.user = {id: 456, token: token, host: config.api};
'''
context = js2py.EvalJs()
context.execute(js_code)
print(context.user.to_dict()) # {'id': 456, 'token': 'abc123', 'host': 'https://api.example.com'}
关键提醒:
-
js2py不支持 DOM、fetch、localStorage等浏览器 API,只适合纯逻辑变量推导 - 若 JS 里调用了未定义函数或依赖外部库,
execute()会抛JsException,需 try-catch - 性能较低,别用它跑大段 JS;仅限提取几行初始化逻辑中的变量
容易被忽略的陷阱:document.write 和内联 <script></script> 执行顺序
有些网页把关键数据藏在 document.write() 生成的脚本里,或者用 <script>document.write('<script>window.x = ...</script>') 动态注入——这种情况下,原始 HTML 字符串里根本找不到 window.x,正则自然匹配不到。
应对方式有限但明确:
- 检查网页是否含
document.write(调用,若有,说明数据在运行时才写入 DOM,必须用 Selenium 或 Playwright 渲染后取driver.execute_script('return window.x') - 用
BeautifulSoup提取所有<script></script>标签内容后,再对每段脚本内容单独做正则或js2py解析,不能只扫 HTML 主体 - 留意
<script type="text/template"></script>或<script id="data-template"></script>这类伪装成模板的 script 标签,里面常塞着 JSON 或 JS 变量
真正难的从来不是正则怎么写,而是得先判断那段 JS 到底有没有、在哪里、什么时候才变成你想要的样子。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











