You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
212 lines
7.1 KiB
212 lines
7.1 KiB
const {jsdomFromText, browser} = require("sdenv"); |
|
const JsUtil = require("../../utils/JsUtil"); |
|
const {Script} = require("node:vm"); |
|
const Store = require("../../utils/Store"); |
|
let TimeUtil = require("../../utils/TimeUtil"); |
|
|
|
class Rs6Service { |
|
store = new Store(); |
|
// service handle |
|
async handle(url, uuid, htmlStr, cookie, userAgent) { |
|
// 获取 origin |
|
var var1 = new URL(url) |
|
let baseUrl = var1.origin; |
|
// 初始化 jsDom 和 cookieJar |
|
const [jsDom, cookieJar] = jsdomFromText({ |
|
url: url, referrer: url, userAgent: userAgent, contentType: "text/html", runScripts: "outside-only", // runScripts: 'dangerously'/'outside-only' |
|
}) |
|
// 加载dom |
|
let dom = await jsDom(htmlStr); |
|
console.log(`${uuid};html 加载长度--->`, dom.serialize().length) |
|
const window = dom.window |
|
// ------------------------------------------------ param ---------------------------------------------------------- |
|
// 标志判断cookie是否生成 |
|
window[uuid] = false |
|
|
|
|
|
// ------------------------------------------------ function ------------------------------------------------------- |
|
// js执行成功后会跳转页面 会触发onbeforeunload钩子 |
|
window.onbeforeunload = async (url) => { |
|
console.debug(`${url} 页面回调完成`); |
|
window[uuid] = true |
|
} |
|
|
|
// 设置 cookie |
|
if (cookie != null) { |
|
let cookieList = this.CookieStr2List(cookie); |
|
console.log(`${uuid};cookie 加载长度--->`, cookieList.length, baseUrl) |
|
for (let i = 0; i < cookieList.length; i++) { |
|
cookieJar.setCookieSync(cookieList[i], baseUrl); |
|
} |
|
} |
|
|
|
// 方案1 通过监听cookie 判断cookie是否生成 |
|
const superSetCookie = cookieJar.setCookie; |
|
let generateCookieKey = null; |
|
// 设置 setCookie 代理 |
|
cookieJar.setCookie = function (cookie, currentUrl, options, callback) { |
|
console.debug(`${uuid};正在设置 Cookie:`, cookie, currentUrl); |
|
let call = superSetCookie.call(this, cookie, currentUrl, options, callback); |
|
// 根据瑞树6 cookie 特性 截取 `enable_XXXXXXXXXXXX=true` XXXXXXXX 为即将生成的 cookie key |
|
if (generateCookieKey != null && cookie.includes(generateCookieKey)) { |
|
window[uuid] = true |
|
console.debug('匹配---->', cookie) |
|
} |
|
let match = cookie.match(/enable_(.*?)=true/); |
|
if (match) { |
|
generateCookieKey = match[1]; |
|
console.debug('设置 匹配---->', generateCookieKey) |
|
} |
|
return call; |
|
}; |
|
|
|
// ------------------------------------------------ 实例化浏览器 ----------------------------------------------------- |
|
browser(window, 'chrome'); |
|
// 加载js |
|
let js = await JsUtil.loadJs(window.document, var1.hostname, cookie); |
|
console.log(`${uuid};js 加载长度--->`, js.length) |
|
|
|
|
|
// 执行 js |
|
let script = new Script(js); |
|
let internalVMContext = dom.getInternalVMContext(); |
|
script.runInContext(internalVMContext, {timeout: 1000}); |
|
|
|
// 等待 cookie 被设置 |
|
for (let i = 0; i < 10; i++) { |
|
if (window[uuid]) { |
|
break; |
|
} |
|
await TimeUtil.sleep(100) |
|
} |
|
// 获取cookie |
|
let resCookie = cookieJar.getCookieStringSync(baseUrl); |
|
// 关闭 |
|
dom.window.close() |
|
return resCookie; |
|
} |
|
|
|
// 将 cookie 转为 list |
|
CookieStr2List(cookies) { |
|
let list = [] |
|
for (let cookie of cookies.trim().split("; ")) { |
|
list.push(cookie); |
|
} |
|
return list |
|
} |
|
|
|
|
|
/** |
|
* 方案1 |
|
* 利用rs特性 js加载完成后会刷新页面 |
|
* 利用 window.onbeforeunload 判断页面是否执行完毕 |
|
* @param window |
|
* @param cookieJar |
|
* @param uuid |
|
* @returns {Promise<*|null>} |
|
*/ |
|
scheme1_before(window, cookieJar, uuid) { |
|
window.onbeforeunload = async (url) => { |
|
let baseUrl = new URL(url).origin; |
|
const cookies = cookieJar.getCookieStringSync(baseUrl); |
|
console.debug(`${url} 页面回调生成cookie:`, cookies); |
|
this.store.set(uuid, cookies) |
|
// window.close(); |
|
} |
|
} |
|
|
|
/** |
|
* 方案1 |
|
* @param window |
|
* @param cookieJar |
|
* @param uuid |
|
* @returns {Promise<*|null>} |
|
*/ |
|
async scheme1_after(window, cookieJar, uuid) { |
|
// 等待 onbeforeunload 钩子触发后的回掉 |
|
let val = await this.store.waitGetAndDelete(uuid, 100, 10) |
|
if (val != null) { |
|
return val; |
|
} |
|
return null; |
|
} |
|
|
|
|
|
/** |
|
* 监听cookie出现指定cookie |
|
* @param window |
|
* @param cookieJar |
|
* @param uuid |
|
* @returns {Promise<null|string>} |
|
*/ |
|
scheme2_before(window, cookieJar, uuid) { |
|
// window[uuid] = false; |
|
const superSetCookie = cookieJar.setCookie; |
|
// 设置 setCookie 代理 |
|
cookieJar.setCookie = function (cookie, currentUrl, options, callback) { |
|
console.log(`${uuid};正在设置 Cookie:`, cookie, currentUrl); |
|
return superSetCookie.call(this, cookie, currentUrl, options, callback); |
|
// let cookieStringSync = super.getCookieStringSync(); |
|
// console.log(cookieStringSync) |
|
// if (cookie.includes(key)) { |
|
// // 设置标志可取标志 |
|
// window[uuid] = true |
|
// } |
|
// return call; |
|
}; |
|
} |
|
|
|
/** |
|
* 方案2 |
|
* @param window |
|
* @param cookieJar |
|
* @param key |
|
* @param uuid |
|
* @returns {Promise<null|string>} |
|
*/ |
|
async scheme2_after(window, cookieJar, key, uuid) { |
|
for (let i = 0; i < 10; i++) { |
|
let cookieStringSync = cookieJar.getCookieStringSync(); |
|
if (cookieStringSync.includes(key)) { |
|
return cookieStringSync; |
|
} |
|
await TimeUtil.sleep(100) |
|
} |
|
return null; |
|
} |
|
|
|
/** |
|
* 方案3 根据cookie现有的数量判断 |
|
* @param window |
|
* @param cookieJar |
|
* @param baseUrl |
|
* @param uuid |
|
*/ |
|
scheme3_before(window, cookieJar, baseUrl, uuid) { |
|
const initCookie = cookieJar.getCookieStringSync(baseUrl); |
|
window[uuid + 'CookieSize'] = initCookie != null ? initCookie.trim().split("; ").length : 0; |
|
} |
|
|
|
/** |
|
* 方案3 |
|
* @param window |
|
* @param cookieJar |
|
* @param baseUrl |
|
* @param uuid |
|
* @returns {Promise<null|string>} |
|
*/ |
|
async scheme3_after(window, cookieJar, baseUrl, uuid) { |
|
let initCookieLength = window[uuid + 'CookieSize'] |
|
for (let i = 0; i < 10; i++) { |
|
let cookieStringSync = cookieJar.getCookieStringSync(baseUrl); |
|
let cookies = cookieStringSync != null ? cookieStringSync.trim().split("; ").length : 0; |
|
if (cookies > initCookieLength) { |
|
return cookieStringSync; |
|
} |
|
await TimeUtil.sleep(100) |
|
} |
|
return null; |
|
} |
|
} |
|
|
|
module.exports = Rs6Service |