forked from pysunday/sdenv
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 0fffebe
Showing
35 changed files
with
753 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
.DS_Store | ||
node_modules/ | ||
output/ | ||
npm-debug.log | ||
yarn-error.log | ||
.idea | ||
.vscode | ||
package-lock.json | ||
yarn.lock | ||
.history | ||
*.swp | ||
build/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/* | ||
!bin/ | ||
!browser/ | ||
!utils/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
module.exports = { | ||
github: { | ||
release: true | ||
}, | ||
git: { | ||
commitMessage: "release: v${version}" | ||
}, | ||
npm: { | ||
publish: false | ||
}, | ||
hooks: { | ||
"after:bump": "echo 更新版本成功" | ||
}, | ||
plugins: { | ||
'@release-it/conventional-changelog': { | ||
preset: 'conventionalcommits', | ||
infile: 'CHANGELOG.md', | ||
sameFile: true, | ||
releaseRules: [ | ||
{ type: 'feat', release: 'minor' }, | ||
{ type: 'fix', release: 'patch' }, | ||
{ type: 'docs', release: 'patch' }, | ||
{ type: 'style', release: 'patch' }, | ||
{ type: 'refactor', release: 'patch' }, | ||
{ type: 'perf', release: 'patch' }, | ||
{ type: 'test', release: 'patch' }, | ||
], | ||
}, | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
<h1 align="center"> | ||
<img width="100" height="100" src="logo.svg" alt=""><br> | ||
sdenv | ||
</h1> | ||
|
||
sdenv是一个javascript运行时补环境框架,与github上其它补环境框架存在较大区别,sdenv是站在巨人的肩膀上实现的,依赖于jsdom的强大dom仿真能力,sdenv可以真实模拟浏览器执行环境,作者在固定随机数与添加[sdenv-extend](https://github.com/pysunday/sdenv-extend)的部分插件后可以达到**瑞数vmp代码在sdenv运行生成的cookie值与浏览器生成的cookie值一致**。 | ||
|
||
* sdenv专用jsdom版本:[sdenv-jsdom](https://github.com/pysunday/sdenv-jsdom) | ||
* sdenv多端环境提取:[sdenv-extend](https://github.com/pysunday/sdenv-extend) | ||
|
||
## 依赖 | ||
|
||
作者开发时使用的是`v20.10.0`版本node,预期最低要求是18版本,由于未做其它版本可用性测试,因此建议使用sdenv的node版本大于等于`v20.10.0` | ||
|
||
## 安装 | ||
|
||
由于`document.all`需要由c代码动态生成,而固定编译环境下的编译产物只能在相同编译环境下运行,因此安装sdenv后需要动态编译生成node文件 | ||
|
||
1. 安装:`npm i sdenv` | ||
2. 编译c代码:`cd node_modules/sdenv && yarn build` | ||
|
||
**在编译过程未实现自动化之前可直接clone项目使用** | ||
|
||
## 使用 | ||
|
||
因为项目核心功能基于jsdom,且jsdom对dom的实现非常完善,因此使用sdenv之前建议有一定html与javascript语言开发基础,然后参考example目录下的样例文件: | ||
|
||
1. [use-local](https://github.com/pysunday/sdenv/example/use-local/README.md) | ||
```javascript | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const { Script } = require("vm"); | ||
const logger = require('../../utils/logger'); | ||
const browser = require('../../browser/'); | ||
const { jsdomFromText } = require('../../utils/jsdom'); | ||
|
||
const baseUrl = "https://wcjs.sbj.cnipa.gov.cn" | ||
|
||
const files = { | ||
html: path.resolve(__dirname, 'output/makecode_input_html.html'), | ||
js: path.resolve(__dirname, 'output/makecode_input_js.js'), | ||
ts: path.resolve(__dirname, 'output/makecode_input_ts.json'), | ||
} | ||
|
||
function getFile(name) { | ||
const filepath = files[name]; | ||
if (!filepath) throw new Error(`getFile: ${name}错误`); | ||
if (!fs.existsSync(filepath)) throw new Error(`文件${filepath}不存在,请使用rs-reverse工具先获取文件`); | ||
return fs.readFileSync(filepath); | ||
} | ||
|
||
function initBrowser(window, cookieJar) { | ||
window.$_ts = JSON.parse(getFile('ts')); | ||
window.onbeforeunload = async (url) => { | ||
const cookies = cookieJar.getCookieStringSync(baseUrl); | ||
logger.debug('生成cookie:', cookies); | ||
process.exit(); | ||
} | ||
browser(window, 'chrome'); | ||
} | ||
|
||
async function loadPages() { | ||
const htmltext = getFile('html'); | ||
const jstext = getFile('js'); | ||
const [jsdomer, cookieJar] = jsdomFromText({ | ||
url: `${baseUrl}/sgtmi`, | ||
referrer: `${baseUrl}/sgtmi`, | ||
contentType: "text/html", | ||
runScripts: "outside-only", | ||
}) | ||
const dom = jsdomer(htmltext); | ||
initBrowser(dom.window, cookieJar); | ||
new Script(jstext).runInContext(dom.getInternalVMContext()); | ||
} | ||
|
||
loadPages() | ||
``` | ||
2. [use-remote](https://github.com/pysunday/sdenv/example/use-remote/README.md) | ||
```javascript | ||
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0" | ||
const logger = require('../../utils/logger'); | ||
const browser = require('../../browser/'); | ||
const { jsdomFromUrl } = require('../../utils/jsdom'); | ||
const baseUrl = "https://wcjs.sbj.cnipa.gov.cn" | ||
async function loadPages() { | ||
const [jsdomer, cookieJar] = jsdomFromUrl({ | ||
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36', | ||
}); | ||
const dom = await jsdomer(`${baseUrl}/sgtmi`); | ||
window = dom.window | ||
window.onbeforeunload = async (url) => { | ||
const cookies = cookieJar.getCookieStringSync(baseUrl); | ||
logger.debug('生成cookie:', cookies); | ||
process.exit(); | ||
} | ||
browser(window, 'chrome'); | ||
} | ||
loadPages() | ||
``` | ||
|
||
## sdenv-extend使用说明 | ||
|
||
为了模拟浏览器执行环境,需要将node环境与浏览器环境共有代码进行提取,并提供返回环境对象用于sdenv内window与dom内容补充使用。 | ||
|
||
sdenv-extend初始化只执行一次,初始化成功后生成的环境对象可以使用`Object.sdenv()`(vm中使用非node)获取。 | ||
|
||
sdenv-extend具体功能可参考项目内README文档。 | ||
|
||
## 声明 | ||
|
||
该项目的开发基于瑞数vmp网站,不能保证在其它反爬虫产品稳定使用,出现问题请及时提issues或者提pull参与共建! | ||
|
||
由于初期版本只做了chrome浏览器的拟真,且项目文档不完善,作者会陆续补充,可以加入技术交流群与订阅号持续关注! | ||
|
||
添加作者微信进技术交流群:howduudu_tech(备注sdenv) | ||
|
||
订阅号会定期发表技术文章:码功 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
#include <node.h> | ||
namespace documentAll { | ||
|
||
using v8::Context; | ||
using v8::Function; | ||
using v8::FunctionCallbackInfo; | ||
using v8::FunctionTemplate; | ||
using v8::Isolate; | ||
using v8::Local; | ||
using v8::Number; | ||
using v8::Object; | ||
using v8::ObjectTemplate; | ||
using v8::String; | ||
using v8::Value; | ||
using v8::Null; | ||
using v8::Array; | ||
|
||
void MyFunctionCallback(const FunctionCallbackInfo<Value>& args) { | ||
Isolate* isolate = args.GetIsolate(); | ||
args.GetReturnValue().Set(Null(isolate)); | ||
} | ||
|
||
void GetDocumentAll(const FunctionCallbackInfo<Value>& args) { | ||
Isolate* isolate = args.GetIsolate(); | ||
Local<Context> context = isolate->GetCurrentContext(); | ||
Local<ObjectTemplate> obj_template = ObjectTemplate::New(isolate); | ||
obj_template->MarkAsUndetectable(); | ||
obj_template->SetCallAsFunctionHandler(MyFunctionCallback); | ||
Local<Object> obj = obj_template->NewInstance(context).ToLocalChecked(); | ||
if (args.Length() > 0 && args[0]->IsObject()) { | ||
Local<Object> argObj = args[0]->ToObject(context).ToLocalChecked(); | ||
Local<Array> propertyNames = argObj->GetPropertyNames(context).ToLocalChecked(); | ||
for (uint32_t i = 0; i < propertyNames->Length(); ++i) { | ||
Local<Value> key = propertyNames->Get(context, i).ToLocalChecked(); | ||
Local<Value> value = argObj->Get(context, key).ToLocalChecked(); | ||
(void)obj->Set(context, key, value); | ||
} | ||
} | ||
args.GetReturnValue().Set(obj); | ||
} | ||
|
||
void Init(Local<Object> exports, Local<Object> module) { | ||
Isolate* isolate = exports->GetIsolate(); | ||
Local<Context> context = isolate->GetCurrentContext(); | ||
Local<FunctionTemplate> method_template = FunctionTemplate::New(isolate, GetDocumentAll); | ||
exports->Set(context, String::NewFromUtf8(isolate, "getDocumentAll").ToLocalChecked(), method_template->GetFunction(context).ToLocalChecked()).FromJust(); | ||
} | ||
|
||
NODE_MODULE(NODE_GYP_MODULE_NAME, Init) | ||
} | ||
|
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"targets": [ | ||
{ | ||
"target_name": "documentAll", | ||
"sources": [ | ||
"bin/documentAll.cc", | ||
] | ||
} | ||
] | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
const sdenv = require('sdenv-extend').sdenv(); | ||
const window = sdenv.memory.sdWindow; | ||
|
||
function RTCPeerConnection() { | ||
if (!(this instanceof RTCPeerConnection)) { | ||
throw new TypeError("Uncaught TypeError: Failed to construct 'RTCPeerConnection': Please use the 'new' operator, this DOM object constructor cannot be called as a function."); | ||
} | ||
this.createDataChannel = function(...params) { | ||
// window.console.log(`【RTCPeerConnection RTCPeerConnection】调用,参数:${params}`) | ||
} | ||
this.createOffer = function(...params) { | ||
// window.console.log(`【RTCPeerConnection createOffer】调用,参数:${params}`) | ||
} | ||
} | ||
sdenv.tools.setNativeFuncName(RTCPeerConnection, 'RTCPeerConnection'); | ||
sdenv.tools.setNativeObjName(RTCPeerConnection.prototype, 'RTCPeerConnection'); | ||
|
||
|
||
window.RTCPeerConnection = RTCPeerConnection; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
const sdenv = require('sdenv-extend').sdenv(); | ||
|
||
sdenv.memory.sdWindow.chrome = { | ||
app: { | ||
isInstalled: false, | ||
InstallState: { | ||
DISABLED: "disabled", | ||
INSTALLED: "installed", | ||
NOT_INSTALLED: "not_installed", | ||
}, | ||
RunningState: { | ||
CANNOT_RUN: "cannot_run", | ||
READY_TO_RUN: "ready_to_run", | ||
RUNNING: "running", | ||
}, | ||
getDetails: function () {}, | ||
getIsInstalled: function() {}, | ||
installState: function() {}, | ||
runningState: function() {}, | ||
}, | ||
csi: function() {}, | ||
loadTimes: function() { | ||
return { | ||
"requestTime": 1700779741.985, | ||
"startLoadTime": 1700779741.985, | ||
"commitLoadTime": 1700779742.021, | ||
"finishDocumentLoadTime": 0, | ||
"finishLoadTime": 0, | ||
"firstPaintTime": 0, | ||
"firstPaintAfterLoadTime": 0, | ||
"navigationType": "Reload", | ||
"wasFetchedViaSpdy": false, | ||
"wasNpnNegotiated": true, | ||
"npnNegotiatedProtocol": "http/1.1", | ||
"wasAlternateProtocolAvailable": false, | ||
"connectionInfo": "http/1.1" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
const logger = require('@utils/logger'); | ||
const utils = require('sdenv-jsdom/lib/jsdom/living/generated/utils.js'); | ||
const sdenv = require('sdenv-extend').sdenv(); | ||
const window = sdenv.memory.sdWindow; | ||
|
||
const ctorRegistry = window[utils.ctorRegistrySymbol] | ||
window[utils.ctorRegistrySymbol] = new window.Proxy(ctorRegistry, { | ||
get(target, propKey, receiver) { | ||
logger.trace('proxy ctorRegistry get', propKey); | ||
return window.Reflect.get(target, propKey, receiver); | ||
} | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
const getDocumentAll = require('@bin/documentAll').getDocumentAll; | ||
const sdenv = require('sdenv-extend').sdenv(); | ||
const window = sdenv.memory.sdWindow; | ||
|
||
window.document.all = getDocumentAll({ length: 3 }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
require('./window'); | ||
require('./document'); | ||
require('./navigation'); | ||
require('./navigator'); | ||
require('./chrome'); | ||
require('./visualViewport'); | ||
require('./styleMedia'); | ||
// require('./webkitRequestFileSystem'); | ||
require('./ctorRegistry'); | ||
require('./location'); | ||
require('./indexedDB'); | ||
require('./RTCPeerConnection'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
const sdenv = require('sdenv-extend').sdenv(); | ||
const window = sdenv.memory.sdWindow; | ||
|
||
const IDBFactory = function IDBFactory() { | ||
throw new TypeError("Illegal constructor"); | ||
} | ||
|
||
const indexedDB = { | ||
__proto__: IDBFactory.prototype | ||
}; | ||
|
||
sdenv.tools.setNativeFuncName(IDBFactory, 'IDBFactory'); | ||
sdenv.tools.setNativeObjName(indexedDB, 'IDBFactory'); | ||
|
||
window.IDBFactory = IDBFactory; | ||
window.indexedDB = indexedDB; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
const sdenv = require('sdenv-extend').sdenv(); | ||
const window = sdenv.memory.sdWindow; | ||
|
||
Object.defineProperty(window.location, 'replace', { | ||
...Object.getOwnPropertyDescriptor(window.location, 'replace'), | ||
writable: false, | ||
value: function(url) { | ||
sdenv.tools.exit({ url }); | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
const sdenv = require('sdenv-extend').sdenv(); | ||
const window = sdenv.memory.sdWindow; | ||
|
||
[window.Navigation, window.navigation] = sdenv.tools.getNativeProto('Navigation', 'navigation', { | ||
canGoBack: false, | ||
canGoForward: false, | ||
oncurrententrychange: null, | ||
onnavigate: null, | ||
onnavigateerror: null, | ||
onnavigatesuccess: null, | ||
transition: null, | ||
currentEntry: { | ||
id: 'c72e7c89-2c22-47b6-86b8-e83db973ad22', | ||
index: 1, | ||
key: 'd6cc1590-0028-48e9-b6e7-b489d28d8481', | ||
ondispose: null, | ||
sameDocument: true, | ||
url: 'http://example.com', | ||
} | ||
}); |
Oops, something went wrong.