nodejs_chromium 1.1.4 → 1.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +178 -82
- package/package.json +15 -15
- package/src/chrome.js +2 -1
- package/src/cookies.js +0 -10
package/index.js
CHANGED
|
@@ -1,95 +1,191 @@
|
|
|
1
1
|
require('nodejs_patch');
|
|
2
2
|
const puppeteer = require("puppeteer");
|
|
3
3
|
const chrome = require("./src/chrome.js");
|
|
4
|
+
const { exec } = require("child_process");
|
|
4
5
|
global.__UA__ = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36';
|
|
6
|
+
const mob_ua = 'Mozilla/5.0 (Linux; Android 13;Build/TKQ1.220905.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/116.0.0.0 Mobile Safari/537.36';
|
|
7
|
+
let browser;
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
async function NormalClose(path) {
|
|
11
|
+
|
|
12
|
+
const fs = require("fs");
|
|
13
|
+
/**
|
|
14
|
+
* 禁止显示【要恢复页面吗?chromium 未正确关闭。】
|
|
15
|
+
* PATH为chrome.userDataDir
|
|
16
|
+
* 修改`PATH\Default\Preferences`文件,
|
|
17
|
+
* 将`"profile.exit_type":“Crashed"` 改为`"Normal"`。
|
|
18
|
+
*/
|
|
19
|
+
let file = `${path}/Default/Preferences`;
|
|
20
|
+
// console.log({file});
|
|
21
|
+
if (!fs.existsSync(file)) return;
|
|
22
|
+
let text = fs.readFileSync(file);
|
|
23
|
+
let json = JSON.parse(text);
|
|
24
|
+
//原值可能为:Crashed
|
|
25
|
+
json.profile.exit_type = 'Normal';
|
|
26
|
+
// console.log('json.profile.exit_type', json.profile.exit_type);
|
|
27
|
+
fs.writeFileSync(file, JSON.stringify(json));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
async function newBrowser(params) {
|
|
32
|
+
try {
|
|
33
|
+
|
|
34
|
+
let {
|
|
35
|
+
id = 'myChrome',
|
|
36
|
+
visible = false, //是否打开浏览器
|
|
37
|
+
width = 1024, //宽
|
|
38
|
+
height = 768, //高
|
|
39
|
+
scale = 1, //缩放比例
|
|
40
|
+
touch = false, //支持触摸
|
|
41
|
+
mobile = false, //手机版
|
|
42
|
+
dumpio = false, //如果为 true,则将浏览器进程 stdout 和 stderr 通过管道传输到 process.stdout 和 process.stderr。
|
|
43
|
+
devtools = false, //打开devtools
|
|
44
|
+
cache = false, //禁用缓存
|
|
45
|
+
incognito = true, //使用无痕模式启动
|
|
46
|
+
path = void 0, //Chrome路径,linux下必填
|
|
47
|
+
slowMo = 1, //每一步停留时间
|
|
48
|
+
env = void 0, //string,指定浏览器可见的环境变量。process.env 的内容。
|
|
49
|
+
proxy = null, //代理,如:https://proxy.com:789/
|
|
50
|
+
wait = true, //是否等待初始页面准备好。当用户明确禁用该功能时很有用(例如 Chrome 的 --no-startup-window)
|
|
51
|
+
timeout = 0, //等待浏览器启动的最长时间(以毫秒为单位)。 0 禁用超时。
|
|
52
|
+
} = params;
|
|
53
|
+
|
|
54
|
+
let option = {
|
|
55
|
+
userDataDir: `runtime/.cache/${id}`,
|
|
56
|
+
timeout, //最大允许超时间,默认为3000,最小215,一般不要设置
|
|
57
|
+
slowMo, //每一步停留时间,不能太大,否则会太慢,特别是在类似写入很多Cookies时,每写入一个都要等一下。
|
|
58
|
+
headless: visible ? false : 'new', //'new',设置是否在无头模式下运行浏览器,false=会启动浏览器,true=无界面
|
|
59
|
+
devtools, //打开调试
|
|
60
|
+
ignoreHTTPSErrors: true, //忽略 HTTPS 错误。屏蔽跳转不同域名的报错
|
|
61
|
+
dumpio, //是否将浏览器的标准输入/输出流(stdio)的内容输出到 Node.js 的 stdout 和 stderr。
|
|
62
|
+
env,
|
|
63
|
+
waitForInitialPage: wait,
|
|
64
|
+
defaultViewport: {
|
|
65
|
+
width,
|
|
66
|
+
height,
|
|
67
|
+
hasTouch: touch,
|
|
68
|
+
deviceScaleFactor: scale, //缩放比例
|
|
69
|
+
isMobile: mobile,
|
|
70
|
+
},
|
|
71
|
+
defaultArgs: [
|
|
72
|
+
'--disable-extensions', //禁止启动扩展
|
|
73
|
+
'--no-sandbox', //禁用沙箱模式
|
|
74
|
+
'--disable-setuid-sandbox', //禁用设置用户身份沙盒
|
|
75
|
+
'--disable-web-security', //禁用同源策略
|
|
76
|
+
],
|
|
77
|
+
ignoreDefaultArgs: [
|
|
78
|
+
"--enable-automation", //忽略默认的 --enable-automation 参数,这有助于防止某些网站检测到自动化行为。
|
|
79
|
+
],
|
|
80
|
+
args: [
|
|
81
|
+
'--enable-chrome-browser-cloud-management', //Cloud Browser Client Management (CBCM)
|
|
82
|
+
'--disable-web-security', //禁用浏览器的同源策略(Same-Origin Policy)和跨站请求伪造(CSRF)保护
|
|
83
|
+
`--window-size=${width},${height}`,
|
|
84
|
+
'--no-sandbox', //禁用沙箱模式
|
|
85
|
+
'--disable-autofill-backend', //禁止自动填充
|
|
86
|
+
'--disable-setuid-sandbox', //禁用 setuid 沙箱。这是另一种沙箱模式,通常用于 Linux 系统上。
|
|
87
|
+
// '--disable-infobars', //禁用自动化控制时显示的信息栏,告诉用户浏览器正在被自动化工具控制。
|
|
88
|
+
'--disable-gpu', //禁用 GPU 加速。这通常用于在服务器环境或某些不支持 GPU 加速的平台上运行 Chrome。
|
|
89
|
+
'--disable-blink-features=AutomationControlled', //防止检测 blink 引擎特性判断是否处于自动化控制状态。
|
|
90
|
+
'--lang=zh-CN', //设置中文环境
|
|
91
|
+
'--disable-extensions', //禁止启动扩展
|
|
92
|
+
'--disable-dev-shm-usage', //Linux系统中使用普通的文件系统缓存避免因为/dev/shm大小不足而导致的问题
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
await NormalClose(option.userDataDir); //禁止显示【要恢复页面吗?chromium 未正确关闭。】
|
|
96
|
+
|
|
97
|
+
if (proxy) option.defaultArgs.push(`--proxy-server=${proxy}`);
|
|
98
|
+
if (incognito) option.args.push('--incognito', '--disable-infobars'); //使用无痕模式启动
|
|
99
|
+
if (!cache) option.args.push('--disable-cache'); //禁缓存
|
|
100
|
+
if (path) option.executablePath = path; //指定chrome安装路径
|
|
101
|
+
|
|
102
|
+
browser = await puppeteer.launch(option);
|
|
103
|
+
return browser;
|
|
104
|
+
}
|
|
105
|
+
catch (e) {
|
|
106
|
+
let mt = e.message.match(/\(ver\. (\d+\.\d+\.\d+\.\d+)\)/);
|
|
107
|
+
if (mt) {
|
|
108
|
+
return { error: `chrome(${mt})未安装`, install: 1 };
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
console.log('checkInstall', e.message);
|
|
112
|
+
return { error: e.message };
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
5
117
|
|
|
6
118
|
async function newChrome(params) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
dumpio, //是否将浏览器的标准输入/输出流(stdio)的内容输出到 Node.js 的 stdout 和 stderr。
|
|
39
|
-
env,
|
|
40
|
-
waitForInitialPage: wait,
|
|
41
|
-
defaultViewport: {
|
|
42
|
-
width,
|
|
43
|
-
height,
|
|
44
|
-
hasTouch: touch,
|
|
45
|
-
deviceScaleFactor: scale, //缩放比例
|
|
46
|
-
isMobile: !!mobile,
|
|
47
|
-
},
|
|
48
|
-
defaultArgs: [
|
|
49
|
-
'--disable-extensions', //禁止启动扩展
|
|
50
|
-
'--no-sandbox', //禁用沙箱模式
|
|
51
|
-
'--disable-setuid-sandbox', //禁用设置用户身份沙盒
|
|
52
|
-
'--disable-web-security', //禁用同源策略
|
|
53
|
-
],
|
|
54
|
-
ignoreDefaultArgs: [
|
|
55
|
-
"--enable-automation", //忽略默认的 --enable-automation 参数,这有助于防止某些网站检测到自动化行为。
|
|
56
|
-
],
|
|
57
|
-
args: [
|
|
58
|
-
'--enable-chrome-browser-cloud-management', //Cloud Browser Client Management (CBCM)
|
|
59
|
-
'--disable-web-security', //禁用浏览器的同源策略(Same-Origin Policy)和跨站请求伪造(CSRF)保护
|
|
60
|
-
`--window-size=${width},${height}`,
|
|
61
|
-
'--no-sandbox', //禁用沙箱模式
|
|
62
|
-
'--disable-autofill-backend', //禁止自动填充
|
|
63
|
-
'--disable-setuid-sandbox', //禁用 setuid 沙箱。这是另一种沙箱模式,通常用于 Linux 系统上。
|
|
64
|
-
// '--disable-infobars', //禁用自动化控制时显示的信息栏,告诉用户浏览器正在被自动化工具控制。
|
|
65
|
-
'--disable-gpu', //禁用 GPU 加速。这通常用于在服务器环境或某些不支持 GPU 加速的平台上运行 Chrome。
|
|
66
|
-
'--disable-blink-features=AutomationControlled', //防止检测 blink 引擎特性判断是否处于自动化控制状态。
|
|
67
|
-
'--lang=zh-CN', //设置中文环境
|
|
68
|
-
'--disable-extensions', //禁止启动扩展
|
|
69
|
-
'--disable-dev-shm-usage', //Linux系统中使用普通的文件系统缓存避免因为/dev/shm大小不足而导致的问题
|
|
70
|
-
]
|
|
119
|
+
try {
|
|
120
|
+
let {
|
|
121
|
+
id = 'myChrome',
|
|
122
|
+
visible = false, //是否打开浏览器
|
|
123
|
+
mobile = false, //手机版
|
|
124
|
+
ua = void 0, //若不指定ua则用__UA__
|
|
125
|
+
cookies = null, //若cookies=false,则不处理cookies,不指定则由chrome处理,若=文件路径
|
|
126
|
+
abort = [], //要禁止的类型,常见["font","image","ping","stylesheet","document","fetch","script","xhr"]
|
|
127
|
+
headers = {},
|
|
128
|
+
} = params;
|
|
129
|
+
|
|
130
|
+
await newBrowser(params);
|
|
131
|
+
|
|
132
|
+
// const version = await browser.version();
|
|
133
|
+
const page = (await browser.pages())[0];
|
|
134
|
+
// const page = await browser.newPage();
|
|
135
|
+
await page.setRequestInterception(true); //允许拦截
|
|
136
|
+
|
|
137
|
+
if (ua) await page.setUserAgent(ua);
|
|
138
|
+
else if (mobile) await page.setUserAgent(mob_ua);
|
|
139
|
+
else await page.setUserAgent(__UA__);
|
|
140
|
+
|
|
141
|
+
await page.evaluateOnNewDocument(() => {
|
|
142
|
+
const newProto = navigator.__proto__;
|
|
143
|
+
delete newProto.webdriver; //删除 navigator.webdriver字段,防止检测到自动化行为
|
|
144
|
+
navigator.__proto__ = newProto;
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
if (cookies !== false) cookies = `runtime/.cache/${id}/cookies.json`;
|
|
148
|
+
const pageOption = { cookies, visible, abort, headers };
|
|
149
|
+
return new chrome(browser, page, pageOption);
|
|
71
150
|
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
return { error: err.message };
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
}
|
|
72
156
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const newProto = navigator.__proto__;
|
|
85
|
-
delete newProto.webdriver; //删除 navigator.webdriver字段,防止检测到自动化行为
|
|
86
|
-
navigator.__proto__ = newProto;
|
|
157
|
+
async function run_install(command) {
|
|
158
|
+
console.log({ command });
|
|
159
|
+
return new Promise(async (trueCall, exitCall) => {
|
|
160
|
+
exec(command, (error, stdout, stderr) => {
|
|
161
|
+
stderr = stderr.replace('\n', '').trim();
|
|
162
|
+
stdout = stdout.replace('\n', '').trim();
|
|
163
|
+
console.log({ error, stdout, stderr });
|
|
164
|
+
if (error) return trueCall({ error });
|
|
165
|
+
if (stderr) return trueCall({ error: stderr });
|
|
166
|
+
if (stdout) return trueCall({ success: stdout });
|
|
167
|
+
});
|
|
87
168
|
});
|
|
169
|
+
}
|
|
88
170
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
171
|
+
async function checkInstall(install = false) {
|
|
172
|
+
try {
|
|
173
|
+
const path = await puppeteer.executablePath();
|
|
174
|
+
if (path) return { success: path };
|
|
175
|
+
return { error: 'none' };
|
|
176
|
+
}
|
|
177
|
+
catch (e) {
|
|
178
|
+
if (!install) return { error: e.message };
|
|
179
|
+
let mt = e.message.match(/\(ver\. (\d+\.\d+\.\d+\.\d+)\)/);
|
|
180
|
+
if (mt) {
|
|
181
|
+
return await run_install('npx puppeteer browsers install chrome');
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
console.log('checkInstall', e.message);
|
|
185
|
+
return { error: e.message };
|
|
186
|
+
}
|
|
187
|
+
}
|
|
92
188
|
}
|
|
93
189
|
|
|
94
190
|
|
|
95
|
-
module.exports = { newChrome }
|
|
191
|
+
module.exports = { newChrome, checkInstall }
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "nodejs_chromium",
|
|
3
|
+
"version": "1.1.6",
|
|
4
|
+
"description": "for pupeteer chromium",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"nodejs_patch": ">1.0.5",
|
|
11
|
+
"puppeteer": ">22.6.0"
|
|
12
|
+
},
|
|
13
|
+
"author": "laoCC",
|
|
14
|
+
"license": "ISC"
|
|
15
|
+
}
|
package/src/chrome.js
CHANGED
|
@@ -588,6 +588,7 @@ module.exports = class {
|
|
|
588
588
|
|
|
589
589
|
value.type = await request.resourceType();
|
|
590
590
|
// value.redirect = await response.redirectURL();
|
|
591
|
+
if (value.type === 'fetch') value.type = 'xhr';
|
|
591
592
|
if (value.type === 'xhr') value.type = 'AJAX';
|
|
592
593
|
value.url = await response.url();
|
|
593
594
|
value.headers = { request: request.headers(), response: headers };
|
|
@@ -602,7 +603,7 @@ module.exports = class {
|
|
|
602
603
|
if (headers['set-cookie']) value.cookies = await this.cookies.parse(headers['set-cookie']);
|
|
603
604
|
value.remote = await response.remoteAddress(); //目标服务器
|
|
604
605
|
if (value.status === 301 || value.status === 302) return value;
|
|
605
|
-
if (['image', 'font', 'other', 'script', 'stylesheet', 'document', 'ping'
|
|
606
|
+
if (['image', 'font', 'other', 'script', 'stylesheet', 'document', 'ping'].has(value.type)) return value;
|
|
606
607
|
if (value.content) {
|
|
607
608
|
if (value.content.startsWith('application/vnd')) return value;
|
|
608
609
|
if (value.content.startsWith('application/xml')) return value;
|
package/src/cookies.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
const fs = require("fs");
|
|
2
|
-
const { parse: parseUrl } = require("url");
|
|
3
|
-
|
|
4
2
|
|
|
5
3
|
module.exports = class {
|
|
6
4
|
page = void 0;
|
|
@@ -29,14 +27,6 @@ module.exports = class {
|
|
|
29
27
|
});
|
|
30
28
|
}
|
|
31
29
|
|
|
32
|
-
/**
|
|
33
|
-
|
|
34
|
-
// const url = parseUrl(this.page.url());
|
|
35
|
-
// const host = '.' + url.host.split('.').slice(-2).join('.');
|
|
36
|
-
// let cookiesVal = read(file, 'utf8');
|
|
37
|
-
// cookiesVal = this.jsonArray(cookiesVal, host);
|
|
38
|
-
|
|
39
|
-
*/
|
|
40
30
|
/**
|
|
41
31
|
* 解析网页set-cookies的值
|
|
42
32
|
*
|