<p>不能。混淆后 class 名变为哈希字符串,getElementsByClassName('btn') 因 DOM 中无原始类名而返回空数组;正确做法是改用 data- 属性定位或构建时导出 class 映射表。</p>
不能。混淆工具(比如 Webpack 的 css-loader + mini-css-extract-plugin 配合类名哈希)会把 btn 替换成类似 cls_8b3e1d 的随机字符串,而 document.getElementsByClassName('btn') 是纯字符串匹配——DOM 里根本没有 'btn' 这个 class 值,返回空数组是必然结果。
常见错误是只混淆 CSS 和 HTML 中的 class,却在 JS 里硬编码原始类名:
<button class="cls_8b3e1d">提交</button>
document.getElementsByClassName('btn') → 查不到可行解只有两个方向:
data- 属性定位:<button data-action="submit"> + document.querySelector('[data-action="submit"]'),data- 不参与混淆,语义稳定且可读性强document.querySelectorAll('[class*="cls_8b3e1d"]') 模糊匹配——但性能差、易误匹配、不推荐用于关键交互节点只要 user_id=123456、price=299.00 或 order_no: ABC789 出现在初始 HTML 的任意位置(包括注释、data- 属性、内联 <script>),爬虫用 requests.get() + BeautifulSoup 就能秒提,根本不用执行 JS。
立即学习“前端免费学习笔记(深入)”;
典型翻车现场:
<div data-id="123456"></div> —— data- 属性照样明文暴露<!-- order_no: ABC789 --> —— 注释在 response.text 里原样可见<span style="display:none">token_xyz</span> —— display 隐藏不影响源码存在真正安全的做法只有一条:不在初始 HTML 渲染任何敏感字段。哪怕只是展示价格或订单号,也得走带登录态校验和风控维度(如设备指纹、请求频率)的动态接口,fetch 回来再插入 DOM。
把数字 99.9 拆成 <span>9</span><i>9</i><u>.9</u> 或用 CSS ::before 拼接,只能拦住基础正则提取(如 re.findall(r'd+.d+', html)),对 Puppeteer、Playwright、Cheerio 这类能执行 JS 并获取渲染后 DOM 的工具完全无效。
更糟的是 Unicode 同形字(如西里尔字母 а 冒充拉丁 a)有实际兼容性坑:
u200b)或乱码实操建议:仅用于非交互型文本(如静态价格、评分),禁用于 input 的 placeholder 或表单提交值;上线前必须在 Noto Sans、PingFang、Segoe UI 等主流字体下实测渲染一致性。
把加密字符串写进 HTML,再靠 JS 解密后填入 DOM(例如 document.getElementById("p").innerText = atob("OTkuOQ==")),看起来“隐藏”了数据,但现代爬虫工具能完整等待 JS 执行完毕再取值——Puppeteer 的 page.evaluate、Playwright 的 textContent() 都能拿到最终渲染结果。
真正起作用的混淆,得让爬虫即使执行了 JS,也拿不到干净数据:
123 换成全角 123),OCR 和人工识别易错,但需验证字体支持u200b),让 textContent 返回乱序或含不可见字符的字符串最常被忽略的一点:混淆后的 DOM 节点如果仍保有清晰的结构特征(比如固定 ID、可预测的 data- 属性名、稳定的 XPath 路径),爬虫用 //div[@id="price"]/text() 一样精准提取——混淆必须覆盖结构、属性、文本三者,缺一不可。