npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

sdenv

v1.1.3

Published

基于jsdom和瑞数vmp开发的补环境框架,模拟浏览器执行网页代码。

Readme

开源兄弟项目(瑞数纯算逆向rs-reverse):rs-reverse

[!WARNING] 免责声明

[!TIP] 💬 为了让交流更顺畅,推荐使用GitHub Discussions(私发微信消息可能不回,沟通建议优先Discussions + 交流群):
🙏 提问/求助
🙌 分享经验或技巧
💬 功能建议
💡 讨论新想法
📚 查阅已有讨论和答案

NPM version

sdenv是一个javascript运行时补环境框架,与github上其它补环境框架存在较大区别,sdenv是站在巨人的肩膀上实现的,依赖于jsdom的强大dom仿真能力,sdenv可以真实模拟浏览器执行环境,作者在固定随机数与添加sdenv-extend的部分插件后可以达到瑞数vmp代码在sdenv运行生成的cookie值与浏览器生成的cookie值一致

依赖

作者开发时使用的是v20.19.5版本Node,由于jsdom27版本需要Node支持ESM,但是v20仅部分支持ESM,因此如果您也使用v20版本,请使用最新的,如当前最新为v20.19.5

编译node插件用的是node-gyp工具,该工具需要有python环境和c环境(如windows系统需安装Visual Studio,Mac系统需要安装XCode),请根据工具文档进行系统环境搭建。

需要注意windows中安装Visual Studio时需要勾选使用C++的桌面开发选项

安装Visual Studio注意

可能出现的问题

  1. npm安装node-gyp报错:请确保操作系统有c++编译环境与python环境,报错示例(感谢用户风流小混沌提供报错图片): npm安装报错
  2. 安装缓慢及canvas报错(基本都是网络问题):由于canvas安装会优先从github获取现成的包,因此请在安装前先设置代理或者其它国内源,如果安装仍然失败请使用npm官方源+代理方式重新尝试;
  3. 旧式TLS Renegotiation不支持报错(目标网站服务器使用旧版OpenSSL,新版node不支持),这个报错纯node层无法解决,需使用抓包工具中转,调用命令时设置环境变量proxy的值,mac命令如proxy=http://127.0.0.1:8888 node example/use-check/index.js 目标网站,docker命令如: docker run -e proxy=http://host.docker.internal:8888 --rm pysunday/sdenv-arm64 check 目标网站 TLS Renegotiation报错

注意:canvas安装失败不会中断安装,但是在运行时,如果网页代码中有调用canvas相关API会报错,如有使用canvas相关api请务必确认安装成功!

解决完报错后记得重新执行下依赖安装!如不确定是否本地问题,可以先以docker方式运行和验证!

有其它问题请提issues!

使用

作者推荐npm包方式或docker方式使用,遇到问题提issues或者提merge,参与sdenv共建!

npm包方式使用

  1. 项目中安装sdenv:npm i sdenv
  2. 在项目中导入api并使用(可以参考example目录下的用例):const { jsdomFromText, jsdomFromUrl, browser } = require('sdenv');

docker方式使用

首先执行uname -a后查看架构类型,支持arm64x86_64,接着执行对应的命令:

  1. 查看sdenv版本:docker run --rm pysunday/sdenv-[arm64/x86_64]:latest -e "console.log(require('sdenv').version)"
  2. 验证sdenv是否适用:docker run --rm pysunday/sdenv-[arm64/x86_64] check 需要测试的网站
  3. 运行宿主机文件(如目录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/,请将项目文件映射到该目录下再运行

源码方式使用

  1. clone项目后执行依赖安装npm i
  2. 验证sdenv是否适用:node example/use-check/index.js 需要测试的网站

全局方式使用

全局安装后会生成全局可执行命令sdenv

  1. 全局安装sdenv: npm i sdenv -g
  2. 验证sdenv是否适用:sdenv 需要测试的网站

npx方式使用

  1. 验证sdenv是否适用:npx sdenv 需要测试的网站

使用示例

  1. 检查sdenv是否适用 检查sdenv是否适用
  2. 运行本地文件 sdenv运行本地用例
  3. 运行案例1(被动接口请求) sdenv运行案例1
  4. 运行案例2(主动接口请求) sdenv运行案例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样例

进一步阅读:

jsdom的JSDOM API

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的ResourceLoader API

jsdom的CookieJar API

jsdom的fromURL API

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')({ ... });
    }
});

提供如下配置项及使用场景

  1. window取值直接报错,如对process的检测,将数组通过windowGetterErrorKeys传入,如:sdenv.getConfig('window')({ windowGetterErrorKeys: ['process'] });
  2. window取值返回undefined,如对jsdom的runScripts参数检测,将数组通过windowGetterUndefinedKeys传入,如:sdenv.getConfig('window')({ windowGetterUndefinedKeys: ['_runScripts'] });
  3. 打印window操作及操作结果,如:
sdenv.getConfig('window')({ log: (type, prop) => {
    if (type === 'get') {
        console.log('getter => ' + prop);
    }
} });
  1. 控制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的检测!

代码贡献

感谢所有为本项目做出贡献的开发者!

声明

该项目的开发基于瑞数vmp网站,不能保证在其它反爬虫产品稳定使用,出现问题请及时提issues或者提pull参与共建!

添加作者微信进技术交流群:howduudu_tech(备注sdenv)

订阅号不定时发表版本动态及技术文章:码功