@skrillex1224/playwright-toolkit 3.0.15 → 3.0.16
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/browser.d.ts +6 -0
- package/dist/browser.js +421 -163
- package/dist/browser.js.map +4 -4
- package/dist/index.cjs +1021 -497
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +1021 -497
- package/dist/index.js.map +4 -4
- package/index.d.ts +49 -9
- package/package.json +9 -1
- package/scripts/postinstall.js +203 -0
package/dist/index.js
CHANGED
|
@@ -13,9 +13,12 @@ __export(constants_exports, {
|
|
|
13
13
|
ActorInfo: () => ActorInfo,
|
|
14
14
|
Code: () => Code,
|
|
15
15
|
Device: () => Device,
|
|
16
|
+
Mode: () => Mode,
|
|
16
17
|
PresetOfLiveViewKey: () => PresetOfLiveViewKey,
|
|
17
18
|
Status: () => Status,
|
|
18
|
-
|
|
19
|
+
mode: () => mode,
|
|
20
|
+
normalizeDevice: () => normalizeDevice,
|
|
21
|
+
normalizeMode: () => normalizeMode
|
|
19
22
|
});
|
|
20
23
|
var Code = {
|
|
21
24
|
Success: 0,
|
|
@@ -35,6 +38,14 @@ var Device = Object.freeze({
|
|
|
35
38
|
Desktop: "desktop",
|
|
36
39
|
Mobile: "mobile"
|
|
37
40
|
});
|
|
41
|
+
var Mode = Object.freeze({
|
|
42
|
+
Default: "default",
|
|
43
|
+
Cloak: "cloak"
|
|
44
|
+
});
|
|
45
|
+
var mode = Object.freeze({
|
|
46
|
+
default: Mode.Default,
|
|
47
|
+
cloak: Mode.Cloak
|
|
48
|
+
});
|
|
38
49
|
var normalizeDevice = (value, fallback = Device.Desktop) => {
|
|
39
50
|
const normalizedFallback = String(fallback || "").trim().toLowerCase() === Device.Mobile ? Device.Mobile : Device.Desktop;
|
|
40
51
|
const raw = String(value || "").trim().toLowerCase();
|
|
@@ -42,6 +53,13 @@ var normalizeDevice = (value, fallback = Device.Desktop) => {
|
|
|
42
53
|
if (raw === Device.Desktop) return Device.Desktop;
|
|
43
54
|
return normalizedFallback;
|
|
44
55
|
};
|
|
56
|
+
var normalizeMode = (value, fallback = Mode.Default) => {
|
|
57
|
+
const normalizedFallback = String(fallback || "").trim().toLowerCase() === Mode.Cloak ? Mode.Cloak : Mode.Default;
|
|
58
|
+
const raw = String(value || "").trim().toLowerCase();
|
|
59
|
+
if (raw === Mode.Cloak) return Mode.Cloak;
|
|
60
|
+
if (raw === Mode.Default) return Mode.Default;
|
|
61
|
+
return normalizedFallback;
|
|
62
|
+
};
|
|
45
63
|
var createActorInfo = (info) => {
|
|
46
64
|
const normalizeDomain = (value) => {
|
|
47
65
|
if (!value) return "";
|
|
@@ -56,7 +74,7 @@ var createActorInfo = (info) => {
|
|
|
56
74
|
const normalizeShare2 = (value) => {
|
|
57
75
|
const raw = value && typeof value === "object" ? value : {};
|
|
58
76
|
const modeRaw = String(raw.mode || "dom").trim().toLowerCase();
|
|
59
|
-
const
|
|
77
|
+
const mode2 = ["dom", "response", "custom"].includes(modeRaw) ? modeRaw : "dom";
|
|
60
78
|
const prefix = String(raw.prefix || "").trim();
|
|
61
79
|
const rawXurl = Array.isArray(raw.xurl) ? raw.xurl : [];
|
|
62
80
|
const normalizeMatcherList = (input) => {
|
|
@@ -101,7 +119,7 @@ var createActorInfo = (info) => {
|
|
|
101
119
|
xurl.push(...extraPaths);
|
|
102
120
|
}
|
|
103
121
|
return {
|
|
104
|
-
mode,
|
|
122
|
+
mode: mode2,
|
|
105
123
|
prefix,
|
|
106
124
|
xurl
|
|
107
125
|
};
|
|
@@ -109,7 +127,6 @@ var createActorInfo = (info) => {
|
|
|
109
127
|
const buildLandingUrl = ({ protocol: protocol2, domain: domain2, path: path4 }) => {
|
|
110
128
|
const safeProtocol = String(protocol2).trim();
|
|
111
129
|
const safeDomain = normalizeDomain(domain2);
|
|
112
|
-
if (!safeDomain) return "";
|
|
113
130
|
const safePath = normalizePath(path4);
|
|
114
131
|
return `${safeProtocol}://${safeDomain}${safePath}`;
|
|
115
132
|
};
|
|
@@ -317,18 +334,6 @@ var ActorInfo = {
|
|
|
317
334
|
prefix: "",
|
|
318
335
|
xurl: []
|
|
319
336
|
}
|
|
320
|
-
}),
|
|
321
|
-
// 通用网页抓取 Actor:入口 URL 来自 query,因此这里只声明统一的 Actor 元信息。
|
|
322
|
-
webpage: createActorInfo({
|
|
323
|
-
key: "webpage",
|
|
324
|
-
name: "\u901A\u7528\u7F51\u9875",
|
|
325
|
-
domain: "",
|
|
326
|
-
path: "/",
|
|
327
|
-
share: {
|
|
328
|
-
mode: "dom",
|
|
329
|
-
prefix: "",
|
|
330
|
-
xurl: []
|
|
331
|
-
}
|
|
332
337
|
})
|
|
333
338
|
};
|
|
334
339
|
|
|
@@ -360,18 +365,18 @@ var fallbackLog = {
|
|
|
360
365
|
error: (...args) => console.error(...args),
|
|
361
366
|
debug: (...args) => console.debug ? console.debug(...args) : console.log(...args)
|
|
362
367
|
};
|
|
363
|
-
var resolveLogMethod = (
|
|
364
|
-
if (
|
|
365
|
-
return
|
|
368
|
+
var resolveLogMethod = (logger17, name) => {
|
|
369
|
+
if (logger17 && typeof logger17[name] === "function") {
|
|
370
|
+
return logger17[name].bind(logger17);
|
|
366
371
|
}
|
|
367
|
-
if (name === "warning" &&
|
|
368
|
-
return
|
|
372
|
+
if (name === "warning" && logger17 && typeof logger17.warn === "function") {
|
|
373
|
+
return logger17.warn.bind(logger17);
|
|
369
374
|
}
|
|
370
375
|
return fallbackLog[name];
|
|
371
376
|
};
|
|
372
377
|
var defaultLogger = null;
|
|
373
|
-
var setDefaultLogger = (
|
|
374
|
-
defaultLogger =
|
|
378
|
+
var setDefaultLogger = (logger17) => {
|
|
379
|
+
defaultLogger = logger17;
|
|
375
380
|
};
|
|
376
381
|
var resolveLogger = (explicitLogger) => {
|
|
377
382
|
if (explicitLogger && typeof explicitLogger.info === "function") {
|
|
@@ -398,8 +403,8 @@ var colorize = (text, color) => {
|
|
|
398
403
|
var createBaseLogger = (prefix = "", explicitLogger) => {
|
|
399
404
|
const name = prefix ? String(prefix) : "";
|
|
400
405
|
const dispatch = (methodName, icon, message, color) => {
|
|
401
|
-
const
|
|
402
|
-
const logFn = resolveLogMethod(
|
|
406
|
+
const logger17 = resolveLogger(explicitLogger);
|
|
407
|
+
const logFn = resolveLogMethod(logger17, methodName);
|
|
403
408
|
const timestamp = colorize(`[${formatTimestamp()}]`, ANSI.gray);
|
|
404
409
|
const line = formatLine(name, icon, message);
|
|
405
410
|
const coloredLine = colorize(line, color);
|
|
@@ -753,7 +758,7 @@ var adjustAffixedElementsForExpandedScreenshot = async (page, options = {}) => {
|
|
|
753
758
|
if (safeTargetHeight <= viewportHeight + 1) {
|
|
754
759
|
return 0;
|
|
755
760
|
}
|
|
756
|
-
const
|
|
761
|
+
const hasOwn2 = (source, key) => Object.prototype.hasOwnProperty.call(source, key);
|
|
757
762
|
const isVisible = (el, style, rect) => {
|
|
758
763
|
if (!el || !style || !rect) return false;
|
|
759
764
|
if (style.display === "none" || style.visibility === "hidden" || style.visibility === "collapse") {
|
|
@@ -793,7 +798,7 @@ var adjustAffixedElementsForExpandedScreenshot = async (page, options = {}) => {
|
|
|
793
798
|
return true;
|
|
794
799
|
});
|
|
795
800
|
topLevelCandidates.forEach(({ el, position, edge }) => {
|
|
796
|
-
if (!
|
|
801
|
+
if (!hasOwn2(el.dataset, "pkAffixedAdjusted")) {
|
|
797
802
|
el.dataset.pkAffixedAdjusted = "1";
|
|
798
803
|
el.dataset.pkOrigPosition = el.style.getPropertyValue("position") || "";
|
|
799
804
|
el.dataset.pkOrigPositionPriority = el.style.getPropertyPriority("position") || "";
|
|
@@ -824,7 +829,7 @@ var adjustAffixedElementsForExpandedScreenshot = async (page, options = {}) => {
|
|
|
824
829
|
};
|
|
825
830
|
var restoreAffixedElementsForExpandedScreenshot = async (page) => {
|
|
826
831
|
await page.evaluate((className) => {
|
|
827
|
-
const
|
|
832
|
+
const hasOwn2 = (source, key) => Object.prototype.hasOwnProperty.call(source, key);
|
|
828
833
|
const expansionKeys = [
|
|
829
834
|
"pkOrigOverflow",
|
|
830
835
|
"pkOrigHeight",
|
|
@@ -832,28 +837,28 @@ var restoreAffixedElementsForExpandedScreenshot = async (page) => {
|
|
|
832
837
|
"pkOrigMaxHeight"
|
|
833
838
|
];
|
|
834
839
|
document.querySelectorAll('[data-pk-affixed-adjusted="1"]').forEach((el) => {
|
|
835
|
-
if (
|
|
840
|
+
if (hasOwn2(el.dataset, "pkOrigPosition")) {
|
|
836
841
|
el.style.setProperty("position", el.dataset.pkOrigPosition || "", el.dataset.pkOrigPositionPriority || "");
|
|
837
842
|
delete el.dataset.pkOrigPosition;
|
|
838
843
|
delete el.dataset.pkOrigPositionPriority;
|
|
839
844
|
}
|
|
840
|
-
if (
|
|
845
|
+
if (hasOwn2(el.dataset, "pkOrigTop")) {
|
|
841
846
|
el.style.setProperty("top", el.dataset.pkOrigTop || "", el.dataset.pkOrigTopPriority || "");
|
|
842
847
|
delete el.dataset.pkOrigTop;
|
|
843
848
|
delete el.dataset.pkOrigTopPriority;
|
|
844
849
|
}
|
|
845
|
-
if (
|
|
850
|
+
if (hasOwn2(el.dataset, "pkOrigBottom")) {
|
|
846
851
|
el.style.setProperty("bottom", el.dataset.pkOrigBottom || "", el.dataset.pkOrigBottomPriority || "");
|
|
847
852
|
delete el.dataset.pkOrigBottom;
|
|
848
853
|
delete el.dataset.pkOrigBottomPriority;
|
|
849
854
|
}
|
|
850
|
-
if (
|
|
855
|
+
if (hasOwn2(el.dataset, "pkOrigTranslate")) {
|
|
851
856
|
el.style.setProperty("translate", el.dataset.pkOrigTranslate || "", el.dataset.pkOrigTranslatePriority || "");
|
|
852
857
|
delete el.dataset.pkOrigTranslate;
|
|
853
858
|
delete el.dataset.pkOrigTranslatePriority;
|
|
854
859
|
}
|
|
855
860
|
delete el.dataset.pkAffixedAdjusted;
|
|
856
|
-
const stillExpanded = expansionKeys.some((key) =>
|
|
861
|
+
const stillExpanded = expansionKeys.some((key) => hasOwn2(el.dataset, key));
|
|
857
862
|
if (!stillExpanded) {
|
|
858
863
|
el.classList.remove(className);
|
|
859
864
|
}
|
|
@@ -896,7 +901,7 @@ var prepareExpandedFullPageScreenshot = async (page, options = {}) => {
|
|
|
896
901
|
viewportResized
|
|
897
902
|
};
|
|
898
903
|
};
|
|
899
|
-
var restoreExpandedFullPageScreenshot = async (page,
|
|
904
|
+
var restoreExpandedFullPageScreenshot = async (page, state2 = {}) => {
|
|
900
905
|
await page.evaluate((className) => {
|
|
901
906
|
const targets = new Set([
|
|
902
907
|
...document.querySelectorAll(`.${className}`),
|
|
@@ -920,8 +925,8 @@ var restoreExpandedFullPageScreenshot = async (page, state = {}) => {
|
|
|
920
925
|
el.classList.remove(className);
|
|
921
926
|
});
|
|
922
927
|
}, EXPANDED_SCROLLABLE_CLASS);
|
|
923
|
-
if (
|
|
924
|
-
await page.setViewportSize(
|
|
928
|
+
if (state2?.originalViewport && state2?.viewportResized) {
|
|
929
|
+
await page.setViewportSize(state2.originalViewport);
|
|
925
930
|
}
|
|
926
931
|
};
|
|
927
932
|
var capturePageScreenshot = async (page, options = {}) => {
|
|
@@ -978,21 +983,21 @@ var capturePageScreenshot = async (page, options = {}) => {
|
|
|
978
983
|
}
|
|
979
984
|
};
|
|
980
985
|
var captureExpandedFullPageScreenshot = async (page, options = {}) => {
|
|
981
|
-
const
|
|
986
|
+
const state2 = await prepareExpandedFullPageScreenshot(page, options);
|
|
982
987
|
try {
|
|
983
988
|
return await capturePageScreenshot(page, {
|
|
984
989
|
fullPage: true,
|
|
985
990
|
type: options.type || "png",
|
|
986
991
|
quality: options.quality,
|
|
987
992
|
timeout: options.timeout,
|
|
988
|
-
maxClipHeight:
|
|
993
|
+
maxClipHeight: state2.targetHeight
|
|
989
994
|
});
|
|
990
995
|
} finally {
|
|
991
996
|
await restoreAffixedElementsForExpandedScreenshot(page).catch((error) => {
|
|
992
997
|
logger.warning(`\u79FB\u52A8\u7AEF\u5438\u9644\u5143\u7D20\u6062\u590D\u5931\u8D25: ${error?.message || error}`);
|
|
993
998
|
});
|
|
994
999
|
if (options.restore) {
|
|
995
|
-
await restoreExpandedFullPageScreenshot(page,
|
|
1000
|
+
await restoreExpandedFullPageScreenshot(page, state2);
|
|
996
1001
|
}
|
|
997
1002
|
}
|
|
998
1003
|
};
|
|
@@ -1910,8 +1915,8 @@ var normalizeBrowserProfile = (value) => {
|
|
|
1910
1915
|
payload: buildBrowserProfilePayload(core, observed)
|
|
1911
1916
|
};
|
|
1912
1917
|
};
|
|
1913
|
-
var rememberRuntimeState = (
|
|
1914
|
-
rememberedRuntimeState = deepClone(
|
|
1918
|
+
var rememberRuntimeState = (state2) => {
|
|
1919
|
+
rememberedRuntimeState = deepClone(state2);
|
|
1915
1920
|
return rememberedRuntimeState;
|
|
1916
1921
|
};
|
|
1917
1922
|
var normalizeRuntimeState = (source = {}, actor = "") => {
|
|
@@ -1970,7 +1975,7 @@ var RuntimeEnv = {
|
|
|
1970
1975
|
} else {
|
|
1971
1976
|
delete normalizedRuntime.browser_profile;
|
|
1972
1977
|
}
|
|
1973
|
-
const
|
|
1978
|
+
const state2 = {
|
|
1974
1979
|
actor: resolvedActor,
|
|
1975
1980
|
device,
|
|
1976
1981
|
runtime: normalizedRuntime,
|
|
@@ -1984,73 +1989,73 @@ var RuntimeEnv = {
|
|
|
1984
1989
|
browserProfileCore: browserProfile.core,
|
|
1985
1990
|
browserProfileObserved: browserProfile.observed
|
|
1986
1991
|
};
|
|
1987
|
-
rememberRuntimeState(
|
|
1988
|
-
return
|
|
1992
|
+
rememberRuntimeState(state2);
|
|
1993
|
+
return state2;
|
|
1989
1994
|
},
|
|
1990
1995
|
// buildEnvPatch 只构造允许回写到后端 env 的字段集合。
|
|
1991
1996
|
buildEnvPatch(source = {}, actor = "") {
|
|
1992
|
-
const
|
|
1993
|
-
const browserProfile = buildBrowserProfilePayload(
|
|
1997
|
+
const state2 = normalizeRuntimeState(source, actor);
|
|
1998
|
+
const browserProfile = buildBrowserProfilePayload(state2.browserProfileCore, state2.browserProfileObserved);
|
|
1994
1999
|
const envPatch = {
|
|
1995
|
-
...Array.isArray(
|
|
1996
|
-
...Object.keys(
|
|
1997
|
-
...Object.keys(
|
|
2000
|
+
...Array.isArray(state2.cookies) && state2.cookies.length > 0 ? { cookies: state2.cookies } : {},
|
|
2001
|
+
...Object.keys(state2.localStorage || {}).length > 0 ? { local_storage: state2.localStorage } : {},
|
|
2002
|
+
...Object.keys(state2.sessionStorage || {}).length > 0 ? { session_storage: state2.sessionStorage } : {},
|
|
1998
2003
|
...Object.keys(browserProfile).length > 0 ? { browser_profile: browserProfile } : {}
|
|
1999
2004
|
};
|
|
2000
2005
|
return Object.keys(envPatch).length > 0 ? envPatch : null;
|
|
2001
2006
|
},
|
|
2002
2007
|
// hasLoginState 只判断 runtime 是否存在有效载荷,不再区分具体字段来源。
|
|
2003
2008
|
hasLoginState(source = {}, actor = "") {
|
|
2004
|
-
const
|
|
2005
|
-
return isPlainObject(
|
|
2009
|
+
const state2 = normalizeRuntimeState(source, actor);
|
|
2010
|
+
return isPlainObject(state2.runtime) && Object.keys(state2.runtime || {}).length > 0;
|
|
2006
2011
|
},
|
|
2007
2012
|
rememberState(source = {}) {
|
|
2008
|
-
const
|
|
2009
|
-
rememberRuntimeState(
|
|
2013
|
+
const state2 = normalizeRuntimeState(source);
|
|
2014
|
+
rememberRuntimeState(state2);
|
|
2010
2015
|
return RuntimeEnv.peekRememberedState();
|
|
2011
2016
|
},
|
|
2012
2017
|
peekRememberedState() {
|
|
2013
2018
|
return rememberedRuntimeState ? deepClone(rememberedRuntimeState) : null;
|
|
2014
2019
|
},
|
|
2015
2020
|
getBrowserProfileCore(source = {}, actor = "") {
|
|
2016
|
-
const
|
|
2017
|
-
return deepClone(
|
|
2021
|
+
const state2 = normalizeRuntimeState(source, actor);
|
|
2022
|
+
return deepClone(state2.browserProfileCore || {});
|
|
2018
2023
|
},
|
|
2019
2024
|
setBrowserProfileCore(source = {}, core = {}, actor = "") {
|
|
2020
|
-
const
|
|
2025
|
+
const state2 = normalizeRuntimeState(source, actor);
|
|
2021
2026
|
const normalizedCore = normalizeBrowserProfileCore({
|
|
2022
2027
|
...core,
|
|
2023
|
-
device: normalizeKnownDevice(core?.device) ||
|
|
2028
|
+
device: normalizeKnownDevice(core?.device) || state2.device
|
|
2024
2029
|
});
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
if (Object.keys(
|
|
2028
|
-
|
|
2030
|
+
state2.browserProfileCore = normalizedCore;
|
|
2031
|
+
state2.browserProfile = buildBrowserProfilePayload(normalizedCore, state2.browserProfileObserved);
|
|
2032
|
+
if (Object.keys(state2.browserProfile).length > 0) {
|
|
2033
|
+
state2.runtime.browser_profile = state2.browserProfile;
|
|
2029
2034
|
} else {
|
|
2030
|
-
delete
|
|
2035
|
+
delete state2.runtime.browser_profile;
|
|
2031
2036
|
}
|
|
2032
|
-
rememberRuntimeState(
|
|
2033
|
-
return
|
|
2037
|
+
rememberRuntimeState(state2);
|
|
2038
|
+
return state2;
|
|
2034
2039
|
},
|
|
2035
2040
|
// applyToPage 只负责把登录态相关字段注入页面:
|
|
2036
2041
|
// cookies / localStorage / sessionStorage。
|
|
2037
2042
|
// 指纹、时区、UA、viewport 的回放发生在 launch.js 启动阶段,不在这里做。
|
|
2038
2043
|
async applyToPage(page, source = {}, options = {}) {
|
|
2039
2044
|
if (!page) return;
|
|
2040
|
-
let
|
|
2045
|
+
let state2 = normalizeRuntimeState(source, options?.actor || "");
|
|
2041
2046
|
if (typeof options?.preapply === "function") {
|
|
2042
|
-
|
|
2043
|
-
rememberRuntimeState(
|
|
2047
|
+
state2 = await options.preapply(state2) || state2;
|
|
2048
|
+
rememberRuntimeState(state2);
|
|
2044
2049
|
}
|
|
2045
2050
|
Object.defineProperty(page, PageRuntimeStateKey, {
|
|
2046
2051
|
configurable: true,
|
|
2047
2052
|
enumerable: false,
|
|
2048
2053
|
writable: true,
|
|
2049
|
-
value:
|
|
2054
|
+
value: state2
|
|
2050
2055
|
});
|
|
2051
|
-
const localStorage =
|
|
2052
|
-
const sessionStorage =
|
|
2053
|
-
const cookies = (
|
|
2056
|
+
const localStorage = state2.localStorage || {};
|
|
2057
|
+
const sessionStorage = state2.sessionStorage || {};
|
|
2058
|
+
const cookies = (state2.cookies || []).map((cookie) => {
|
|
2054
2059
|
const normalized = { ...cookie };
|
|
2055
2060
|
if (!normalized.path) {
|
|
2056
2061
|
normalized.path = "/";
|
|
@@ -2088,8 +2093,8 @@ var RuntimeEnv = {
|
|
|
2088
2093
|
},
|
|
2089
2094
|
// captureEnvPatch 在任务结束时采集最新环境快照,用于 pushSuccess / pushFailed 自动回写。
|
|
2090
2095
|
async captureEnvPatch(page, source = {}, options = {}) {
|
|
2091
|
-
const
|
|
2092
|
-
const baseline = RuntimeEnv.buildEnvPatch(
|
|
2096
|
+
const state2 = normalizeRuntimeState(source, options?.actor || "");
|
|
2097
|
+
const baseline = RuntimeEnv.buildEnvPatch(state2) || {};
|
|
2093
2098
|
if (!page || typeof page.evaluate !== "function" || typeof page.context !== "function") {
|
|
2094
2099
|
return Object.keys(baseline).length > 0 ? baseline : null;
|
|
2095
2100
|
}
|
|
@@ -2108,7 +2113,7 @@ var RuntimeEnv = {
|
|
|
2108
2113
|
cookies
|
|
2109
2114
|
},
|
|
2110
2115
|
{
|
|
2111
|
-
browserProfileCore:
|
|
2116
|
+
browserProfileCore: state2.browserProfileCore
|
|
2112
2117
|
}
|
|
2113
2118
|
);
|
|
2114
2119
|
return RuntimeEnv.mergeEnvPatches(baseline, capturedPatch);
|
|
@@ -2122,11 +2127,11 @@ var RuntimeEnv = {
|
|
|
2122
2127
|
var logger3 = createInternalLogger("ApifyKit");
|
|
2123
2128
|
var resolveRuntimeContext = (input) => {
|
|
2124
2129
|
const rememberedState = RuntimeEnv.peekRememberedState();
|
|
2125
|
-
const
|
|
2126
|
-
const envPatch = RuntimeEnv.buildEnvPatch(
|
|
2130
|
+
const state2 = rememberedState || RuntimeEnv.parseInput(input || {});
|
|
2131
|
+
const envPatch = RuntimeEnv.buildEnvPatch(state2) || null;
|
|
2127
2132
|
return {
|
|
2128
|
-
actor:
|
|
2129
|
-
runtime:
|
|
2133
|
+
actor: state2.actor,
|
|
2134
|
+
runtime: state2.runtime,
|
|
2130
2135
|
envPatch
|
|
2131
2136
|
};
|
|
2132
2137
|
};
|
|
@@ -2485,8 +2490,82 @@ var Utils = {
|
|
|
2485
2490
|
}
|
|
2486
2491
|
};
|
|
2487
2492
|
|
|
2488
|
-
// src/
|
|
2489
|
-
var
|
|
2493
|
+
// src/internals/context.js
|
|
2494
|
+
var state = {
|
|
2495
|
+
mode: Mode.Default
|
|
2496
|
+
};
|
|
2497
|
+
var normalizeStrategies = (strategies) => strategies && typeof strategies === "object" ? strategies : {};
|
|
2498
|
+
var ToolkitContext = {
|
|
2499
|
+
get mode() {
|
|
2500
|
+
return state.mode;
|
|
2501
|
+
},
|
|
2502
|
+
setMode(mode2 = Mode.Default) {
|
|
2503
|
+
state.mode = normalizeMode(mode2, Mode.Default);
|
|
2504
|
+
return state.mode;
|
|
2505
|
+
}
|
|
2506
|
+
};
|
|
2507
|
+
var getToolkitMode = () => state.mode;
|
|
2508
|
+
var setToolkitMode = (mode2 = Mode.Default) => ToolkitContext.setMode(mode2);
|
|
2509
|
+
var resolveModeStrategy = (strategies = {}, mode2 = getToolkitMode(), fallbackMode = Mode.Default) => {
|
|
2510
|
+
const normalizedStrategies = normalizeStrategies(strategies);
|
|
2511
|
+
const normalizedMode = normalizeMode(mode2, fallbackMode);
|
|
2512
|
+
const strategy = normalizedStrategies[normalizedMode] ?? normalizedStrategies[fallbackMode] ?? Object.values(normalizedStrategies).find(Boolean) ?? null;
|
|
2513
|
+
return {
|
|
2514
|
+
mode: normalizedMode,
|
|
2515
|
+
strategy
|
|
2516
|
+
};
|
|
2517
|
+
};
|
|
2518
|
+
|
|
2519
|
+
// src/internals/reflect.js
|
|
2520
|
+
var normalizeStrategies2 = (strategies) => strategies && typeof strategies === "object" ? strategies : {};
|
|
2521
|
+
var collectFunctionNames = (strategies = []) => {
|
|
2522
|
+
const names = /* @__PURE__ */ new Set();
|
|
2523
|
+
for (const strategy of strategies) {
|
|
2524
|
+
if (!strategy || typeof strategy !== "object") continue;
|
|
2525
|
+
for (const name of Reflect.ownKeys(strategy)) {
|
|
2526
|
+
if (typeof name === "string" && typeof strategy[name] === "function") {
|
|
2527
|
+
names.add(name);
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
return names;
|
|
2532
|
+
};
|
|
2533
|
+
var methodDescriptor = (namespace, name, resolveTarget) => ({
|
|
2534
|
+
enumerable: true,
|
|
2535
|
+
configurable: true,
|
|
2536
|
+
writable: true,
|
|
2537
|
+
value: (...args) => {
|
|
2538
|
+
const { mode: mode2, strategy } = resolveTarget(args);
|
|
2539
|
+
const method = strategy?.[name];
|
|
2540
|
+
if (typeof method !== "function") {
|
|
2541
|
+
throw new Error(`${namespace}.${name} is not available in ${mode2} mode`);
|
|
2542
|
+
}
|
|
2543
|
+
return method.apply(strategy, args);
|
|
2544
|
+
}
|
|
2545
|
+
});
|
|
2546
|
+
var withModeReflect = (namespace, strategies = {}) => {
|
|
2547
|
+
const normalizedStrategies = normalizeStrategies2(strategies);
|
|
2548
|
+
const baseStrategy = normalizedStrategies.default ?? Object.values(normalizedStrategies).find(Boolean);
|
|
2549
|
+
const names = collectFunctionNames([baseStrategy]);
|
|
2550
|
+
const descriptors = {};
|
|
2551
|
+
for (const name of names) {
|
|
2552
|
+
descriptors[name] = methodDescriptor(namespace, name, () => resolveModeStrategy(normalizedStrategies));
|
|
2553
|
+
}
|
|
2554
|
+
return Object.defineProperties({}, descriptors);
|
|
2555
|
+
};
|
|
2556
|
+
var withPageReflect = (namespace, resolveStrategy, strategies = []) => {
|
|
2557
|
+
const names = collectFunctionNames(strategies);
|
|
2558
|
+
const descriptors = {};
|
|
2559
|
+
for (const name of names) {
|
|
2560
|
+
descriptors[name] = methodDescriptor(namespace, name, ([page]) => ({
|
|
2561
|
+
mode: "page",
|
|
2562
|
+
strategy: resolveStrategy(page)
|
|
2563
|
+
}));
|
|
2564
|
+
}
|
|
2565
|
+
return Object.defineProperties({}, descriptors);
|
|
2566
|
+
};
|
|
2567
|
+
|
|
2568
|
+
// src/internals/anti-cheat/default.js
|
|
2490
2569
|
var BASE_CONFIG = Object.freeze({
|
|
2491
2570
|
locale: "zh-CN",
|
|
2492
2571
|
acceptLanguage: "zh-CN,zh;q=0.9",
|
|
@@ -2521,7 +2600,7 @@ function buildFingerprintOptions({ locale = BASE_CONFIG.locale, browserMajorVers
|
|
|
2521
2600
|
}
|
|
2522
2601
|
return options;
|
|
2523
2602
|
}
|
|
2524
|
-
var
|
|
2603
|
+
var DefaultAntiCheat = {
|
|
2525
2604
|
/**
|
|
2526
2605
|
* 获取统一的基础配置
|
|
2527
2606
|
*/
|
|
@@ -2558,6 +2637,47 @@ var AntiCheat = {
|
|
|
2558
2637
|
}
|
|
2559
2638
|
};
|
|
2560
2639
|
|
|
2640
|
+
// src/internals/anti-cheat/cloak.js
|
|
2641
|
+
var CLOAK_BASE_CONFIG = Object.freeze({
|
|
2642
|
+
locale: "",
|
|
2643
|
+
acceptLanguage: "",
|
|
2644
|
+
timezoneId: "",
|
|
2645
|
+
timezoneOffset: null,
|
|
2646
|
+
geolocation: null
|
|
2647
|
+
});
|
|
2648
|
+
var normalizeHeaders = (headers) => headers && typeof headers === "object" ? headers : {};
|
|
2649
|
+
var CloakAntiCheat = {
|
|
2650
|
+
/**
|
|
2651
|
+
* Cloak 自身会负责浏览器指纹,toolkit 在该模式下尽量不再注入额外反检测配置。
|
|
2652
|
+
*/
|
|
2653
|
+
getBaseConfig() {
|
|
2654
|
+
return { ...CLOAK_BASE_CONFIG };
|
|
2655
|
+
},
|
|
2656
|
+
getFingerprintGeneratorOptions() {
|
|
2657
|
+
return {};
|
|
2658
|
+
},
|
|
2659
|
+
getLaunchArgs() {
|
|
2660
|
+
return [];
|
|
2661
|
+
},
|
|
2662
|
+
getTlsFingerprintOptions() {
|
|
2663
|
+
return {};
|
|
2664
|
+
},
|
|
2665
|
+
applyLocaleHeaders(headers, acceptLanguage = "") {
|
|
2666
|
+
const normalizedHeaders = normalizeHeaders(headers);
|
|
2667
|
+
if (acceptLanguage && !normalizedHeaders["accept-language"]) {
|
|
2668
|
+
normalizedHeaders["accept-language"] = acceptLanguage;
|
|
2669
|
+
}
|
|
2670
|
+
return normalizedHeaders;
|
|
2671
|
+
}
|
|
2672
|
+
};
|
|
2673
|
+
|
|
2674
|
+
// src/anti-cheat.js
|
|
2675
|
+
var antiCheatStrategies = {
|
|
2676
|
+
[Mode.Default]: DefaultAntiCheat,
|
|
2677
|
+
[Mode.Cloak]: CloakAntiCheat
|
|
2678
|
+
};
|
|
2679
|
+
var AntiCheat = withModeReflect("AntiCheat", antiCheatStrategies);
|
|
2680
|
+
|
|
2561
2681
|
// src/device-input.js
|
|
2562
2682
|
var resolveDeviceFromPage = (page) => normalizeDevice(page?.[PageRuntimeStateKey]?.device);
|
|
2563
2683
|
var assertPage = (page, method) => {
|
|
@@ -2957,12 +3077,12 @@ var resolveDescriptor = (descriptor, device) => {
|
|
|
2957
3077
|
}
|
|
2958
3078
|
return resolved;
|
|
2959
3079
|
};
|
|
2960
|
-
var attachRuntimeState = (page,
|
|
3080
|
+
var attachRuntimeState = (page, state2) => {
|
|
2961
3081
|
Object.defineProperty(page, PageRuntimeStateKey, {
|
|
2962
3082
|
configurable: true,
|
|
2963
3083
|
enumerable: false,
|
|
2964
3084
|
writable: true,
|
|
2965
|
-
value:
|
|
3085
|
+
value: state2
|
|
2966
3086
|
});
|
|
2967
3087
|
};
|
|
2968
3088
|
var restoreRuntimeState = (page, snapshot) => {
|
|
@@ -3108,10 +3228,13 @@ var DeviceView = {
|
|
|
3108
3228
|
}
|
|
3109
3229
|
};
|
|
3110
3230
|
|
|
3231
|
+
// src/internals/humanize/index.js
|
|
3232
|
+
import delay4 from "delay";
|
|
3233
|
+
|
|
3111
3234
|
// src/internals/humanize/desktop.js
|
|
3112
3235
|
import delay2 from "delay";
|
|
3113
3236
|
import { createCursor } from "ghost-cursor-playwright";
|
|
3114
|
-
var
|
|
3237
|
+
var logger5 = createInternalLogger("Humanize");
|
|
3115
3238
|
var $CursorWeakMap = /* @__PURE__ */ new WeakMap();
|
|
3116
3239
|
function $GetCursor(page) {
|
|
3117
3240
|
const cursor = $CursorWeakMap.get(page);
|
|
@@ -3139,13 +3262,13 @@ var Humanize = {
|
|
|
3139
3262
|
*/
|
|
3140
3263
|
async initializeCursor(page) {
|
|
3141
3264
|
if ($CursorWeakMap.has(page)) {
|
|
3142
|
-
|
|
3265
|
+
logger5.debug("initializeCursor: cursor already exists, skipping");
|
|
3143
3266
|
return;
|
|
3144
3267
|
}
|
|
3145
|
-
|
|
3268
|
+
logger5.start("initializeCursor", "creating cursor");
|
|
3146
3269
|
const cursor = await createCursor(page);
|
|
3147
3270
|
$CursorWeakMap.set(page, cursor);
|
|
3148
|
-
|
|
3271
|
+
logger5.success("initializeCursor", "cursor initialized");
|
|
3149
3272
|
},
|
|
3150
3273
|
/**
|
|
3151
3274
|
* 人类化鼠标移动 - 使用 ghost-cursor 移动到指定位置或元素
|
|
@@ -3155,17 +3278,17 @@ var Humanize = {
|
|
|
3155
3278
|
*/
|
|
3156
3279
|
async humanMove(page, target) {
|
|
3157
3280
|
const cursor = $GetCursor(page);
|
|
3158
|
-
|
|
3281
|
+
logger5.start("humanMove", `target=${typeof target === "string" ? target : "element/coords"}`);
|
|
3159
3282
|
try {
|
|
3160
3283
|
if (typeof target === "string") {
|
|
3161
3284
|
const element = await page.$(target);
|
|
3162
3285
|
if (!element) {
|
|
3163
|
-
|
|
3286
|
+
logger5.warn(`humanMove: \u5143\u7D20\u4E0D\u5B58\u5728 ${target}`);
|
|
3164
3287
|
return false;
|
|
3165
3288
|
}
|
|
3166
3289
|
const box = await element.boundingBox();
|
|
3167
3290
|
if (!box) {
|
|
3168
|
-
|
|
3291
|
+
logger5.warn(`humanMove: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E ${target}`);
|
|
3169
3292
|
return false;
|
|
3170
3293
|
}
|
|
3171
3294
|
const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.2;
|
|
@@ -3181,10 +3304,10 @@ var Humanize = {
|
|
|
3181
3304
|
await cursor.actions.move({ x, y });
|
|
3182
3305
|
}
|
|
3183
3306
|
}
|
|
3184
|
-
|
|
3307
|
+
logger5.success("humanMove");
|
|
3185
3308
|
return true;
|
|
3186
3309
|
} catch (error) {
|
|
3187
|
-
|
|
3310
|
+
logger5.fail("humanMove", error);
|
|
3188
3311
|
throw error;
|
|
3189
3312
|
}
|
|
3190
3313
|
},
|
|
@@ -3208,12 +3331,12 @@ var Humanize = {
|
|
|
3208
3331
|
maxDurationMs = maxSteps * 220 + 800
|
|
3209
3332
|
} = options;
|
|
3210
3333
|
const targetDesc = typeof target === "string" ? target : "ElementHandle";
|
|
3211
|
-
|
|
3334
|
+
logger5.start("humanScroll", `target=${targetDesc}`);
|
|
3212
3335
|
let element;
|
|
3213
3336
|
if (typeof target === "string") {
|
|
3214
3337
|
element = await page.$(target);
|
|
3215
3338
|
if (!element) {
|
|
3216
|
-
|
|
3339
|
+
logger5.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${target}`);
|
|
3217
3340
|
return { element: null, didScroll: false };
|
|
3218
3341
|
}
|
|
3219
3342
|
} else {
|
|
@@ -3288,26 +3411,26 @@ var Humanize = {
|
|
|
3288
3411
|
try {
|
|
3289
3412
|
for (let i = 0; i < maxSteps; i++) {
|
|
3290
3413
|
if (Date.now() - startTime > maxDurationMs) {
|
|
3291
|
-
|
|
3414
|
+
logger5.warn(`humanScroll | \u8D85\u65F6\u4FDD\u62A4\u89E6\u53D1 (${maxDurationMs}ms)`);
|
|
3292
3415
|
return { element, didScroll };
|
|
3293
3416
|
}
|
|
3294
3417
|
const status = await checkVisibility();
|
|
3295
3418
|
if (status.code === "VISIBLE") {
|
|
3296
3419
|
if (status.isFixed) {
|
|
3297
|
-
|
|
3420
|
+
logger5.info("humanScroll | fixed \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
|
|
3298
3421
|
} else {
|
|
3299
|
-
|
|
3422
|
+
logger5.debug("humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321");
|
|
3300
3423
|
}
|
|
3301
|
-
|
|
3424
|
+
logger5.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
|
|
3302
3425
|
return { element, didScroll };
|
|
3303
3426
|
}
|
|
3304
|
-
|
|
3427
|
+
logger5.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason} ${status.direction ? `(${status.direction})` : ""}`);
|
|
3305
3428
|
if (status.code === "OBSTRUCTED" && status.obstruction) {
|
|
3306
|
-
|
|
3429
|
+
logger5.debug(`humanScroll | \u88AB\u4EE5\u4E0B\u5143\u7D20\u906E\u6321 <${status.obstruction.tag} id="${status.obstruction.id}">`);
|
|
3307
3430
|
}
|
|
3308
3431
|
const scrollRect = await getScrollableRect2();
|
|
3309
3432
|
if (!scrollRect && status.isFixed) {
|
|
3310
|
-
|
|
3433
|
+
logger5.warn("humanScroll | fixed \u5BB9\u5668\u5185\u4E14\u65E0\u53EF\u6EDA\u52A8\u7956\u5148\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
|
|
3311
3434
|
return { element, didScroll };
|
|
3312
3435
|
}
|
|
3313
3436
|
const stepMin = scrollRect ? Math.min(minStep, Math.max(60, scrollRect.height * 0.4)) : minStep;
|
|
@@ -3343,10 +3466,10 @@ var Humanize = {
|
|
|
3343
3466
|
didScroll = true;
|
|
3344
3467
|
await delay2(this.jitterMs(20 + Math.random() * 40, 0.2));
|
|
3345
3468
|
}
|
|
3346
|
-
|
|
3469
|
+
logger5.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);
|
|
3347
3470
|
return { element, didScroll };
|
|
3348
3471
|
} catch (error) {
|
|
3349
|
-
|
|
3472
|
+
logger5.fail("humanScroll", error);
|
|
3350
3473
|
throw error;
|
|
3351
3474
|
}
|
|
3352
3475
|
},
|
|
@@ -3364,7 +3487,7 @@ var Humanize = {
|
|
|
3364
3487
|
const cursor = $GetCursor(page);
|
|
3365
3488
|
const { reactionDelay = 250, throwOnMissing = true, scrollIfNeeded = true, restore = false } = options;
|
|
3366
3489
|
const targetDesc = target == null ? "Current Position" : typeof target === "string" ? target : "ElementHandle";
|
|
3367
|
-
|
|
3490
|
+
logger5.start("humanClick", `target=${targetDesc}`);
|
|
3368
3491
|
const restoreOnce = async () => {
|
|
3369
3492
|
if (restoreOnce.restored) return;
|
|
3370
3493
|
restoreOnce.restored = true;
|
|
@@ -3373,14 +3496,14 @@ var Humanize = {
|
|
|
3373
3496
|
await delay2(this.jitterMs(1e3));
|
|
3374
3497
|
await restoreOnce.do();
|
|
3375
3498
|
} catch (restoreError) {
|
|
3376
|
-
|
|
3499
|
+
logger5.warn(`humanClick: \u6062\u590D\u6EDA\u52A8\u4F4D\u7F6E\u5931\u8D25: ${restoreError.message}`);
|
|
3377
3500
|
}
|
|
3378
3501
|
};
|
|
3379
3502
|
try {
|
|
3380
3503
|
if (target == null) {
|
|
3381
3504
|
await delay2(this.jitterMs(reactionDelay, 0.4));
|
|
3382
3505
|
await cursor.actions.click();
|
|
3383
|
-
|
|
3506
|
+
logger5.success("humanClick", "Clicked current position");
|
|
3384
3507
|
return true;
|
|
3385
3508
|
}
|
|
3386
3509
|
let element;
|
|
@@ -3390,7 +3513,7 @@ var Humanize = {
|
|
|
3390
3513
|
if (throwOnMissing) {
|
|
3391
3514
|
throw new Error(`\u627E\u4E0D\u5230\u5143\u7D20 ${target}`);
|
|
3392
3515
|
}
|
|
3393
|
-
|
|
3516
|
+
logger5.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${target}`);
|
|
3394
3517
|
return false;
|
|
3395
3518
|
}
|
|
3396
3519
|
} else {
|
|
@@ -3406,7 +3529,7 @@ var Humanize = {
|
|
|
3406
3529
|
if (throwOnMissing) {
|
|
3407
3530
|
throw new Error("\u65E0\u6CD5\u83B7\u53D6\u5143\u7D20\u4F4D\u7F6E");
|
|
3408
3531
|
}
|
|
3409
|
-
|
|
3532
|
+
logger5.warn("humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB");
|
|
3410
3533
|
return false;
|
|
3411
3534
|
}
|
|
3412
3535
|
const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.3;
|
|
@@ -3415,11 +3538,11 @@ var Humanize = {
|
|
|
3415
3538
|
await delay2(this.jitterMs(reactionDelay, 0.4));
|
|
3416
3539
|
await cursor.actions.click();
|
|
3417
3540
|
await restoreOnce();
|
|
3418
|
-
|
|
3541
|
+
logger5.success("humanClick");
|
|
3419
3542
|
return true;
|
|
3420
3543
|
} catch (error) {
|
|
3421
3544
|
await restoreOnce();
|
|
3422
|
-
|
|
3545
|
+
logger5.fail("humanClick", error);
|
|
3423
3546
|
throw error;
|
|
3424
3547
|
}
|
|
3425
3548
|
},
|
|
@@ -3430,9 +3553,9 @@ var Humanize = {
|
|
|
3430
3553
|
*/
|
|
3431
3554
|
async randomSleep(baseMs, jitterPercent = 0.3) {
|
|
3432
3555
|
const ms = this.jitterMs(baseMs, jitterPercent);
|
|
3433
|
-
|
|
3556
|
+
logger5.start("randomSleep", `base=${baseMs}, actual=${ms}ms`);
|
|
3434
3557
|
await delay2(ms);
|
|
3435
|
-
|
|
3558
|
+
logger5.success("randomSleep");
|
|
3436
3559
|
},
|
|
3437
3560
|
/**
|
|
3438
3561
|
* 模拟人类"注视"或"阅读"行为:鼠标在页面上随机微动
|
|
@@ -3442,7 +3565,7 @@ var Humanize = {
|
|
|
3442
3565
|
async simulateGaze(page, baseDurationMs = 2500) {
|
|
3443
3566
|
const cursor = $GetCursor(page);
|
|
3444
3567
|
const durationMs = this.jitterMs(baseDurationMs, 0.4);
|
|
3445
|
-
|
|
3568
|
+
logger5.start("simulateGaze", `duration=${durationMs}ms`);
|
|
3446
3569
|
const startTime = Date.now();
|
|
3447
3570
|
const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };
|
|
3448
3571
|
while (Date.now() - startTime < durationMs) {
|
|
@@ -3451,7 +3574,7 @@ var Humanize = {
|
|
|
3451
3574
|
await cursor.actions.move({ x, y });
|
|
3452
3575
|
await delay2(this.jitterMs(600, 0.5));
|
|
3453
3576
|
}
|
|
3454
|
-
|
|
3577
|
+
logger5.success("simulateGaze");
|
|
3455
3578
|
},
|
|
3456
3579
|
/**
|
|
3457
3580
|
* 人类化输入 - 带节奏变化(快-慢-停顿-偶尔加速)
|
|
@@ -3464,7 +3587,7 @@ var Humanize = {
|
|
|
3464
3587
|
* @param {number} [options.pauseBase=800] - 停顿时长基础值 (ms),实际 ±50% 抖动
|
|
3465
3588
|
*/
|
|
3466
3589
|
async humanType(page, selector, text, options = {}) {
|
|
3467
|
-
|
|
3590
|
+
logger5.start("humanType", `selector=${selector}, textLen=${text.length}`);
|
|
3468
3591
|
const {
|
|
3469
3592
|
baseDelay = 180,
|
|
3470
3593
|
pauseProbability = 0.08,
|
|
@@ -3488,13 +3611,13 @@ var Humanize = {
|
|
|
3488
3611
|
await delay2(charDelay);
|
|
3489
3612
|
if (Math.random() < pauseProbability && i < text.length - 1) {
|
|
3490
3613
|
const pauseTime = this.jitterMs(pauseBase, 0.5);
|
|
3491
|
-
|
|
3614
|
+
logger5.debug(`\u505C\u987F ${pauseTime}ms...`);
|
|
3492
3615
|
await delay2(pauseTime);
|
|
3493
3616
|
}
|
|
3494
3617
|
}
|
|
3495
|
-
|
|
3618
|
+
logger5.success("humanType");
|
|
3496
3619
|
} catch (error) {
|
|
3497
|
-
|
|
3620
|
+
logger5.fail("humanType", error);
|
|
3498
3621
|
throw error;
|
|
3499
3622
|
}
|
|
3500
3623
|
},
|
|
@@ -3518,7 +3641,7 @@ var Humanize = {
|
|
|
3518
3641
|
keyboardOptions = {}
|
|
3519
3642
|
} = pressOptions || {};
|
|
3520
3643
|
const targetDesc = hasTarget ? typeof targetOrKey === "string" ? targetOrKey : "ElementHandle" : "current focus";
|
|
3521
|
-
|
|
3644
|
+
logger5.start("humanPress", `key=${key}, target=${targetDesc}`);
|
|
3522
3645
|
try {
|
|
3523
3646
|
if (hasTarget) {
|
|
3524
3647
|
await this.humanClick(page, targetOrKey, { reactionDelay: focusDelay, scrollIfNeeded, throwOnMissing });
|
|
@@ -3528,10 +3651,10 @@ var Humanize = {
|
|
|
3528
3651
|
...keyboardOptions,
|
|
3529
3652
|
delay: this.jitterMs(holdDelay, 0.5)
|
|
3530
3653
|
});
|
|
3531
|
-
|
|
3654
|
+
logger5.success("humanPress");
|
|
3532
3655
|
return true;
|
|
3533
3656
|
} catch (error) {
|
|
3534
|
-
|
|
3657
|
+
logger5.fail("humanPress", error);
|
|
3535
3658
|
throw error;
|
|
3536
3659
|
}
|
|
3537
3660
|
},
|
|
@@ -3541,22 +3664,22 @@ var Humanize = {
|
|
|
3541
3664
|
* @param {string} selector - 输入框选择器
|
|
3542
3665
|
*/
|
|
3543
3666
|
async humanClear(page, selector) {
|
|
3544
|
-
|
|
3667
|
+
logger5.start("humanClear", `selector=${selector}`);
|
|
3545
3668
|
try {
|
|
3546
3669
|
const locator = page.locator(selector);
|
|
3547
3670
|
await locator.click();
|
|
3548
3671
|
await delay2(this.jitterMs(200, 0.4));
|
|
3549
3672
|
const currentValue = await locator.inputValue();
|
|
3550
3673
|
if (!currentValue || currentValue.length === 0) {
|
|
3551
|
-
|
|
3674
|
+
logger5.success("humanClear", "already empty");
|
|
3552
3675
|
return;
|
|
3553
3676
|
}
|
|
3554
3677
|
await page.keyboard.press("Meta+A");
|
|
3555
3678
|
await delay2(this.jitterMs(100, 0.4));
|
|
3556
3679
|
await page.keyboard.press("Backspace");
|
|
3557
|
-
|
|
3680
|
+
logger5.success("humanClear");
|
|
3558
3681
|
} catch (error) {
|
|
3559
|
-
|
|
3682
|
+
logger5.fail("humanClear", error);
|
|
3560
3683
|
throw error;
|
|
3561
3684
|
}
|
|
3562
3685
|
},
|
|
@@ -3568,7 +3691,7 @@ var Humanize = {
|
|
|
3568
3691
|
async warmUpBrowsing(page, baseDuration = 3500) {
|
|
3569
3692
|
const cursor = $GetCursor(page);
|
|
3570
3693
|
const durationMs = this.jitterMs(baseDuration, 0.4);
|
|
3571
|
-
|
|
3694
|
+
logger5.start("warmUpBrowsing", `duration=${durationMs}ms`);
|
|
3572
3695
|
const startTime = Date.now();
|
|
3573
3696
|
const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };
|
|
3574
3697
|
try {
|
|
@@ -3587,9 +3710,9 @@ var Humanize = {
|
|
|
3587
3710
|
await delay2(this.jitterMs(800, 0.5));
|
|
3588
3711
|
}
|
|
3589
3712
|
}
|
|
3590
|
-
|
|
3713
|
+
logger5.success("warmUpBrowsing");
|
|
3591
3714
|
} catch (error) {
|
|
3592
|
-
|
|
3715
|
+
logger5.fail("warmUpBrowsing", error);
|
|
3593
3716
|
throw error;
|
|
3594
3717
|
}
|
|
3595
3718
|
},
|
|
@@ -3603,7 +3726,7 @@ var Humanize = {
|
|
|
3603
3726
|
async naturalScroll(page, direction = "down", distance = 300, baseSteps = 5) {
|
|
3604
3727
|
const steps = Math.max(3, baseSteps + Math.floor(Math.random() * 3) - 1);
|
|
3605
3728
|
const actualDistance = this.jitterMs(distance, 0.15);
|
|
3606
|
-
|
|
3729
|
+
logger5.start("naturalScroll", `dir=${direction}, dist=${actualDistance}, steps=${steps}`);
|
|
3607
3730
|
const sign = direction === "down" ? 1 : -1;
|
|
3608
3731
|
const stepDistance = actualDistance / steps;
|
|
3609
3732
|
try {
|
|
@@ -3615,9 +3738,9 @@ var Humanize = {
|
|
|
3615
3738
|
const baseDelay = 60 + i * 25;
|
|
3616
3739
|
await delay2(this.jitterMs(baseDelay, 0.3));
|
|
3617
3740
|
}
|
|
3618
|
-
|
|
3741
|
+
logger5.success("naturalScroll");
|
|
3619
3742
|
} catch (error) {
|
|
3620
|
-
|
|
3743
|
+
logger5.fail("naturalScroll", error);
|
|
3621
3744
|
throw error;
|
|
3622
3745
|
}
|
|
3623
3746
|
}
|
|
@@ -3646,7 +3769,7 @@ var resolveElement = async (page, target, { throwOnMissing = true } = {}) => {
|
|
|
3646
3769
|
var waitJitter = (base, jitterPercent = 0.3) => delay3(jitterMs(base, jitterPercent));
|
|
3647
3770
|
|
|
3648
3771
|
// src/internals/humanize/mobile.js
|
|
3649
|
-
var
|
|
3772
|
+
var logger6 = createInternalLogger("Humanize.Mobile");
|
|
3650
3773
|
var initializedPages = /* @__PURE__ */ new WeakSet();
|
|
3651
3774
|
var DEFAULT_TAP_TIMEOUT_MS = 2500;
|
|
3652
3775
|
var DEFAULT_MOUSE_TAP_FALLBACK_TIMEOUT_MS = 1200;
|
|
@@ -4016,7 +4139,7 @@ var restoreWindowFromSnapshot = async (page, before, after) => {
|
|
|
4016
4139
|
return;
|
|
4017
4140
|
}
|
|
4018
4141
|
await page.evaluate(
|
|
4019
|
-
(
|
|
4142
|
+
(state2) => window.scrollTo(state2.x, state2.y),
|
|
4020
4143
|
{ x: Number(before.scrollX || 0), y: Number(before.scrollY || 0) }
|
|
4021
4144
|
).catch(() => {
|
|
4022
4145
|
});
|
|
@@ -4103,7 +4226,7 @@ var dispatchTouchSwipe = async (page, deltaY, options = {}) => {
|
|
|
4103
4226
|
}
|
|
4104
4227
|
return true;
|
|
4105
4228
|
} catch (error) {
|
|
4106
|
-
|
|
4229
|
+
logger6.debug(`touch swipe fallback: ${error?.message || error}`);
|
|
4107
4230
|
try {
|
|
4108
4231
|
await page.evaluate((amount) => window.scrollBy(0, amount), deltaY);
|
|
4109
4232
|
await waitJitter(120, 0.35);
|
|
@@ -4137,7 +4260,7 @@ var tapPoint = async (page, point, options = {}) => {
|
|
|
4137
4260
|
);
|
|
4138
4261
|
return { method: "touchscreen" };
|
|
4139
4262
|
} catch (error) {
|
|
4140
|
-
|
|
4263
|
+
logger6.warn(`tapPoint | touchscreen.tap \u5931\u8D25\u6216\u8D85\u65F6\uFF0C\u5C1D\u8BD5\u9F20\u6807\u515C\u5E95: ${error?.message || error}`);
|
|
4141
4264
|
if (!allowMouseFallback) throw error;
|
|
4142
4265
|
}
|
|
4143
4266
|
}
|
|
@@ -4153,10 +4276,10 @@ var MobileHumanize = {
|
|
|
4153
4276
|
async initializeCursor(page) {
|
|
4154
4277
|
if (initializedPages.has(page)) return;
|
|
4155
4278
|
initializedPages.add(page);
|
|
4156
|
-
|
|
4279
|
+
logger6.debug("initializeCursor: mobile mode uses touch gestures, cursor init skipped");
|
|
4157
4280
|
},
|
|
4158
4281
|
async humanMove(page, target) {
|
|
4159
|
-
|
|
4282
|
+
logger6.debug(`humanMove: mobile no-op target=${typeof target === "string" ? target : "element/coords"}`);
|
|
4160
4283
|
if (typeof target === "string" || target && typeof target.boundingBox === "function") {
|
|
4161
4284
|
const element = await resolveElement(page, target, { throwOnMissing: false });
|
|
4162
4285
|
if (!element) {
|
|
@@ -4175,10 +4298,10 @@ var MobileHumanize = {
|
|
|
4175
4298
|
throwOnMissing = false
|
|
4176
4299
|
} = options;
|
|
4177
4300
|
const targetDesc = describeTarget(target);
|
|
4178
|
-
|
|
4301
|
+
logger6.start("humanScroll", `target=${targetDesc}`);
|
|
4179
4302
|
const element = await resolveElement(page, target, { throwOnMissing });
|
|
4180
4303
|
if (!element) {
|
|
4181
|
-
|
|
4304
|
+
logger6.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${targetDesc}`);
|
|
4182
4305
|
return { element: null, didScroll: false, restore: null };
|
|
4183
4306
|
}
|
|
4184
4307
|
const startTime = Date.now();
|
|
@@ -4187,42 +4310,42 @@ var MobileHumanize = {
|
|
|
4187
4310
|
const status = await checkElementVisibility(element);
|
|
4188
4311
|
if (status.code === "VISIBLE") {
|
|
4189
4312
|
if (status.isFixed) {
|
|
4190
|
-
|
|
4313
|
+
logger6.info("humanScroll | fixed/sticky \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
|
|
4191
4314
|
} else {
|
|
4192
|
-
|
|
4315
|
+
logger6.debug("humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321");
|
|
4193
4316
|
}
|
|
4194
|
-
|
|
4317
|
+
logger6.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
|
|
4195
4318
|
return { element, didScroll, restore: null };
|
|
4196
4319
|
}
|
|
4197
4320
|
if (status.code === "ZERO_DIMENSIONS" || status.code === "NOT_INTERACTABLE") {
|
|
4198
|
-
|
|
4321
|
+
logger6.warn(`humanScroll | \u5143\u7D20\u4E0D\u53EF\u6EDA\u52A8\u81F3\u53EF\u70B9\u51FB\u72B6\u6001: ${status.reason || status.code}`);
|
|
4199
4322
|
return { element, didScroll, restore: null };
|
|
4200
4323
|
}
|
|
4201
4324
|
const scrollRect = await getScrollableRect(element);
|
|
4202
4325
|
if (!scrollRect && status.isFixed && status.code === "OUT_OF_VIEWPORT") {
|
|
4203
|
-
|
|
4326
|
+
logger6.warn(`humanScroll | fixed/sticky \u76EE\u6807\u4E0D\u5728\u89C6\u53E3\u5185\uFF0C\u9875\u9762\u6EDA\u52A8\u65E0\u6CD5\u6539\u53D8\u5176\u4F4D\u7F6E (direction=${status.direction || "unknown"})`);
|
|
4204
4327
|
return { element, didScroll, restore: null, unscrollable: true };
|
|
4205
4328
|
}
|
|
4206
4329
|
if (!scrollRect && status.isFixed && status.code === "OBSTRUCTED") {
|
|
4207
|
-
|
|
4330
|
+
logger6.warn(`humanScroll | fixed/sticky \u76EE\u6807\u88AB\u906E\u6321\uFF0C\u6EDA\u52A8\u65E0\u6CD5\u89E3\u9664 (${status.obstruction?.tag || "unknown"})`);
|
|
4208
4331
|
return { element, didScroll, restore: null, unscrollable: true };
|
|
4209
4332
|
}
|
|
4210
4333
|
if (scrollRect && status.code === "OBSTRUCTED" && status.obstruction?.isFixed) {
|
|
4211
4334
|
const moved = await scrollAwayFromObstruction(element, status);
|
|
4212
4335
|
if (moved.moved) {
|
|
4213
|
-
|
|
4336
|
+
logger6.debug(`humanScroll | sticky/fixed \u906E\u6321\u8865\u507F\u6EDA\u52A8 top=${Math.round(moved.scrollTop || 0)}`);
|
|
4214
4337
|
await waitJitter(90, 0.3);
|
|
4215
4338
|
didScroll = true;
|
|
4216
4339
|
continue;
|
|
4217
4340
|
}
|
|
4218
4341
|
}
|
|
4219
4342
|
if (Date.now() - startTime > maxDurationMs) {
|
|
4220
|
-
|
|
4343
|
+
logger6.warn(`humanScroll | mobile timeout (${maxDurationMs}ms, status=${status.code}, direction=${status.direction || "unknown"}, fixed=${Boolean(status.isFixed)})`);
|
|
4221
4344
|
return { element, didScroll, restore: null };
|
|
4222
4345
|
}
|
|
4223
4346
|
const stepMin = scrollRect ? Math.min(minStep, Math.max(60, scrollRect.height * 0.4)) : minStep;
|
|
4224
4347
|
const stepMax = scrollRect ? Math.min(maxStep, Math.max(stepMin + 40, scrollRect.height * 0.8)) : maxStep;
|
|
4225
|
-
|
|
4348
|
+
logger6.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason || status.code} ${status.direction ? `(${status.direction})` : ""}`);
|
|
4226
4349
|
const distance = stepMin + Math.random() * Math.max(1, stepMax - stepMin);
|
|
4227
4350
|
let deltaY = status.direction === "up" ? -distance : distance;
|
|
4228
4351
|
if (status.code === "OBSTRUCTED") {
|
|
@@ -4262,8 +4385,8 @@ var MobileHumanize = {
|
|
|
4262
4385
|
if (scrollRect && beforeWindowState) {
|
|
4263
4386
|
const afterWindowState = await page.evaluate(() => ({ x: window.scrollX, y: window.scrollY }));
|
|
4264
4387
|
if (Math.abs(afterWindowState.x - beforeWindowState.x) > 2 || Math.abs(afterWindowState.y - beforeWindowState.y) > 2) {
|
|
4265
|
-
await page.evaluate((
|
|
4266
|
-
|
|
4388
|
+
await page.evaluate((state2) => window.scrollTo(state2.x, state2.y), beforeWindowState);
|
|
4389
|
+
logger6.debug(`humanScroll | \u7A97\u53E3\u6EDA\u52A8\u56DE\u6536 from=${Math.round(afterWindowState.y)} to=${Math.round(beforeWindowState.y)}`);
|
|
4267
4390
|
}
|
|
4268
4391
|
}
|
|
4269
4392
|
let afterElementSnapshot = null;
|
|
@@ -4277,7 +4400,7 @@ var MobileHumanize = {
|
|
|
4277
4400
|
const afterSnapshot = await readAfterElementSnapshot();
|
|
4278
4401
|
if (isTargetImmobileAfterScroll(beforeElementSnapshot, afterSnapshot)) {
|
|
4279
4402
|
await restoreWindowFromSnapshot(page, beforeElementSnapshot, afterSnapshot);
|
|
4280
|
-
|
|
4403
|
+
logger6.warn(`humanScroll | \u76EE\u6807\u4E0D\u968F\u9875\u9762\u6EDA\u52A8\u79FB\u52A8\uFF0C\u9875\u9762\u6EDA\u52A8\u65E0\u6CD5\u6539\u53D8\u5176\u4F4D\u7F6E (status=${status.code}, direction=${status.direction || "unknown"})`);
|
|
4281
4404
|
return { element, didScroll, restore: null, unscrollable: true };
|
|
4282
4405
|
}
|
|
4283
4406
|
}
|
|
@@ -4309,12 +4432,12 @@ var MobileHumanize = {
|
|
|
4309
4432
|
const moved = beforeState.kind !== afterState.kind || Math.abs(topDelta) > 2 || Math.abs(leftDelta) > 2;
|
|
4310
4433
|
if (!moved) {
|
|
4311
4434
|
const fallback = await scrollScrollableAncestor(element, deltaY);
|
|
4312
|
-
|
|
4435
|
+
logger6.debug(`humanScroll | \u5BB9\u5668\u89E6\u6478\u65E0\u6548\uFF0C\u76F4\u63A5\u6EDA\u52A8 fallback=${fallback.scroller ? "ancestor" : "window"} top=${Math.round(fallback.scrollTop || 0)}`);
|
|
4313
4436
|
} else if (beforeState.kind === afterState.kind && Math.abs(expectedDelta) > 24 && Math.sign(topDelta || expectedDelta) === Math.sign(expectedDelta) && Math.abs(topDelta) < Math.min(Math.abs(expectedDelta) * 0.45, 96)) {
|
|
4314
4437
|
const residualDelta = expectedDelta - topDelta;
|
|
4315
4438
|
if (Math.sign(residualDelta) === Math.sign(expectedDelta) && Math.abs(residualDelta) > 24) {
|
|
4316
4439
|
const fallback = await scrollScrollableAncestor(element, residualDelta);
|
|
4317
|
-
|
|
4440
|
+
logger6.debug(`humanScroll | \u5BB9\u5668\u89E6\u6478\u8DDD\u79BB\u4E0D\u8DB3\uFF0C\u8865\u507F\u6EDA\u52A8 fallback=${fallback.scroller ? "ancestor" : "window"} top=${Math.round(fallback.scrollTop || 0)}`);
|
|
4318
4441
|
}
|
|
4319
4442
|
}
|
|
4320
4443
|
}
|
|
@@ -4322,7 +4445,7 @@ var MobileHumanize = {
|
|
|
4322
4445
|
const afterSnapshot = await getElementViewportSnapshot(element).catch(() => null);
|
|
4323
4446
|
if (isTargetImmobileAfterScroll(beforeElementSnapshot, afterSnapshot)) {
|
|
4324
4447
|
await restoreWindowFromSnapshot(page, beforeElementSnapshot, afterSnapshot);
|
|
4325
|
-
|
|
4448
|
+
logger6.warn(`humanScroll | \u76EE\u6807\u4E0D\u968F\u6EDA\u52A8\u5BB9\u5668\u79FB\u52A8\uFF0C\u6EDA\u52A8\u65E0\u6CD5\u6539\u53D8\u5176\u4F4D\u7F6E (status=${status.code}, direction=${status.direction || "unknown"})`);
|
|
4326
4449
|
return { element, didScroll, restore: null, unscrollable: true };
|
|
4327
4450
|
}
|
|
4328
4451
|
}
|
|
@@ -4333,14 +4456,14 @@ var MobileHumanize = {
|
|
|
4333
4456
|
await waitJitter(80, 0.3);
|
|
4334
4457
|
const finalStatus = await checkElementVisibility(element);
|
|
4335
4458
|
if (finalStatus.code === "VISIBLE") {
|
|
4336
|
-
|
|
4337
|
-
|
|
4459
|
+
logger6.info("humanScroll | \u539F\u751F scrollIntoViewIfNeeded \u515C\u5E95\u6210\u529F");
|
|
4460
|
+
logger6.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
|
|
4338
4461
|
return { element, didScroll: true, restore: null };
|
|
4339
4462
|
}
|
|
4340
4463
|
} catch (fallbackError) {
|
|
4341
|
-
|
|
4464
|
+
logger6.debug(`humanScroll | native fallback failed: ${fallbackError?.message || fallbackError}`);
|
|
4342
4465
|
}
|
|
4343
|
-
|
|
4466
|
+
logger6.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);
|
|
4344
4467
|
return { element, didScroll, restore: null };
|
|
4345
4468
|
},
|
|
4346
4469
|
async humanClick(page, target, options = {}) {
|
|
@@ -4355,7 +4478,7 @@ var MobileHumanize = {
|
|
|
4355
4478
|
fallbackDomClickOnTapError = true
|
|
4356
4479
|
} = options;
|
|
4357
4480
|
const targetDesc = describeTarget(target);
|
|
4358
|
-
|
|
4481
|
+
logger6.start("humanClick", `target=${targetDesc}`);
|
|
4359
4482
|
try {
|
|
4360
4483
|
if (target == null) {
|
|
4361
4484
|
const viewport = resolveViewport(page);
|
|
@@ -4367,12 +4490,12 @@ var MobileHumanize = {
|
|
|
4367
4490
|
timeoutMs: tapTimeoutMs,
|
|
4368
4491
|
mouseFallbackTimeoutMs
|
|
4369
4492
|
});
|
|
4370
|
-
|
|
4493
|
+
logger6.success("humanClick", "Tapped current position");
|
|
4371
4494
|
return true;
|
|
4372
4495
|
}
|
|
4373
4496
|
const element = await resolveElement(page, target, { throwOnMissing });
|
|
4374
4497
|
if (!element) {
|
|
4375
|
-
|
|
4498
|
+
logger6.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${targetDesc}`);
|
|
4376
4499
|
return false;
|
|
4377
4500
|
}
|
|
4378
4501
|
const scrollResult = scrollIfNeeded ? await MobileHumanize.humanScroll(page, element, { throwOnMissing }) : null;
|
|
@@ -4396,19 +4519,19 @@ var MobileHumanize = {
|
|
|
4396
4519
|
).catch(() => null);
|
|
4397
4520
|
}
|
|
4398
4521
|
if (fallback?.activated) {
|
|
4399
|
-
|
|
4522
|
+
logger6.warn(`humanClick: \u4E0D\u53EF\u6EDA\u52A8\u76EE\u6807\u4E0D\u53EF\u7269\u7406\u70B9\u51FB\uFF0C\u5DF2\u7528 ${fallback.method} \u6FC0\u6D3B`);
|
|
4400
4523
|
return true;
|
|
4401
4524
|
}
|
|
4402
4525
|
}
|
|
4403
4526
|
const message = `\u5143\u7D20\u4E0D\u53EF\u70B9\u51FB: ${status.reason || status.code}`;
|
|
4404
4527
|
if (throwOnMissing) throw new Error(message);
|
|
4405
|
-
|
|
4528
|
+
logger6.warn(`humanClick: ${message}\uFF0C\u8DF3\u8FC7\u70B9\u51FB`);
|
|
4406
4529
|
return false;
|
|
4407
4530
|
}
|
|
4408
4531
|
const box = await element.boundingBox();
|
|
4409
4532
|
if (!box) {
|
|
4410
4533
|
if (throwOnMissing) throw new Error("\u65E0\u6CD5\u83B7\u53D6\u5143\u7D20\u4F4D\u7F6E");
|
|
4411
|
-
|
|
4534
|
+
logger6.warn("humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB");
|
|
4412
4535
|
return false;
|
|
4413
4536
|
}
|
|
4414
4537
|
await waitJitter(reactionDelay, 0.45);
|
|
@@ -4429,13 +4552,13 @@ var MobileHumanize = {
|
|
|
4429
4552
|
"activation fallback"
|
|
4430
4553
|
).catch(() => null);
|
|
4431
4554
|
if (!fallback?.activated) throw tapError;
|
|
4432
|
-
|
|
4555
|
+
logger6.warn(`humanClick: tap \u5931\u8D25\u540E\u5DF2\u7528 ${fallback.method} \u515C\u5E95: ${tapError?.message || tapError}`);
|
|
4433
4556
|
}
|
|
4434
4557
|
await waitJitter(120, 0.35);
|
|
4435
|
-
|
|
4558
|
+
logger6.success("humanClick");
|
|
4436
4559
|
return true;
|
|
4437
4560
|
} catch (error) {
|
|
4438
|
-
|
|
4561
|
+
logger6.fail("humanClick", error);
|
|
4439
4562
|
throw error;
|
|
4440
4563
|
}
|
|
4441
4564
|
},
|
|
@@ -4488,7 +4611,7 @@ var MobileHumanize = {
|
|
|
4488
4611
|
keyboardOptions = {}
|
|
4489
4612
|
} = pressOptions || {};
|
|
4490
4613
|
const targetDesc = hasTarget ? describeTarget(targetOrKey) : "current focus";
|
|
4491
|
-
|
|
4614
|
+
logger6.start("humanPress", `key=${key}, target=${targetDesc}`);
|
|
4492
4615
|
try {
|
|
4493
4616
|
if (hasTarget) {
|
|
4494
4617
|
await MobileHumanize.humanClick(page, targetOrKey, {
|
|
@@ -4502,10 +4625,10 @@ var MobileHumanize = {
|
|
|
4502
4625
|
...keyboardOptions,
|
|
4503
4626
|
delay: jitterMs(holdDelay, 0.5)
|
|
4504
4627
|
});
|
|
4505
|
-
|
|
4628
|
+
logger6.success("humanPress");
|
|
4506
4629
|
return true;
|
|
4507
4630
|
} catch (error) {
|
|
4508
|
-
|
|
4631
|
+
logger6.fail("humanPress", error);
|
|
4509
4632
|
throw error;
|
|
4510
4633
|
}
|
|
4511
4634
|
},
|
|
@@ -4572,65 +4695,96 @@ var MobileHumanize = {
|
|
|
4572
4695
|
}
|
|
4573
4696
|
};
|
|
4574
4697
|
|
|
4575
|
-
// src/humanize.js
|
|
4698
|
+
// src/internals/humanize/default.js
|
|
4576
4699
|
var resolveDeviceFromPage2 = (page) => normalizeDevice(page?.[PageRuntimeStateKey]?.device);
|
|
4577
4700
|
var resolveDelegate = (page) => {
|
|
4578
4701
|
return resolveDeviceFromPage2(page) === Device.Mobile ? MobileHumanize : Humanize;
|
|
4579
4702
|
};
|
|
4580
|
-
var
|
|
4581
|
-
|
|
4582
|
-
|
|
4703
|
+
var DefaultHumanizeDevice = withPageReflect(
|
|
4704
|
+
"DefaultHumanize",
|
|
4705
|
+
resolveDelegate,
|
|
4706
|
+
[Humanize, MobileHumanize]
|
|
4707
|
+
);
|
|
4708
|
+
|
|
4709
|
+
// src/internals/humanize/cloak.js
|
|
4710
|
+
var FORCE_CLICK = Object.freeze({
|
|
4711
|
+
forceClick: true,
|
|
4712
|
+
clickOptions: { force: true }
|
|
4713
|
+
});
|
|
4714
|
+
var pointOrNull = async (target) => {
|
|
4715
|
+
if (!target || typeof target.boundingBox !== "function") return null;
|
|
4716
|
+
const box = await target.boundingBox().catch(() => null);
|
|
4717
|
+
return box ? { x: box.x + box.width / 2, y: box.y + box.height / 2 } : null;
|
|
4583
4718
|
};
|
|
4584
|
-
var
|
|
4585
|
-
|
|
4586
|
-
return
|
|
4587
|
-
},
|
|
4588
|
-
initializeCursor(page) {
|
|
4589
|
-
return callDelegate("initializeCursor", page, []);
|
|
4719
|
+
var CloakHumanizeInput = {
|
|
4720
|
+
async initializeCursor(page) {
|
|
4721
|
+
return Boolean(page);
|
|
4590
4722
|
},
|
|
4591
|
-
humanMove(page, target) {
|
|
4592
|
-
|
|
4723
|
+
async humanMove(page, target) {
|
|
4724
|
+
const point = target?.x != null && target?.y != null ? target : await pointOrNull(typeof target === "string" ? page.locator(target).first() : target);
|
|
4725
|
+
return point ? await DeviceInput.move(page, point, { forceMouse: true }) : false;
|
|
4593
4726
|
},
|
|
4594
|
-
humanScroll(page, target
|
|
4595
|
-
|
|
4727
|
+
async humanScroll(page, target) {
|
|
4728
|
+
const element = typeof target === "string" ? page.locator(target).first() : target;
|
|
4729
|
+
if (!element) return { element: null, didScroll: false, restore: null };
|
|
4730
|
+
await element.scrollIntoViewIfNeeded?.();
|
|
4731
|
+
return { element, didScroll: true, restore: null };
|
|
4596
4732
|
},
|
|
4597
|
-
humanClick(page, target
|
|
4598
|
-
return
|
|
4733
|
+
async humanClick(page, target) {
|
|
4734
|
+
return await DeviceInput.click(page, target, FORCE_CLICK);
|
|
4599
4735
|
},
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
return delegate.randomSleep(maybeBaseMs, maybeJitterPercent);
|
|
4604
|
-
}
|
|
4605
|
-
return Humanize.randomSleep(pageOrBaseMs, maybeBaseMs);
|
|
4736
|
+
async humanType(page, selector, text) {
|
|
4737
|
+
await DeviceInput.click(page, selector, FORCE_CLICK);
|
|
4738
|
+
return await DeviceInput.keyboardType(page, text);
|
|
4606
4739
|
},
|
|
4607
|
-
|
|
4608
|
-
return
|
|
4740
|
+
async humanPress(page, targetOrKey, maybeKey) {
|
|
4741
|
+
return await DeviceInput.press(page, targetOrKey, maybeKey, {
|
|
4742
|
+
clickOptions: FORCE_CLICK,
|
|
4743
|
+
keyboardOptions: {}
|
|
4744
|
+
});
|
|
4609
4745
|
},
|
|
4610
|
-
|
|
4611
|
-
return
|
|
4746
|
+
async humanClear(page, selector) {
|
|
4747
|
+
return await DeviceInput.fill(page, selector, "", { force: true });
|
|
4612
4748
|
},
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
return callDelegate("humanPress", page, [targetOrKey, maybeKey, options]);
|
|
4616
|
-
}
|
|
4617
|
-
return callDelegate("humanPress", page, [targetOrKey, maybeKey || options]);
|
|
4749
|
+
async simulateGaze(page) {
|
|
4750
|
+
return await DeviceInput.move(page, { x: 0, y: 0 }, { forceMouse: true });
|
|
4618
4751
|
},
|
|
4619
|
-
|
|
4620
|
-
return
|
|
4752
|
+
async warmUpBrowsing(page) {
|
|
4753
|
+
return await this.simulateGaze(page);
|
|
4621
4754
|
},
|
|
4622
|
-
|
|
4623
|
-
|
|
4755
|
+
async naturalScroll(page, direction = "down", distance = 300) {
|
|
4756
|
+
const sign = direction === "down" ? 1 : -1;
|
|
4757
|
+
await page.mouse.wheel(0, Number(distance || 0) * sign);
|
|
4758
|
+
}
|
|
4759
|
+
};
|
|
4760
|
+
|
|
4761
|
+
// src/internals/humanize/index.js
|
|
4762
|
+
var HumanizeCommon = {
|
|
4763
|
+
jitterMs(base, jitterPercent = 0.3) {
|
|
4764
|
+
return jitterMs(base, jitterPercent);
|
|
4624
4765
|
},
|
|
4625
|
-
|
|
4626
|
-
|
|
4766
|
+
async randomSleep(pageOrBaseMs, maybeBaseMs, maybeJitterPercent) {
|
|
4767
|
+
const hasPage = pageOrBaseMs && typeof pageOrBaseMs === "object" && typeof pageOrBaseMs.evaluate === "function";
|
|
4768
|
+
const baseMs = hasPage ? maybeBaseMs : pageOrBaseMs;
|
|
4769
|
+
const jitterPercent = hasPage ? maybeJitterPercent : maybeBaseMs;
|
|
4770
|
+
await delay4(jitterMs(baseMs, jitterPercent ?? 0.3));
|
|
4627
4771
|
}
|
|
4628
4772
|
};
|
|
4773
|
+
var DefaultHumanize = Object.assign({}, DefaultHumanizeDevice, HumanizeCommon);
|
|
4774
|
+
var CloakHumanize = Object.assign({}, CloakHumanizeInput, HumanizeCommon);
|
|
4629
4775
|
|
|
4630
|
-
// src/
|
|
4776
|
+
// src/humanize.js
|
|
4777
|
+
var humanizeStrategies = {
|
|
4778
|
+
[Mode.Default]: DefaultHumanize,
|
|
4779
|
+
[Mode.Cloak]: CloakHumanize
|
|
4780
|
+
};
|
|
4781
|
+
var Humanize2 = withModeReflect("Humanize", humanizeStrategies);
|
|
4782
|
+
|
|
4783
|
+
// src/internals/launch/default.js
|
|
4631
4784
|
import { execFileSync } from "node:child_process";
|
|
4632
4785
|
import { FingerprintGenerator } from "fingerprint-generator";
|
|
4633
4786
|
import { FingerprintInjector } from "fingerprint-injector";
|
|
4787
|
+
import { chromium as defaultChromiumLauncher } from "playwright";
|
|
4634
4788
|
|
|
4635
4789
|
// src/proxy-bypass.js
|
|
4636
4790
|
import picomatch from "picomatch";
|
|
@@ -4712,9 +4866,107 @@ var ByPass = {
|
|
|
4712
4866
|
resolveRouteByProxy
|
|
4713
4867
|
};
|
|
4714
4868
|
|
|
4715
|
-
// src/launch.js
|
|
4869
|
+
// src/internals/launch/traffic.js
|
|
4870
|
+
var logger7 = createInternalLogger("Launch");
|
|
4871
|
+
var normalizeObject = (value) => {
|
|
4872
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
4873
|
+
return {};
|
|
4874
|
+
}
|
|
4875
|
+
return value;
|
|
4876
|
+
};
|
|
4877
|
+
var parseProxyConfiguration = (proxyConfiguration = {}) => {
|
|
4878
|
+
const config = normalizeObject(proxyConfiguration);
|
|
4879
|
+
const proxyUrl = String(config.proxy_url || "").trim();
|
|
4880
|
+
const enableProxy = typeof config.enable_proxy === "boolean" ? config.enable_proxy : proxyUrl !== "";
|
|
4881
|
+
const byPassDomains = enableProxy && proxyUrl ? ByPass.normalizeByPassDomains(config.by_pass_domains) : [];
|
|
4882
|
+
return {
|
|
4883
|
+
byPassDomains,
|
|
4884
|
+
enableProxy,
|
|
4885
|
+
proxyUrl
|
|
4886
|
+
};
|
|
4887
|
+
};
|
|
4888
|
+
var resolveLaunchTraffic = ({
|
|
4889
|
+
proxyConfiguration = {},
|
|
4890
|
+
debugMode = false,
|
|
4891
|
+
useMeter = true
|
|
4892
|
+
} = {}) => {
|
|
4893
|
+
const { byPassDomains, enableProxy, proxyUrl } = parseProxyConfiguration(proxyConfiguration);
|
|
4894
|
+
const byPassRules = ByPass.buildByPassDomainRules(byPassDomains);
|
|
4895
|
+
const proxyMeter = useMeter && enableProxy && proxyUrl ? ProxyMeterRuntime.startProxyMeter({ proxyUrl, debugMode }) : null;
|
|
4896
|
+
const launchProxy = proxyMeter ? { server: proxyMeter.server } : null;
|
|
4897
|
+
if (launchProxy && byPassDomains.length > 0) {
|
|
4898
|
+
launchProxy.bypass = byPassDomains.join(",");
|
|
4899
|
+
}
|
|
4900
|
+
return {
|
|
4901
|
+
byPassDomains,
|
|
4902
|
+
byPassRules,
|
|
4903
|
+
enableProxy,
|
|
4904
|
+
proxyUrl,
|
|
4905
|
+
launchProxy
|
|
4906
|
+
};
|
|
4907
|
+
};
|
|
4908
|
+
var logLaunchTraffic = ({
|
|
4909
|
+
byPassDomains = [],
|
|
4910
|
+
debugMode = false,
|
|
4911
|
+
enabled = false,
|
|
4912
|
+
enableProxy = false,
|
|
4913
|
+
explicitProxy = false,
|
|
4914
|
+
launchProxy = null,
|
|
4915
|
+
proxyUrl = ""
|
|
4916
|
+
} = {}) => {
|
|
4917
|
+
if (!enabled) return;
|
|
4918
|
+
if (explicitProxy) {
|
|
4919
|
+
logger7.info("[\u4EE3\u7406\u5DF2\u542F\u7528] \u4F7F\u7528\u663E\u5F0F proxy \u914D\u7F6E\uFF0C\u8DF3\u8FC7 toolkit \u672C\u5730\u6D41\u91CF\u89C2\u6D4B");
|
|
4920
|
+
return;
|
|
4921
|
+
}
|
|
4922
|
+
if (launchProxy) {
|
|
4923
|
+
let upstreamLabel = "";
|
|
4924
|
+
try {
|
|
4925
|
+
const parsedProxyUrl = new URL(proxyUrl.includes("://") ? proxyUrl : `http://${proxyUrl}`);
|
|
4926
|
+
upstreamLabel = `${parsedProxyUrl.protocol}//${parsedProxyUrl.host}`;
|
|
4927
|
+
} catch {
|
|
4928
|
+
}
|
|
4929
|
+
logger7.info(
|
|
4930
|
+
`[\u4EE3\u7406\u5DF2\u542F\u7528] \u672C\u5730=${launchProxy.server} \u4E0A\u6E38=${upstreamLabel || "-"} \u76F4\u8FDE\u57DF\u540D=${byPassDomains.join(",")}`
|
|
4931
|
+
);
|
|
4932
|
+
logger7.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? "\u5F00\u542F" : "\u5173\u95ED"}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);
|
|
4933
|
+
return;
|
|
4934
|
+
}
|
|
4935
|
+
if (enableProxy) {
|
|
4936
|
+
logger7.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=true \u4F46 proxy_url \u4E3A\u7A7A");
|
|
4937
|
+
} else if (proxyUrl) {
|
|
4938
|
+
logger7.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=false \u4E14 proxy_url \u5DF2\u914D\u7F6E");
|
|
4939
|
+
}
|
|
4940
|
+
logger7.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? "\u5F00\u542F" : "\u5173\u95ED"}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);
|
|
4941
|
+
};
|
|
4942
|
+
var createLaunchTrafficHook = ({
|
|
4943
|
+
byPassDomains = [],
|
|
4944
|
+
byPassRules = [],
|
|
4945
|
+
enabled = false,
|
|
4946
|
+
launchProxy = null
|
|
4947
|
+
} = {}) => {
|
|
4948
|
+
const patchedPages = /* @__PURE__ */ new WeakSet();
|
|
4949
|
+
return (page) => {
|
|
4950
|
+
if (!page || typeof page.on !== "function" || patchedPages.has(page)) {
|
|
4951
|
+
return;
|
|
4952
|
+
}
|
|
4953
|
+
patchedPages.add(page);
|
|
4954
|
+
page.on("request", (req) => {
|
|
4955
|
+
const requestUrl = req.url();
|
|
4956
|
+
const resourceType = req.resourceType();
|
|
4957
|
+
const matched = byPassDomains.length > 0 ? ByPass.findMatchedByPassRule(byPassRules, requestUrl) : null;
|
|
4958
|
+
if (launchProxy) {
|
|
4959
|
+
ProxyMeterRuntime.recordProxyMeterResourceType(requestUrl, resourceType);
|
|
4960
|
+
}
|
|
4961
|
+
if (!enabled || byPassDomains.length === 0) return;
|
|
4962
|
+
if (!matched || !matched.rule) return;
|
|
4963
|
+
logger7.info(`[\u76F4\u8FDE\u547D\u4E2D] \u89C4\u5219=${matched.rule.pattern} \u57DF\u540D=${matched.hostname} \u8D44\u6E90\u7C7B\u578B=${resourceType} \u65B9\u6CD5=${req.method()} \u5730\u5740=${requestUrl}`);
|
|
4964
|
+
});
|
|
4965
|
+
};
|
|
4966
|
+
};
|
|
4967
|
+
|
|
4968
|
+
// src/internals/launch/default.js
|
|
4716
4969
|
var logger8 = createInternalLogger("Launch");
|
|
4717
|
-
var REQUEST_HOOK_FLAG = Symbol("playwright-toolkit-request-hook");
|
|
4718
4970
|
var injectedContexts = /* @__PURE__ */ new WeakSet();
|
|
4719
4971
|
var browserMajorVersionCache = /* @__PURE__ */ new Map();
|
|
4720
4972
|
var DEFAULT_BROWSER_PROFILE_SCHEMA_VERSION = 1;
|
|
@@ -4726,16 +4978,6 @@ var DEFAULT_CRAWLER_BASE_OPTIONS = Object.freeze({
|
|
|
4726
4978
|
navigationTimeoutSecs: 120
|
|
4727
4979
|
});
|
|
4728
4980
|
var fingerprintInjector = new FingerprintInjector();
|
|
4729
|
-
var resolveProxyLaunchOptions = (proxyConfiguration = {}) => {
|
|
4730
|
-
const config = proxyConfiguration && typeof proxyConfiguration === "object" && !Array.isArray(proxyConfiguration) ? proxyConfiguration : {};
|
|
4731
|
-
const proxyUrl = String(config.proxy_url || "").trim();
|
|
4732
|
-
const enableProxy = typeof config.enable_proxy === "boolean" ? config.enable_proxy : proxyUrl !== "";
|
|
4733
|
-
if (!enableProxy || !proxyUrl) {
|
|
4734
|
-
return { byPassDomains: [], enableProxy, proxyUrl };
|
|
4735
|
-
}
|
|
4736
|
-
const byPassDomains = ByPass.normalizeByPassDomains(config.by_pass_domains);
|
|
4737
|
-
return { byPassDomains, enableProxy, proxyUrl };
|
|
4738
|
-
};
|
|
4739
4981
|
var parseChromeMajorVersion = (rawValue = "") => {
|
|
4740
4982
|
const match = String(rawValue || "").match(/(?:Chrome|Chromium)(?:\/|\s+(?:for Testing\s+)?)(\d+)/i);
|
|
4741
4983
|
return match ? Number(match[1] || 0) : 0;
|
|
@@ -4779,7 +5021,7 @@ var resolveCoreDevice = (core = {}) => {
|
|
|
4779
5021
|
};
|
|
4780
5022
|
var buildFingerprintGenerator = ({ locale, browserMajorVersion, device }) => {
|
|
4781
5023
|
return new FingerprintGenerator(
|
|
4782
|
-
|
|
5024
|
+
DefaultAntiCheat.getFingerprintGeneratorOptions({
|
|
4783
5025
|
locale,
|
|
4784
5026
|
browserMajorVersion,
|
|
4785
5027
|
device
|
|
@@ -4823,7 +5065,7 @@ var buildReplayableBrowserProfile = (runtimeState, launcher) => {
|
|
|
4823
5065
|
}
|
|
4824
5066
|
let nextState = RuntimeEnv.rememberState(runtimeState);
|
|
4825
5067
|
let browserProfileCore = RuntimeEnv.getBrowserProfileCore(nextState);
|
|
4826
|
-
const timezoneId = String(browserProfileCore?.timezone_id || "").trim() ||
|
|
5068
|
+
const timezoneId = String(browserProfileCore?.timezone_id || "").trim() || DefaultAntiCheat.getBaseConfig().timezoneId;
|
|
4827
5069
|
const locale = DEFAULT_LOCALE;
|
|
4828
5070
|
const currentBrowserMajorVersion = detectBrowserMajorVersion(launcher);
|
|
4829
5071
|
const storedBrowserMajorVersion = Number(browserProfileCore?.browser_major_version || 0);
|
|
@@ -4902,7 +5144,7 @@ var applyFingerprintPageOptions = (pageOptions = {}, { fingerprintWithHeaders =
|
|
|
4902
5144
|
pageOptions.timezoneId = timezoneId;
|
|
4903
5145
|
}
|
|
4904
5146
|
};
|
|
4905
|
-
var buildReplayBrowserPoolOptions = (browserProfileCore
|
|
5147
|
+
var buildReplayBrowserPoolOptions = (browserProfileCore) => {
|
|
4906
5148
|
const fingerprintWithHeaders = browserProfileCore?.fingerprint;
|
|
4907
5149
|
const fingerprint = fingerprintWithHeaders?.fingerprint;
|
|
4908
5150
|
if (!fingerprintWithHeaders || !fingerprint) {
|
|
@@ -4911,16 +5153,13 @@ var buildReplayBrowserPoolOptions = (browserProfileCore, modifyPageOptions = nul
|
|
|
4911
5153
|
return {
|
|
4912
5154
|
useFingerprints: false,
|
|
4913
5155
|
prePageCreateHooks: [
|
|
4914
|
-
|
|
5156
|
+
(_pageId, _browserController, pageOptions = {}) => {
|
|
4915
5157
|
if (!pageOptions || typeof pageOptions !== "object") return;
|
|
4916
5158
|
applyFingerprintPageOptions(pageOptions, {
|
|
4917
5159
|
fingerprintWithHeaders,
|
|
4918
5160
|
locale: browserProfileCore.locale,
|
|
4919
5161
|
timezoneId: browserProfileCore.timezone_id
|
|
4920
5162
|
});
|
|
4921
|
-
if (modifyPageOptions) {
|
|
4922
|
-
await modifyPageOptions(pageOptions, { pageId, browserController });
|
|
4923
|
-
}
|
|
4924
5163
|
}
|
|
4925
5164
|
],
|
|
4926
5165
|
postPageCreateHooks: [
|
|
@@ -4935,7 +5174,7 @@ var buildReplayBrowserPoolOptions = (browserProfileCore, modifyPageOptions = nul
|
|
|
4935
5174
|
]
|
|
4936
5175
|
};
|
|
4937
5176
|
};
|
|
4938
|
-
var
|
|
5177
|
+
var DefaultLaunch = {
|
|
4939
5178
|
getPlaywrightCrawlerOptions(options = {}) {
|
|
4940
5179
|
const normalizedOptions = Array.isArray(options) ? { customArgs: options } : options || {};
|
|
4941
5180
|
const {
|
|
@@ -4946,54 +5185,36 @@ var Launch = {
|
|
|
4946
5185
|
debugMode = false,
|
|
4947
5186
|
isRunningOnApify = false,
|
|
4948
5187
|
launcher = null,
|
|
4949
|
-
hooks = {},
|
|
4950
5188
|
preNavigationHooks = [],
|
|
4951
5189
|
postNavigationHooks = [],
|
|
4952
5190
|
runtimeState = null
|
|
4953
5191
|
} = normalizedOptions;
|
|
4954
5192
|
const device = resolveRuntimeDevice(runtimeState);
|
|
4955
|
-
const
|
|
4956
|
-
const
|
|
4957
|
-
const
|
|
4958
|
-
const
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
const
|
|
4964
|
-
const replayBrowserPoolOptions = buildReplayBrowserPoolOptions(replayContext.browserProfileCore, modifyPageOptions);
|
|
5193
|
+
const effectiveLauncher = launcher || defaultChromiumLauncher;
|
|
5194
|
+
const enableByPassLogger = Boolean(logOptions && logOptions.enable);
|
|
5195
|
+
const traffic = resolveLaunchTraffic({ proxyConfiguration, debugMode });
|
|
5196
|
+
const trafficHook = createLaunchTrafficHook({
|
|
5197
|
+
...traffic,
|
|
5198
|
+
enabled: enableByPassLogger
|
|
5199
|
+
});
|
|
5200
|
+
const replayContext = buildReplayableBrowserProfile(runtimeState, effectiveLauncher);
|
|
5201
|
+
const replayBrowserPoolOptions = buildReplayBrowserPoolOptions(replayContext.browserProfileCore);
|
|
4965
5202
|
const launchLocale = String(replayContext.browserProfileCore?.locale || DEFAULT_LOCALE).trim() || DEFAULT_LOCALE;
|
|
4966
5203
|
const launchOptions = {
|
|
4967
5204
|
args: [
|
|
4968
|
-
...
|
|
5205
|
+
...DefaultAntiCheat.getLaunchArgs({ locale: launchLocale }),
|
|
4969
5206
|
...customArgs
|
|
4970
5207
|
],
|
|
4971
5208
|
ignoreDefaultArgs: ["--enable-automation"]
|
|
4972
5209
|
};
|
|
4973
|
-
if (launchProxy) {
|
|
4974
|
-
launchOptions.proxy = launchProxy;
|
|
4975
|
-
}
|
|
4976
|
-
const enableByPassLogger = Boolean(logOptions && logOptions.enable);
|
|
4977
|
-
if (enableByPassLogger && launchProxy) {
|
|
4978
|
-
let upstreamLabel = "";
|
|
4979
|
-
try {
|
|
4980
|
-
const parsedProxyUrl = new URL(proxyUrl.includes("://") ? proxyUrl : `http://${proxyUrl}`);
|
|
4981
|
-
upstreamLabel = `${parsedProxyUrl.protocol}//${parsedProxyUrl.host}`;
|
|
4982
|
-
} catch {
|
|
4983
|
-
}
|
|
4984
|
-
logger8.info(
|
|
4985
|
-
`[\u4EE3\u7406\u5DF2\u542F\u7528] \u672C\u5730=${launchProxy.server} \u4E0A\u6E38=${upstreamLabel || "-"} \u76F4\u8FDE\u57DF\u540D=${(byPassDomains || []).join(",")}`
|
|
4986
|
-
);
|
|
4987
|
-
logger8.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? "\u5F00\u542F" : "\u5173\u95ED"}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);
|
|
4988
|
-
} else if (enableByPassLogger && enableProxy && !launchProxy) {
|
|
4989
|
-
logger8.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=true \u4F46 proxy_url \u4E3A\u7A7A");
|
|
4990
|
-
logger8.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? "\u5F00\u542F" : "\u5173\u95ED"}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);
|
|
4991
|
-
} else if (enableByPassLogger && !enableProxy && proxyUrl) {
|
|
4992
|
-
logger8.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=false \u4E14 proxy_url \u5DF2\u914D\u7F6E");
|
|
4993
|
-
logger8.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? "\u5F00\u542F" : "\u5173\u95ED"}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);
|
|
4994
|
-
} else if (enableByPassLogger) {
|
|
4995
|
-
logger8.info(`[\u6D41\u91CF\u89C2\u6D4B] \u9010\u8BF7\u6C42\u8C03\u8BD5=${Boolean(debugMode) ? "\u5F00\u542F" : "\u5173\u95ED"}\uFF08\u6C47\u603B\u59CB\u7EC8\u5F00\u542F\uFF09`);
|
|
5210
|
+
if (traffic.launchProxy) {
|
|
5211
|
+
launchOptions.proxy = traffic.launchProxy;
|
|
4996
5212
|
}
|
|
5213
|
+
logLaunchTraffic({
|
|
5214
|
+
...traffic,
|
|
5215
|
+
debugMode,
|
|
5216
|
+
enabled: enableByPassLogger
|
|
5217
|
+
});
|
|
4997
5218
|
const onPageCreated = (page) => {
|
|
4998
5219
|
const recommendedGotoOptions = {
|
|
4999
5220
|
waitUntil: "commit"
|
|
@@ -5001,31 +5222,14 @@ var Launch = {
|
|
|
5001
5222
|
if (!page || typeof page.on !== "function") {
|
|
5002
5223
|
return recommendedGotoOptions;
|
|
5003
5224
|
}
|
|
5004
|
-
|
|
5005
|
-
return recommendedGotoOptions;
|
|
5006
|
-
}
|
|
5007
|
-
page[REQUEST_HOOK_FLAG] = true;
|
|
5008
|
-
const requestHandler = (req) => {
|
|
5009
|
-
const requestUrl = req.url();
|
|
5010
|
-
const resourceType = req.resourceType();
|
|
5011
|
-
const matched = byPassDomains.length > 0 ? ByPass.findMatchedByPassRule(byPassRules, requestUrl) : null;
|
|
5012
|
-
if (launchProxy) {
|
|
5013
|
-
ProxyMeterRuntime.recordProxyMeterResourceType(requestUrl, resourceType);
|
|
5014
|
-
}
|
|
5015
|
-
if (!enableByPassLogger || byPassDomains.length === 0) return;
|
|
5016
|
-
if (!matched || !matched.rule) return;
|
|
5017
|
-
logger8.info(`[\u76F4\u8FDE\u547D\u4E2D] \u89C4\u5219=${matched.rule.pattern} \u57DF\u540D=${matched.hostname} \u8D44\u6E90\u7C7B\u578B=${resourceType} \u65B9\u6CD5=${req.method()} \u5730\u5740=${requestUrl}`);
|
|
5018
|
-
};
|
|
5019
|
-
page.on("request", requestHandler);
|
|
5225
|
+
trafficHook(page);
|
|
5020
5226
|
return recommendedGotoOptions;
|
|
5021
5227
|
};
|
|
5022
5228
|
const launchContext = {
|
|
5023
5229
|
useIncognitoPages: true,
|
|
5024
|
-
launchOptions
|
|
5230
|
+
launchOptions,
|
|
5231
|
+
launcher: effectiveLauncher
|
|
5025
5232
|
};
|
|
5026
|
-
if (launcher) {
|
|
5027
|
-
launchContext.launcher = launcher;
|
|
5028
|
-
}
|
|
5029
5233
|
const crawlerBaseOptions = {
|
|
5030
5234
|
...DEFAULT_CRAWLER_BASE_OPTIONS,
|
|
5031
5235
|
headless: !runInHeadfulMode || isRunningOnApify,
|
|
@@ -5033,23 +5237,20 @@ var Launch = {
|
|
|
5033
5237
|
browserPoolOptions: replayBrowserPoolOptions || {
|
|
5034
5238
|
useFingerprints: true,
|
|
5035
5239
|
fingerprintOptions: {
|
|
5036
|
-
fingerprintGeneratorOptions:
|
|
5240
|
+
fingerprintGeneratorOptions: DefaultAntiCheat.getFingerprintGeneratorOptions({
|
|
5037
5241
|
locale: launchLocale,
|
|
5038
5242
|
device
|
|
5039
5243
|
})
|
|
5040
5244
|
},
|
|
5041
5245
|
prePageCreateHooks: [
|
|
5042
|
-
|
|
5246
|
+
(_pageId, browserController, pageOptions = {}) => {
|
|
5043
5247
|
const fingerprintWithHeaders = browserController?.launchContext?.fingerprint;
|
|
5044
|
-
const timezoneId =
|
|
5248
|
+
const timezoneId = DefaultAntiCheat.getBaseConfig().timezoneId;
|
|
5045
5249
|
applyFingerprintPageOptions(pageOptions, {
|
|
5046
5250
|
fingerprintWithHeaders,
|
|
5047
5251
|
locale: launchLocale,
|
|
5048
5252
|
timezoneId
|
|
5049
5253
|
});
|
|
5050
|
-
if (modifyPageOptions) {
|
|
5051
|
-
await modifyPageOptions(pageOptions, { pageId, browserController });
|
|
5052
|
-
}
|
|
5053
5254
|
}
|
|
5054
5255
|
]
|
|
5055
5256
|
},
|
|
@@ -5071,10 +5272,303 @@ var Launch = {
|
|
|
5071
5272
|
}
|
|
5072
5273
|
};
|
|
5073
5274
|
|
|
5275
|
+
// src/internals/launch/cloak.js
|
|
5276
|
+
import { execFile } from "node:child_process";
|
|
5277
|
+
import { promisify } from "node:util";
|
|
5278
|
+
var logger9 = createInternalLogger("Launch");
|
|
5279
|
+
var execFileAsync = promisify(execFile);
|
|
5280
|
+
var DEFAULT_CLOAK_CRAWLER_BASE_OPTIONS = Object.freeze({
|
|
5281
|
+
maxConcurrency: 1,
|
|
5282
|
+
maxRequestRetries: 0,
|
|
5283
|
+
requestHandlerTimeoutSecs: 240,
|
|
5284
|
+
navigationTimeoutSecs: 120
|
|
5285
|
+
});
|
|
5286
|
+
var DEFAULT_CLOAK_HUMANIZE_OPTIONS = Object.freeze({
|
|
5287
|
+
humanize: true
|
|
5288
|
+
});
|
|
5289
|
+
var DEFAULT_CLOAK_GOTO_OPTIONS = Object.freeze({
|
|
5290
|
+
waitUntil: "commit"
|
|
5291
|
+
});
|
|
5292
|
+
var DEFAULT_CLOAK_FINGERPRINT_PLATFORM = "linux";
|
|
5293
|
+
var CLOAK_FINGERPRINT_PLATFORM_ARG_PREFIX = "--fingerprint-platform=";
|
|
5294
|
+
var SUPPORTED_CLOAK_FINGERPRINT_PLATFORMS = /* @__PURE__ */ new Set(["linux", "macos", "windows"]);
|
|
5295
|
+
var cachedCloakModulePromise = null;
|
|
5296
|
+
var hasOwn = (target, key) => Object.prototype.hasOwnProperty.call(target, key);
|
|
5297
|
+
var loadCloakModule = async () => {
|
|
5298
|
+
if (!cachedCloakModulePromise) {
|
|
5299
|
+
cachedCloakModulePromise = import("cloakbrowser").catch((error) => {
|
|
5300
|
+
cachedCloakModulePromise = null;
|
|
5301
|
+
throw new Error("Cloak \u6A21\u5757\u52A0\u8F7D\u5931\u8D25\uFF0C\u8BF7\u786E\u8BA4\u5F53\u524D\u8FD0\u884C\u73AF\u5883\u5DF2\u5B89\u88C5 cloakbrowser\u3002", {
|
|
5302
|
+
cause: error
|
|
5303
|
+
});
|
|
5304
|
+
});
|
|
5305
|
+
}
|
|
5306
|
+
return cachedCloakModulePromise;
|
|
5307
|
+
};
|
|
5308
|
+
var buildCloakLaunchOptions = async (options = {}) => {
|
|
5309
|
+
const { buildLaunchOptions } = await loadCloakModule();
|
|
5310
|
+
return await buildLaunchOptions(normalizeObject2(options));
|
|
5311
|
+
};
|
|
5312
|
+
var normalizeObject2 = (value) => {
|
|
5313
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
5314
|
+
return {};
|
|
5315
|
+
}
|
|
5316
|
+
return value;
|
|
5317
|
+
};
|
|
5318
|
+
var normalizeStringArray = (value) => {
|
|
5319
|
+
if (!Array.isArray(value)) {
|
|
5320
|
+
return [];
|
|
5321
|
+
}
|
|
5322
|
+
return value.map((item) => String(item || "").trim()).filter(Boolean);
|
|
5323
|
+
};
|
|
5324
|
+
var resolveCloakFingerprintPlatformArg = (fingerprintPlatform = "", args = []) => {
|
|
5325
|
+
const normalizedFingerprintPlatform = String(fingerprintPlatform || "").trim().toLowerCase();
|
|
5326
|
+
if (SUPPORTED_CLOAK_FINGERPRINT_PLATFORMS.has(normalizedFingerprintPlatform)) {
|
|
5327
|
+
return `${CLOAK_FINGERPRINT_PLATFORM_ARG_PREFIX}${normalizedFingerprintPlatform}`;
|
|
5328
|
+
}
|
|
5329
|
+
const existingArg = normalizeStringArray(args).find((value) => value.startsWith(CLOAK_FINGERPRINT_PLATFORM_ARG_PREFIX));
|
|
5330
|
+
if (existingArg) {
|
|
5331
|
+
return existingArg;
|
|
5332
|
+
}
|
|
5333
|
+
return `${CLOAK_FINGERPRINT_PLATFORM_ARG_PREFIX}${DEFAULT_CLOAK_FINGERPRINT_PLATFORM}`;
|
|
5334
|
+
};
|
|
5335
|
+
var resolveCloakProxy = (proxyConfiguration = {}) => {
|
|
5336
|
+
const config = normalizeObject2(proxyConfiguration);
|
|
5337
|
+
const proxyUrl = String(config.proxy_url || "").trim();
|
|
5338
|
+
const enableProxy = typeof config.enable_proxy === "boolean" ? config.enable_proxy : proxyUrl !== "";
|
|
5339
|
+
if (!enableProxy || !proxyUrl) {
|
|
5340
|
+
return null;
|
|
5341
|
+
}
|
|
5342
|
+
const byPassDomains = ByPass.normalizeByPassDomains(config.by_pass_domains);
|
|
5343
|
+
if (byPassDomains.length === 0) {
|
|
5344
|
+
return proxyUrl;
|
|
5345
|
+
}
|
|
5346
|
+
const parsedProxyUrl = new URL(proxyUrl.includes("://") ? proxyUrl : `http://${proxyUrl}`);
|
|
5347
|
+
return {
|
|
5348
|
+
server: `${parsedProxyUrl.protocol}//${parsedProxyUrl.host}`,
|
|
5349
|
+
username: decodeURIComponent(parsedProxyUrl.username || ""),
|
|
5350
|
+
password: decodeURIComponent(parsedProxyUrl.password || ""),
|
|
5351
|
+
bypass: byPassDomains.join(",")
|
|
5352
|
+
};
|
|
5353
|
+
};
|
|
5354
|
+
var extractFingerprintArg = (launchOptions = {}) => {
|
|
5355
|
+
const args = Array.isArray(launchOptions?.args) ? launchOptions.args : [];
|
|
5356
|
+
return args.find((value) => String(value || "").startsWith("--fingerprint=")) || "";
|
|
5357
|
+
};
|
|
5358
|
+
var createStableGotoHook = (recommendedGotoOptions = DEFAULT_CLOAK_GOTO_OPTIONS) => {
|
|
5359
|
+
const normalizedRecommendedGotoOptions = normalizeObject2(recommendedGotoOptions);
|
|
5360
|
+
const fallbackGotoOptions = Object.keys(normalizedRecommendedGotoOptions).length > 0 ? normalizedRecommendedGotoOptions : DEFAULT_CLOAK_GOTO_OPTIONS;
|
|
5361
|
+
return async (_crawlingContext, gotoOptions = {}) => {
|
|
5362
|
+
for (const [key, value] of Object.entries(fallbackGotoOptions)) {
|
|
5363
|
+
if (gotoOptions[key] == null) {
|
|
5364
|
+
gotoOptions[key] = value;
|
|
5365
|
+
}
|
|
5366
|
+
}
|
|
5367
|
+
};
|
|
5368
|
+
};
|
|
5369
|
+
var attachCloakHumanizeHook = ({
|
|
5370
|
+
browserPoolOptions = {},
|
|
5371
|
+
activeBrowsers,
|
|
5372
|
+
patchedBrowsers,
|
|
5373
|
+
humanizeOptions = DEFAULT_CLOAK_HUMANIZE_OPTIONS
|
|
5374
|
+
} = {}) => {
|
|
5375
|
+
const normalizedBrowserPoolOptions = normalizeObject2(browserPoolOptions);
|
|
5376
|
+
const shouldHumanize = humanizeOptions !== false;
|
|
5377
|
+
const normalizedHumanizeOptions = shouldHumanize ? {
|
|
5378
|
+
...DEFAULT_CLOAK_HUMANIZE_OPTIONS,
|
|
5379
|
+
...normalizeObject2(humanizeOptions)
|
|
5380
|
+
} : null;
|
|
5381
|
+
return {
|
|
5382
|
+
...normalizedBrowserPoolOptions,
|
|
5383
|
+
useFingerprints: false,
|
|
5384
|
+
postLaunchHooks: [
|
|
5385
|
+
...Array.isArray(normalizedBrowserPoolOptions.postLaunchHooks) ? normalizedBrowserPoolOptions.postLaunchHooks : [],
|
|
5386
|
+
async (_pageId, browserController) => {
|
|
5387
|
+
const browser = browserController?.browser;
|
|
5388
|
+
if (!browser || typeof browser.contexts !== "function") {
|
|
5389
|
+
return;
|
|
5390
|
+
}
|
|
5391
|
+
activeBrowsers.add(browser);
|
|
5392
|
+
if (typeof browser.once === "function") {
|
|
5393
|
+
browser.once("disconnected", () => {
|
|
5394
|
+
activeBrowsers.delete(browser);
|
|
5395
|
+
});
|
|
5396
|
+
}
|
|
5397
|
+
if (!shouldHumanize || patchedBrowsers.has(browser)) {
|
|
5398
|
+
return;
|
|
5399
|
+
}
|
|
5400
|
+
const { humanizeBrowser } = await loadCloakModule();
|
|
5401
|
+
await humanizeBrowser(browser, normalizedHumanizeOptions);
|
|
5402
|
+
patchedBrowsers.add(browser);
|
|
5403
|
+
}
|
|
5404
|
+
]
|
|
5405
|
+
};
|
|
5406
|
+
};
|
|
5407
|
+
var closeTrackedBrowsers = async (activeBrowsers) => {
|
|
5408
|
+
const browsers = Array.from(activeBrowsers || []);
|
|
5409
|
+
activeBrowsers?.clear?.();
|
|
5410
|
+
await Promise.allSettled(
|
|
5411
|
+
browsers.map(async (browser) => {
|
|
5412
|
+
if (!browser || typeof browser.isConnected !== "function" || !browser.isConnected()) {
|
|
5413
|
+
return;
|
|
5414
|
+
}
|
|
5415
|
+
await browser.close().catch(() => {
|
|
5416
|
+
});
|
|
5417
|
+
})
|
|
5418
|
+
);
|
|
5419
|
+
};
|
|
5420
|
+
var forceTerminateBrowsersByFingerprintArg = async (fingerprintArg) => {
|
|
5421
|
+
if (!fingerprintArg) {
|
|
5422
|
+
return;
|
|
5423
|
+
}
|
|
5424
|
+
await execFileAsync("pkill", ["-f", "--", fingerprintArg]).catch((error) => {
|
|
5425
|
+
if (error?.code === 1 || error?.code === "ENOENT") {
|
|
5426
|
+
return;
|
|
5427
|
+
}
|
|
5428
|
+
logger9.info(`\u5F3A\u5236\u5173\u95ED Cloak \u8FDB\u7A0B\u5931\u8D25\uFF08\u5FFD\u7565\uFF09: ${error?.message || String(error)}`);
|
|
5429
|
+
});
|
|
5430
|
+
};
|
|
5431
|
+
var CloakLaunch = {
|
|
5432
|
+
resolveProxyConfiguration(proxyConfiguration = {}) {
|
|
5433
|
+
return resolveCloakProxy(proxyConfiguration);
|
|
5434
|
+
},
|
|
5435
|
+
extractFingerprintArg(launchOptions = {}) {
|
|
5436
|
+
return extractFingerprintArg(launchOptions);
|
|
5437
|
+
},
|
|
5438
|
+
createStableGotoHook(recommendedGotoOptions = DEFAULT_CLOAK_GOTO_OPTIONS) {
|
|
5439
|
+
return createStableGotoHook(recommendedGotoOptions);
|
|
5440
|
+
},
|
|
5441
|
+
async getPlaywrightCrawlerOptions(options = {}) {
|
|
5442
|
+
const runtime2 = await CloakLaunch.createPlaywrightCrawlerRuntime(options);
|
|
5443
|
+
return Object.defineProperties(runtime2.crawlerOptions, {
|
|
5444
|
+
cleanup: {
|
|
5445
|
+
enumerable: false,
|
|
5446
|
+
value: runtime2.cleanup
|
|
5447
|
+
},
|
|
5448
|
+
closeActiveBrowsers: {
|
|
5449
|
+
enumerable: false,
|
|
5450
|
+
value: runtime2.closeActiveBrowsers
|
|
5451
|
+
},
|
|
5452
|
+
forceTerminateActiveProcesses: {
|
|
5453
|
+
enumerable: false,
|
|
5454
|
+
value: runtime2.forceTerminateActiveProcesses
|
|
5455
|
+
}
|
|
5456
|
+
});
|
|
5457
|
+
},
|
|
5458
|
+
async buildLaunchOptions(options = {}) {
|
|
5459
|
+
return await buildCloakLaunchOptions(options);
|
|
5460
|
+
},
|
|
5461
|
+
async createPlaywrightCrawlerRuntime(options = {}) {
|
|
5462
|
+
const normalizedOptions = normalizeObject2(options);
|
|
5463
|
+
const {
|
|
5464
|
+
proxyConfiguration = {},
|
|
5465
|
+
log: logOptions = null,
|
|
5466
|
+
debugMode = false,
|
|
5467
|
+
runInHeadfulMode = false,
|
|
5468
|
+
isRunningOnApify = false,
|
|
5469
|
+
launcher = null,
|
|
5470
|
+
fingerprintPlatform = "",
|
|
5471
|
+
cloakOptions = {},
|
|
5472
|
+
humanizeOptions = DEFAULT_CLOAK_HUMANIZE_OPTIONS,
|
|
5473
|
+
crawlerBaseOptions = {},
|
|
5474
|
+
browserPoolOptions = {},
|
|
5475
|
+
launchContext = {},
|
|
5476
|
+
preNavigationHooks = [],
|
|
5477
|
+
postNavigationHooks = [],
|
|
5478
|
+
recommendedGotoOptions = DEFAULT_CLOAK_GOTO_OPTIONS
|
|
5479
|
+
} = normalizedOptions;
|
|
5480
|
+
const normalizedCloakOptions = normalizeObject2(cloakOptions);
|
|
5481
|
+
const activeBrowsers = /* @__PURE__ */ new Set();
|
|
5482
|
+
const patchedBrowsers = /* @__PURE__ */ new WeakSet();
|
|
5483
|
+
const defaultArgs = isRunningOnApify ? ["--no-sandbox", "--disable-setuid-sandbox"] : [];
|
|
5484
|
+
const fingerprintPlatformArg = resolveCloakFingerprintPlatformArg(fingerprintPlatform, normalizedCloakOptions.args);
|
|
5485
|
+
const extraArgs = normalizeStringArray(normalizedCloakOptions.args).filter((value) => !value.startsWith(CLOAK_FINGERPRINT_PLATFORM_ARG_PREFIX));
|
|
5486
|
+
const hasExplicitProxy = hasOwn(normalizedCloakOptions, "proxy");
|
|
5487
|
+
const proxyLaunchState = hasExplicitProxy ? resolveLaunchTraffic({ proxyConfiguration, debugMode, useMeter: false }) : resolveLaunchTraffic({ proxyConfiguration, debugMode });
|
|
5488
|
+
const proxy = hasExplicitProxy ? normalizedCloakOptions.proxy : proxyLaunchState.launchProxy;
|
|
5489
|
+
const headless = hasOwn(normalizedCloakOptions, "headless") ? normalizedCloakOptions.headless : !runInHeadfulMode || isRunningOnApify;
|
|
5490
|
+
const enableByPassLogger = Boolean(logOptions && logOptions.enable);
|
|
5491
|
+
const mergedCloakOptions = {
|
|
5492
|
+
...normalizedCloakOptions,
|
|
5493
|
+
headless,
|
|
5494
|
+
proxy,
|
|
5495
|
+
args: [...defaultArgs, ...extraArgs, fingerprintPlatformArg]
|
|
5496
|
+
};
|
|
5497
|
+
const launchOptions = await buildCloakLaunchOptions(mergedCloakOptions);
|
|
5498
|
+
const fingerprintArg = extractFingerprintArg(launchOptions);
|
|
5499
|
+
const internalPreNavigationHook = createStableGotoHook(recommendedGotoOptions);
|
|
5500
|
+
const trafficHook = createLaunchTrafficHook({
|
|
5501
|
+
byPassDomains: proxyLaunchState.byPassDomains,
|
|
5502
|
+
byPassRules: proxyLaunchState.byPassRules,
|
|
5503
|
+
enabled: enableByPassLogger,
|
|
5504
|
+
launchProxy: proxyLaunchState.launchProxy
|
|
5505
|
+
});
|
|
5506
|
+
const normalizedPreNavigationHooks = Array.isArray(preNavigationHooks) ? preNavigationHooks : [];
|
|
5507
|
+
const normalizedPostNavigationHooks = Array.isArray(postNavigationHooks) ? postNavigationHooks : [];
|
|
5508
|
+
logLaunchTraffic({
|
|
5509
|
+
...proxyLaunchState,
|
|
5510
|
+
debugMode,
|
|
5511
|
+
enabled: enableByPassLogger,
|
|
5512
|
+
explicitProxy: hasExplicitProxy
|
|
5513
|
+
});
|
|
5514
|
+
const crawlerOptions = {
|
|
5515
|
+
...DEFAULT_CLOAK_CRAWLER_BASE_OPTIONS,
|
|
5516
|
+
...normalizeObject2(crawlerBaseOptions),
|
|
5517
|
+
headless,
|
|
5518
|
+
launchContext: {
|
|
5519
|
+
useIncognitoPages: true,
|
|
5520
|
+
...normalizeObject2(launchContext),
|
|
5521
|
+
...launcher ? { launcher } : {},
|
|
5522
|
+
launchOptions
|
|
5523
|
+
},
|
|
5524
|
+
browserPoolOptions: attachCloakHumanizeHook({
|
|
5525
|
+
browserPoolOptions,
|
|
5526
|
+
activeBrowsers,
|
|
5527
|
+
patchedBrowsers,
|
|
5528
|
+
humanizeOptions
|
|
5529
|
+
}),
|
|
5530
|
+
preNavigationHooks: [
|
|
5531
|
+
async (crawlingContext, gotoOptions = {}) => {
|
|
5532
|
+
trafficHook(crawlingContext?.page);
|
|
5533
|
+
await internalPreNavigationHook(crawlingContext, gotoOptions);
|
|
5534
|
+
},
|
|
5535
|
+
...normalizedPreNavigationHooks
|
|
5536
|
+
],
|
|
5537
|
+
...normalizedPostNavigationHooks.length > 0 ? { postNavigationHooks: normalizedPostNavigationHooks } : {}
|
|
5538
|
+
};
|
|
5539
|
+
const closeActiveBrowsers = async () => {
|
|
5540
|
+
await closeTrackedBrowsers(activeBrowsers);
|
|
5541
|
+
};
|
|
5542
|
+
const forceTerminateActiveProcesses = async () => {
|
|
5543
|
+
await forceTerminateBrowsersByFingerprintArg(fingerprintArg);
|
|
5544
|
+
};
|
|
5545
|
+
const cleanup = async () => {
|
|
5546
|
+
await closeActiveBrowsers();
|
|
5547
|
+
await forceTerminateActiveProcesses();
|
|
5548
|
+
};
|
|
5549
|
+
return {
|
|
5550
|
+
headless,
|
|
5551
|
+
launchOptions,
|
|
5552
|
+
fingerprintArg,
|
|
5553
|
+
crawlerOptions,
|
|
5554
|
+
closeActiveBrowsers,
|
|
5555
|
+
forceTerminateActiveProcesses,
|
|
5556
|
+
cleanup
|
|
5557
|
+
};
|
|
5558
|
+
}
|
|
5559
|
+
};
|
|
5560
|
+
|
|
5561
|
+
// src/launch.js
|
|
5562
|
+
var launchStrategies = {
|
|
5563
|
+
[Mode.Default]: DefaultLaunch,
|
|
5564
|
+
[Mode.Cloak]: CloakLaunch
|
|
5565
|
+
};
|
|
5566
|
+
var Launch = withModeReflect("Launch", launchStrategies);
|
|
5567
|
+
|
|
5074
5568
|
// src/live-view.js
|
|
5075
5569
|
import express from "express";
|
|
5076
5570
|
import { Actor } from "apify";
|
|
5077
|
-
var
|
|
5571
|
+
var logger10 = createInternalLogger("LiveView");
|
|
5078
5572
|
async function startLiveViewServer(liveViewKey) {
|
|
5079
5573
|
const app = express();
|
|
5080
5574
|
app.get("/", async (req, res) => {
|
|
@@ -5099,13 +5593,13 @@ async function startLiveViewServer(liveViewKey) {
|
|
|
5099
5593
|
</html>
|
|
5100
5594
|
`);
|
|
5101
5595
|
} catch (error) {
|
|
5102
|
-
|
|
5596
|
+
logger10.fail("Live View Server", error);
|
|
5103
5597
|
res.status(500).send(`\u65E0\u6CD5\u52A0\u8F7D\u5C4F\u5E55\u622A\u56FE: ${error.message}`);
|
|
5104
5598
|
}
|
|
5105
5599
|
});
|
|
5106
5600
|
const port = process.env.APIFY_CONTAINER_PORT || 4321;
|
|
5107
5601
|
app.listen(port, () => {
|
|
5108
|
-
|
|
5602
|
+
logger10.success("startLiveViewServer", `\u76D1\u542C\u7AEF\u53E3 ${port}`);
|
|
5109
5603
|
});
|
|
5110
5604
|
}
|
|
5111
5605
|
async function takeLiveScreenshot(liveViewKey, page, logMessage) {
|
|
@@ -5113,10 +5607,10 @@ async function takeLiveScreenshot(liveViewKey, page, logMessage) {
|
|
|
5113
5607
|
const buffer = await capturePageScreenshot(page, { type: "png" });
|
|
5114
5608
|
await Actor.setValue(liveViewKey, buffer, { contentType: "image/png" });
|
|
5115
5609
|
if (logMessage) {
|
|
5116
|
-
|
|
5610
|
+
logger10.info(`(\u622A\u56FE): ${logMessage}`);
|
|
5117
5611
|
}
|
|
5118
5612
|
} catch (e) {
|
|
5119
|
-
|
|
5613
|
+
logger10.warn(`\u65E0\u6CD5\u6355\u83B7 Live View \u5C4F\u5E55\u622A\u56FE: ${e.message}`);
|
|
5120
5614
|
}
|
|
5121
5615
|
}
|
|
5122
5616
|
var useLiveView = (liveViewKey = PresetOfLiveViewKey) => {
|
|
@@ -5133,9 +5627,6 @@ var LiveView = {
|
|
|
5133
5627
|
useLiveView
|
|
5134
5628
|
};
|
|
5135
5629
|
|
|
5136
|
-
// src/chaptcha.js
|
|
5137
|
-
import { v4 as uuidv4 } from "uuid";
|
|
5138
|
-
|
|
5139
5630
|
// src/internals/captcha/bytedance.js
|
|
5140
5631
|
import { mkdir, writeFile } from "fs/promises";
|
|
5141
5632
|
import path2 from "path";
|
|
@@ -5225,7 +5716,7 @@ var dragCaptchaAction = async (page, sourceLocator, targetLocator, options = {})
|
|
|
5225
5716
|
};
|
|
5226
5717
|
|
|
5227
5718
|
// src/internals/captcha/bytedance.js
|
|
5228
|
-
var
|
|
5719
|
+
var logger11 = createInternalLogger("Captcha");
|
|
5229
5720
|
var DEFAULT_BYTEDANCE_CAPTCHA_OPTIONS = Object.freeze({
|
|
5230
5721
|
apiType: "31234",
|
|
5231
5722
|
maxRetries: 3,
|
|
@@ -5357,7 +5848,7 @@ var collectCaptchaDebugInfo = async (page, frame, iframeLocator, attempt, phase,
|
|
|
5357
5848
|
}
|
|
5358
5849
|
await writeFile(infoPath, JSON.stringify(payload, null, 2), "utf8");
|
|
5359
5850
|
}
|
|
5360
|
-
|
|
5851
|
+
logger11.info(`\u5DF2\u5199\u51FA\u9A8C\u8BC1\u7801\u8C03\u8BD5\u4EA7\u7269\uFF1A${debugDir}`);
|
|
5361
5852
|
};
|
|
5362
5853
|
var maybeCollectCaptchaDebugInfo = async (page, frame, iframeLocator, attempt, phase, options, extra = null) => {
|
|
5363
5854
|
if (!options.debugArtifacts) {
|
|
@@ -5394,14 +5885,14 @@ var getVerifycenterCaptchaContext = async (page, options) => {
|
|
|
5394
5885
|
if (!isContainerVisible) {
|
|
5395
5886
|
return null;
|
|
5396
5887
|
}
|
|
5397
|
-
|
|
5888
|
+
logger11.info("\u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\u5BB9\u5668\uFF0C\u5F00\u59CB\u7B49\u5F85 iframe \u52A0\u8F7D\u3002");
|
|
5398
5889
|
let iframeLocator = page.locator(options.iframeSelector).first();
|
|
5399
5890
|
let isIframeVisible = await waitForVisible(
|
|
5400
5891
|
iframeLocator,
|
|
5401
5892
|
options.iframeVisibleTimeoutMs
|
|
5402
5893
|
);
|
|
5403
5894
|
if (!isIframeVisible) {
|
|
5404
|
-
|
|
5895
|
+
logger11.warn("\u672A\u5728\u9884\u671F\u9009\u62E9\u5668\u4E2D\u627E\u5230 verifycenter iframe\uFF0C\u5C1D\u8BD5\u5BB9\u5668\u5185\u4EFB\u610F iframe\u3002");
|
|
5405
5896
|
iframeLocator = captchaContainer.locator(options.iframeFallbackSelector).first();
|
|
5406
5897
|
isIframeVisible = await waitForVisible(
|
|
5407
5898
|
iframeLocator,
|
|
@@ -5411,7 +5902,7 @@ var getVerifycenterCaptchaContext = async (page, options) => {
|
|
|
5411
5902
|
if (!isIframeVisible) {
|
|
5412
5903
|
throw new Error("verifycenter iframe not found inside captcha container.");
|
|
5413
5904
|
}
|
|
5414
|
-
|
|
5905
|
+
logger11.info("\u9A8C\u8BC1\u7801 iframe \u5DF2\u53EF\u89C1\uFF0C\u5F00\u59CB\u89E3\u6790\u5185\u5BB9 frame\u3002");
|
|
5415
5906
|
const frame = await resolveContentFrame(page, iframeLocator, options);
|
|
5416
5907
|
if (!frame) {
|
|
5417
5908
|
throw new Error("Failed to resolve verifycenter iframe content frame.");
|
|
@@ -5527,11 +6018,11 @@ var refreshCaptcha = async (page, frame, options) => {
|
|
|
5527
6018
|
const clicked = await clickCaptchaAction(frame, options.refreshTexts, {
|
|
5528
6019
|
...options,
|
|
5529
6020
|
page,
|
|
5530
|
-
logger:
|
|
6021
|
+
logger: logger11,
|
|
5531
6022
|
forceMouse: true
|
|
5532
6023
|
}).catch(() => false);
|
|
5533
6024
|
if (!clicked) {
|
|
5534
|
-
|
|
6025
|
+
logger11.warn("Refresh button not found.");
|
|
5535
6026
|
return false;
|
|
5536
6027
|
}
|
|
5537
6028
|
await page.waitForTimeout(options.refreshWaitMs);
|
|
@@ -5562,24 +6053,24 @@ var waitForCaptchaChallengeReady = async (page, frame, options) => {
|
|
|
5562
6053
|
const hasGuideMaskVisible = options.guideMaskSelector ? await frame.locator(options.guideMaskSelector).first().isVisible({ timeout: options.loadingIndicatorVisibleTimeoutMs }).catch(() => false) : false;
|
|
5563
6054
|
hasSeenGuideMask = hasSeenGuideMask || hasGuideMaskVisible;
|
|
5564
6055
|
if (hasGuideMaskVisible && !hasLoggedGuideMask) {
|
|
5565
|
-
|
|
6056
|
+
logger11.info("\u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\u64CD\u4F5C\u5F15\u5BFC\u5C42\uFF0C\u7B49\u5F85\u5176\u6D88\u5931\u540E\u518D\u5F00\u59CB\u8BC6\u522B\u3002");
|
|
5566
6057
|
hasLoggedGuideMask = true;
|
|
5567
6058
|
}
|
|
5568
6059
|
if (!isLoadingVisible && hasVisibleSourceImage && hasVisibleDropTarget && !hasGuideMaskVisible) {
|
|
5569
|
-
|
|
6060
|
+
logger11.info(
|
|
5570
6061
|
hasSeenGuideMask ? "\u9A8C\u8BC1\u7801\u56FE\u7247\u548C\u62D6\u62FD\u533A\u57DF\u5DF2\u5C31\u7EEA\uFF0C\u5F15\u5BFC\u5C42\u5DF2\u6D88\u5931\u3002" : hasSeenLoading ? "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u52A0\u8F7D\u5B8C\u6210\u3002" : "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u5C31\u7EEA\u3002"
|
|
5571
6062
|
);
|
|
5572
6063
|
return;
|
|
5573
6064
|
}
|
|
5574
6065
|
if (hasErrorTextVisible) {
|
|
5575
|
-
|
|
6066
|
+
logger11.warn("\u9A8C\u8BC1\u7801\u9762\u677F\u51FA\u73B0\u7F51\u7EDC\u5F02\u5E38\u6587\u6848\uFF0C\u5C1D\u8BD5\u7ACB\u5373\u5237\u65B0\u9898\u76EE\u3002");
|
|
5576
6067
|
await refreshCaptcha(page, frame, options);
|
|
5577
6068
|
refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
|
|
5578
6069
|
hasSeenLoading = false;
|
|
5579
6070
|
continue;
|
|
5580
6071
|
}
|
|
5581
6072
|
if ((!hasVisibleSourceImage || !hasVisibleDropTarget) && Date.now() >= refreshDeadline) {
|
|
5582
|
-
|
|
6073
|
+
logger11.warn(`\u9A8C\u8BC1\u7801\u9898\u76EE\u8D85\u8FC7 ${options.challengeReadyRefreshTimeoutMs}ms \u4ECD\u672A\u51C6\u5907\u597D\uFF0C\u5C1D\u8BD5\u5237\u65B0\u9898\u76EE\u3002`);
|
|
5583
6074
|
await refreshCaptcha(page, frame, options);
|
|
5584
6075
|
refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
|
|
5585
6076
|
hasSeenLoading = false;
|
|
@@ -5627,7 +6118,7 @@ var dragPromptCaptchaImage = async (page, frame, iframeLocator, sourceLocator, d
|
|
|
5627
6118
|
accepted
|
|
5628
6119
|
};
|
|
5629
6120
|
dragAttempts.push(attemptInfo);
|
|
5630
|
-
|
|
6121
|
+
logger11.info(
|
|
5631
6122
|
`\u9A8C\u8BC1\u7801\u62D6\u62FD\u7B2C ${visualIndex + 1} \u5F20\uFF0C\u65B9\u6848 ${plan.name}\uFF0Cbadge ${baselineState.badgeCount} -> ${afterState.badgeCount}\uFF0Cselected ${baselineState.selectedCount} -> ${afterState.selectedCount}`
|
|
5632
6123
|
);
|
|
5633
6124
|
if (accepted) {
|
|
@@ -5645,7 +6136,7 @@ var dragPromptCaptchaImage = async (page, frame, iframeLocator, sourceLocator, d
|
|
|
5645
6136
|
dragAttempts,
|
|
5646
6137
|
finalState: await readPromptCaptchaState(frame, options)
|
|
5647
6138
|
}).catch((error) => {
|
|
5648
|
-
|
|
6139
|
+
logger11.warn(`\u9A8C\u8BC1\u7801\u62D6\u62FD\u5931\u8D25\u8C03\u8BD5\u6293\u53D6\u5931\u8D25\uFF1A${error?.message || error}`);
|
|
5649
6140
|
});
|
|
5650
6141
|
return {
|
|
5651
6142
|
accepted: false,
|
|
@@ -5662,16 +6153,16 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
|
|
|
5662
6153
|
...options
|
|
5663
6154
|
};
|
|
5664
6155
|
if (!config.token) {
|
|
5665
|
-
|
|
6156
|
+
logger11.warn("\u7F3A\u5C11\u9A8C\u8BC1\u7801 token\uFF0C\u8DF3\u8FC7\u81EA\u52A8\u8BC6\u522B\u3002");
|
|
5666
6157
|
return false;
|
|
5667
6158
|
}
|
|
5668
|
-
|
|
6159
|
+
logger11.info("\u5F53\u524D\u4F7F\u7528\u672Ctool\u2014\u2014\u6D4B\u8BD5\u7248\u672C");
|
|
5669
6160
|
for (let attempt = 1; attempt <= config.maxRetries; attempt += 1) {
|
|
5670
|
-
|
|
6161
|
+
logger11.info(`\u5F00\u59CB\u7B2C ${attempt}/${config.maxRetries} \u6B21 verifycenter \u9A8C\u8BC1\u7801\u8BC6\u522B\u3002`);
|
|
5671
6162
|
try {
|
|
5672
6163
|
const captchaContext = await getVerifycenterCaptchaContext(page, config);
|
|
5673
6164
|
if (!captchaContext) {
|
|
5674
|
-
|
|
6165
|
+
logger11.info("Captcha container is not visible anymore.");
|
|
5675
6166
|
return true;
|
|
5676
6167
|
}
|
|
5677
6168
|
const { iframeLocator, frame } = captchaContext;
|
|
@@ -5684,7 +6175,7 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
|
|
|
5684
6175
|
"ready",
|
|
5685
6176
|
config
|
|
5686
6177
|
).catch((error) => {
|
|
5687
|
-
|
|
6178
|
+
logger11.warn(`\u9A8C\u8BC1\u7801\u8C03\u8BD5\u6293\u53D6\u5931\u8D25\uFF1A${error?.message || error}`);
|
|
5688
6179
|
});
|
|
5689
6180
|
await page.waitForTimeout(config.recognitionDelayMs);
|
|
5690
6181
|
const screenshotBuffer = await iframeLocator.screenshot();
|
|
@@ -5696,16 +6187,16 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
|
|
|
5696
6187
|
});
|
|
5697
6188
|
const serialNumbers = extractCaptchaSerialNumbers(apiResponse);
|
|
5698
6189
|
if (apiResponse?.code !== config.recognitionSuccessCode || serialNumbers.length === 0) {
|
|
5699
|
-
|
|
6190
|
+
logger11.warn(
|
|
5700
6191
|
`\u9A8C\u8BC1\u7801\u8BC6\u522B\u5931\u8D25\u3002code=${apiResponse?.code}, msg=${apiResponse?.msg || "unknown"}`
|
|
5701
6192
|
);
|
|
5702
6193
|
await refreshCaptcha(page, frame, config);
|
|
5703
6194
|
continue;
|
|
5704
6195
|
}
|
|
5705
|
-
|
|
6196
|
+
logger11.info(`\u9A8C\u8BC1\u7801\u8BC6\u522B\u6210\u529F\uFF0C\u5E8F\u53F7\uFF1A${serialNumbers.join(", ")}`);
|
|
5706
6197
|
const dropTarget = await findCaptchaDropTarget(frame, config);
|
|
5707
6198
|
if (!dropTarget) {
|
|
5708
|
-
|
|
6199
|
+
logger11.warn("\u672A\u627E\u5230\u9A8C\u8BC1\u7801\u62D6\u62FD\u76EE\u6807\u533A\u57DF\u3002");
|
|
5709
6200
|
await refreshCaptcha(page, frame, config);
|
|
5710
6201
|
continue;
|
|
5711
6202
|
}
|
|
@@ -5716,7 +6207,7 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
|
|
|
5716
6207
|
`Captcha image indexes could not be normalized. raw=${serialNumbers.join(", ")}, count=${orderedSourceImages.length}`
|
|
5717
6208
|
);
|
|
5718
6209
|
}
|
|
5719
|
-
|
|
6210
|
+
logger11.info(`\u9A8C\u8BC1\u7801\u89C6\u89C9\u4F4D\u5E8F\u6620\u5C04\uFF1A${normalizedIndexes.map((index) => index + 1).join(", ")}`);
|
|
5720
6211
|
for (const imageIndex of normalizedIndexes) {
|
|
5721
6212
|
if (imageIndex < 0 || imageIndex >= orderedSourceImages.length) {
|
|
5722
6213
|
throw new Error(
|
|
@@ -5748,52 +6239,55 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
|
|
|
5748
6239
|
}
|
|
5749
6240
|
}
|
|
5750
6241
|
const beforeSubmitState = await readPromptCaptchaState(frame, config);
|
|
5751
|
-
|
|
6242
|
+
logger11.info(
|
|
5752
6243
|
`\u63D0\u4EA4\u524D\u9A8C\u8BC1\u7801\u72B6\u6001\uFF1Abadge=${beforeSubmitState.badgeCount}, selected=${beforeSubmitState.selectedCount}, submitDisabled=${beforeSubmitState.submitDisabled}`
|
|
5753
6244
|
);
|
|
5754
6245
|
const submitted = await clickCaptchaAction(frame, config.submitTexts, {
|
|
5755
6246
|
...config,
|
|
5756
6247
|
page,
|
|
5757
|
-
logger:
|
|
6248
|
+
logger: logger11,
|
|
5758
6249
|
forceMouse: true,
|
|
5759
6250
|
actionVisibleTimeoutMs: config.submitReadyTimeoutMs
|
|
5760
6251
|
}).catch(() => false);
|
|
5761
6252
|
if (!submitted) {
|
|
5762
|
-
|
|
6253
|
+
logger11.warn("\u672A\u627E\u5230\u63D0\u4EA4\u6309\u94AE\uFF0C\u53EF\u80FD\u4F1A\u81EA\u52A8\u63D0\u4EA4\u3002");
|
|
5763
6254
|
}
|
|
5764
6255
|
await page.waitForTimeout(config.submitWaitMs);
|
|
5765
6256
|
const afterSubmitState = await readPromptCaptchaState(frame, config);
|
|
5766
|
-
|
|
6257
|
+
logger11.info(
|
|
5767
6258
|
`\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801\u72B6\u6001\uFF1Abadge=${afterSubmitState.badgeCount}, selected=${afterSubmitState.selectedCount}, submitDisabled=${afterSubmitState.submitDisabled}`
|
|
5768
6259
|
);
|
|
5769
6260
|
const stillVisible = await iframeLocator.isVisible({ timeout: config.containerVisibleTimeoutMs }).catch(() => false);
|
|
5770
6261
|
if (!stillVisible) {
|
|
5771
|
-
|
|
6262
|
+
logger11.info("\u9A8C\u8BC1\u7801\u8BC6\u522B\u5E76\u63D0\u4EA4\u6210\u529F\u3002");
|
|
5772
6263
|
return true;
|
|
5773
6264
|
}
|
|
5774
6265
|
await maybeCollectCaptchaDebugInfo(page, frame, iframeLocator, attempt, "submit-still-visible", config, {
|
|
5775
6266
|
beforeSubmitState,
|
|
5776
6267
|
afterSubmitState
|
|
5777
6268
|
}).catch((error) => {
|
|
5778
|
-
|
|
6269
|
+
logger11.warn(`\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801\u8C03\u8BD5\u6293\u53D6\u5931\u8D25\uFF1A${error?.message || error}`);
|
|
5779
6270
|
});
|
|
5780
|
-
|
|
6271
|
+
logger11.warn("\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801 iframe \u4ECD\u7136\u53EF\u89C1\uFF0C\u51C6\u5907\u5237\u65B0\u540E\u91CD\u8BD5\u3002");
|
|
5781
6272
|
await page.waitForTimeout(2e3);
|
|
5782
6273
|
await refreshCaptcha(page, frame, config);
|
|
5783
6274
|
} catch (error) {
|
|
5784
|
-
|
|
6275
|
+
logger11.error(`\u7B2C ${attempt}/${config.maxRetries} \u6B21\u9A8C\u8BC1\u7801\u8BC6\u522B\u5931\u8D25\uFF1A${error?.message || error}`);
|
|
5785
6276
|
}
|
|
5786
6277
|
if (attempt < config.maxRetries) {
|
|
5787
6278
|
await page.waitForTimeout(config.retryDelayBaseMs + attempt * config.retryDelayStepMs);
|
|
5788
6279
|
}
|
|
5789
6280
|
}
|
|
5790
|
-
|
|
6281
|
+
logger11.error(`\u91CD\u8BD5 ${config.maxRetries} \u6B21\u540E\uFF0C\u9A8C\u8BC1\u7801\u4ECD\u672A\u8BC6\u522B\u6210\u529F\u3002`);
|
|
5791
6282
|
return false;
|
|
5792
6283
|
}
|
|
5793
6284
|
var sloveCaptcha = solveCaptcha;
|
|
5794
6285
|
|
|
5795
6286
|
// src/chaptcha.js
|
|
5796
|
-
var
|
|
6287
|
+
var logger12 = createInternalLogger("Captcha");
|
|
6288
|
+
var DOM_MONITOR_WAIT_TIMEOUT_MS = 1e3;
|
|
6289
|
+
var DOM_MONITOR_POST_DETECT_HIDDEN_WAIT_MS = 300;
|
|
6290
|
+
var DOM_MONITOR_RECOVERY_WAIT_MS = 100;
|
|
5797
6291
|
var DEFAULT_CAPTCHA_RECOGNITION_OPTIONS = Object.freeze({
|
|
5798
6292
|
token: "eKJvBfwfN0YRav0-VD_44E2VBSfm7l0YtddUQ7cFySI",
|
|
5799
6293
|
apiUrl: "https://api.jfbym.com/api/YmServer/customApi"
|
|
@@ -5814,6 +6308,15 @@ var mergeDefinedOptions = (...sources) => {
|
|
|
5814
6308
|
}
|
|
5815
6309
|
return merged;
|
|
5816
6310
|
};
|
|
6311
|
+
var sleep = (ms) => new Promise((resolve) => {
|
|
6312
|
+
setTimeout(resolve, ms);
|
|
6313
|
+
});
|
|
6314
|
+
var getErrorMessage = (error) => String(error?.message || error || "");
|
|
6315
|
+
var isTimeoutError = (error) => error?.name === "TimeoutError" || getErrorMessage(error).includes("Timeout");
|
|
6316
|
+
var isPageLifecycleError = (error) => {
|
|
6317
|
+
const message = getErrorMessage(error);
|
|
6318
|
+
return message.includes("Execution context was destroyed") || message.includes("Frame was detached") || message.includes("Target page, context or browser has been closed") || message.includes("Target closed") || message.includes("Most likely the page has been closed");
|
|
6319
|
+
};
|
|
5817
6320
|
function useCaptchaMonitor(page, options) {
|
|
5818
6321
|
const { domSelector, urlPattern, onDetected } = options;
|
|
5819
6322
|
if (!domSelector && !urlPattern) {
|
|
@@ -5825,10 +6328,13 @@ function useCaptchaMonitor(page, options) {
|
|
|
5825
6328
|
let isStopped = false;
|
|
5826
6329
|
let isHandling = false;
|
|
5827
6330
|
let frameHandler = null;
|
|
5828
|
-
let
|
|
6331
|
+
let domMonitorTask = null;
|
|
6332
|
+
let lastTriggeredAt = 0;
|
|
5829
6333
|
const triggerDetected = async () => {
|
|
5830
|
-
|
|
6334
|
+
const now = Date.now();
|
|
6335
|
+
if (isStopped || isHandling || now - lastTriggeredAt < 250) return;
|
|
5831
6336
|
isHandling = true;
|
|
6337
|
+
lastTriggeredAt = now;
|
|
5832
6338
|
try {
|
|
5833
6339
|
await onDetected();
|
|
5834
6340
|
} finally {
|
|
@@ -5837,60 +6343,38 @@ function useCaptchaMonitor(page, options) {
|
|
|
5837
6343
|
};
|
|
5838
6344
|
const cleanupFns = [];
|
|
5839
6345
|
if (domSelector) {
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
}
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
const shouldCheck = mutations.some((mutation) => mutation.addedNodes.length > 0);
|
|
5860
|
-
if (shouldCheck && observer) {
|
|
5861
|
-
checkAndReport();
|
|
5862
|
-
}
|
|
5863
|
-
});
|
|
5864
|
-
const mountObserver = () => {
|
|
5865
|
-
const target = document.documentElement;
|
|
5866
|
-
if (target && observer) {
|
|
5867
|
-
observer.observe(target, { childList: true, subtree: true });
|
|
6346
|
+
domMonitorTask = (async () => {
|
|
6347
|
+
const locator = page.locator(domSelector).first();
|
|
6348
|
+
while (!isStopped) {
|
|
6349
|
+
try {
|
|
6350
|
+
await locator.waitFor({ state: "visible", timeout: DOM_MONITOR_WAIT_TIMEOUT_MS });
|
|
6351
|
+
if (isStopped) break;
|
|
6352
|
+
await triggerDetected();
|
|
6353
|
+
if (isStopped) break;
|
|
6354
|
+
await locator.waitFor({
|
|
6355
|
+
state: "hidden",
|
|
6356
|
+
timeout: DOM_MONITOR_POST_DETECT_HIDDEN_WAIT_MS
|
|
6357
|
+
}).catch(() => {
|
|
6358
|
+
});
|
|
6359
|
+
} catch (error) {
|
|
6360
|
+
if (isStopped) break;
|
|
6361
|
+
if (page?.isClosed?.() && isPageLifecycleError(error)) break;
|
|
6362
|
+
if (isTimeoutError(error) || isPageLifecycleError(error)) {
|
|
6363
|
+
await sleep(DOM_MONITOR_RECOVERY_WAIT_MS);
|
|
6364
|
+
continue;
|
|
5868
6365
|
}
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
6366
|
+
logger12.warning(
|
|
6367
|
+
"useCaptchaMonitor",
|
|
6368
|
+
`DOM \u76D1\u63A7\u51FA\u73B0\u5F02\u5E38\uFF08\u7EE7\u7EED\u91CD\u8BD5\uFF09: selector=${domSelector}, error=${getErrorMessage(error)}`
|
|
6369
|
+
);
|
|
6370
|
+
await sleep(DOM_MONITOR_RECOVERY_WAIT_MS);
|
|
5874
6371
|
}
|
|
5875
|
-
window[cleanupName] = () => {
|
|
5876
|
-
if (observer) {
|
|
5877
|
-
observer.disconnect();
|
|
5878
|
-
observer = null;
|
|
5879
|
-
}
|
|
5880
|
-
};
|
|
5881
|
-
})();
|
|
5882
|
-
}, { selector: domSelector, callbackName: exposedFunctionName, cleanerName });
|
|
5883
|
-
logger11.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${domSelector}`);
|
|
5884
|
-
cleanupFns.push(async () => {
|
|
5885
|
-
try {
|
|
5886
|
-
await page.evaluate((name) => {
|
|
5887
|
-
if (window[name]) {
|
|
5888
|
-
window[name]();
|
|
5889
|
-
delete window[name];
|
|
5890
|
-
}
|
|
5891
|
-
}, cleanerName);
|
|
5892
|
-
} catch {
|
|
5893
6372
|
}
|
|
6373
|
+
})();
|
|
6374
|
+
logger12.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${domSelector}`);
|
|
6375
|
+
cleanupFns.push(async () => {
|
|
6376
|
+
await domMonitorTask?.catch(() => {
|
|
6377
|
+
});
|
|
5894
6378
|
});
|
|
5895
6379
|
}
|
|
5896
6380
|
if (urlPattern) {
|
|
@@ -5904,18 +6388,24 @@ function useCaptchaMonitor(page, options) {
|
|
|
5904
6388
|
}
|
|
5905
6389
|
};
|
|
5906
6390
|
page.on("framenavigated", frameHandler);
|
|
5907
|
-
|
|
6391
|
+
logger12.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${urlPattern}`);
|
|
6392
|
+
Promise.resolve().then(async () => {
|
|
6393
|
+
if (!isStopped && page.url().includes(urlPattern)) {
|
|
6394
|
+
await triggerDetected();
|
|
6395
|
+
}
|
|
6396
|
+
}).catch(() => {
|
|
6397
|
+
});
|
|
5908
6398
|
cleanupFns.push(async () => {
|
|
5909
6399
|
page.off("framenavigated", frameHandler);
|
|
5910
6400
|
});
|
|
5911
6401
|
}
|
|
5912
6402
|
return {
|
|
5913
6403
|
stop: async () => {
|
|
5914
|
-
|
|
6404
|
+
logger12.info("\u6B63\u5728\u505C\u6B62\u9A8C\u8BC1\u7801\u76D1\u63A7...");
|
|
6405
|
+
isStopped = true;
|
|
5915
6406
|
for (const fn of cleanupFns) {
|
|
5916
6407
|
await fn();
|
|
5917
6408
|
}
|
|
5918
|
-
isStopped = true;
|
|
5919
6409
|
}
|
|
5920
6410
|
};
|
|
5921
6411
|
}
|
|
@@ -5950,7 +6440,7 @@ async function solveCaptchaWithStrategy(strategyName, page, options = {}) {
|
|
|
5950
6440
|
);
|
|
5951
6441
|
return strategy.sloveCaptcha(page, resolvedOptions, {
|
|
5952
6442
|
callCaptchaRecognitionApi,
|
|
5953
|
-
logger:
|
|
6443
|
+
logger: logger12
|
|
5954
6444
|
});
|
|
5955
6445
|
}
|
|
5956
6446
|
var Captcha = {
|
|
@@ -5960,15 +6450,15 @@ var Captcha = {
|
|
|
5960
6450
|
|
|
5961
6451
|
// src/mutation.js
|
|
5962
6452
|
import { createHash } from "node:crypto";
|
|
5963
|
-
import { v4 as
|
|
5964
|
-
var
|
|
6453
|
+
import { v4 as uuidv4 } from "uuid";
|
|
6454
|
+
var logger13 = createInternalLogger("Mutation");
|
|
5965
6455
|
var MUTATION_MONITOR_MODE = Object.freeze({
|
|
5966
6456
|
Added: "added",
|
|
5967
6457
|
Changed: "changed",
|
|
5968
6458
|
All: "all"
|
|
5969
6459
|
});
|
|
5970
6460
|
function generateKey(prefix) {
|
|
5971
|
-
return `__${prefix}_${
|
|
6461
|
+
return `__${prefix}_${uuidv4().replace(/-/g, "_")}`;
|
|
5972
6462
|
}
|
|
5973
6463
|
var Mutation = {
|
|
5974
6464
|
Mode: MUTATION_MONITOR_MODE,
|
|
@@ -5994,14 +6484,14 @@ var Mutation = {
|
|
|
5994
6484
|
const stableTime = options.stableTime ?? 5 * 1e3;
|
|
5995
6485
|
const timeout = options.timeout ?? 120 * 1e3;
|
|
5996
6486
|
const onMutation = options.onMutation;
|
|
5997
|
-
|
|
6487
|
+
logger13.start("waitForStable", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);
|
|
5998
6488
|
if (initialTimeout > 0) {
|
|
5999
6489
|
const selectorQuery = selectorList.join(",");
|
|
6000
6490
|
try {
|
|
6001
6491
|
await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
|
|
6002
|
-
|
|
6492
|
+
logger13.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
|
|
6003
6493
|
} catch (e) {
|
|
6004
|
-
|
|
6494
|
+
logger13.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
|
|
6005
6495
|
throw e;
|
|
6006
6496
|
}
|
|
6007
6497
|
}
|
|
@@ -6017,7 +6507,7 @@ var Mutation = {
|
|
|
6017
6507
|
return "__CONTINUE__";
|
|
6018
6508
|
}
|
|
6019
6509
|
});
|
|
6020
|
-
|
|
6510
|
+
logger13.info("waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03");
|
|
6021
6511
|
} catch (e) {
|
|
6022
6512
|
}
|
|
6023
6513
|
}
|
|
@@ -6132,9 +6622,9 @@ var Mutation = {
|
|
|
6132
6622
|
{ selectorList, stableTime, timeout, callbackName, hasCallback: !!onMutation }
|
|
6133
6623
|
);
|
|
6134
6624
|
if (result.mutationCount === 0 && result.stableTime === 0) {
|
|
6135
|
-
|
|
6625
|
+
logger13.warning("waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
|
|
6136
6626
|
}
|
|
6137
|
-
|
|
6627
|
+
logger13.success("waitForStable", `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
|
|
6138
6628
|
return result;
|
|
6139
6629
|
},
|
|
6140
6630
|
/**
|
|
@@ -6158,7 +6648,7 @@ var Mutation = {
|
|
|
6158
6648
|
const overallTimeout = options.timeout ?? 180 * 1e3;
|
|
6159
6649
|
const onMutation = options.onMutation;
|
|
6160
6650
|
const pollInterval = 500;
|
|
6161
|
-
const
|
|
6651
|
+
const sleep2 = (ms) => new Promise((resolve) => {
|
|
6162
6652
|
setTimeout(resolve, ms);
|
|
6163
6653
|
});
|
|
6164
6654
|
const truncate = (value, max = 800) => {
|
|
@@ -6306,29 +6796,29 @@ var Mutation = {
|
|
|
6306
6796
|
return "__CONTINUE__";
|
|
6307
6797
|
}
|
|
6308
6798
|
};
|
|
6309
|
-
|
|
6799
|
+
logger13.start(
|
|
6310
6800
|
"waitForStableAcrossRoots",
|
|
6311
6801
|
`\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668(\u8DE8 root), \u7A33\u5B9A\u65F6\u95F4=${waitForStableTime}ms`
|
|
6312
6802
|
);
|
|
6313
6803
|
if (initialTimeout > 0) {
|
|
6314
6804
|
try {
|
|
6315
6805
|
await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
|
|
6316
|
-
|
|
6806
|
+
logger13.info(`waitForStableAcrossRoots \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
|
|
6317
6807
|
} catch (e) {
|
|
6318
|
-
|
|
6808
|
+
logger13.warning(`waitForStableAcrossRoots \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
|
|
6319
6809
|
throw e;
|
|
6320
6810
|
}
|
|
6321
6811
|
}
|
|
6322
|
-
let
|
|
6323
|
-
if (!
|
|
6324
|
-
|
|
6812
|
+
let state2 = await buildState();
|
|
6813
|
+
if (!state2?.hasMatched) {
|
|
6814
|
+
logger13.warning("waitForStableAcrossRoots \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
|
|
6325
6815
|
return { mutationCount: 0, stableTime: 0, wasPaused: false };
|
|
6326
6816
|
}
|
|
6327
6817
|
let mutationCount = 0;
|
|
6328
6818
|
let stableSince = 0;
|
|
6329
6819
|
let isPaused = false;
|
|
6330
6820
|
let wasPaused = false;
|
|
6331
|
-
let lastSnapshotKey =
|
|
6821
|
+
let lastSnapshotKey = state2.snapshotKey;
|
|
6332
6822
|
const applyPauseSignal = (signal) => {
|
|
6333
6823
|
const nextPaused = signal === "__PAUSE__";
|
|
6334
6824
|
if (nextPaused) {
|
|
@@ -6342,15 +6832,15 @@ var Mutation = {
|
|
|
6342
6832
|
};
|
|
6343
6833
|
const initialSignal = await invokeMutationCallback({
|
|
6344
6834
|
mutationCount: 0,
|
|
6345
|
-
html:
|
|
6346
|
-
text:
|
|
6347
|
-
mutationNodes:
|
|
6835
|
+
html: state2.html || "",
|
|
6836
|
+
text: state2.text || "",
|
|
6837
|
+
mutationNodes: state2.mutationNodes || []
|
|
6348
6838
|
});
|
|
6349
6839
|
applyPauseSignal(initialSignal);
|
|
6350
6840
|
const deadline = Date.now() + overallTimeout;
|
|
6351
|
-
let lastState =
|
|
6841
|
+
let lastState = state2;
|
|
6352
6842
|
while (Date.now() < deadline) {
|
|
6353
|
-
await
|
|
6843
|
+
await sleep2(pollInterval);
|
|
6354
6844
|
lastState = await buildState();
|
|
6355
6845
|
if (!lastState?.hasMatched) {
|
|
6356
6846
|
continue;
|
|
@@ -6358,7 +6848,7 @@ var Mutation = {
|
|
|
6358
6848
|
if (lastState.snapshotKey !== lastSnapshotKey) {
|
|
6359
6849
|
lastSnapshotKey = lastState.snapshotKey;
|
|
6360
6850
|
mutationCount += 1;
|
|
6361
|
-
|
|
6851
|
+
logger13.info(
|
|
6362
6852
|
`waitForStableAcrossRoots \u53D8\u5316#${mutationCount}, len=${lastState.snapshotLength}, path=${lastState.primaryPath || "unknown"}, preview="${truncate(lastState.text, 120)}"`
|
|
6363
6853
|
);
|
|
6364
6854
|
const signal = await invokeMutationCallback({
|
|
@@ -6371,7 +6861,7 @@ var Mutation = {
|
|
|
6371
6861
|
continue;
|
|
6372
6862
|
}
|
|
6373
6863
|
if (!isPaused && stableSince > 0 && Date.now() - stableSince >= waitForStableTime) {
|
|
6374
|
-
|
|
6864
|
+
logger13.success("waitForStableAcrossRoots", `DOM \u7A33\u5B9A, \u603B\u5171 ${mutationCount} \u6B21\u53D8\u5316${wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
|
|
6375
6865
|
return {
|
|
6376
6866
|
mutationCount,
|
|
6377
6867
|
stableTime: waitForStableTime,
|
|
@@ -6397,8 +6887,8 @@ var Mutation = {
|
|
|
6397
6887
|
const selectorList = Array.isArray(selectors) ? selectors : [selectors];
|
|
6398
6888
|
const onMutation = options.onMutation;
|
|
6399
6889
|
const rawMode = String(options.mode || MUTATION_MONITOR_MODE.Added).toLowerCase();
|
|
6400
|
-
const
|
|
6401
|
-
|
|
6890
|
+
const mode2 = [MUTATION_MONITOR_MODE.Added, MUTATION_MONITOR_MODE.Changed, MUTATION_MONITOR_MODE.All].includes(rawMode) ? rawMode : MUTATION_MONITOR_MODE.Added;
|
|
6891
|
+
logger13.start("useMonitor", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode2}`);
|
|
6402
6892
|
const monitorKey = generateKey("pk_mon");
|
|
6403
6893
|
const callbackName = generateKey("pk_mon_cb");
|
|
6404
6894
|
const cleanerName = generateKey("pk_mon_clean");
|
|
@@ -6413,7 +6903,7 @@ var Mutation = {
|
|
|
6413
6903
|
} catch (e) {
|
|
6414
6904
|
}
|
|
6415
6905
|
}
|
|
6416
|
-
await page.evaluate(({ selectorList: selectorList2, monitorKey: monitorKey2, callbackName: callbackName2, cleanerName: cleanerName2, hasCallback, mode:
|
|
6906
|
+
await page.evaluate(({ selectorList: selectorList2, monitorKey: monitorKey2, callbackName: callbackName2, cleanerName: cleanerName2, hasCallback, mode: mode3 }) => {
|
|
6417
6907
|
const monitor = {
|
|
6418
6908
|
observers: [],
|
|
6419
6909
|
totalMutations: 0,
|
|
@@ -6457,7 +6947,7 @@ var Mutation = {
|
|
|
6457
6947
|
const collectMutationNodes = (mutations) => {
|
|
6458
6948
|
const mutationNodes = [];
|
|
6459
6949
|
for (const mutation of mutations) {
|
|
6460
|
-
if (
|
|
6950
|
+
if (mode3 === "added") {
|
|
6461
6951
|
if (mutation.type !== "childList") continue;
|
|
6462
6952
|
const added = Array.from(mutation.addedNodes || []);
|
|
6463
6953
|
for (const node of added) {
|
|
@@ -6465,7 +6955,7 @@ var Mutation = {
|
|
|
6465
6955
|
}
|
|
6466
6956
|
continue;
|
|
6467
6957
|
}
|
|
6468
|
-
if (
|
|
6958
|
+
if (mode3 === "changed") {
|
|
6469
6959
|
if (mutation.type === "attributes" || mutation.type === "characterData") {
|
|
6470
6960
|
mutationNodes.push(serializeNode(mutation.target, mutation.type));
|
|
6471
6961
|
} else if (mutation.type === "childList") {
|
|
@@ -6525,8 +7015,8 @@ var Mutation = {
|
|
|
6525
7015
|
observer.observe(element, {
|
|
6526
7016
|
childList: true,
|
|
6527
7017
|
subtree: true,
|
|
6528
|
-
characterData:
|
|
6529
|
-
attributes:
|
|
7018
|
+
characterData: mode3 !== "added",
|
|
7019
|
+
attributes: mode3 !== "added"
|
|
6530
7020
|
});
|
|
6531
7021
|
monitor.observers.push(observer);
|
|
6532
7022
|
});
|
|
@@ -6540,8 +7030,8 @@ var Mutation = {
|
|
|
6540
7030
|
delete window[cleanerName2];
|
|
6541
7031
|
return total;
|
|
6542
7032
|
};
|
|
6543
|
-
}, { selectorList, monitorKey, callbackName, cleanerName, hasCallback: !!onMutation, mode });
|
|
6544
|
-
|
|
7033
|
+
}, { selectorList, monitorKey, callbackName, cleanerName, hasCallback: !!onMutation, mode: mode2 });
|
|
7034
|
+
logger13.success("useMonitor", "\u76D1\u63A7\u5668\u5DF2\u542F\u52A8");
|
|
6545
7035
|
return {
|
|
6546
7036
|
stop: async () => {
|
|
6547
7037
|
let totalMutations = 0;
|
|
@@ -6554,7 +7044,7 @@ var Mutation = {
|
|
|
6554
7044
|
}, cleanerName);
|
|
6555
7045
|
} catch (e) {
|
|
6556
7046
|
}
|
|
6557
|
-
|
|
7047
|
+
logger13.success("useMonitor.stop", `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);
|
|
6558
7048
|
return { totalMutations };
|
|
6559
7049
|
}
|
|
6560
7050
|
};
|
|
@@ -7423,7 +7913,7 @@ var createTemplateLogger = (baseLogger = createBaseLogger()) => {
|
|
|
7423
7913
|
};
|
|
7424
7914
|
var getDefaultBaseLogger = () => createBaseLogger("");
|
|
7425
7915
|
var Logger = {
|
|
7426
|
-
setLogger: (
|
|
7916
|
+
setLogger: (logger17) => setDefaultLogger(logger17),
|
|
7427
7917
|
info: (message) => getDefaultBaseLogger().info(message),
|
|
7428
7918
|
success: (message) => getDefaultBaseLogger().success(message),
|
|
7429
7919
|
warning: (message) => getDefaultBaseLogger().warning(message),
|
|
@@ -7431,14 +7921,14 @@ var Logger = {
|
|
|
7431
7921
|
error: (message) => getDefaultBaseLogger().error(message),
|
|
7432
7922
|
debug: (message) => getDefaultBaseLogger().debug(message),
|
|
7433
7923
|
start: (message) => getDefaultBaseLogger().start(message),
|
|
7434
|
-
useTemplate: (
|
|
7435
|
-
if (
|
|
7924
|
+
useTemplate: (logger17) => {
|
|
7925
|
+
if (logger17) return createTemplateLogger(createBaseLogger("", logger17));
|
|
7436
7926
|
return createTemplateLogger();
|
|
7437
7927
|
}
|
|
7438
7928
|
};
|
|
7439
7929
|
|
|
7440
7930
|
// src/share.js
|
|
7441
|
-
import
|
|
7931
|
+
import delay5 from "delay";
|
|
7442
7932
|
|
|
7443
7933
|
// src/internals/watermarkify.js
|
|
7444
7934
|
var DEFAULT_TIMEZONE_OFFSET = 8;
|
|
@@ -7506,7 +7996,7 @@ var LOCATION_NETWORK_SUFFIX_PATTERNS = [
|
|
|
7506
7996
|
];
|
|
7507
7997
|
var cachedStripLogoSrcPromise = null;
|
|
7508
7998
|
var cachedEnrichmentByContext = /* @__PURE__ */ new WeakMap();
|
|
7509
|
-
var
|
|
7999
|
+
var logger14 = createInternalLogger("Watermarkify");
|
|
7510
8000
|
var normalizeText = (value) => String(value || "").trim();
|
|
7511
8001
|
var toInline = (value, maxLen = 200) => {
|
|
7512
8002
|
const text = normalizeText(value);
|
|
@@ -7748,9 +8238,9 @@ var resolveWithCustomResolver = async (page, baseMeta, options = {}) => {
|
|
|
7748
8238
|
location: toInline(resolved.location, 80)
|
|
7749
8239
|
};
|
|
7750
8240
|
if (enrichment.ip || enrichment.location) {
|
|
7751
|
-
|
|
8241
|
+
logger14.info(`\u81EA\u5B9A\u4E49 resolver \u547D\u4E2D: ip=${enrichment.ip || "-"}, loc=${enrichment.location || "-"}`);
|
|
7752
8242
|
} else {
|
|
7753
|
-
|
|
8243
|
+
logger14.warning("\u81EA\u5B9A\u4E49 resolver \u5DF2\u6267\u884C\uFF0C\u4F46\u672A\u8FD4\u56DE IP/Loc");
|
|
7754
8244
|
}
|
|
7755
8245
|
return enrichment;
|
|
7756
8246
|
} finally {
|
|
@@ -7934,14 +8424,17 @@ var buildWatermarkifyRenderHtml = ({ imageSrc, overlaySvg, width, height, imageH
|
|
|
7934
8424
|
</html>
|
|
7935
8425
|
`;
|
|
7936
8426
|
};
|
|
7937
|
-
var
|
|
8427
|
+
var normalizeWatermarkifyRenderMode = (value) => {
|
|
8428
|
+
return String(value || Mode.Default).trim().toLowerCase() === Mode.Cloak ? Mode.Cloak : Mode.Default;
|
|
8429
|
+
};
|
|
8430
|
+
var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageInfo = {}, options = {}) => {
|
|
7938
8431
|
if (!page || typeof page.context !== "function") {
|
|
7939
|
-
|
|
8432
|
+
logger14.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u7F3A\u5C11\u53EF\u7528 page");
|
|
7940
8433
|
return buffer;
|
|
7941
8434
|
}
|
|
7942
8435
|
const renderScope = await openProbePage(page);
|
|
7943
8436
|
if (!renderScope?.page) {
|
|
7944
|
-
|
|
8437
|
+
logger14.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA render page");
|
|
7945
8438
|
return buffer;
|
|
7946
8439
|
}
|
|
7947
8440
|
try {
|
|
@@ -7958,15 +8451,35 @@ var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageI
|
|
|
7958
8451
|
height: viewportHeight
|
|
7959
8452
|
}).catch(() => {
|
|
7960
8453
|
});
|
|
7961
|
-
|
|
7962
|
-
|
|
7963
|
-
|
|
7964
|
-
|
|
7965
|
-
|
|
7966
|
-
|
|
7967
|
-
|
|
7968
|
-
|
|
7969
|
-
|
|
8454
|
+
const renderMode = normalizeWatermarkifyRenderMode(options.mode);
|
|
8455
|
+
if (renderMode === Mode.Cloak) {
|
|
8456
|
+
const renderHtml = buildWatermarkifyRenderHtml({
|
|
8457
|
+
imageSrc: `data:${imageInfo.mimeType || "image/png"};base64,${buffer.toString("base64")}`,
|
|
8458
|
+
overlaySvg,
|
|
8459
|
+
width: safeWidth,
|
|
8460
|
+
height: safeHeight,
|
|
8461
|
+
imageHeight: safeImageHeight
|
|
8462
|
+
});
|
|
8463
|
+
await renderPage.goto("about:blank", {
|
|
8464
|
+
waitUntil: "commit"
|
|
8465
|
+
}).catch(() => {
|
|
8466
|
+
});
|
|
8467
|
+
await renderPage.evaluate((html) => {
|
|
8468
|
+
document.open();
|
|
8469
|
+
document.write(html);
|
|
8470
|
+
document.close();
|
|
8471
|
+
}, renderHtml);
|
|
8472
|
+
} else {
|
|
8473
|
+
await renderPage.setContent(buildWatermarkifyRenderHtml({
|
|
8474
|
+
imageSrc: `data:${imageInfo.mimeType || "image/png"};base64,${buffer.toString("base64")}`,
|
|
8475
|
+
overlaySvg,
|
|
8476
|
+
width: safeWidth,
|
|
8477
|
+
height: safeHeight,
|
|
8478
|
+
imageHeight: safeImageHeight
|
|
8479
|
+
}), {
|
|
8480
|
+
waitUntil: "load"
|
|
8481
|
+
});
|
|
8482
|
+
}
|
|
7970
8483
|
await renderPage.waitForFunction(() => {
|
|
7971
8484
|
const image = document.getElementById("pk-base-image");
|
|
7972
8485
|
return image instanceof HTMLImageElement && image.complete && image.naturalWidth > 0 && image.naturalHeight > 0;
|
|
@@ -7986,13 +8499,13 @@ var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageI
|
|
|
7986
8499
|
fullPage: true,
|
|
7987
8500
|
animations: "disabled"
|
|
7988
8501
|
}).catch((error) => {
|
|
7989
|
-
|
|
8502
|
+
logger14.warning(`watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
7990
8503
|
return null;
|
|
7991
8504
|
});
|
|
7992
8505
|
if (Buffer.isBuffer(composed) && composed.length > 0) {
|
|
7993
8506
|
return composed;
|
|
7994
8507
|
}
|
|
7995
|
-
|
|
8508
|
+
logger14.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: \u672A\u5F97\u5230\u6709\u6548\u622A\u56FE\u7ED3\u679C");
|
|
7996
8509
|
return buffer;
|
|
7997
8510
|
} finally {
|
|
7998
8511
|
await renderScope.close().catch(() => {
|
|
@@ -8005,7 +8518,7 @@ var resolveWithIpLookup = async (page, options = {}) => {
|
|
|
8005
8518
|
}
|
|
8006
8519
|
const probeScope = await openProbePage(page);
|
|
8007
8520
|
if (!probeScope?.page) {
|
|
8008
|
-
|
|
8521
|
+
logger14.warning("ipLookup \u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA probe page");
|
|
8009
8522
|
return null;
|
|
8010
8523
|
}
|
|
8011
8524
|
const timeoutMs = Math.max(
|
|
@@ -8014,12 +8527,12 @@ var resolveWithIpLookup = async (page, options = {}) => {
|
|
|
8014
8527
|
);
|
|
8015
8528
|
try {
|
|
8016
8529
|
const probePage = probeScope.page;
|
|
8017
|
-
|
|
8530
|
+
logger14.info(`ipLookup \u5C1D\u8BD5: url=${DEFAULT_IP_LOOKUP_URL}, timeoutMs=${timeoutMs}`);
|
|
8018
8531
|
const response = await probePage.goto(DEFAULT_IP_LOOKUP_URL, {
|
|
8019
8532
|
waitUntil: "commit",
|
|
8020
8533
|
timeout: timeoutMs
|
|
8021
8534
|
}).catch((error) => {
|
|
8022
|
-
|
|
8535
|
+
logger14.warning(`ipLookup \u8BF7\u6C42\u5931\u8D25: url=${DEFAULT_IP_LOOKUP_URL}, error=${error instanceof Error ? error.message : String(error)}`);
|
|
8023
8536
|
return null;
|
|
8024
8537
|
});
|
|
8025
8538
|
const status = response && typeof response.status === "function" ? response.status() : 0;
|
|
@@ -8041,13 +8554,13 @@ var resolveWithIpLookup = async (page, options = {}) => {
|
|
|
8041
8554
|
}
|
|
8042
8555
|
const parsed = parseIpIpJsonResponse(rawText);
|
|
8043
8556
|
if (parsed?.ip || parsed?.location) {
|
|
8044
|
-
|
|
8557
|
+
logger14.info(`ipLookup \u6210\u529F: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, ip=${parsed.ip || "-"}, loc=${parsed.location || "-"}`);
|
|
8045
8558
|
return parsed;
|
|
8046
8559
|
}
|
|
8047
|
-
|
|
8560
|
+
logger14.warning(`ipLookup \u672A\u89E3\u6790\u51FA IP/Loc: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, preview=${shortenTail(rawText, 120) || "[empty]"}`);
|
|
8048
8561
|
return null;
|
|
8049
8562
|
} catch (error) {
|
|
8050
|
-
|
|
8563
|
+
logger14.warning(`ipLookup \u6267\u884C\u5F02\u5E38\uFF0C\u672A\u83B7\u5F97 IP/Loc: ${error instanceof Error ? error.message : String(error)}`);
|
|
8051
8564
|
return null;
|
|
8052
8565
|
} finally {
|
|
8053
8566
|
await probeScope.close().catch(() => {
|
|
@@ -8061,10 +8574,10 @@ var resolveEnrichment = async (page, baseMeta, options) => {
|
|
|
8061
8574
|
ip: toInline(options.ip, 80),
|
|
8062
8575
|
location: toInline(options.location, 80)
|
|
8063
8576
|
};
|
|
8064
|
-
|
|
8577
|
+
logger14.info(`enrichment \u5F00\u59CB: host=${baseMeta.hostname || "-"}, hasPresetIp=${Boolean(merged.ip)}, hasPresetLoc=${Boolean(merged.location)}, ipLookup=${options.ipLookup !== false}`);
|
|
8065
8578
|
if (!merged.ip || !merged.location) {
|
|
8066
8579
|
if (cached?.ip || cached?.location) {
|
|
8067
|
-
|
|
8580
|
+
logger14.info(`enrichment \u547D\u4E2D\u4E0A\u4E0B\u6587\u7F13\u5B58: ip=${cached.ip || "-"}, loc=${cached.location || "-"}`);
|
|
8068
8581
|
}
|
|
8069
8582
|
fillEnrichment(merged, cached);
|
|
8070
8583
|
}
|
|
@@ -8088,15 +8601,15 @@ var resolveEnrichment = async (page, baseMeta, options) => {
|
|
|
8088
8601
|
"x-geo-country"
|
|
8089
8602
|
]), 80);
|
|
8090
8603
|
if (!merged.location || isWeakLocationValue(merged.location) && headerLocation) {
|
|
8091
|
-
|
|
8604
|
+
logger14.info(`enrichment \u4F7F\u7528\u54CD\u5E94\u5934\u8865\u5145 Loc: ${headerLocation || "-"}`);
|
|
8092
8605
|
merged.location = headerLocation || merged.location;
|
|
8093
8606
|
}
|
|
8094
8607
|
}
|
|
8095
8608
|
writeCachedEnrichment(page, merged);
|
|
8096
8609
|
if (merged.ip || merged.location) {
|
|
8097
|
-
|
|
8610
|
+
logger14.info(`enrichment \u5B8C\u6210: ip=${merged.ip || "-"}, loc=${merged.location || "-"}`);
|
|
8098
8611
|
} else {
|
|
8099
|
-
|
|
8612
|
+
logger14.warning("enrichment \u5B8C\u6210: \u672A\u83B7\u5F97 IP/Loc");
|
|
8100
8613
|
}
|
|
8101
8614
|
return merged;
|
|
8102
8615
|
};
|
|
@@ -8901,7 +9414,7 @@ var buildWatermarkifySvg = (meta, imageWidth, imageHeight) => {
|
|
|
8901
9414
|
</svg>
|
|
8902
9415
|
`;
|
|
8903
9416
|
};
|
|
8904
|
-
var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
|
|
9417
|
+
var watermarkifyScreenshotBuffer = async (buffer, meta, page = null, options = {}) => {
|
|
8905
9418
|
const hasWatermark = meta?.watermark?.enabled !== false && normalizeText(meta?.watermarkText);
|
|
8906
9419
|
const hasStrip = meta?.strip?.enabled !== false && Array.isArray(meta?.stripSegments) && meta.stripSegments.length > 0;
|
|
8907
9420
|
if (!Buffer.isBuffer(buffer) || !meta || !hasWatermark && !hasStrip) {
|
|
@@ -8909,7 +9422,7 @@ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
|
|
|
8909
9422
|
}
|
|
8910
9423
|
const imageInfo = readImageInfo(buffer);
|
|
8911
9424
|
if (!imageInfo.width || !imageInfo.height || !imageInfo.mimeType) {
|
|
8912
|
-
|
|
9425
|
+
logger14.warning("watermarkify \u8DF3\u8FC7: \u65E0\u6CD5\u89E3\u6790\u622A\u56FE\u5C3A\u5BF8\u6216\u683C\u5F0F");
|
|
8913
9426
|
return buffer;
|
|
8914
9427
|
}
|
|
8915
9428
|
const isMobileStrip = normalizeDevice(meta.device) === Device.Mobile && hasStrip;
|
|
@@ -8922,12 +9435,12 @@ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
|
|
|
8922
9435
|
if (!overlaySvg) {
|
|
8923
9436
|
return buffer;
|
|
8924
9437
|
}
|
|
8925
|
-
return await composeScreenshotBufferWithBrowser(page, buffer, overlaySvg, outputImageInfo);
|
|
9438
|
+
return await composeScreenshotBufferWithBrowser(page, buffer, overlaySvg, outputImageInfo, options);
|
|
8926
9439
|
};
|
|
8927
9440
|
|
|
8928
9441
|
// src/internals/compression.js
|
|
8929
9442
|
import { Jimp, JimpMime, ResizeStrategy } from "jimp";
|
|
8930
|
-
var
|
|
9443
|
+
var logger15 = createInternalLogger("Compression");
|
|
8931
9444
|
var DEFAULT_SCREENSHOT_MAX_BYTES = 5 * 1024 * 1024;
|
|
8932
9445
|
var DEFAULT_SCREENSHOT_OUTPUT_TYPE = "jpeg";
|
|
8933
9446
|
var DEFAULT_SCREENSHOT_QUALITY = 0.72;
|
|
@@ -9046,18 +9559,18 @@ var compressImageBufferToBase64 = async (buffer, compression) => {
|
|
|
9046
9559
|
return buffer.toString("base64");
|
|
9047
9560
|
}
|
|
9048
9561
|
const result = await compressImageBuffer(buffer, compression).catch((error) => {
|
|
9049
|
-
|
|
9562
|
+
logger15.warning(`captureScreen \u538B\u7F29\u5931\u8D25\uFF0C\u8FD4\u56DE\u539F\u56FE: ${error instanceof Error ? error.message : String(error)}`);
|
|
9050
9563
|
return null;
|
|
9051
9564
|
});
|
|
9052
9565
|
if (!result?.buffer) {
|
|
9053
9566
|
return buffer.toString("base64");
|
|
9054
9567
|
}
|
|
9055
9568
|
if (result.withinLimit) {
|
|
9056
|
-
|
|
9569
|
+
logger15.info(
|
|
9057
9570
|
`captureScreen \u5DF2\u538B\u7F29: ${originalBytes} -> ${result.bytes} bytes, format=${result.format}, quality=${result.quality}, scale=${result.scale}, size=${result.width}x${result.height}`
|
|
9058
9571
|
);
|
|
9059
9572
|
} else {
|
|
9060
|
-
|
|
9573
|
+
logger15.warning(
|
|
9061
9574
|
`captureScreen \u538B\u7F29\u540E\u4ECD\u8D85\u8FC7\u76EE\u6807: ${originalBytes} -> ${result.bytes} bytes, maxBytes=${compression.maxBytes}, format=${result.format}, quality=${result.quality}, scale=${result.scale}`
|
|
9062
9575
|
);
|
|
9063
9576
|
}
|
|
@@ -9065,7 +9578,7 @@ var compressImageBufferToBase64 = async (buffer, compression) => {
|
|
|
9065
9578
|
};
|
|
9066
9579
|
|
|
9067
9580
|
// src/share.js
|
|
9068
|
-
var
|
|
9581
|
+
var logger16 = createInternalLogger("Share");
|
|
9069
9582
|
var DEFAULT_TIMEOUT_MS2 = 50 * 1e3;
|
|
9070
9583
|
var DEFAULT_PAYLOAD_SNAPSHOT_MAX_LEN = 500;
|
|
9071
9584
|
var DEFAULT_POLL_INTERVAL_MS = 120;
|
|
@@ -9135,9 +9648,9 @@ var normalizeXurl = (value) => {
|
|
|
9135
9648
|
var normalizeShare = (share) => {
|
|
9136
9649
|
const source = share && typeof share === "object" ? share : {};
|
|
9137
9650
|
const modeRaw = String(source.mode || "dom").trim().toLowerCase();
|
|
9138
|
-
const
|
|
9651
|
+
const mode2 = ["dom", "response", "custom"].includes(modeRaw) ? modeRaw : "dom";
|
|
9139
9652
|
return {
|
|
9140
|
-
mode,
|
|
9653
|
+
mode: mode2,
|
|
9141
9654
|
prefix: normalizePrefix(source.prefix),
|
|
9142
9655
|
xurl: normalizeXurl(source.xurl)
|
|
9143
9656
|
};
|
|
@@ -9198,13 +9711,13 @@ var parseJsonSafely = (text) => {
|
|
|
9198
9711
|
var createDomShareMonitor = async (page, options = {}) => {
|
|
9199
9712
|
const prefix = normalizePrefix(options.prefix);
|
|
9200
9713
|
const selectors = options.selectors ?? "html";
|
|
9201
|
-
const
|
|
9714
|
+
const mode2 = options.mode ?? Mutation.Mode.All;
|
|
9202
9715
|
const onMatch = typeof options.onMatch === "function" ? options.onMatch : null;
|
|
9203
9716
|
const onTelemetry = typeof options.onTelemetry === "function" ? options.onTelemetry : null;
|
|
9204
9717
|
let matched = false;
|
|
9205
|
-
|
|
9718
|
+
logger16.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode2}`);
|
|
9206
9719
|
const monitor = await Mutation.useMonitor(page, selectors, {
|
|
9207
|
-
mode,
|
|
9720
|
+
mode: mode2,
|
|
9208
9721
|
onMutation: (context = {}) => {
|
|
9209
9722
|
if (matched) return;
|
|
9210
9723
|
const mutationCount = Number(context.mutationCount || 0);
|
|
@@ -9220,12 +9733,12 @@ ${text}`;
|
|
|
9220
9733
|
});
|
|
9221
9734
|
}
|
|
9222
9735
|
if (mutationCount <= 5 || mutationCount % 50 === 0) {
|
|
9223
|
-
|
|
9736
|
+
logger16.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);
|
|
9224
9737
|
}
|
|
9225
9738
|
const [candidate] = Utils.parseLinks(rawDom, { prefix }) || [];
|
|
9226
9739
|
if (!candidate) return;
|
|
9227
9740
|
matched = true;
|
|
9228
|
-
|
|
9741
|
+
logger16.success("captureLink.domHit", `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);
|
|
9229
9742
|
if (onMatch) {
|
|
9230
9743
|
onMatch({
|
|
9231
9744
|
link: candidate,
|
|
@@ -9241,7 +9754,7 @@ ${text}`;
|
|
|
9241
9754
|
return {
|
|
9242
9755
|
stop: async () => {
|
|
9243
9756
|
const result = await monitor.stop();
|
|
9244
|
-
|
|
9757
|
+
logger16.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);
|
|
9245
9758
|
return result;
|
|
9246
9759
|
}
|
|
9247
9760
|
};
|
|
@@ -9290,8 +9803,8 @@ var Share = {
|
|
|
9290
9803
|
if (share.mode === "response" && apiMatchers.length === 0) {
|
|
9291
9804
|
throw new Error("Share.captureLink requires share.xurl[0] api matcher when mode=response");
|
|
9292
9805
|
}
|
|
9293
|
-
|
|
9294
|
-
|
|
9806
|
+
logger16.start("captureLink", `mode=${share.mode}, timeoutMs=${timeoutDisabled ? "disabled" : timeoutMs}, prefix=${share.prefix}`);
|
|
9807
|
+
logger16.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);
|
|
9295
9808
|
const stats = {
|
|
9296
9809
|
actionTimedOut: false,
|
|
9297
9810
|
domMutationCount: 0,
|
|
@@ -9303,7 +9816,7 @@ var Share = {
|
|
|
9303
9816
|
responseSampleUrls: []
|
|
9304
9817
|
};
|
|
9305
9818
|
if (isAborted()) {
|
|
9306
|
-
|
|
9819
|
+
logger16.warning(`captureLink \u5DF2\u53D6\u6D88: ${abortReason()}`);
|
|
9307
9820
|
return {
|
|
9308
9821
|
link: null,
|
|
9309
9822
|
payloadText: "",
|
|
@@ -9326,7 +9839,7 @@ var Share = {
|
|
|
9326
9839
|
link: validated,
|
|
9327
9840
|
payloadText: String(payloadText || "")
|
|
9328
9841
|
};
|
|
9329
|
-
|
|
9842
|
+
logger16.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);
|
|
9330
9843
|
return true;
|
|
9331
9844
|
};
|
|
9332
9845
|
const resolveResponseCandidate = (responseText) => {
|
|
@@ -9361,7 +9874,7 @@ var Share = {
|
|
|
9361
9874
|
try {
|
|
9362
9875
|
await monitor.stop();
|
|
9363
9876
|
} catch (error) {
|
|
9364
|
-
|
|
9877
|
+
logger16.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
9365
9878
|
}
|
|
9366
9879
|
};
|
|
9367
9880
|
const onResponse = async (response) => {
|
|
@@ -9375,29 +9888,29 @@ var Share = {
|
|
|
9375
9888
|
stats.responseSampleUrls.push(url);
|
|
9376
9889
|
}
|
|
9377
9890
|
if (stats.responseObserved <= 5) {
|
|
9378
|
-
|
|
9891
|
+
logger16.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);
|
|
9379
9892
|
}
|
|
9380
9893
|
if (!apiMatchers.some((matcher) => url.includes(matcher))) return;
|
|
9381
9894
|
stats.responseMatched += 1;
|
|
9382
9895
|
stats.lastMatchedUrl = url;
|
|
9383
|
-
|
|
9896
|
+
logger16.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);
|
|
9384
9897
|
const text = await response.text();
|
|
9385
9898
|
const hit = resolveResponseCandidate(text);
|
|
9386
9899
|
if (!hit?.link) {
|
|
9387
9900
|
if (stats.responseMatched <= 3) {
|
|
9388
|
-
|
|
9901
|
+
logger16.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);
|
|
9389
9902
|
}
|
|
9390
9903
|
return;
|
|
9391
9904
|
}
|
|
9392
9905
|
stats.responseResolved += 1;
|
|
9393
|
-
|
|
9906
|
+
logger16.success("captureLink.responseHit", `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);
|
|
9394
9907
|
setCandidate("response", hit.link, hit.payloadText);
|
|
9395
9908
|
} catch (error) {
|
|
9396
|
-
|
|
9909
|
+
logger16.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);
|
|
9397
9910
|
}
|
|
9398
9911
|
};
|
|
9399
9912
|
if (share.mode === "dom") {
|
|
9400
|
-
|
|
9913
|
+
logger16.info("\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C");
|
|
9401
9914
|
domMonitor = await createDomShareMonitor(page, {
|
|
9402
9915
|
prefix: share.prefix,
|
|
9403
9916
|
selectors: domSelectors,
|
|
@@ -9412,17 +9925,17 @@ var Share = {
|
|
|
9412
9925
|
});
|
|
9413
9926
|
}
|
|
9414
9927
|
if (share.mode === "response") {
|
|
9415
|
-
|
|
9928
|
+
logger16.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);
|
|
9416
9929
|
page.on("response", onResponse);
|
|
9417
9930
|
}
|
|
9418
9931
|
if (share.mode === "custom") {
|
|
9419
|
-
|
|
9932
|
+
logger16.info("\u5F53\u524D\u4E3A custom \u6A21\u5F0F\uFF0C\u5C06\u4F7F\u7528 performActions \u8FD4\u56DE\u503C");
|
|
9420
9933
|
}
|
|
9421
9934
|
const deadline = timeoutDisabled ? Infinity : Date.now() + timeoutMs;
|
|
9422
9935
|
const getRemainingMs = () => timeoutDisabled ? Infinity : Math.max(0, deadline - Date.now());
|
|
9423
9936
|
try {
|
|
9424
9937
|
const actionTimeout = getRemainingMs();
|
|
9425
|
-
|
|
9938
|
+
logger16.start("captureLink.performActions", `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${timeoutDisabled ? "disabled" : `${actionTimeout}ms`}`);
|
|
9426
9939
|
let actionValue;
|
|
9427
9940
|
if (!isAborted() && actionTimeout > 0) {
|
|
9428
9941
|
let timer = null;
|
|
@@ -9435,30 +9948,30 @@ var Share = {
|
|
|
9435
9948
|
]);
|
|
9436
9949
|
if (timer) clearTimeout(timer);
|
|
9437
9950
|
if (actionResult.type === "error") {
|
|
9438
|
-
|
|
9951
|
+
logger16.fail("captureLink.performActions", actionResult.error);
|
|
9439
9952
|
throw actionResult.error;
|
|
9440
9953
|
}
|
|
9441
9954
|
if (actionResult.type === "timeout") {
|
|
9442
9955
|
stats.actionTimedOut = true;
|
|
9443
|
-
|
|
9956
|
+
logger16.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);
|
|
9444
9957
|
} else {
|
|
9445
9958
|
actionValue = actionResult.result;
|
|
9446
|
-
|
|
9959
|
+
logger16.success("captureLink.performActions", "\u6267\u884C\u52A8\u4F5C\u5B8C\u6210");
|
|
9447
9960
|
}
|
|
9448
9961
|
}
|
|
9449
9962
|
if (share.mode === "custom") {
|
|
9450
9963
|
const customLink = typeof actionValue === "string" ? actionValue : actionValue?.link || actionValue?.payloadText;
|
|
9451
9964
|
const customPayloadText = typeof actionValue === "string" ? actionValue : actionValue?.payloadText;
|
|
9452
9965
|
if (setCandidate("custom", customLink, customPayloadText)) {
|
|
9453
|
-
|
|
9966
|
+
logger16.success("captureLink.customResult", `custom \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: link=${candidates.custom.link}`);
|
|
9454
9967
|
} else {
|
|
9455
|
-
|
|
9968
|
+
logger16.warning("performActions \u6267\u884C\u5B8C\u6210\u4F46\u672A\u8FD4\u56DE\u6709\u6548\u5206\u4EAB\u94FE\u63A5");
|
|
9456
9969
|
}
|
|
9457
9970
|
}
|
|
9458
9971
|
let nextProgressLogTs = Date.now() + 3e3;
|
|
9459
9972
|
while (true) {
|
|
9460
9973
|
if (isAborted()) {
|
|
9461
|
-
|
|
9974
|
+
logger16.warning(`captureLink \u5DF2\u53D6\u6D88: ${abortReason()}`);
|
|
9462
9975
|
return {
|
|
9463
9976
|
link: null,
|
|
9464
9977
|
payloadText: "",
|
|
@@ -9468,7 +9981,7 @@ var Share = {
|
|
|
9468
9981
|
}
|
|
9469
9982
|
const selected = candidates[share.mode];
|
|
9470
9983
|
if (selected?.link) {
|
|
9471
|
-
|
|
9984
|
+
logger16.success("captureLink", `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);
|
|
9472
9985
|
return {
|
|
9473
9986
|
link: selected.link,
|
|
9474
9987
|
payloadText: selected.payloadText,
|
|
@@ -9481,19 +9994,19 @@ var Share = {
|
|
|
9481
9994
|
if (remaining <= 0) break;
|
|
9482
9995
|
const now = Date.now();
|
|
9483
9996
|
if (now >= nextProgressLogTs) {
|
|
9484
|
-
|
|
9997
|
+
logger16.info(
|
|
9485
9998
|
`captureLink \u7B49\u5F85\u4E2D: remaining=${timeoutDisabled ? "disabled" : `${remaining}ms`}, domMutationCount=${stats.domMutationCount}, responseMatched=${stats.responseMatched}`
|
|
9486
9999
|
);
|
|
9487
10000
|
nextProgressLogTs = now + 5e3;
|
|
9488
10001
|
}
|
|
9489
|
-
await
|
|
10002
|
+
await delay5(Math.max(0, Math.min(DEFAULT_POLL_INTERVAL_MS, remaining)));
|
|
9490
10003
|
}
|
|
9491
10004
|
if (!timeoutDisabled && share.mode === "response" && stats.responseMatched === 0) {
|
|
9492
|
-
|
|
10005
|
+
logger16.warning(
|
|
9493
10006
|
`\u63A5\u53E3\u76D1\u542C\u672A\u547D\u4E2D: apiMatchers=${toJsonInline(apiMatchers, 220)}, \u54CD\u5E94\u6837\u672CURLs=${toJsonInline(stats.responseSampleUrls, 420)}`
|
|
9494
10007
|
);
|
|
9495
10008
|
}
|
|
9496
|
-
|
|
10009
|
+
logger16.warning(
|
|
9497
10010
|
`captureLink ${timeoutDisabled ? "\u672A\u62FF\u5230\u94FE\u63A5" : "\u8D85\u65F6\u672A\u62FF\u5230\u94FE\u63A5"}: mode=${share.mode}, actionTimedOut=${stats.actionTimedOut}, domMutationCount=${stats.domMutationCount}, responseObserved=${stats.responseObserved}, responseMatched=${stats.responseMatched}, lastMatchedUrl=${stats.lastMatchedUrl || "none"}`
|
|
9498
10011
|
);
|
|
9499
10012
|
return {
|
|
@@ -9505,7 +10018,7 @@ var Share = {
|
|
|
9505
10018
|
} finally {
|
|
9506
10019
|
if (share.mode === "response") {
|
|
9507
10020
|
page.off("response", onResponse);
|
|
9508
|
-
|
|
10021
|
+
logger16.info("response \u76D1\u542C\u5DF2\u5378\u8F7D");
|
|
9509
10022
|
}
|
|
9510
10023
|
await stopDomMonitor();
|
|
9511
10024
|
}
|
|
@@ -9520,12 +10033,14 @@ var Share = {
|
|
|
9520
10033
|
* @param {number} [options.maxBytes] 默认 5MiB,返回 base64 超过后会压缩
|
|
9521
10034
|
* @param {'jpeg'|'jpg'} [options.type] 压缩输出格式,默认 jpeg
|
|
9522
10035
|
* @param {boolean|Object} [options.compression] 传 false 可关闭压缩
|
|
10036
|
+
* @param {'default'|'cloak'} [options.mode] 截图水印合成模式,默认取当前 toolkit mode
|
|
9523
10037
|
* @returns {Promise<string>} base64 image
|
|
9524
10038
|
*/
|
|
9525
10039
|
async captureScreen(page, options = {}) {
|
|
9526
10040
|
const restore = options.restore ?? false;
|
|
9527
10041
|
const screenshotWatermarkify = resolveCaptureScreenWatermarkify(page, options.watermarkify);
|
|
9528
10042
|
const compression = resolveImageCompression(options);
|
|
10043
|
+
const screenshotMode = options.mode ?? getToolkitMode();
|
|
9529
10044
|
const captureOptions = {
|
|
9530
10045
|
restore,
|
|
9531
10046
|
maxHeight: options.maxHeight,
|
|
@@ -9540,7 +10055,9 @@ var Share = {
|
|
|
9540
10055
|
...screenshotWatermarkify,
|
|
9541
10056
|
capturedAt
|
|
9542
10057
|
});
|
|
9543
|
-
outputBuffer = await watermarkifyScreenshotBuffer(rawBuffer, watermarkifyMeta, page
|
|
10058
|
+
outputBuffer = await watermarkifyScreenshotBuffer(rawBuffer, watermarkifyMeta, page, {
|
|
10059
|
+
mode: screenshotMode
|
|
10060
|
+
});
|
|
9544
10061
|
}
|
|
9545
10062
|
return await compressImageBufferToBase64(outputBuffer, compression);
|
|
9546
10063
|
}
|
|
@@ -9548,8 +10065,13 @@ var Share = {
|
|
|
9548
10065
|
|
|
9549
10066
|
// entrys/node.js
|
|
9550
10067
|
Logger.setLogger(crawleeLog);
|
|
9551
|
-
var
|
|
9552
|
-
|
|
10068
|
+
var ToolkitMode = Object.freeze({
|
|
10069
|
+
default: Mode.Default,
|
|
10070
|
+
cloak: Mode.Cloak
|
|
10071
|
+
});
|
|
10072
|
+
var usePlaywrightToolKit = (mode2 = Mode.Default) => {
|
|
10073
|
+
setToolkitMode(mode2);
|
|
10074
|
+
const toolkit = {
|
|
9553
10075
|
ApifyKit,
|
|
9554
10076
|
AntiCheat,
|
|
9555
10077
|
DeviceInput,
|
|
@@ -9569,7 +10091,9 @@ var usePlaywrightToolKit = () => {
|
|
|
9569
10091
|
ByPass,
|
|
9570
10092
|
$Internals: { LOG_TEMPLATES, stripAnsi }
|
|
9571
10093
|
};
|
|
10094
|
+
return toolkit;
|
|
9572
10095
|
};
|
|
10096
|
+
usePlaywrightToolKit.Mode = ToolkitMode;
|
|
9573
10097
|
export {
|
|
9574
10098
|
usePlaywrightToolKit
|
|
9575
10099
|
};
|