在 Web 反爬对抗中,环境模拟是绕不开的一环。之前尝试过魔改 Node.js 源码的思路,虽然可行但编译周期太长。这次决定先走轻量路线,通过 Node.js C++ Addon 的方式实现一套基础方案,后续再考虑移植到原生。这种方式的优势在于,只要编译好 .node 扩展,任何 Node 环境都能直接 require 使用。
为什么 document.all 这么难模拟?
document.all 是 IE4 时代的遗留产物。为了兼容旧网页,现代浏览器(Chrome/Firefox)保留了它,但 W3C 和厂商设计了一个非常反直觉的特性:Undetectable。这意味着它在 JS 层面既存在,又表现得像不存在。
在 Chrome 控制台里试一下就能感受到这种诡异:
// 既存在,又不存在
typeof document.all === 'undefined' // true
document.all === undefined // false (严格相等)
document.all == undefined // true (宽松相等)
// 看起来是 falsy,但能取值
if(document.all) { /* 不会执行 */ }
document.all.length // 正常返回数字
document.all[0] // 正常返回元素
这就是纯 JS 模拟的死穴。无论怎么用 Proxy 拦截,或者用 Object.defineProperty,在 JS 层面你永远无法让一个对象的 typeof 变成 'undefined'。JSDOM 至今没有完美支持这一点(它返回的是 'object'),这也是很多反爬脚本检测 JSDOM 的核心依据。
常见的检测逻辑
对方想抓你,通常只需要一行代码:
// 绝杀检测
if(typeof document.all !== 'undefined' && .) {
.();
}


