Sdenv
补环境框架sdenv,完美过瑞数vmp理论通杀,配合瑞数vmp纯算法逆向项目(rs-reverse)更好学习原理
Install / Use
/learn @pysunday/SdenvREADME
开源兄弟项目(瑞数纯算逆向rs-reverse):rs-reverse
[!WARNING] 免责声明
<h1 align="center"> <img width="100" height="100" src="./logo.png" alt=""><br> sdenv </h1>[!TIP] 💬 为了让交流更顺畅,推荐使用GitHub Discussions(私发微信消息可能不回,沟通建议优先Discussions + 交流群):
🙏 提问/求助
🙌 分享经验或技巧
💬 功能建议
💡 讨论新想法
📚 查阅已有讨论和答案
sdenv是一个javascript运行时补环境框架,与github上其它补环境框架存在较大区别,sdenv是站在巨人的肩膀上实现的,依赖于jsdom的强大dom仿真能力,sdenv可以真实模拟浏览器执行环境,作者在固定随机数与添加sdenv-extend的部分插件后可以达到瑞数vmp代码在sdenv运行生成的cookie值与浏览器生成的cookie值一致。
- sdenv专用jsdom版本:sdenv-jsdom
- sdenv多端环境提取:sdenv-extend
依赖
作者开发时使用的是v20.19.5版本Node,Mac系统Node版本支持情况(测试使用example/use-check命令) 点击反馈:
Node版本 | 是否支持 -------- | -------- v20.19.5 | ✅ v21.7.3 | ❌ v22.21.1 | ✅ v23.11.1 | ✅ v24.12.0 | ✅ v25.2.1 | ✅
编译node插件用的是node-gyp工具,该工具需要有python环境和c环境(如windows系统需安装Visual Studio,Mac系统需要安装XCode),请根据工具文档进行系统环境搭建,完成后自行执行npm i -g node-gyp安装。
需要注意windows中安装Visual Studio时需要勾选使用C++的桌面开发选项

报错收集
常见报错已经放到discussions中, 点击链接查看: 报错收集
解决完报错后记得重新执行下依赖安装!如不确定是否本地问题,可以先以docker方式运行和验证!
使用
作者推荐npm包方式或docker方式使用,遇到问题提issues或者提merge,参与sdenv共建!
npm包方式使用
- 项目中安装sdenv:
npm i sdenv - 在项目中导入api并使用(可以参考example目录下的用例):
const { jsdomFromText, jsdomFromUrl, browser } = require('sdenv');
docker方式使用
首先执行uname -a后查看架构类型,支持arm64和x86_64,接着执行对应的命令:
- 查看sdenv版本:
docker run --rm pysunday/sdenv-[arm64/x86_64]:latest -e "console.log(require('sdenv').version)" - 验证sdenv是否适用:
docker run --rm pysunday/sdenv-[arm64/x86_64] check 需要测试的网站 - 运行宿主机文件(如目录example内文件):
docker run --rm -v $(pwd)/example/use-remote/passive.js:/app/myapp pysunday/sdenv-[arm64/x86_64]:latest myapp
注意:
- docker仅内置check命令,对应项目文件
example/use-check/index.js - docker默认工作目录为
/app/,请将项目文件映射到该目录下再运行
源码方式使用
- clone项目后执行依赖安装
npm i - 验证sdenv是否适用:
node example/use-check/index.js 需要测试的网站
全局方式使用
全局安装后会生成全局可执行命令sdenv
- 全局安装sdenv:
npm i sdenv -g - 验证sdenv是否适用:
sdenv 需要测试的网站
npx方式使用
- 验证sdenv是否适用:
npx sdenv 需要测试的网站
使用示例
- 检查sdenv是否适用

- 运行本地文件

- 运行案例1(被动接口请求)

- 运行案例2(主动接口请求)

API
sdenv设计极其简单,它的核心API只有一个,即browser(sdenv补的环境通过browser方法注入)!
browser(window: object, type: string)
传入window对象,和需要拟真的浏览器类型,browser方法会自动将浏览器特性集成到window对象中。
const { browser } = require('sdenv');
...
browser(window, 'chrome')
浏览器类型及支持情况:
类型 | 是否支持 ---- | -------- Chrome | Y Firefox | N Safari | N
jsdomFromText(htmlText: string, config: object)
除返回与jsdom保持一致外,同时返回sdenv属性,如常用的属性值有:const { window, cookieJar, sdenv, ... } = jsdomFromText(...)
const vm = require("vm");
const { jsdomFromText } = require('sdenv');
const dom = jsdomFromText('<html>...</html>', {
url: 'https://host/path',
referrer: 'https://host/path',
contentType: "text/html",
runScripts: "outside-only", // 不会执行html文本中的js代码
})
vm.runInContext('javascript代码', dom.getInternalVMContext());
console.log('cookie值:', dom.cookieJar.getCookieStringSync('https://host'));
注:代码仅演示,具体使用请移步use-local样例
进一步阅读:
jsdomFromUrl(url: string, config?: object)
返回与jsdom保持一致,同时sdenv实例会挂载到window下,常用的属性值有:const { window, cookieJar, serialize, ... } = jsdomFromUrl(...)
const { jsdomFromUrl } = require('sdenv');
const config = { userAgent: 'native browser userAgent' };
const oneDom = await jsdomFromUrl('https://host/path', config); // 返回自动生成的cookieJar
const twoDom = await jsdomFromUrl('https://host/path', { ...config, cookieJar: oneDom.cookieJar }); // 使用已经存在的cookieJar,因为要沿用上一次产生的cookie
console.log('cookie值:', twoDom.cookieJar.getCookieStringSync('https://host'));
注:代码仅演示,具体使用请移步use-remote样例目录
进一步阅读:
jsdom API
为方便开发,sdenv通过jsdom属性值主动暴露jsdom API,同时暴露额外agentFactory、 Request方便自定义资源管理器,如:
const { jsdom } = require('sdenv');
const { ResourceLoader, agentFactory, Request } = jsdom;
其它
监听页面跳转
sdenv提供专属事件名称来监听页面事件,最终通过addEventListener方法监听事件并挂载相关方法,见下表:
事件名称 | 事件说明
-------- | --------
sdenv:location.replace | replace方法引起的跳转
sdenv:location.assign | assign方法引起的跳转
sdenv:exit | 引起页面关闭最终会执行的监听事件
window代理
sdenv支持vm中window值变化代理(Proxy),需要注意的是,开启window代理需要在beforeParse方法中通过sdenv.getConfig('window')(配置项对象)方法导入配置项,如:
const { jsdomFromUrl } = require('sdenv');
const dom = await jsdomFromUrl('https://host/path', {
beforeParse: function (window, sdenv) {
sdenv.getConfig('window')({ ... });
}
});
提供如下配置项及使用场景
- window取值直接报错,如对process的检测,将数组通过windowGetterErrorKeys传入,如:
sdenv.getConfig('window')({ windowGetterErrorKeys: ['process'] }); - window取值返回undefined,如对jsdom的runScripts参数检测,将数组通过windowGetterUndefinedKeys传入,如:
sdenv.getConfig('window')({ windowGetterUndefinedKeys: ['_runScripts'] }); - 打印window操作及操作结果,如:
sdenv.getConfig('window')({ log: (type, prop) => {
if (type === 'get') {
console.log('getter => ' + prop);
}
} });
- 控制window操作返回结果
sdenv.getConfig('window')({ parse: (type, prop, value) => {
if (type === 'set' && prop === '需要控制返回值的属性名称') {
return '返回给调用者任何值';
}
return value;
} });
注意:如window代理功能不符合预期请及时通过issues或者discussions反馈!
sdenv-extend使用说明
为了模拟浏览器执行环境,需要将node环境与浏览器环境共有代码进行提取,并提供返回环境对象用于sdenv内window与dom内容补充使用。
sdenv-extend具体功能可参考项目内README文档。
sdenv-jsdom使用说明
sdenv-jsdom包是sdenv补环境框架能运行瑞数vmp网站并产生正确cookie的核心,该包仓库fork自jsdom仓库,并应对瑞数vmp对jsdom的检测做了代码修改,因此sdenv可以过网站对jsdom的检测!
代码贡献
感谢所有为本项目做出贡献的开发者!
<a href="https://github.com/pysunday/sdenv/graphs/contributors"> <img src="https://contrib.rocks/image?repo=pysunday/sdenv" /> </a>声明
该项目的开发基于瑞数vmp网站,不能保证在其它反爬虫产品稳定使用,出现问题请及时提issues或者提pull参与共建!
添加作者微信进技术交流群:howduudu_tech(备注sdenv)
订阅号不定时发表版本动态及技术文章:码功
<img src="./static/qrcode.png" alt="订阅号:码功" width="320">Related Skills
node-connect
335.9kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
82.7kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
335.9kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
82.7kCommit, push, and open a PR
