@skrillex1224/playwright-toolkit 3.0.15 → 3.0.17
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 +446 -163
- package/dist/browser.js.map +4 -4
- package/dist/index.cjs +1224 -517
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +1222 -515
- 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
|
};
|
|
@@ -1445,6 +1450,7 @@ var ProxyMeterRuntime = {
|
|
|
1445
1450
|
|
|
1446
1451
|
// src/runtime-env.js
|
|
1447
1452
|
var BROWSER_PROFILE_SCHEMA_VERSION = 1;
|
|
1453
|
+
var SUPPORTED_CLOAK_FINGERPRINT_PLATFORMS = /* @__PURE__ */ new Set(["linux", "macos", "windows"]);
|
|
1448
1454
|
var rememberedRuntimeState = null;
|
|
1449
1455
|
var isPlainObject = (value) => value && typeof value === "object" && !Array.isArray(value);
|
|
1450
1456
|
var normalizeKnownDevice = (value) => {
|
|
@@ -1453,6 +1459,22 @@ var normalizeKnownDevice = (value) => {
|
|
|
1453
1459
|
if (raw === Device.Desktop) return Device.Desktop;
|
|
1454
1460
|
return "";
|
|
1455
1461
|
};
|
|
1462
|
+
var normalizeCloakSeed = (value) => {
|
|
1463
|
+
const numericSeed = Number(value);
|
|
1464
|
+
if (Number.isSafeInteger(numericSeed) && numericSeed > 0) {
|
|
1465
|
+
return numericSeed;
|
|
1466
|
+
}
|
|
1467
|
+
const raw = String(value || "").trim();
|
|
1468
|
+
if (!/^\d+$/.test(raw)) {
|
|
1469
|
+
return 0;
|
|
1470
|
+
}
|
|
1471
|
+
const parsedSeed = Number(raw);
|
|
1472
|
+
return Number.isSafeInteger(parsedSeed) && parsedSeed > 0 ? parsedSeed : 0;
|
|
1473
|
+
};
|
|
1474
|
+
var normalizeCloakFingerprintPlatform = (value) => {
|
|
1475
|
+
const raw = String(value || "").trim().toLowerCase();
|
|
1476
|
+
return SUPPORTED_CLOAK_FINGERPRINT_PLATFORMS.has(raw) ? raw : "";
|
|
1477
|
+
};
|
|
1456
1478
|
var deepClone = (value) => {
|
|
1457
1479
|
if (value == null) return value;
|
|
1458
1480
|
try {
|
|
@@ -1823,6 +1845,14 @@ var normalizeBrowserProfileCore = (value) => {
|
|
|
1823
1845
|
if (Number.isFinite(browserMajorVersion) && browserMajorVersion > 0) {
|
|
1824
1846
|
profile.browser_major_version = browserMajorVersion;
|
|
1825
1847
|
}
|
|
1848
|
+
const cloakSeed = normalizeCloakSeed(source.cloak_seed);
|
|
1849
|
+
if (cloakSeed > 0) {
|
|
1850
|
+
profile.cloak_seed = cloakSeed;
|
|
1851
|
+
}
|
|
1852
|
+
const cloakFingerprintPlatform = normalizeCloakFingerprintPlatform(source.cloak_fingerprint_platform);
|
|
1853
|
+
if (cloakFingerprintPlatform) {
|
|
1854
|
+
profile.cloak_fingerprint_platform = cloakFingerprintPlatform;
|
|
1855
|
+
}
|
|
1826
1856
|
const schemaVersion = Number(source.schema_version || 0);
|
|
1827
1857
|
if (Number.isFinite(schemaVersion) && schemaVersion > 0) {
|
|
1828
1858
|
profile.schema_version = schemaVersion;
|
|
@@ -1910,8 +1940,8 @@ var normalizeBrowserProfile = (value) => {
|
|
|
1910
1940
|
payload: buildBrowserProfilePayload(core, observed)
|
|
1911
1941
|
};
|
|
1912
1942
|
};
|
|
1913
|
-
var rememberRuntimeState = (
|
|
1914
|
-
rememberedRuntimeState = deepClone(
|
|
1943
|
+
var rememberRuntimeState = (state2) => {
|
|
1944
|
+
rememberedRuntimeState = deepClone(state2);
|
|
1915
1945
|
return rememberedRuntimeState;
|
|
1916
1946
|
};
|
|
1917
1947
|
var normalizeRuntimeState = (source = {}, actor = "") => {
|
|
@@ -1970,7 +2000,7 @@ var RuntimeEnv = {
|
|
|
1970
2000
|
} else {
|
|
1971
2001
|
delete normalizedRuntime.browser_profile;
|
|
1972
2002
|
}
|
|
1973
|
-
const
|
|
2003
|
+
const state2 = {
|
|
1974
2004
|
actor: resolvedActor,
|
|
1975
2005
|
device,
|
|
1976
2006
|
runtime: normalizedRuntime,
|
|
@@ -1984,73 +2014,73 @@ var RuntimeEnv = {
|
|
|
1984
2014
|
browserProfileCore: browserProfile.core,
|
|
1985
2015
|
browserProfileObserved: browserProfile.observed
|
|
1986
2016
|
};
|
|
1987
|
-
rememberRuntimeState(
|
|
1988
|
-
return
|
|
2017
|
+
rememberRuntimeState(state2);
|
|
2018
|
+
return state2;
|
|
1989
2019
|
},
|
|
1990
2020
|
// buildEnvPatch 只构造允许回写到后端 env 的字段集合。
|
|
1991
2021
|
buildEnvPatch(source = {}, actor = "") {
|
|
1992
|
-
const
|
|
1993
|
-
const browserProfile = buildBrowserProfilePayload(
|
|
2022
|
+
const state2 = normalizeRuntimeState(source, actor);
|
|
2023
|
+
const browserProfile = buildBrowserProfilePayload(state2.browserProfileCore, state2.browserProfileObserved);
|
|
1994
2024
|
const envPatch = {
|
|
1995
|
-
...Array.isArray(
|
|
1996
|
-
...Object.keys(
|
|
1997
|
-
...Object.keys(
|
|
2025
|
+
...Array.isArray(state2.cookies) && state2.cookies.length > 0 ? { cookies: state2.cookies } : {},
|
|
2026
|
+
...Object.keys(state2.localStorage || {}).length > 0 ? { local_storage: state2.localStorage } : {},
|
|
2027
|
+
...Object.keys(state2.sessionStorage || {}).length > 0 ? { session_storage: state2.sessionStorage } : {},
|
|
1998
2028
|
...Object.keys(browserProfile).length > 0 ? { browser_profile: browserProfile } : {}
|
|
1999
2029
|
};
|
|
2000
2030
|
return Object.keys(envPatch).length > 0 ? envPatch : null;
|
|
2001
2031
|
},
|
|
2002
2032
|
// hasLoginState 只判断 runtime 是否存在有效载荷,不再区分具体字段来源。
|
|
2003
2033
|
hasLoginState(source = {}, actor = "") {
|
|
2004
|
-
const
|
|
2005
|
-
return isPlainObject(
|
|
2034
|
+
const state2 = normalizeRuntimeState(source, actor);
|
|
2035
|
+
return isPlainObject(state2.runtime) && Object.keys(state2.runtime || {}).length > 0;
|
|
2006
2036
|
},
|
|
2007
2037
|
rememberState(source = {}) {
|
|
2008
|
-
const
|
|
2009
|
-
rememberRuntimeState(
|
|
2038
|
+
const state2 = normalizeRuntimeState(source);
|
|
2039
|
+
rememberRuntimeState(state2);
|
|
2010
2040
|
return RuntimeEnv.peekRememberedState();
|
|
2011
2041
|
},
|
|
2012
2042
|
peekRememberedState() {
|
|
2013
2043
|
return rememberedRuntimeState ? deepClone(rememberedRuntimeState) : null;
|
|
2014
2044
|
},
|
|
2015
2045
|
getBrowserProfileCore(source = {}, actor = "") {
|
|
2016
|
-
const
|
|
2017
|
-
return deepClone(
|
|
2046
|
+
const state2 = normalizeRuntimeState(source, actor);
|
|
2047
|
+
return deepClone(state2.browserProfileCore || {});
|
|
2018
2048
|
},
|
|
2019
2049
|
setBrowserProfileCore(source = {}, core = {}, actor = "") {
|
|
2020
|
-
const
|
|
2050
|
+
const state2 = normalizeRuntimeState(source, actor);
|
|
2021
2051
|
const normalizedCore = normalizeBrowserProfileCore({
|
|
2022
2052
|
...core,
|
|
2023
|
-
device: normalizeKnownDevice(core?.device) ||
|
|
2053
|
+
device: normalizeKnownDevice(core?.device) || state2.device
|
|
2024
2054
|
});
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
if (Object.keys(
|
|
2028
|
-
|
|
2055
|
+
state2.browserProfileCore = normalizedCore;
|
|
2056
|
+
state2.browserProfile = buildBrowserProfilePayload(normalizedCore, state2.browserProfileObserved);
|
|
2057
|
+
if (Object.keys(state2.browserProfile).length > 0) {
|
|
2058
|
+
state2.runtime.browser_profile = state2.browserProfile;
|
|
2029
2059
|
} else {
|
|
2030
|
-
delete
|
|
2060
|
+
delete state2.runtime.browser_profile;
|
|
2031
2061
|
}
|
|
2032
|
-
rememberRuntimeState(
|
|
2033
|
-
return
|
|
2062
|
+
rememberRuntimeState(state2);
|
|
2063
|
+
return state2;
|
|
2034
2064
|
},
|
|
2035
2065
|
// applyToPage 只负责把登录态相关字段注入页面:
|
|
2036
2066
|
// cookies / localStorage / sessionStorage。
|
|
2037
2067
|
// 指纹、时区、UA、viewport 的回放发生在 launch.js 启动阶段,不在这里做。
|
|
2038
2068
|
async applyToPage(page, source = {}, options = {}) {
|
|
2039
2069
|
if (!page) return;
|
|
2040
|
-
let
|
|
2070
|
+
let state2 = normalizeRuntimeState(source, options?.actor || "");
|
|
2041
2071
|
if (typeof options?.preapply === "function") {
|
|
2042
|
-
|
|
2043
|
-
rememberRuntimeState(
|
|
2072
|
+
state2 = await options.preapply(state2) || state2;
|
|
2073
|
+
rememberRuntimeState(state2);
|
|
2044
2074
|
}
|
|
2045
2075
|
Object.defineProperty(page, PageRuntimeStateKey, {
|
|
2046
2076
|
configurable: true,
|
|
2047
2077
|
enumerable: false,
|
|
2048
2078
|
writable: true,
|
|
2049
|
-
value:
|
|
2079
|
+
value: state2
|
|
2050
2080
|
});
|
|
2051
|
-
const localStorage =
|
|
2052
|
-
const sessionStorage =
|
|
2053
|
-
const cookies = (
|
|
2081
|
+
const localStorage = state2.localStorage || {};
|
|
2082
|
+
const sessionStorage = state2.sessionStorage || {};
|
|
2083
|
+
const cookies = (state2.cookies || []).map((cookie) => {
|
|
2054
2084
|
const normalized = { ...cookie };
|
|
2055
2085
|
if (!normalized.path) {
|
|
2056
2086
|
normalized.path = "/";
|
|
@@ -2088,8 +2118,8 @@ var RuntimeEnv = {
|
|
|
2088
2118
|
},
|
|
2089
2119
|
// captureEnvPatch 在任务结束时采集最新环境快照,用于 pushSuccess / pushFailed 自动回写。
|
|
2090
2120
|
async captureEnvPatch(page, source = {}, options = {}) {
|
|
2091
|
-
const
|
|
2092
|
-
const baseline = RuntimeEnv.buildEnvPatch(
|
|
2121
|
+
const state2 = normalizeRuntimeState(source, options?.actor || "");
|
|
2122
|
+
const baseline = RuntimeEnv.buildEnvPatch(state2) || {};
|
|
2093
2123
|
if (!page || typeof page.evaluate !== "function" || typeof page.context !== "function") {
|
|
2094
2124
|
return Object.keys(baseline).length > 0 ? baseline : null;
|
|
2095
2125
|
}
|
|
@@ -2108,7 +2138,7 @@ var RuntimeEnv = {
|
|
|
2108
2138
|
cookies
|
|
2109
2139
|
},
|
|
2110
2140
|
{
|
|
2111
|
-
browserProfileCore:
|
|
2141
|
+
browserProfileCore: state2.browserProfileCore
|
|
2112
2142
|
}
|
|
2113
2143
|
);
|
|
2114
2144
|
return RuntimeEnv.mergeEnvPatches(baseline, capturedPatch);
|
|
@@ -2122,11 +2152,11 @@ var RuntimeEnv = {
|
|
|
2122
2152
|
var logger3 = createInternalLogger("ApifyKit");
|
|
2123
2153
|
var resolveRuntimeContext = (input) => {
|
|
2124
2154
|
const rememberedState = RuntimeEnv.peekRememberedState();
|
|
2125
|
-
const
|
|
2126
|
-
const envPatch = RuntimeEnv.buildEnvPatch(
|
|
2155
|
+
const state2 = rememberedState || RuntimeEnv.parseInput(input || {});
|
|
2156
|
+
const envPatch = RuntimeEnv.buildEnvPatch(state2) || null;
|
|
2127
2157
|
return {
|
|
2128
|
-
actor:
|
|
2129
|
-
runtime:
|
|
2158
|
+
actor: state2.actor,
|
|
2159
|
+
runtime: state2.runtime,
|
|
2130
2160
|
envPatch
|
|
2131
2161
|
};
|
|
2132
2162
|
};
|
|
@@ -2485,8 +2515,82 @@ var Utils = {
|
|
|
2485
2515
|
}
|
|
2486
2516
|
};
|
|
2487
2517
|
|
|
2488
|
-
// src/
|
|
2489
|
-
var
|
|
2518
|
+
// src/internals/context.js
|
|
2519
|
+
var state = {
|
|
2520
|
+
mode: Mode.Default
|
|
2521
|
+
};
|
|
2522
|
+
var normalizeStrategies = (strategies) => strategies && typeof strategies === "object" ? strategies : {};
|
|
2523
|
+
var ToolkitContext = {
|
|
2524
|
+
get mode() {
|
|
2525
|
+
return state.mode;
|
|
2526
|
+
},
|
|
2527
|
+
setMode(mode2 = Mode.Default) {
|
|
2528
|
+
state.mode = normalizeMode(mode2, Mode.Default);
|
|
2529
|
+
return state.mode;
|
|
2530
|
+
}
|
|
2531
|
+
};
|
|
2532
|
+
var getToolkitMode = () => state.mode;
|
|
2533
|
+
var setToolkitMode = (mode2 = Mode.Default) => ToolkitContext.setMode(mode2);
|
|
2534
|
+
var resolveModeStrategy = (strategies = {}, mode2 = getToolkitMode(), fallbackMode = Mode.Default) => {
|
|
2535
|
+
const normalizedStrategies = normalizeStrategies(strategies);
|
|
2536
|
+
const normalizedMode = normalizeMode(mode2, fallbackMode);
|
|
2537
|
+
const strategy = normalizedStrategies[normalizedMode] ?? normalizedStrategies[fallbackMode] ?? Object.values(normalizedStrategies).find(Boolean) ?? null;
|
|
2538
|
+
return {
|
|
2539
|
+
mode: normalizedMode,
|
|
2540
|
+
strategy
|
|
2541
|
+
};
|
|
2542
|
+
};
|
|
2543
|
+
|
|
2544
|
+
// src/internals/reflect.js
|
|
2545
|
+
var normalizeStrategies2 = (strategies) => strategies && typeof strategies === "object" ? strategies : {};
|
|
2546
|
+
var collectFunctionNames = (strategies = []) => {
|
|
2547
|
+
const names = /* @__PURE__ */ new Set();
|
|
2548
|
+
for (const strategy of strategies) {
|
|
2549
|
+
if (!strategy || typeof strategy !== "object") continue;
|
|
2550
|
+
for (const name of Reflect.ownKeys(strategy)) {
|
|
2551
|
+
if (typeof name === "string" && typeof strategy[name] === "function") {
|
|
2552
|
+
names.add(name);
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
}
|
|
2556
|
+
return names;
|
|
2557
|
+
};
|
|
2558
|
+
var methodDescriptor = (namespace, name, resolveTarget) => ({
|
|
2559
|
+
enumerable: true,
|
|
2560
|
+
configurable: true,
|
|
2561
|
+
writable: true,
|
|
2562
|
+
value: (...args) => {
|
|
2563
|
+
const { mode: mode2, strategy } = resolveTarget(args);
|
|
2564
|
+
const method = strategy?.[name];
|
|
2565
|
+
if (typeof method !== "function") {
|
|
2566
|
+
throw new Error(`${namespace}.${name} is not available in ${mode2} mode`);
|
|
2567
|
+
}
|
|
2568
|
+
return method.apply(strategy, args);
|
|
2569
|
+
}
|
|
2570
|
+
});
|
|
2571
|
+
var withModeReflect = (namespace, strategies = {}) => {
|
|
2572
|
+
const normalizedStrategies = normalizeStrategies2(strategies);
|
|
2573
|
+
const baseStrategy = normalizedStrategies.default ?? Object.values(normalizedStrategies).find(Boolean);
|
|
2574
|
+
const names = collectFunctionNames([baseStrategy]);
|
|
2575
|
+
const descriptors = {};
|
|
2576
|
+
for (const name of names) {
|
|
2577
|
+
descriptors[name] = methodDescriptor(namespace, name, () => resolveModeStrategy(normalizedStrategies));
|
|
2578
|
+
}
|
|
2579
|
+
return Object.defineProperties({}, descriptors);
|
|
2580
|
+
};
|
|
2581
|
+
var withPageReflect = (namespace, resolveStrategy, strategies = []) => {
|
|
2582
|
+
const names = collectFunctionNames(strategies);
|
|
2583
|
+
const descriptors = {};
|
|
2584
|
+
for (const name of names) {
|
|
2585
|
+
descriptors[name] = methodDescriptor(namespace, name, ([page]) => ({
|
|
2586
|
+
mode: "page",
|
|
2587
|
+
strategy: resolveStrategy(page)
|
|
2588
|
+
}));
|
|
2589
|
+
}
|
|
2590
|
+
return Object.defineProperties({}, descriptors);
|
|
2591
|
+
};
|
|
2592
|
+
|
|
2593
|
+
// src/internals/anti-cheat/default.js
|
|
2490
2594
|
var BASE_CONFIG = Object.freeze({
|
|
2491
2595
|
locale: "zh-CN",
|
|
2492
2596
|
acceptLanguage: "zh-CN,zh;q=0.9",
|
|
@@ -2521,7 +2625,7 @@ function buildFingerprintOptions({ locale = BASE_CONFIG.locale, browserMajorVers
|
|
|
2521
2625
|
}
|
|
2522
2626
|
return options;
|
|
2523
2627
|
}
|
|
2524
|
-
var
|
|
2628
|
+
var DefaultAntiCheat = {
|
|
2525
2629
|
/**
|
|
2526
2630
|
* 获取统一的基础配置
|
|
2527
2631
|
*/
|
|
@@ -2558,6 +2662,47 @@ var AntiCheat = {
|
|
|
2558
2662
|
}
|
|
2559
2663
|
};
|
|
2560
2664
|
|
|
2665
|
+
// src/internals/anti-cheat/cloak.js
|
|
2666
|
+
var CLOAK_BASE_CONFIG = Object.freeze({
|
|
2667
|
+
locale: "",
|
|
2668
|
+
acceptLanguage: "",
|
|
2669
|
+
timezoneId: "",
|
|
2670
|
+
timezoneOffset: null,
|
|
2671
|
+
geolocation: null
|
|
2672
|
+
});
|
|
2673
|
+
var normalizeHeaders = (headers) => headers && typeof headers === "object" ? headers : {};
|
|
2674
|
+
var CloakAntiCheat = {
|
|
2675
|
+
/**
|
|
2676
|
+
* Cloak 自身会负责浏览器指纹,toolkit 在该模式下尽量不再注入额外反检测配置。
|
|
2677
|
+
*/
|
|
2678
|
+
getBaseConfig() {
|
|
2679
|
+
return { ...CLOAK_BASE_CONFIG };
|
|
2680
|
+
},
|
|
2681
|
+
getFingerprintGeneratorOptions() {
|
|
2682
|
+
return {};
|
|
2683
|
+
},
|
|
2684
|
+
getLaunchArgs() {
|
|
2685
|
+
return [];
|
|
2686
|
+
},
|
|
2687
|
+
getTlsFingerprintOptions() {
|
|
2688
|
+
return {};
|
|
2689
|
+
},
|
|
2690
|
+
applyLocaleHeaders(headers, acceptLanguage = "") {
|
|
2691
|
+
const normalizedHeaders = normalizeHeaders(headers);
|
|
2692
|
+
if (acceptLanguage && !normalizedHeaders["accept-language"]) {
|
|
2693
|
+
normalizedHeaders["accept-language"] = acceptLanguage;
|
|
2694
|
+
}
|
|
2695
|
+
return normalizedHeaders;
|
|
2696
|
+
}
|
|
2697
|
+
};
|
|
2698
|
+
|
|
2699
|
+
// src/anti-cheat.js
|
|
2700
|
+
var antiCheatStrategies = {
|
|
2701
|
+
[Mode.Default]: DefaultAntiCheat,
|
|
2702
|
+
[Mode.Cloak]: CloakAntiCheat
|
|
2703
|
+
};
|
|
2704
|
+
var AntiCheat = withModeReflect("AntiCheat", antiCheatStrategies);
|
|
2705
|
+
|
|
2561
2706
|
// src/device-input.js
|
|
2562
2707
|
var resolveDeviceFromPage = (page) => normalizeDevice(page?.[PageRuntimeStateKey]?.device);
|
|
2563
2708
|
var assertPage = (page, method) => {
|
|
@@ -2957,12 +3102,12 @@ var resolveDescriptor = (descriptor, device) => {
|
|
|
2957
3102
|
}
|
|
2958
3103
|
return resolved;
|
|
2959
3104
|
};
|
|
2960
|
-
var attachRuntimeState = (page,
|
|
3105
|
+
var attachRuntimeState = (page, state2) => {
|
|
2961
3106
|
Object.defineProperty(page, PageRuntimeStateKey, {
|
|
2962
3107
|
configurable: true,
|
|
2963
3108
|
enumerable: false,
|
|
2964
3109
|
writable: true,
|
|
2965
|
-
value:
|
|
3110
|
+
value: state2
|
|
2966
3111
|
});
|
|
2967
3112
|
};
|
|
2968
3113
|
var restoreRuntimeState = (page, snapshot) => {
|
|
@@ -3108,10 +3253,13 @@ var DeviceView = {
|
|
|
3108
3253
|
}
|
|
3109
3254
|
};
|
|
3110
3255
|
|
|
3256
|
+
// src/internals/humanize/index.js
|
|
3257
|
+
import delay4 from "delay";
|
|
3258
|
+
|
|
3111
3259
|
// src/internals/humanize/desktop.js
|
|
3112
3260
|
import delay2 from "delay";
|
|
3113
3261
|
import { createCursor } from "ghost-cursor-playwright";
|
|
3114
|
-
var
|
|
3262
|
+
var logger5 = createInternalLogger("Humanize");
|
|
3115
3263
|
var $CursorWeakMap = /* @__PURE__ */ new WeakMap();
|
|
3116
3264
|
function $GetCursor(page) {
|
|
3117
3265
|
const cursor = $CursorWeakMap.get(page);
|
|
@@ -3139,13 +3287,13 @@ var Humanize = {
|
|
|
3139
3287
|
*/
|
|
3140
3288
|
async initializeCursor(page) {
|
|
3141
3289
|
if ($CursorWeakMap.has(page)) {
|
|
3142
|
-
|
|
3290
|
+
logger5.debug("initializeCursor: cursor already exists, skipping");
|
|
3143
3291
|
return;
|
|
3144
3292
|
}
|
|
3145
|
-
|
|
3293
|
+
logger5.start("initializeCursor", "creating cursor");
|
|
3146
3294
|
const cursor = await createCursor(page);
|
|
3147
3295
|
$CursorWeakMap.set(page, cursor);
|
|
3148
|
-
|
|
3296
|
+
logger5.success("initializeCursor", "cursor initialized");
|
|
3149
3297
|
},
|
|
3150
3298
|
/**
|
|
3151
3299
|
* 人类化鼠标移动 - 使用 ghost-cursor 移动到指定位置或元素
|
|
@@ -3155,17 +3303,17 @@ var Humanize = {
|
|
|
3155
3303
|
*/
|
|
3156
3304
|
async humanMove(page, target) {
|
|
3157
3305
|
const cursor = $GetCursor(page);
|
|
3158
|
-
|
|
3306
|
+
logger5.start("humanMove", `target=${typeof target === "string" ? target : "element/coords"}`);
|
|
3159
3307
|
try {
|
|
3160
3308
|
if (typeof target === "string") {
|
|
3161
3309
|
const element = await page.$(target);
|
|
3162
3310
|
if (!element) {
|
|
3163
|
-
|
|
3311
|
+
logger5.warn(`humanMove: \u5143\u7D20\u4E0D\u5B58\u5728 ${target}`);
|
|
3164
3312
|
return false;
|
|
3165
3313
|
}
|
|
3166
3314
|
const box = await element.boundingBox();
|
|
3167
3315
|
if (!box) {
|
|
3168
|
-
|
|
3316
|
+
logger5.warn(`humanMove: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E ${target}`);
|
|
3169
3317
|
return false;
|
|
3170
3318
|
}
|
|
3171
3319
|
const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.2;
|
|
@@ -3181,10 +3329,10 @@ var Humanize = {
|
|
|
3181
3329
|
await cursor.actions.move({ x, y });
|
|
3182
3330
|
}
|
|
3183
3331
|
}
|
|
3184
|
-
|
|
3332
|
+
logger5.success("humanMove");
|
|
3185
3333
|
return true;
|
|
3186
3334
|
} catch (error) {
|
|
3187
|
-
|
|
3335
|
+
logger5.fail("humanMove", error);
|
|
3188
3336
|
throw error;
|
|
3189
3337
|
}
|
|
3190
3338
|
},
|
|
@@ -3208,12 +3356,12 @@ var Humanize = {
|
|
|
3208
3356
|
maxDurationMs = maxSteps * 220 + 800
|
|
3209
3357
|
} = options;
|
|
3210
3358
|
const targetDesc = typeof target === "string" ? target : "ElementHandle";
|
|
3211
|
-
|
|
3359
|
+
logger5.start("humanScroll", `target=${targetDesc}`);
|
|
3212
3360
|
let element;
|
|
3213
3361
|
if (typeof target === "string") {
|
|
3214
3362
|
element = await page.$(target);
|
|
3215
3363
|
if (!element) {
|
|
3216
|
-
|
|
3364
|
+
logger5.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${target}`);
|
|
3217
3365
|
return { element: null, didScroll: false };
|
|
3218
3366
|
}
|
|
3219
3367
|
} else {
|
|
@@ -3288,26 +3436,26 @@ var Humanize = {
|
|
|
3288
3436
|
try {
|
|
3289
3437
|
for (let i = 0; i < maxSteps; i++) {
|
|
3290
3438
|
if (Date.now() - startTime > maxDurationMs) {
|
|
3291
|
-
|
|
3439
|
+
logger5.warn(`humanScroll | \u8D85\u65F6\u4FDD\u62A4\u89E6\u53D1 (${maxDurationMs}ms)`);
|
|
3292
3440
|
return { element, didScroll };
|
|
3293
3441
|
}
|
|
3294
3442
|
const status = await checkVisibility();
|
|
3295
3443
|
if (status.code === "VISIBLE") {
|
|
3296
3444
|
if (status.isFixed) {
|
|
3297
|
-
|
|
3445
|
+
logger5.info("humanScroll | fixed \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
|
|
3298
3446
|
} else {
|
|
3299
|
-
|
|
3447
|
+
logger5.debug("humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321");
|
|
3300
3448
|
}
|
|
3301
|
-
|
|
3449
|
+
logger5.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
|
|
3302
3450
|
return { element, didScroll };
|
|
3303
3451
|
}
|
|
3304
|
-
|
|
3452
|
+
logger5.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason} ${status.direction ? `(${status.direction})` : ""}`);
|
|
3305
3453
|
if (status.code === "OBSTRUCTED" && status.obstruction) {
|
|
3306
|
-
|
|
3454
|
+
logger5.debug(`humanScroll | \u88AB\u4EE5\u4E0B\u5143\u7D20\u906E\u6321 <${status.obstruction.tag} id="${status.obstruction.id}">`);
|
|
3307
3455
|
}
|
|
3308
3456
|
const scrollRect = await getScrollableRect2();
|
|
3309
3457
|
if (!scrollRect && status.isFixed) {
|
|
3310
|
-
|
|
3458
|
+
logger5.warn("humanScroll | fixed \u5BB9\u5668\u5185\u4E14\u65E0\u53EF\u6EDA\u52A8\u7956\u5148\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
|
|
3311
3459
|
return { element, didScroll };
|
|
3312
3460
|
}
|
|
3313
3461
|
const stepMin = scrollRect ? Math.min(minStep, Math.max(60, scrollRect.height * 0.4)) : minStep;
|
|
@@ -3343,10 +3491,10 @@ var Humanize = {
|
|
|
3343
3491
|
didScroll = true;
|
|
3344
3492
|
await delay2(this.jitterMs(20 + Math.random() * 40, 0.2));
|
|
3345
3493
|
}
|
|
3346
|
-
|
|
3494
|
+
logger5.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);
|
|
3347
3495
|
return { element, didScroll };
|
|
3348
3496
|
} catch (error) {
|
|
3349
|
-
|
|
3497
|
+
logger5.fail("humanScroll", error);
|
|
3350
3498
|
throw error;
|
|
3351
3499
|
}
|
|
3352
3500
|
},
|
|
@@ -3364,7 +3512,7 @@ var Humanize = {
|
|
|
3364
3512
|
const cursor = $GetCursor(page);
|
|
3365
3513
|
const { reactionDelay = 250, throwOnMissing = true, scrollIfNeeded = true, restore = false } = options;
|
|
3366
3514
|
const targetDesc = target == null ? "Current Position" : typeof target === "string" ? target : "ElementHandle";
|
|
3367
|
-
|
|
3515
|
+
logger5.start("humanClick", `target=${targetDesc}`);
|
|
3368
3516
|
const restoreOnce = async () => {
|
|
3369
3517
|
if (restoreOnce.restored) return;
|
|
3370
3518
|
restoreOnce.restored = true;
|
|
@@ -3373,14 +3521,14 @@ var Humanize = {
|
|
|
3373
3521
|
await delay2(this.jitterMs(1e3));
|
|
3374
3522
|
await restoreOnce.do();
|
|
3375
3523
|
} catch (restoreError) {
|
|
3376
|
-
|
|
3524
|
+
logger5.warn(`humanClick: \u6062\u590D\u6EDA\u52A8\u4F4D\u7F6E\u5931\u8D25: ${restoreError.message}`);
|
|
3377
3525
|
}
|
|
3378
3526
|
};
|
|
3379
3527
|
try {
|
|
3380
3528
|
if (target == null) {
|
|
3381
3529
|
await delay2(this.jitterMs(reactionDelay, 0.4));
|
|
3382
3530
|
await cursor.actions.click();
|
|
3383
|
-
|
|
3531
|
+
logger5.success("humanClick", "Clicked current position");
|
|
3384
3532
|
return true;
|
|
3385
3533
|
}
|
|
3386
3534
|
let element;
|
|
@@ -3390,7 +3538,7 @@ var Humanize = {
|
|
|
3390
3538
|
if (throwOnMissing) {
|
|
3391
3539
|
throw new Error(`\u627E\u4E0D\u5230\u5143\u7D20 ${target}`);
|
|
3392
3540
|
}
|
|
3393
|
-
|
|
3541
|
+
logger5.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${target}`);
|
|
3394
3542
|
return false;
|
|
3395
3543
|
}
|
|
3396
3544
|
} else {
|
|
@@ -3406,7 +3554,7 @@ var Humanize = {
|
|
|
3406
3554
|
if (throwOnMissing) {
|
|
3407
3555
|
throw new Error("\u65E0\u6CD5\u83B7\u53D6\u5143\u7D20\u4F4D\u7F6E");
|
|
3408
3556
|
}
|
|
3409
|
-
|
|
3557
|
+
logger5.warn("humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB");
|
|
3410
3558
|
return false;
|
|
3411
3559
|
}
|
|
3412
3560
|
const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.3;
|
|
@@ -3415,11 +3563,11 @@ var Humanize = {
|
|
|
3415
3563
|
await delay2(this.jitterMs(reactionDelay, 0.4));
|
|
3416
3564
|
await cursor.actions.click();
|
|
3417
3565
|
await restoreOnce();
|
|
3418
|
-
|
|
3566
|
+
logger5.success("humanClick");
|
|
3419
3567
|
return true;
|
|
3420
3568
|
} catch (error) {
|
|
3421
3569
|
await restoreOnce();
|
|
3422
|
-
|
|
3570
|
+
logger5.fail("humanClick", error);
|
|
3423
3571
|
throw error;
|
|
3424
3572
|
}
|
|
3425
3573
|
},
|
|
@@ -3430,9 +3578,9 @@ var Humanize = {
|
|
|
3430
3578
|
*/
|
|
3431
3579
|
async randomSleep(baseMs, jitterPercent = 0.3) {
|
|
3432
3580
|
const ms = this.jitterMs(baseMs, jitterPercent);
|
|
3433
|
-
|
|
3581
|
+
logger5.start("randomSleep", `base=${baseMs}, actual=${ms}ms`);
|
|
3434
3582
|
await delay2(ms);
|
|
3435
|
-
|
|
3583
|
+
logger5.success("randomSleep");
|
|
3436
3584
|
},
|
|
3437
3585
|
/**
|
|
3438
3586
|
* 模拟人类"注视"或"阅读"行为:鼠标在页面上随机微动
|
|
@@ -3442,7 +3590,7 @@ var Humanize = {
|
|
|
3442
3590
|
async simulateGaze(page, baseDurationMs = 2500) {
|
|
3443
3591
|
const cursor = $GetCursor(page);
|
|
3444
3592
|
const durationMs = this.jitterMs(baseDurationMs, 0.4);
|
|
3445
|
-
|
|
3593
|
+
logger5.start("simulateGaze", `duration=${durationMs}ms`);
|
|
3446
3594
|
const startTime = Date.now();
|
|
3447
3595
|
const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };
|
|
3448
3596
|
while (Date.now() - startTime < durationMs) {
|
|
@@ -3451,7 +3599,7 @@ var Humanize = {
|
|
|
3451
3599
|
await cursor.actions.move({ x, y });
|
|
3452
3600
|
await delay2(this.jitterMs(600, 0.5));
|
|
3453
3601
|
}
|
|
3454
|
-
|
|
3602
|
+
logger5.success("simulateGaze");
|
|
3455
3603
|
},
|
|
3456
3604
|
/**
|
|
3457
3605
|
* 人类化输入 - 带节奏变化(快-慢-停顿-偶尔加速)
|
|
@@ -3464,7 +3612,7 @@ var Humanize = {
|
|
|
3464
3612
|
* @param {number} [options.pauseBase=800] - 停顿时长基础值 (ms),实际 ±50% 抖动
|
|
3465
3613
|
*/
|
|
3466
3614
|
async humanType(page, selector, text, options = {}) {
|
|
3467
|
-
|
|
3615
|
+
logger5.start("humanType", `selector=${selector}, textLen=${text.length}`);
|
|
3468
3616
|
const {
|
|
3469
3617
|
baseDelay = 180,
|
|
3470
3618
|
pauseProbability = 0.08,
|
|
@@ -3488,13 +3636,13 @@ var Humanize = {
|
|
|
3488
3636
|
await delay2(charDelay);
|
|
3489
3637
|
if (Math.random() < pauseProbability && i < text.length - 1) {
|
|
3490
3638
|
const pauseTime = this.jitterMs(pauseBase, 0.5);
|
|
3491
|
-
|
|
3639
|
+
logger5.debug(`\u505C\u987F ${pauseTime}ms...`);
|
|
3492
3640
|
await delay2(pauseTime);
|
|
3493
3641
|
}
|
|
3494
3642
|
}
|
|
3495
|
-
|
|
3643
|
+
logger5.success("humanType");
|
|
3496
3644
|
} catch (error) {
|
|
3497
|
-
|
|
3645
|
+
logger5.fail("humanType", error);
|
|
3498
3646
|
throw error;
|
|
3499
3647
|
}
|
|
3500
3648
|
},
|
|
@@ -3518,7 +3666,7 @@ var Humanize = {
|
|
|
3518
3666
|
keyboardOptions = {}
|
|
3519
3667
|
} = pressOptions || {};
|
|
3520
3668
|
const targetDesc = hasTarget ? typeof targetOrKey === "string" ? targetOrKey : "ElementHandle" : "current focus";
|
|
3521
|
-
|
|
3669
|
+
logger5.start("humanPress", `key=${key}, target=${targetDesc}`);
|
|
3522
3670
|
try {
|
|
3523
3671
|
if (hasTarget) {
|
|
3524
3672
|
await this.humanClick(page, targetOrKey, { reactionDelay: focusDelay, scrollIfNeeded, throwOnMissing });
|
|
@@ -3528,10 +3676,10 @@ var Humanize = {
|
|
|
3528
3676
|
...keyboardOptions,
|
|
3529
3677
|
delay: this.jitterMs(holdDelay, 0.5)
|
|
3530
3678
|
});
|
|
3531
|
-
|
|
3679
|
+
logger5.success("humanPress");
|
|
3532
3680
|
return true;
|
|
3533
3681
|
} catch (error) {
|
|
3534
|
-
|
|
3682
|
+
logger5.fail("humanPress", error);
|
|
3535
3683
|
throw error;
|
|
3536
3684
|
}
|
|
3537
3685
|
},
|
|
@@ -3541,22 +3689,22 @@ var Humanize = {
|
|
|
3541
3689
|
* @param {string} selector - 输入框选择器
|
|
3542
3690
|
*/
|
|
3543
3691
|
async humanClear(page, selector) {
|
|
3544
|
-
|
|
3692
|
+
logger5.start("humanClear", `selector=${selector}`);
|
|
3545
3693
|
try {
|
|
3546
3694
|
const locator = page.locator(selector);
|
|
3547
3695
|
await locator.click();
|
|
3548
3696
|
await delay2(this.jitterMs(200, 0.4));
|
|
3549
3697
|
const currentValue = await locator.inputValue();
|
|
3550
3698
|
if (!currentValue || currentValue.length === 0) {
|
|
3551
|
-
|
|
3699
|
+
logger5.success("humanClear", "already empty");
|
|
3552
3700
|
return;
|
|
3553
3701
|
}
|
|
3554
3702
|
await page.keyboard.press("Meta+A");
|
|
3555
3703
|
await delay2(this.jitterMs(100, 0.4));
|
|
3556
3704
|
await page.keyboard.press("Backspace");
|
|
3557
|
-
|
|
3705
|
+
logger5.success("humanClear");
|
|
3558
3706
|
} catch (error) {
|
|
3559
|
-
|
|
3707
|
+
logger5.fail("humanClear", error);
|
|
3560
3708
|
throw error;
|
|
3561
3709
|
}
|
|
3562
3710
|
},
|
|
@@ -3568,7 +3716,7 @@ var Humanize = {
|
|
|
3568
3716
|
async warmUpBrowsing(page, baseDuration = 3500) {
|
|
3569
3717
|
const cursor = $GetCursor(page);
|
|
3570
3718
|
const durationMs = this.jitterMs(baseDuration, 0.4);
|
|
3571
|
-
|
|
3719
|
+
logger5.start("warmUpBrowsing", `duration=${durationMs}ms`);
|
|
3572
3720
|
const startTime = Date.now();
|
|
3573
3721
|
const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };
|
|
3574
3722
|
try {
|
|
@@ -3587,9 +3735,9 @@ var Humanize = {
|
|
|
3587
3735
|
await delay2(this.jitterMs(800, 0.5));
|
|
3588
3736
|
}
|
|
3589
3737
|
}
|
|
3590
|
-
|
|
3738
|
+
logger5.success("warmUpBrowsing");
|
|
3591
3739
|
} catch (error) {
|
|
3592
|
-
|
|
3740
|
+
logger5.fail("warmUpBrowsing", error);
|
|
3593
3741
|
throw error;
|
|
3594
3742
|
}
|
|
3595
3743
|
},
|
|
@@ -3603,7 +3751,7 @@ var Humanize = {
|
|
|
3603
3751
|
async naturalScroll(page, direction = "down", distance = 300, baseSteps = 5) {
|
|
3604
3752
|
const steps = Math.max(3, baseSteps + Math.floor(Math.random() * 3) - 1);
|
|
3605
3753
|
const actualDistance = this.jitterMs(distance, 0.15);
|
|
3606
|
-
|
|
3754
|
+
logger5.start("naturalScroll", `dir=${direction}, dist=${actualDistance}, steps=${steps}`);
|
|
3607
3755
|
const sign = direction === "down" ? 1 : -1;
|
|
3608
3756
|
const stepDistance = actualDistance / steps;
|
|
3609
3757
|
try {
|
|
@@ -3615,9 +3763,9 @@ var Humanize = {
|
|
|
3615
3763
|
const baseDelay = 60 + i * 25;
|
|
3616
3764
|
await delay2(this.jitterMs(baseDelay, 0.3));
|
|
3617
3765
|
}
|
|
3618
|
-
|
|
3766
|
+
logger5.success("naturalScroll");
|
|
3619
3767
|
} catch (error) {
|
|
3620
|
-
|
|
3768
|
+
logger5.fail("naturalScroll", error);
|
|
3621
3769
|
throw error;
|
|
3622
3770
|
}
|
|
3623
3771
|
}
|
|
@@ -3646,7 +3794,7 @@ var resolveElement = async (page, target, { throwOnMissing = true } = {}) => {
|
|
|
3646
3794
|
var waitJitter = (base, jitterPercent = 0.3) => delay3(jitterMs(base, jitterPercent));
|
|
3647
3795
|
|
|
3648
3796
|
// src/internals/humanize/mobile.js
|
|
3649
|
-
var
|
|
3797
|
+
var logger6 = createInternalLogger("Humanize.Mobile");
|
|
3650
3798
|
var initializedPages = /* @__PURE__ */ new WeakSet();
|
|
3651
3799
|
var DEFAULT_TAP_TIMEOUT_MS = 2500;
|
|
3652
3800
|
var DEFAULT_MOUSE_TAP_FALLBACK_TIMEOUT_MS = 1200;
|
|
@@ -4016,7 +4164,7 @@ var restoreWindowFromSnapshot = async (page, before, after) => {
|
|
|
4016
4164
|
return;
|
|
4017
4165
|
}
|
|
4018
4166
|
await page.evaluate(
|
|
4019
|
-
(
|
|
4167
|
+
(state2) => window.scrollTo(state2.x, state2.y),
|
|
4020
4168
|
{ x: Number(before.scrollX || 0), y: Number(before.scrollY || 0) }
|
|
4021
4169
|
).catch(() => {
|
|
4022
4170
|
});
|
|
@@ -4103,7 +4251,7 @@ var dispatchTouchSwipe = async (page, deltaY, options = {}) => {
|
|
|
4103
4251
|
}
|
|
4104
4252
|
return true;
|
|
4105
4253
|
} catch (error) {
|
|
4106
|
-
|
|
4254
|
+
logger6.debug(`touch swipe fallback: ${error?.message || error}`);
|
|
4107
4255
|
try {
|
|
4108
4256
|
await page.evaluate((amount) => window.scrollBy(0, amount), deltaY);
|
|
4109
4257
|
await waitJitter(120, 0.35);
|
|
@@ -4137,7 +4285,7 @@ var tapPoint = async (page, point, options = {}) => {
|
|
|
4137
4285
|
);
|
|
4138
4286
|
return { method: "touchscreen" };
|
|
4139
4287
|
} catch (error) {
|
|
4140
|
-
|
|
4288
|
+
logger6.warn(`tapPoint | touchscreen.tap \u5931\u8D25\u6216\u8D85\u65F6\uFF0C\u5C1D\u8BD5\u9F20\u6807\u515C\u5E95: ${error?.message || error}`);
|
|
4141
4289
|
if (!allowMouseFallback) throw error;
|
|
4142
4290
|
}
|
|
4143
4291
|
}
|
|
@@ -4153,10 +4301,10 @@ var MobileHumanize = {
|
|
|
4153
4301
|
async initializeCursor(page) {
|
|
4154
4302
|
if (initializedPages.has(page)) return;
|
|
4155
4303
|
initializedPages.add(page);
|
|
4156
|
-
|
|
4304
|
+
logger6.debug("initializeCursor: mobile mode uses touch gestures, cursor init skipped");
|
|
4157
4305
|
},
|
|
4158
4306
|
async humanMove(page, target) {
|
|
4159
|
-
|
|
4307
|
+
logger6.debug(`humanMove: mobile no-op target=${typeof target === "string" ? target : "element/coords"}`);
|
|
4160
4308
|
if (typeof target === "string" || target && typeof target.boundingBox === "function") {
|
|
4161
4309
|
const element = await resolveElement(page, target, { throwOnMissing: false });
|
|
4162
4310
|
if (!element) {
|
|
@@ -4175,10 +4323,10 @@ var MobileHumanize = {
|
|
|
4175
4323
|
throwOnMissing = false
|
|
4176
4324
|
} = options;
|
|
4177
4325
|
const targetDesc = describeTarget(target);
|
|
4178
|
-
|
|
4326
|
+
logger6.start("humanScroll", `target=${targetDesc}`);
|
|
4179
4327
|
const element = await resolveElement(page, target, { throwOnMissing });
|
|
4180
4328
|
if (!element) {
|
|
4181
|
-
|
|
4329
|
+
logger6.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${targetDesc}`);
|
|
4182
4330
|
return { element: null, didScroll: false, restore: null };
|
|
4183
4331
|
}
|
|
4184
4332
|
const startTime = Date.now();
|
|
@@ -4187,42 +4335,42 @@ var MobileHumanize = {
|
|
|
4187
4335
|
const status = await checkElementVisibility(element);
|
|
4188
4336
|
if (status.code === "VISIBLE") {
|
|
4189
4337
|
if (status.isFixed) {
|
|
4190
|
-
|
|
4338
|
+
logger6.info("humanScroll | fixed/sticky \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
|
|
4191
4339
|
} else {
|
|
4192
|
-
|
|
4340
|
+
logger6.debug("humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321");
|
|
4193
4341
|
}
|
|
4194
|
-
|
|
4342
|
+
logger6.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
|
|
4195
4343
|
return { element, didScroll, restore: null };
|
|
4196
4344
|
}
|
|
4197
4345
|
if (status.code === "ZERO_DIMENSIONS" || status.code === "NOT_INTERACTABLE") {
|
|
4198
|
-
|
|
4346
|
+
logger6.warn(`humanScroll | \u5143\u7D20\u4E0D\u53EF\u6EDA\u52A8\u81F3\u53EF\u70B9\u51FB\u72B6\u6001: ${status.reason || status.code}`);
|
|
4199
4347
|
return { element, didScroll, restore: null };
|
|
4200
4348
|
}
|
|
4201
4349
|
const scrollRect = await getScrollableRect(element);
|
|
4202
4350
|
if (!scrollRect && status.isFixed && status.code === "OUT_OF_VIEWPORT") {
|
|
4203
|
-
|
|
4351
|
+
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
4352
|
return { element, didScroll, restore: null, unscrollable: true };
|
|
4205
4353
|
}
|
|
4206
4354
|
if (!scrollRect && status.isFixed && status.code === "OBSTRUCTED") {
|
|
4207
|
-
|
|
4355
|
+
logger6.warn(`humanScroll | fixed/sticky \u76EE\u6807\u88AB\u906E\u6321\uFF0C\u6EDA\u52A8\u65E0\u6CD5\u89E3\u9664 (${status.obstruction?.tag || "unknown"})`);
|
|
4208
4356
|
return { element, didScroll, restore: null, unscrollable: true };
|
|
4209
4357
|
}
|
|
4210
4358
|
if (scrollRect && status.code === "OBSTRUCTED" && status.obstruction?.isFixed) {
|
|
4211
4359
|
const moved = await scrollAwayFromObstruction(element, status);
|
|
4212
4360
|
if (moved.moved) {
|
|
4213
|
-
|
|
4361
|
+
logger6.debug(`humanScroll | sticky/fixed \u906E\u6321\u8865\u507F\u6EDA\u52A8 top=${Math.round(moved.scrollTop || 0)}`);
|
|
4214
4362
|
await waitJitter(90, 0.3);
|
|
4215
4363
|
didScroll = true;
|
|
4216
4364
|
continue;
|
|
4217
4365
|
}
|
|
4218
4366
|
}
|
|
4219
4367
|
if (Date.now() - startTime > maxDurationMs) {
|
|
4220
|
-
|
|
4368
|
+
logger6.warn(`humanScroll | mobile timeout (${maxDurationMs}ms, status=${status.code}, direction=${status.direction || "unknown"}, fixed=${Boolean(status.isFixed)})`);
|
|
4221
4369
|
return { element, didScroll, restore: null };
|
|
4222
4370
|
}
|
|
4223
4371
|
const stepMin = scrollRect ? Math.min(minStep, Math.max(60, scrollRect.height * 0.4)) : minStep;
|
|
4224
4372
|
const stepMax = scrollRect ? Math.min(maxStep, Math.max(stepMin + 40, scrollRect.height * 0.8)) : maxStep;
|
|
4225
|
-
|
|
4373
|
+
logger6.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason || status.code} ${status.direction ? `(${status.direction})` : ""}`);
|
|
4226
4374
|
const distance = stepMin + Math.random() * Math.max(1, stepMax - stepMin);
|
|
4227
4375
|
let deltaY = status.direction === "up" ? -distance : distance;
|
|
4228
4376
|
if (status.code === "OBSTRUCTED") {
|
|
@@ -4262,8 +4410,8 @@ var MobileHumanize = {
|
|
|
4262
4410
|
if (scrollRect && beforeWindowState) {
|
|
4263
4411
|
const afterWindowState = await page.evaluate(() => ({ x: window.scrollX, y: window.scrollY }));
|
|
4264
4412
|
if (Math.abs(afterWindowState.x - beforeWindowState.x) > 2 || Math.abs(afterWindowState.y - beforeWindowState.y) > 2) {
|
|
4265
|
-
await page.evaluate((
|
|
4266
|
-
|
|
4413
|
+
await page.evaluate((state2) => window.scrollTo(state2.x, state2.y), beforeWindowState);
|
|
4414
|
+
logger6.debug(`humanScroll | \u7A97\u53E3\u6EDA\u52A8\u56DE\u6536 from=${Math.round(afterWindowState.y)} to=${Math.round(beforeWindowState.y)}`);
|
|
4267
4415
|
}
|
|
4268
4416
|
}
|
|
4269
4417
|
let afterElementSnapshot = null;
|
|
@@ -4277,7 +4425,7 @@ var MobileHumanize = {
|
|
|
4277
4425
|
const afterSnapshot = await readAfterElementSnapshot();
|
|
4278
4426
|
if (isTargetImmobileAfterScroll(beforeElementSnapshot, afterSnapshot)) {
|
|
4279
4427
|
await restoreWindowFromSnapshot(page, beforeElementSnapshot, afterSnapshot);
|
|
4280
|
-
|
|
4428
|
+
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
4429
|
return { element, didScroll, restore: null, unscrollable: true };
|
|
4282
4430
|
}
|
|
4283
4431
|
}
|
|
@@ -4309,12 +4457,12 @@ var MobileHumanize = {
|
|
|
4309
4457
|
const moved = beforeState.kind !== afterState.kind || Math.abs(topDelta) > 2 || Math.abs(leftDelta) > 2;
|
|
4310
4458
|
if (!moved) {
|
|
4311
4459
|
const fallback = await scrollScrollableAncestor(element, deltaY);
|
|
4312
|
-
|
|
4460
|
+
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
4461
|
} 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
4462
|
const residualDelta = expectedDelta - topDelta;
|
|
4315
4463
|
if (Math.sign(residualDelta) === Math.sign(expectedDelta) && Math.abs(residualDelta) > 24) {
|
|
4316
4464
|
const fallback = await scrollScrollableAncestor(element, residualDelta);
|
|
4317
|
-
|
|
4465
|
+
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
4466
|
}
|
|
4319
4467
|
}
|
|
4320
4468
|
}
|
|
@@ -4322,7 +4470,7 @@ var MobileHumanize = {
|
|
|
4322
4470
|
const afterSnapshot = await getElementViewportSnapshot(element).catch(() => null);
|
|
4323
4471
|
if (isTargetImmobileAfterScroll(beforeElementSnapshot, afterSnapshot)) {
|
|
4324
4472
|
await restoreWindowFromSnapshot(page, beforeElementSnapshot, afterSnapshot);
|
|
4325
|
-
|
|
4473
|
+
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
4474
|
return { element, didScroll, restore: null, unscrollable: true };
|
|
4327
4475
|
}
|
|
4328
4476
|
}
|
|
@@ -4333,14 +4481,14 @@ var MobileHumanize = {
|
|
|
4333
4481
|
await waitJitter(80, 0.3);
|
|
4334
4482
|
const finalStatus = await checkElementVisibility(element);
|
|
4335
4483
|
if (finalStatus.code === "VISIBLE") {
|
|
4336
|
-
|
|
4337
|
-
|
|
4484
|
+
logger6.info("humanScroll | \u539F\u751F scrollIntoViewIfNeeded \u515C\u5E95\u6210\u529F");
|
|
4485
|
+
logger6.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
|
|
4338
4486
|
return { element, didScroll: true, restore: null };
|
|
4339
4487
|
}
|
|
4340
4488
|
} catch (fallbackError) {
|
|
4341
|
-
|
|
4489
|
+
logger6.debug(`humanScroll | native fallback failed: ${fallbackError?.message || fallbackError}`);
|
|
4342
4490
|
}
|
|
4343
|
-
|
|
4491
|
+
logger6.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);
|
|
4344
4492
|
return { element, didScroll, restore: null };
|
|
4345
4493
|
},
|
|
4346
4494
|
async humanClick(page, target, options = {}) {
|
|
@@ -4355,7 +4503,7 @@ var MobileHumanize = {
|
|
|
4355
4503
|
fallbackDomClickOnTapError = true
|
|
4356
4504
|
} = options;
|
|
4357
4505
|
const targetDesc = describeTarget(target);
|
|
4358
|
-
|
|
4506
|
+
logger6.start("humanClick", `target=${targetDesc}`);
|
|
4359
4507
|
try {
|
|
4360
4508
|
if (target == null) {
|
|
4361
4509
|
const viewport = resolveViewport(page);
|
|
@@ -4367,12 +4515,12 @@ var MobileHumanize = {
|
|
|
4367
4515
|
timeoutMs: tapTimeoutMs,
|
|
4368
4516
|
mouseFallbackTimeoutMs
|
|
4369
4517
|
});
|
|
4370
|
-
|
|
4518
|
+
logger6.success("humanClick", "Tapped current position");
|
|
4371
4519
|
return true;
|
|
4372
4520
|
}
|
|
4373
4521
|
const element = await resolveElement(page, target, { throwOnMissing });
|
|
4374
4522
|
if (!element) {
|
|
4375
|
-
|
|
4523
|
+
logger6.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${targetDesc}`);
|
|
4376
4524
|
return false;
|
|
4377
4525
|
}
|
|
4378
4526
|
const scrollResult = scrollIfNeeded ? await MobileHumanize.humanScroll(page, element, { throwOnMissing }) : null;
|
|
@@ -4396,19 +4544,19 @@ var MobileHumanize = {
|
|
|
4396
4544
|
).catch(() => null);
|
|
4397
4545
|
}
|
|
4398
4546
|
if (fallback?.activated) {
|
|
4399
|
-
|
|
4547
|
+
logger6.warn(`humanClick: \u4E0D\u53EF\u6EDA\u52A8\u76EE\u6807\u4E0D\u53EF\u7269\u7406\u70B9\u51FB\uFF0C\u5DF2\u7528 ${fallback.method} \u6FC0\u6D3B`);
|
|
4400
4548
|
return true;
|
|
4401
4549
|
}
|
|
4402
4550
|
}
|
|
4403
4551
|
const message = `\u5143\u7D20\u4E0D\u53EF\u70B9\u51FB: ${status.reason || status.code}`;
|
|
4404
4552
|
if (throwOnMissing) throw new Error(message);
|
|
4405
|
-
|
|
4553
|
+
logger6.warn(`humanClick: ${message}\uFF0C\u8DF3\u8FC7\u70B9\u51FB`);
|
|
4406
4554
|
return false;
|
|
4407
4555
|
}
|
|
4408
4556
|
const box = await element.boundingBox();
|
|
4409
4557
|
if (!box) {
|
|
4410
4558
|
if (throwOnMissing) throw new Error("\u65E0\u6CD5\u83B7\u53D6\u5143\u7D20\u4F4D\u7F6E");
|
|
4411
|
-
|
|
4559
|
+
logger6.warn("humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB");
|
|
4412
4560
|
return false;
|
|
4413
4561
|
}
|
|
4414
4562
|
await waitJitter(reactionDelay, 0.45);
|
|
@@ -4429,13 +4577,13 @@ var MobileHumanize = {
|
|
|
4429
4577
|
"activation fallback"
|
|
4430
4578
|
).catch(() => null);
|
|
4431
4579
|
if (!fallback?.activated) throw tapError;
|
|
4432
|
-
|
|
4580
|
+
logger6.warn(`humanClick: tap \u5931\u8D25\u540E\u5DF2\u7528 ${fallback.method} \u515C\u5E95: ${tapError?.message || tapError}`);
|
|
4433
4581
|
}
|
|
4434
4582
|
await waitJitter(120, 0.35);
|
|
4435
|
-
|
|
4583
|
+
logger6.success("humanClick");
|
|
4436
4584
|
return true;
|
|
4437
4585
|
} catch (error) {
|
|
4438
|
-
|
|
4586
|
+
logger6.fail("humanClick", error);
|
|
4439
4587
|
throw error;
|
|
4440
4588
|
}
|
|
4441
4589
|
},
|
|
@@ -4488,7 +4636,7 @@ var MobileHumanize = {
|
|
|
4488
4636
|
keyboardOptions = {}
|
|
4489
4637
|
} = pressOptions || {};
|
|
4490
4638
|
const targetDesc = hasTarget ? describeTarget(targetOrKey) : "current focus";
|
|
4491
|
-
|
|
4639
|
+
logger6.start("humanPress", `key=${key}, target=${targetDesc}`);
|
|
4492
4640
|
try {
|
|
4493
4641
|
if (hasTarget) {
|
|
4494
4642
|
await MobileHumanize.humanClick(page, targetOrKey, {
|
|
@@ -4502,10 +4650,10 @@ var MobileHumanize = {
|
|
|
4502
4650
|
...keyboardOptions,
|
|
4503
4651
|
delay: jitterMs(holdDelay, 0.5)
|
|
4504
4652
|
});
|
|
4505
|
-
|
|
4653
|
+
logger6.success("humanPress");
|
|
4506
4654
|
return true;
|
|
4507
4655
|
} catch (error) {
|
|
4508
|
-
|
|
4656
|
+
logger6.fail("humanPress", error);
|
|
4509
4657
|
throw error;
|
|
4510
4658
|
}
|
|
4511
4659
|
},
|
|
@@ -4572,65 +4720,96 @@ var MobileHumanize = {
|
|
|
4572
4720
|
}
|
|
4573
4721
|
};
|
|
4574
4722
|
|
|
4575
|
-
// src/humanize.js
|
|
4723
|
+
// src/internals/humanize/default.js
|
|
4576
4724
|
var resolveDeviceFromPage2 = (page) => normalizeDevice(page?.[PageRuntimeStateKey]?.device);
|
|
4577
4725
|
var resolveDelegate = (page) => {
|
|
4578
4726
|
return resolveDeviceFromPage2(page) === Device.Mobile ? MobileHumanize : Humanize;
|
|
4579
4727
|
};
|
|
4580
|
-
var
|
|
4581
|
-
|
|
4582
|
-
|
|
4728
|
+
var DefaultHumanizeDevice = withPageReflect(
|
|
4729
|
+
"DefaultHumanize",
|
|
4730
|
+
resolveDelegate,
|
|
4731
|
+
[Humanize, MobileHumanize]
|
|
4732
|
+
);
|
|
4733
|
+
|
|
4734
|
+
// src/internals/humanize/cloak.js
|
|
4735
|
+
var FORCE_CLICK = Object.freeze({
|
|
4736
|
+
forceClick: true,
|
|
4737
|
+
clickOptions: { force: true }
|
|
4738
|
+
});
|
|
4739
|
+
var pointOrNull = async (target) => {
|
|
4740
|
+
if (!target || typeof target.boundingBox !== "function") return null;
|
|
4741
|
+
const box = await target.boundingBox().catch(() => null);
|
|
4742
|
+
return box ? { x: box.x + box.width / 2, y: box.y + box.height / 2 } : null;
|
|
4583
4743
|
};
|
|
4584
|
-
var
|
|
4585
|
-
|
|
4586
|
-
return
|
|
4587
|
-
},
|
|
4588
|
-
initializeCursor(page) {
|
|
4589
|
-
return callDelegate("initializeCursor", page, []);
|
|
4744
|
+
var CloakHumanizeInput = {
|
|
4745
|
+
async initializeCursor(page) {
|
|
4746
|
+
return Boolean(page);
|
|
4590
4747
|
},
|
|
4591
|
-
humanMove(page, target) {
|
|
4592
|
-
|
|
4748
|
+
async humanMove(page, target) {
|
|
4749
|
+
const point = target?.x != null && target?.y != null ? target : await pointOrNull(typeof target === "string" ? page.locator(target).first() : target);
|
|
4750
|
+
return point ? await DeviceInput.move(page, point, { forceMouse: true }) : false;
|
|
4593
4751
|
},
|
|
4594
|
-
humanScroll(page, target
|
|
4595
|
-
|
|
4752
|
+
async humanScroll(page, target) {
|
|
4753
|
+
const element = typeof target === "string" ? page.locator(target).first() : target;
|
|
4754
|
+
if (!element) return { element: null, didScroll: false, restore: null };
|
|
4755
|
+
await element.scrollIntoViewIfNeeded?.();
|
|
4756
|
+
return { element, didScroll: true, restore: null };
|
|
4596
4757
|
},
|
|
4597
|
-
humanClick(page, target
|
|
4598
|
-
return
|
|
4758
|
+
async humanClick(page, target) {
|
|
4759
|
+
return await DeviceInput.click(page, target, FORCE_CLICK);
|
|
4599
4760
|
},
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
return delegate.randomSleep(maybeBaseMs, maybeJitterPercent);
|
|
4604
|
-
}
|
|
4605
|
-
return Humanize.randomSleep(pageOrBaseMs, maybeBaseMs);
|
|
4761
|
+
async humanType(page, selector, text) {
|
|
4762
|
+
await DeviceInput.click(page, selector, FORCE_CLICK);
|
|
4763
|
+
return await DeviceInput.keyboardType(page, text);
|
|
4606
4764
|
},
|
|
4607
|
-
|
|
4608
|
-
return
|
|
4765
|
+
async humanPress(page, targetOrKey, maybeKey) {
|
|
4766
|
+
return await DeviceInput.press(page, targetOrKey, maybeKey, {
|
|
4767
|
+
clickOptions: FORCE_CLICK,
|
|
4768
|
+
keyboardOptions: {}
|
|
4769
|
+
});
|
|
4609
4770
|
},
|
|
4610
|
-
|
|
4611
|
-
return
|
|
4771
|
+
async humanClear(page, selector) {
|
|
4772
|
+
return await DeviceInput.fill(page, selector, "", { force: true });
|
|
4612
4773
|
},
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
return callDelegate("humanPress", page, [targetOrKey, maybeKey, options]);
|
|
4616
|
-
}
|
|
4617
|
-
return callDelegate("humanPress", page, [targetOrKey, maybeKey || options]);
|
|
4774
|
+
async simulateGaze(page) {
|
|
4775
|
+
return await DeviceInput.move(page, { x: 0, y: 0 }, { forceMouse: true });
|
|
4618
4776
|
},
|
|
4619
|
-
|
|
4620
|
-
return
|
|
4777
|
+
async warmUpBrowsing(page) {
|
|
4778
|
+
return await this.simulateGaze(page);
|
|
4621
4779
|
},
|
|
4622
|
-
|
|
4623
|
-
|
|
4780
|
+
async naturalScroll(page, direction = "down", distance = 300) {
|
|
4781
|
+
const sign = direction === "down" ? 1 : -1;
|
|
4782
|
+
await page.mouse.wheel(0, Number(distance || 0) * sign);
|
|
4783
|
+
}
|
|
4784
|
+
};
|
|
4785
|
+
|
|
4786
|
+
// src/internals/humanize/index.js
|
|
4787
|
+
var HumanizeCommon = {
|
|
4788
|
+
jitterMs(base, jitterPercent = 0.3) {
|
|
4789
|
+
return jitterMs(base, jitterPercent);
|
|
4624
4790
|
},
|
|
4625
|
-
|
|
4626
|
-
|
|
4791
|
+
async randomSleep(pageOrBaseMs, maybeBaseMs, maybeJitterPercent) {
|
|
4792
|
+
const hasPage = pageOrBaseMs && typeof pageOrBaseMs === "object" && typeof pageOrBaseMs.evaluate === "function";
|
|
4793
|
+
const baseMs = hasPage ? maybeBaseMs : pageOrBaseMs;
|
|
4794
|
+
const jitterPercent = hasPage ? maybeJitterPercent : maybeBaseMs;
|
|
4795
|
+
await delay4(jitterMs(baseMs, jitterPercent ?? 0.3));
|
|
4627
4796
|
}
|
|
4628
4797
|
};
|
|
4798
|
+
var DefaultHumanize = Object.assign({}, DefaultHumanizeDevice, HumanizeCommon);
|
|
4799
|
+
var CloakHumanize = Object.assign({}, CloakHumanizeInput, HumanizeCommon);
|
|
4629
4800
|
|
|
4630
|
-
// src/
|
|
4801
|
+
// src/humanize.js
|
|
4802
|
+
var humanizeStrategies = {
|
|
4803
|
+
[Mode.Default]: DefaultHumanize,
|
|
4804
|
+
[Mode.Cloak]: CloakHumanize
|
|
4805
|
+
};
|
|
4806
|
+
var Humanize2 = withModeReflect("Humanize", humanizeStrategies);
|
|
4807
|
+
|
|
4808
|
+
// src/internals/launch/default.js
|
|
4631
4809
|
import { execFileSync } from "node:child_process";
|
|
4632
4810
|
import { FingerprintGenerator } from "fingerprint-generator";
|
|
4633
4811
|
import { FingerprintInjector } from "fingerprint-injector";
|
|
4812
|
+
import { chromium as defaultChromiumLauncher } from "playwright";
|
|
4634
4813
|
|
|
4635
4814
|
// src/proxy-bypass.js
|
|
4636
4815
|
import picomatch from "picomatch";
|
|
@@ -4712,9 +4891,107 @@ var ByPass = {
|
|
|
4712
4891
|
resolveRouteByProxy
|
|
4713
4892
|
};
|
|
4714
4893
|
|
|
4715
|
-
// src/launch.js
|
|
4894
|
+
// src/internals/launch/traffic.js
|
|
4895
|
+
var logger7 = createInternalLogger("Launch");
|
|
4896
|
+
var normalizeObject = (value) => {
|
|
4897
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
4898
|
+
return {};
|
|
4899
|
+
}
|
|
4900
|
+
return value;
|
|
4901
|
+
};
|
|
4902
|
+
var parseProxyConfiguration = (proxyConfiguration = {}) => {
|
|
4903
|
+
const config = normalizeObject(proxyConfiguration);
|
|
4904
|
+
const proxyUrl = String(config.proxy_url || "").trim();
|
|
4905
|
+
const enableProxy = typeof config.enable_proxy === "boolean" ? config.enable_proxy : proxyUrl !== "";
|
|
4906
|
+
const byPassDomains = enableProxy && proxyUrl ? ByPass.normalizeByPassDomains(config.by_pass_domains) : [];
|
|
4907
|
+
return {
|
|
4908
|
+
byPassDomains,
|
|
4909
|
+
enableProxy,
|
|
4910
|
+
proxyUrl
|
|
4911
|
+
};
|
|
4912
|
+
};
|
|
4913
|
+
var resolveLaunchTraffic = ({
|
|
4914
|
+
proxyConfiguration = {},
|
|
4915
|
+
debugMode = false,
|
|
4916
|
+
useMeter = true
|
|
4917
|
+
} = {}) => {
|
|
4918
|
+
const { byPassDomains, enableProxy, proxyUrl } = parseProxyConfiguration(proxyConfiguration);
|
|
4919
|
+
const byPassRules = ByPass.buildByPassDomainRules(byPassDomains);
|
|
4920
|
+
const proxyMeter = useMeter && enableProxy && proxyUrl ? ProxyMeterRuntime.startProxyMeter({ proxyUrl, debugMode }) : null;
|
|
4921
|
+
const launchProxy = proxyMeter ? { server: proxyMeter.server } : null;
|
|
4922
|
+
if (launchProxy && byPassDomains.length > 0) {
|
|
4923
|
+
launchProxy.bypass = byPassDomains.join(",");
|
|
4924
|
+
}
|
|
4925
|
+
return {
|
|
4926
|
+
byPassDomains,
|
|
4927
|
+
byPassRules,
|
|
4928
|
+
enableProxy,
|
|
4929
|
+
proxyUrl,
|
|
4930
|
+
launchProxy
|
|
4931
|
+
};
|
|
4932
|
+
};
|
|
4933
|
+
var logLaunchTraffic = ({
|
|
4934
|
+
byPassDomains = [],
|
|
4935
|
+
debugMode = false,
|
|
4936
|
+
enabled = false,
|
|
4937
|
+
enableProxy = false,
|
|
4938
|
+
explicitProxy = false,
|
|
4939
|
+
launchProxy = null,
|
|
4940
|
+
proxyUrl = ""
|
|
4941
|
+
} = {}) => {
|
|
4942
|
+
if (!enabled) return;
|
|
4943
|
+
if (explicitProxy) {
|
|
4944
|
+
logger7.info("[\u4EE3\u7406\u5DF2\u542F\u7528] \u4F7F\u7528\u663E\u5F0F proxy \u914D\u7F6E\uFF0C\u8DF3\u8FC7 toolkit \u672C\u5730\u6D41\u91CF\u89C2\u6D4B");
|
|
4945
|
+
return;
|
|
4946
|
+
}
|
|
4947
|
+
if (launchProxy) {
|
|
4948
|
+
let upstreamLabel = "";
|
|
4949
|
+
try {
|
|
4950
|
+
const parsedProxyUrl = new URL(proxyUrl.includes("://") ? proxyUrl : `http://${proxyUrl}`);
|
|
4951
|
+
upstreamLabel = `${parsedProxyUrl.protocol}//${parsedProxyUrl.host}`;
|
|
4952
|
+
} catch {
|
|
4953
|
+
}
|
|
4954
|
+
logger7.info(
|
|
4955
|
+
`[\u4EE3\u7406\u5DF2\u542F\u7528] \u672C\u5730=${launchProxy.server} \u4E0A\u6E38=${upstreamLabel || "-"} \u76F4\u8FDE\u57DF\u540D=${byPassDomains.join(",")}`
|
|
4956
|
+
);
|
|
4957
|
+
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`);
|
|
4958
|
+
return;
|
|
4959
|
+
}
|
|
4960
|
+
if (enableProxy) {
|
|
4961
|
+
logger7.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=true \u4F46 proxy_url \u4E3A\u7A7A");
|
|
4962
|
+
} else if (proxyUrl) {
|
|
4963
|
+
logger7.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=false \u4E14 proxy_url \u5DF2\u914D\u7F6E");
|
|
4964
|
+
}
|
|
4965
|
+
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`);
|
|
4966
|
+
};
|
|
4967
|
+
var createLaunchTrafficHook = ({
|
|
4968
|
+
byPassDomains = [],
|
|
4969
|
+
byPassRules = [],
|
|
4970
|
+
enabled = false,
|
|
4971
|
+
launchProxy = null
|
|
4972
|
+
} = {}) => {
|
|
4973
|
+
const patchedPages = /* @__PURE__ */ new WeakSet();
|
|
4974
|
+
return (page) => {
|
|
4975
|
+
if (!page || typeof page.on !== "function" || patchedPages.has(page)) {
|
|
4976
|
+
return;
|
|
4977
|
+
}
|
|
4978
|
+
patchedPages.add(page);
|
|
4979
|
+
page.on("request", (req) => {
|
|
4980
|
+
const requestUrl = req.url();
|
|
4981
|
+
const resourceType = req.resourceType();
|
|
4982
|
+
const matched = byPassDomains.length > 0 ? ByPass.findMatchedByPassRule(byPassRules, requestUrl) : null;
|
|
4983
|
+
if (launchProxy) {
|
|
4984
|
+
ProxyMeterRuntime.recordProxyMeterResourceType(requestUrl, resourceType);
|
|
4985
|
+
}
|
|
4986
|
+
if (!enabled || byPassDomains.length === 0) return;
|
|
4987
|
+
if (!matched || !matched.rule) return;
|
|
4988
|
+
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}`);
|
|
4989
|
+
});
|
|
4990
|
+
};
|
|
4991
|
+
};
|
|
4992
|
+
|
|
4993
|
+
// src/internals/launch/default.js
|
|
4716
4994
|
var logger8 = createInternalLogger("Launch");
|
|
4717
|
-
var REQUEST_HOOK_FLAG = Symbol("playwright-toolkit-request-hook");
|
|
4718
4995
|
var injectedContexts = /* @__PURE__ */ new WeakSet();
|
|
4719
4996
|
var browserMajorVersionCache = /* @__PURE__ */ new Map();
|
|
4720
4997
|
var DEFAULT_BROWSER_PROFILE_SCHEMA_VERSION = 1;
|
|
@@ -4726,16 +5003,6 @@ var DEFAULT_CRAWLER_BASE_OPTIONS = Object.freeze({
|
|
|
4726
5003
|
navigationTimeoutSecs: 120
|
|
4727
5004
|
});
|
|
4728
5005
|
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
5006
|
var parseChromeMajorVersion = (rawValue = "") => {
|
|
4740
5007
|
const match = String(rawValue || "").match(/(?:Chrome|Chromium)(?:\/|\s+(?:for Testing\s+)?)(\d+)/i);
|
|
4741
5008
|
return match ? Number(match[1] || 0) : 0;
|
|
@@ -4779,7 +5046,7 @@ var resolveCoreDevice = (core = {}) => {
|
|
|
4779
5046
|
};
|
|
4780
5047
|
var buildFingerprintGenerator = ({ locale, browserMajorVersion, device }) => {
|
|
4781
5048
|
return new FingerprintGenerator(
|
|
4782
|
-
|
|
5049
|
+
DefaultAntiCheat.getFingerprintGeneratorOptions({
|
|
4783
5050
|
locale,
|
|
4784
5051
|
browserMajorVersion,
|
|
4785
5052
|
device
|
|
@@ -4823,7 +5090,7 @@ var buildReplayableBrowserProfile = (runtimeState, launcher) => {
|
|
|
4823
5090
|
}
|
|
4824
5091
|
let nextState = RuntimeEnv.rememberState(runtimeState);
|
|
4825
5092
|
let browserProfileCore = RuntimeEnv.getBrowserProfileCore(nextState);
|
|
4826
|
-
const timezoneId = String(browserProfileCore?.timezone_id || "").trim() ||
|
|
5093
|
+
const timezoneId = String(browserProfileCore?.timezone_id || "").trim() || DefaultAntiCheat.getBaseConfig().timezoneId;
|
|
4827
5094
|
const locale = DEFAULT_LOCALE;
|
|
4828
5095
|
const currentBrowserMajorVersion = detectBrowserMajorVersion(launcher);
|
|
4829
5096
|
const storedBrowserMajorVersion = Number(browserProfileCore?.browser_major_version || 0);
|
|
@@ -4839,6 +5106,7 @@ var buildReplayableBrowserProfile = (runtimeState, launcher) => {
|
|
|
4839
5106
|
const fingerprint = generated.fingerprint;
|
|
4840
5107
|
const fingerprintBrowserMajorVersion = parseChromeMajorVersion(fingerprint?.fingerprint?.navigator?.userAgent || "");
|
|
4841
5108
|
browserProfileCore = {
|
|
5109
|
+
...browserProfileCore,
|
|
4842
5110
|
fingerprint,
|
|
4843
5111
|
device,
|
|
4844
5112
|
timezone_id: timezoneId,
|
|
@@ -4902,7 +5170,7 @@ var applyFingerprintPageOptions = (pageOptions = {}, { fingerprintWithHeaders =
|
|
|
4902
5170
|
pageOptions.timezoneId = timezoneId;
|
|
4903
5171
|
}
|
|
4904
5172
|
};
|
|
4905
|
-
var buildReplayBrowserPoolOptions = (browserProfileCore
|
|
5173
|
+
var buildReplayBrowserPoolOptions = (browserProfileCore) => {
|
|
4906
5174
|
const fingerprintWithHeaders = browserProfileCore?.fingerprint;
|
|
4907
5175
|
const fingerprint = fingerprintWithHeaders?.fingerprint;
|
|
4908
5176
|
if (!fingerprintWithHeaders || !fingerprint) {
|
|
@@ -4911,16 +5179,13 @@ var buildReplayBrowserPoolOptions = (browserProfileCore, modifyPageOptions = nul
|
|
|
4911
5179
|
return {
|
|
4912
5180
|
useFingerprints: false,
|
|
4913
5181
|
prePageCreateHooks: [
|
|
4914
|
-
|
|
5182
|
+
(_pageId, _browserController, pageOptions = {}) => {
|
|
4915
5183
|
if (!pageOptions || typeof pageOptions !== "object") return;
|
|
4916
5184
|
applyFingerprintPageOptions(pageOptions, {
|
|
4917
5185
|
fingerprintWithHeaders,
|
|
4918
5186
|
locale: browserProfileCore.locale,
|
|
4919
5187
|
timezoneId: browserProfileCore.timezone_id
|
|
4920
5188
|
});
|
|
4921
|
-
if (modifyPageOptions) {
|
|
4922
|
-
await modifyPageOptions(pageOptions, { pageId, browserController });
|
|
4923
|
-
}
|
|
4924
5189
|
}
|
|
4925
5190
|
],
|
|
4926
5191
|
postPageCreateHooks: [
|
|
@@ -4935,7 +5200,7 @@ var buildReplayBrowserPoolOptions = (browserProfileCore, modifyPageOptions = nul
|
|
|
4935
5200
|
]
|
|
4936
5201
|
};
|
|
4937
5202
|
};
|
|
4938
|
-
var
|
|
5203
|
+
var DefaultLaunch = {
|
|
4939
5204
|
getPlaywrightCrawlerOptions(options = {}) {
|
|
4940
5205
|
const normalizedOptions = Array.isArray(options) ? { customArgs: options } : options || {};
|
|
4941
5206
|
const {
|
|
@@ -4946,54 +5211,36 @@ var Launch = {
|
|
|
4946
5211
|
debugMode = false,
|
|
4947
5212
|
isRunningOnApify = false,
|
|
4948
5213
|
launcher = null,
|
|
4949
|
-
hooks = {},
|
|
4950
5214
|
preNavigationHooks = [],
|
|
4951
5215
|
postNavigationHooks = [],
|
|
4952
5216
|
runtimeState = null
|
|
4953
5217
|
} = normalizedOptions;
|
|
4954
5218
|
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);
|
|
5219
|
+
const effectiveLauncher = launcher || defaultChromiumLauncher;
|
|
5220
|
+
const enableByPassLogger = Boolean(logOptions && logOptions.enable);
|
|
5221
|
+
const traffic = resolveLaunchTraffic({ proxyConfiguration, debugMode });
|
|
5222
|
+
const trafficHook = createLaunchTrafficHook({
|
|
5223
|
+
...traffic,
|
|
5224
|
+
enabled: enableByPassLogger
|
|
5225
|
+
});
|
|
5226
|
+
const replayContext = buildReplayableBrowserProfile(runtimeState, effectiveLauncher);
|
|
5227
|
+
const replayBrowserPoolOptions = buildReplayBrowserPoolOptions(replayContext.browserProfileCore);
|
|
4965
5228
|
const launchLocale = String(replayContext.browserProfileCore?.locale || DEFAULT_LOCALE).trim() || DEFAULT_LOCALE;
|
|
4966
5229
|
const launchOptions = {
|
|
4967
5230
|
args: [
|
|
4968
|
-
...
|
|
5231
|
+
...DefaultAntiCheat.getLaunchArgs({ locale: launchLocale }),
|
|
4969
5232
|
...customArgs
|
|
4970
5233
|
],
|
|
4971
5234
|
ignoreDefaultArgs: ["--enable-automation"]
|
|
4972
5235
|
};
|
|
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`);
|
|
5236
|
+
if (traffic.launchProxy) {
|
|
5237
|
+
launchOptions.proxy = traffic.launchProxy;
|
|
4996
5238
|
}
|
|
5239
|
+
logLaunchTraffic({
|
|
5240
|
+
...traffic,
|
|
5241
|
+
debugMode,
|
|
5242
|
+
enabled: enableByPassLogger
|
|
5243
|
+
});
|
|
4997
5244
|
const onPageCreated = (page) => {
|
|
4998
5245
|
const recommendedGotoOptions = {
|
|
4999
5246
|
waitUntil: "commit"
|
|
@@ -5001,31 +5248,14 @@ var Launch = {
|
|
|
5001
5248
|
if (!page || typeof page.on !== "function") {
|
|
5002
5249
|
return recommendedGotoOptions;
|
|
5003
5250
|
}
|
|
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);
|
|
5251
|
+
trafficHook(page);
|
|
5020
5252
|
return recommendedGotoOptions;
|
|
5021
5253
|
};
|
|
5022
5254
|
const launchContext = {
|
|
5023
5255
|
useIncognitoPages: true,
|
|
5024
|
-
launchOptions
|
|
5256
|
+
launchOptions,
|
|
5257
|
+
launcher: effectiveLauncher
|
|
5025
5258
|
};
|
|
5026
|
-
if (launcher) {
|
|
5027
|
-
launchContext.launcher = launcher;
|
|
5028
|
-
}
|
|
5029
5259
|
const crawlerBaseOptions = {
|
|
5030
5260
|
...DEFAULT_CRAWLER_BASE_OPTIONS,
|
|
5031
5261
|
headless: !runInHeadfulMode || isRunningOnApify,
|
|
@@ -5033,23 +5263,20 @@ var Launch = {
|
|
|
5033
5263
|
browserPoolOptions: replayBrowserPoolOptions || {
|
|
5034
5264
|
useFingerprints: true,
|
|
5035
5265
|
fingerprintOptions: {
|
|
5036
|
-
fingerprintGeneratorOptions:
|
|
5266
|
+
fingerprintGeneratorOptions: DefaultAntiCheat.getFingerprintGeneratorOptions({
|
|
5037
5267
|
locale: launchLocale,
|
|
5038
5268
|
device
|
|
5039
5269
|
})
|
|
5040
5270
|
},
|
|
5041
5271
|
prePageCreateHooks: [
|
|
5042
|
-
|
|
5272
|
+
(_pageId, browserController, pageOptions = {}) => {
|
|
5043
5273
|
const fingerprintWithHeaders = browserController?.launchContext?.fingerprint;
|
|
5044
|
-
const timezoneId =
|
|
5274
|
+
const timezoneId = DefaultAntiCheat.getBaseConfig().timezoneId;
|
|
5045
5275
|
applyFingerprintPageOptions(pageOptions, {
|
|
5046
5276
|
fingerprintWithHeaders,
|
|
5047
5277
|
locale: launchLocale,
|
|
5048
5278
|
timezoneId
|
|
5049
5279
|
});
|
|
5050
|
-
if (modifyPageOptions) {
|
|
5051
|
-
await modifyPageOptions(pageOptions, { pageId, browserController });
|
|
5052
|
-
}
|
|
5053
5280
|
}
|
|
5054
5281
|
]
|
|
5055
5282
|
},
|
|
@@ -5071,10 +5298,464 @@ var Launch = {
|
|
|
5071
5298
|
}
|
|
5072
5299
|
};
|
|
5073
5300
|
|
|
5301
|
+
// src/internals/launch/cloak.js
|
|
5302
|
+
import { execFile } from "node:child_process";
|
|
5303
|
+
import { randomInt } from "node:crypto";
|
|
5304
|
+
import { promisify } from "node:util";
|
|
5305
|
+
var logger9 = createInternalLogger("Launch");
|
|
5306
|
+
var execFileAsync = promisify(execFile);
|
|
5307
|
+
var DEFAULT_CLOAK_CRAWLER_BASE_OPTIONS = Object.freeze({
|
|
5308
|
+
maxConcurrency: 1,
|
|
5309
|
+
maxRequestRetries: 0,
|
|
5310
|
+
requestHandlerTimeoutSecs: 240,
|
|
5311
|
+
navigationTimeoutSecs: 120
|
|
5312
|
+
});
|
|
5313
|
+
var DEFAULT_CLOAK_HUMANIZE_OPTIONS = Object.freeze({
|
|
5314
|
+
humanize: true
|
|
5315
|
+
});
|
|
5316
|
+
var DEFAULT_CLOAK_GOTO_OPTIONS = Object.freeze({
|
|
5317
|
+
waitUntil: "commit"
|
|
5318
|
+
});
|
|
5319
|
+
var DEFAULT_CLOAK_SEED_MIN = 1e4;
|
|
5320
|
+
var DEFAULT_CLOAK_SEED_MAX = 99999;
|
|
5321
|
+
var DEFAULT_CLOAK_FINGERPRINT_PLATFORM = "linux";
|
|
5322
|
+
var CLOAK_FINGERPRINT_ARG_PREFIX = "--fingerprint=";
|
|
5323
|
+
var CLOAK_FINGERPRINT_PLATFORM_ARG_PREFIX = "--fingerprint-platform=";
|
|
5324
|
+
var CLOAK_FINGERPRINT_TIMEZONE_ARG_PREFIX = "--fingerprint-timezone=";
|
|
5325
|
+
var CLOAK_FINGERPRINT_LOCALE_ARG_PREFIX = "--fingerprint-locale=";
|
|
5326
|
+
var CLOAK_LANG_ARG_PREFIX = "--lang=";
|
|
5327
|
+
var SUPPORTED_CLOAK_FINGERPRINT_PLATFORMS2 = /* @__PURE__ */ new Set(["linux", "macos", "windows"]);
|
|
5328
|
+
var cachedCloakModulePromise = null;
|
|
5329
|
+
var hasOwn = (target, key) => Object.prototype.hasOwnProperty.call(target, key);
|
|
5330
|
+
var loadCloakModule = async () => {
|
|
5331
|
+
if (!cachedCloakModulePromise) {
|
|
5332
|
+
cachedCloakModulePromise = import("cloakbrowser").catch((error) => {
|
|
5333
|
+
cachedCloakModulePromise = null;
|
|
5334
|
+
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", {
|
|
5335
|
+
cause: error
|
|
5336
|
+
});
|
|
5337
|
+
});
|
|
5338
|
+
}
|
|
5339
|
+
return cachedCloakModulePromise;
|
|
5340
|
+
};
|
|
5341
|
+
var buildCloakLaunchOptions = async (options = {}) => {
|
|
5342
|
+
const { buildLaunchOptions } = await loadCloakModule();
|
|
5343
|
+
return await buildLaunchOptions(normalizeObject2(options));
|
|
5344
|
+
};
|
|
5345
|
+
var normalizeObject2 = (value) => {
|
|
5346
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
5347
|
+
return {};
|
|
5348
|
+
}
|
|
5349
|
+
return value;
|
|
5350
|
+
};
|
|
5351
|
+
var normalizeStringArray = (value) => {
|
|
5352
|
+
if (!Array.isArray(value)) {
|
|
5353
|
+
return [];
|
|
5354
|
+
}
|
|
5355
|
+
return value.map((item) => String(item || "").trim()).filter(Boolean);
|
|
5356
|
+
};
|
|
5357
|
+
var normalizeText = (value) => String(value || "").trim();
|
|
5358
|
+
var normalizePositiveInteger = (value) => {
|
|
5359
|
+
const numericValue = Number(value);
|
|
5360
|
+
if (Number.isSafeInteger(numericValue) && numericValue > 0) {
|
|
5361
|
+
return numericValue;
|
|
5362
|
+
}
|
|
5363
|
+
const raw = normalizeText(value);
|
|
5364
|
+
if (!/^\d+$/.test(raw)) {
|
|
5365
|
+
return 0;
|
|
5366
|
+
}
|
|
5367
|
+
const parsedValue = Number(raw);
|
|
5368
|
+
return Number.isSafeInteger(parsedValue) && parsedValue > 0 ? parsedValue : 0;
|
|
5369
|
+
};
|
|
5370
|
+
var normalizeCloakFingerprintPlatform2 = (value) => {
|
|
5371
|
+
const normalizedFingerprintPlatform = String(value || "").trim().toLowerCase();
|
|
5372
|
+
return SUPPORTED_CLOAK_FINGERPRINT_PLATFORMS2.has(normalizedFingerprintPlatform) ? normalizedFingerprintPlatform : "";
|
|
5373
|
+
};
|
|
5374
|
+
var buildCloakFingerprintPlatformArg = (fingerprintPlatform = DEFAULT_CLOAK_FINGERPRINT_PLATFORM) => `${CLOAK_FINGERPRINT_PLATFORM_ARG_PREFIX}${fingerprintPlatform}`;
|
|
5375
|
+
var resolveCloakFingerprintPlatformArg = (fingerprintPlatform = "", args = []) => {
|
|
5376
|
+
const normalizedFingerprintPlatform = normalizeCloakFingerprintPlatform2(fingerprintPlatform);
|
|
5377
|
+
if (normalizedFingerprintPlatform) {
|
|
5378
|
+
return buildCloakFingerprintPlatformArg(normalizedFingerprintPlatform);
|
|
5379
|
+
}
|
|
5380
|
+
const existingFingerprintPlatform = normalizeCloakFingerprintPlatform2(
|
|
5381
|
+
extractArgValue(args, CLOAK_FINGERPRINT_PLATFORM_ARG_PREFIX)
|
|
5382
|
+
);
|
|
5383
|
+
if (existingFingerprintPlatform) {
|
|
5384
|
+
return buildCloakFingerprintPlatformArg(existingFingerprintPlatform);
|
|
5385
|
+
}
|
|
5386
|
+
return buildCloakFingerprintPlatformArg(DEFAULT_CLOAK_FINGERPRINT_PLATFORM);
|
|
5387
|
+
};
|
|
5388
|
+
var resolveCloakProxy = (proxyConfiguration = {}) => {
|
|
5389
|
+
const config = normalizeObject2(proxyConfiguration);
|
|
5390
|
+
const proxyUrl = String(config.proxy_url || "").trim();
|
|
5391
|
+
const enableProxy = typeof config.enable_proxy === "boolean" ? config.enable_proxy : proxyUrl !== "";
|
|
5392
|
+
if (!enableProxy || !proxyUrl) {
|
|
5393
|
+
return null;
|
|
5394
|
+
}
|
|
5395
|
+
const byPassDomains = ByPass.normalizeByPassDomains(config.by_pass_domains);
|
|
5396
|
+
if (byPassDomains.length === 0) {
|
|
5397
|
+
return proxyUrl;
|
|
5398
|
+
}
|
|
5399
|
+
const parsedProxyUrl = new URL(proxyUrl.includes("://") ? proxyUrl : `http://${proxyUrl}`);
|
|
5400
|
+
return {
|
|
5401
|
+
server: `${parsedProxyUrl.protocol}//${parsedProxyUrl.host}`,
|
|
5402
|
+
username: decodeURIComponent(parsedProxyUrl.username || ""),
|
|
5403
|
+
password: decodeURIComponent(parsedProxyUrl.password || ""),
|
|
5404
|
+
bypass: byPassDomains.join(",")
|
|
5405
|
+
};
|
|
5406
|
+
};
|
|
5407
|
+
var extractFingerprintArg = (launchOptions = {}) => {
|
|
5408
|
+
const args = Array.isArray(launchOptions?.args) ? launchOptions.args : [];
|
|
5409
|
+
return args.find((value) => String(value || "").startsWith(CLOAK_FINGERPRINT_ARG_PREFIX)) || "";
|
|
5410
|
+
};
|
|
5411
|
+
var buildFingerprintArg = (seed) => `${CLOAK_FINGERPRINT_ARG_PREFIX}${seed}`;
|
|
5412
|
+
var extractArgValue = (args = [], prefix = "") => {
|
|
5413
|
+
const matchedArg = normalizeStringArray(args).find((value) => value.startsWith(prefix));
|
|
5414
|
+
if (!matchedArg) {
|
|
5415
|
+
return "";
|
|
5416
|
+
}
|
|
5417
|
+
return normalizeText(matchedArg.slice(prefix.length));
|
|
5418
|
+
};
|
|
5419
|
+
var extractFingerprintSeedFromArgs = (args = []) => normalizePositiveInteger(
|
|
5420
|
+
extractArgValue(args, CLOAK_FINGERPRINT_ARG_PREFIX)
|
|
5421
|
+
);
|
|
5422
|
+
var extractLocaleFromArgs = (args = []) => extractArgValue(args, CLOAK_LANG_ARG_PREFIX) || extractArgValue(args, CLOAK_FINGERPRINT_LOCALE_ARG_PREFIX);
|
|
5423
|
+
var extractTimezoneFromArgs = (args = []) => extractArgValue(args, CLOAK_FINGERPRINT_TIMEZONE_ARG_PREFIX);
|
|
5424
|
+
var hashStringToSeed = (value = "") => {
|
|
5425
|
+
let hash = 2166136261;
|
|
5426
|
+
const text = normalizeText(value);
|
|
5427
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
5428
|
+
hash ^= text.charCodeAt(index);
|
|
5429
|
+
hash = Math.imul(hash, 16777619);
|
|
5430
|
+
}
|
|
5431
|
+
const numericHash = hash >>> 0;
|
|
5432
|
+
const seedRange = DEFAULT_CLOAK_SEED_MAX - DEFAULT_CLOAK_SEED_MIN + 1;
|
|
5433
|
+
return DEFAULT_CLOAK_SEED_MIN + numericHash % seedRange;
|
|
5434
|
+
};
|
|
5435
|
+
var buildCloakSeedIdentity = (runtimeState = {}) => {
|
|
5436
|
+
const normalizedRuntimeState = normalizeObject2(runtimeState);
|
|
5437
|
+
const normalizedEnvId = normalizeText(normalizedRuntimeState.envId);
|
|
5438
|
+
if (normalizedEnvId) {
|
|
5439
|
+
return `env:${normalizedEnvId}`;
|
|
5440
|
+
}
|
|
5441
|
+
const runtimePayload = normalizeObject2(normalizedRuntimeState.runtime);
|
|
5442
|
+
if (Object.keys(runtimePayload).length === 0) {
|
|
5443
|
+
return "";
|
|
5444
|
+
}
|
|
5445
|
+
return JSON.stringify({
|
|
5446
|
+
actor: normalizeText(normalizedRuntimeState.actor),
|
|
5447
|
+
device: normalizeText(normalizedRuntimeState.device),
|
|
5448
|
+
runtime: runtimePayload
|
|
5449
|
+
});
|
|
5450
|
+
};
|
|
5451
|
+
var generateCloakSeed = (runtimeState = {}) => {
|
|
5452
|
+
const identity = buildCloakSeedIdentity(runtimeState);
|
|
5453
|
+
if (identity) {
|
|
5454
|
+
return hashStringToSeed(`cloak:${identity}`);
|
|
5455
|
+
}
|
|
5456
|
+
return randomInt(DEFAULT_CLOAK_SEED_MIN, DEFAULT_CLOAK_SEED_MAX + 1);
|
|
5457
|
+
};
|
|
5458
|
+
var resolveReplayableCloakProfile = (runtimeState, { fingerprintPlatform = "", cloakOptions = {} } = {}) => {
|
|
5459
|
+
const normalizedCloakOptions = normalizeObject2(cloakOptions);
|
|
5460
|
+
const normalizedArgs = normalizeStringArray(normalizedCloakOptions.args);
|
|
5461
|
+
const explicitFingerprintSeed = extractFingerprintSeedFromArgs(normalizedArgs);
|
|
5462
|
+
const explicitFingerprintPlatform = normalizeCloakFingerprintPlatform2(fingerprintPlatform) || normalizeCloakFingerprintPlatform2(
|
|
5463
|
+
extractArgValue(normalizedArgs, CLOAK_FINGERPRINT_PLATFORM_ARG_PREFIX)
|
|
5464
|
+
);
|
|
5465
|
+
const explicitTimezone = normalizeText(
|
|
5466
|
+
normalizedCloakOptions.timezone || normalizedCloakOptions.timezoneId || extractTimezoneFromArgs(normalizedArgs)
|
|
5467
|
+
);
|
|
5468
|
+
const explicitLocale = normalizeText(
|
|
5469
|
+
normalizedCloakOptions.locale || extractLocaleFromArgs(normalizedArgs)
|
|
5470
|
+
);
|
|
5471
|
+
if (!runtimeState || !RuntimeEnv.hasLoginState(runtimeState)) {
|
|
5472
|
+
return {
|
|
5473
|
+
runtimeState,
|
|
5474
|
+
browserProfileCore: null,
|
|
5475
|
+
fingerprintSeed: explicitFingerprintSeed,
|
|
5476
|
+
fingerprintPlatform: explicitFingerprintPlatform,
|
|
5477
|
+
locale: explicitLocale,
|
|
5478
|
+
timezone: explicitTimezone,
|
|
5479
|
+
hasExplicitFingerprintSeed: explicitFingerprintSeed > 0,
|
|
5480
|
+
hasExplicitLocale: Boolean(explicitLocale),
|
|
5481
|
+
hasExplicitTimezone: Boolean(explicitTimezone)
|
|
5482
|
+
};
|
|
5483
|
+
}
|
|
5484
|
+
let nextState = RuntimeEnv.rememberState(runtimeState);
|
|
5485
|
+
const currentBrowserProfileCore = RuntimeEnv.getBrowserProfileCore(nextState);
|
|
5486
|
+
const storedFingerprintSeed = normalizePositiveInteger(currentBrowserProfileCore?.cloak_seed);
|
|
5487
|
+
const storedFingerprintPlatform = normalizeCloakFingerprintPlatform2(
|
|
5488
|
+
currentBrowserProfileCore?.cloak_fingerprint_platform
|
|
5489
|
+
);
|
|
5490
|
+
const storedLocale = normalizeText(currentBrowserProfileCore?.locale);
|
|
5491
|
+
const storedTimezone = normalizeText(currentBrowserProfileCore?.timezone_id);
|
|
5492
|
+
const fingerprintSeed = explicitFingerprintSeed || storedFingerprintSeed || generateCloakSeed(nextState);
|
|
5493
|
+
const resolvedFingerprintPlatform = explicitFingerprintPlatform || storedFingerprintPlatform || DEFAULT_CLOAK_FINGERPRINT_PLATFORM;
|
|
5494
|
+
const locale = explicitLocale || storedLocale;
|
|
5495
|
+
const timezone = explicitTimezone || storedTimezone;
|
|
5496
|
+
const nextBrowserProfileCore = {
|
|
5497
|
+
...currentBrowserProfileCore,
|
|
5498
|
+
cloak_seed: fingerprintSeed,
|
|
5499
|
+
cloak_fingerprint_platform: resolvedFingerprintPlatform
|
|
5500
|
+
};
|
|
5501
|
+
if (locale) {
|
|
5502
|
+
nextBrowserProfileCore.locale = locale;
|
|
5503
|
+
}
|
|
5504
|
+
if (timezone) {
|
|
5505
|
+
nextBrowserProfileCore.timezone_id = timezone;
|
|
5506
|
+
}
|
|
5507
|
+
const currentCoreRaw = JSON.stringify(currentBrowserProfileCore || {});
|
|
5508
|
+
const nextCoreRaw = JSON.stringify(nextBrowserProfileCore);
|
|
5509
|
+
if (currentCoreRaw !== nextCoreRaw) {
|
|
5510
|
+
nextState = RuntimeEnv.setBrowserProfileCore(nextState, nextBrowserProfileCore);
|
|
5511
|
+
logger9.info(
|
|
5512
|
+
`\u5DF2\u540C\u6B65 Cloak \u6307\u7EB9\u771F\u6E90 | env=${String(nextState.envId || "-")} | seed=${fingerprintSeed} | platform=${resolvedFingerprintPlatform} | timezone=${timezone || "-"} | locale=${locale || "-"}`
|
|
5513
|
+
);
|
|
5514
|
+
}
|
|
5515
|
+
const rememberedBrowserProfileCore = RuntimeEnv.getBrowserProfileCore(nextState);
|
|
5516
|
+
return {
|
|
5517
|
+
runtimeState: nextState,
|
|
5518
|
+
browserProfileCore: rememberedBrowserProfileCore,
|
|
5519
|
+
fingerprintSeed,
|
|
5520
|
+
fingerprintPlatform: resolvedFingerprintPlatform,
|
|
5521
|
+
locale,
|
|
5522
|
+
timezone,
|
|
5523
|
+
hasExplicitFingerprintSeed: explicitFingerprintSeed > 0,
|
|
5524
|
+
hasExplicitLocale: Boolean(explicitLocale),
|
|
5525
|
+
hasExplicitTimezone: Boolean(explicitTimezone)
|
|
5526
|
+
};
|
|
5527
|
+
};
|
|
5528
|
+
var createStableGotoHook = (recommendedGotoOptions = DEFAULT_CLOAK_GOTO_OPTIONS) => {
|
|
5529
|
+
const normalizedRecommendedGotoOptions = normalizeObject2(recommendedGotoOptions);
|
|
5530
|
+
const fallbackGotoOptions = Object.keys(normalizedRecommendedGotoOptions).length > 0 ? normalizedRecommendedGotoOptions : DEFAULT_CLOAK_GOTO_OPTIONS;
|
|
5531
|
+
return async (_crawlingContext, gotoOptions = {}) => {
|
|
5532
|
+
for (const [key, value] of Object.entries(fallbackGotoOptions)) {
|
|
5533
|
+
if (gotoOptions[key] == null) {
|
|
5534
|
+
gotoOptions[key] = value;
|
|
5535
|
+
}
|
|
5536
|
+
}
|
|
5537
|
+
};
|
|
5538
|
+
};
|
|
5539
|
+
var attachCloakHumanizeHook = ({
|
|
5540
|
+
browserPoolOptions = {},
|
|
5541
|
+
activeBrowsers,
|
|
5542
|
+
patchedBrowsers,
|
|
5543
|
+
humanizeOptions = DEFAULT_CLOAK_HUMANIZE_OPTIONS
|
|
5544
|
+
} = {}) => {
|
|
5545
|
+
const normalizedBrowserPoolOptions = normalizeObject2(browserPoolOptions);
|
|
5546
|
+
const shouldHumanize = humanizeOptions !== false;
|
|
5547
|
+
const normalizedHumanizeOptions = shouldHumanize ? {
|
|
5548
|
+
...DEFAULT_CLOAK_HUMANIZE_OPTIONS,
|
|
5549
|
+
...normalizeObject2(humanizeOptions)
|
|
5550
|
+
} : null;
|
|
5551
|
+
return {
|
|
5552
|
+
...normalizedBrowserPoolOptions,
|
|
5553
|
+
useFingerprints: false,
|
|
5554
|
+
postLaunchHooks: [
|
|
5555
|
+
...Array.isArray(normalizedBrowserPoolOptions.postLaunchHooks) ? normalizedBrowserPoolOptions.postLaunchHooks : [],
|
|
5556
|
+
async (_pageId, browserController) => {
|
|
5557
|
+
const browser = browserController?.browser;
|
|
5558
|
+
if (!browser || typeof browser.contexts !== "function") {
|
|
5559
|
+
return;
|
|
5560
|
+
}
|
|
5561
|
+
activeBrowsers.add(browser);
|
|
5562
|
+
if (typeof browser.once === "function") {
|
|
5563
|
+
browser.once("disconnected", () => {
|
|
5564
|
+
activeBrowsers.delete(browser);
|
|
5565
|
+
});
|
|
5566
|
+
}
|
|
5567
|
+
if (!shouldHumanize || patchedBrowsers.has(browser)) {
|
|
5568
|
+
return;
|
|
5569
|
+
}
|
|
5570
|
+
const { humanizeBrowser } = await loadCloakModule();
|
|
5571
|
+
await humanizeBrowser(browser, normalizedHumanizeOptions);
|
|
5572
|
+
patchedBrowsers.add(browser);
|
|
5573
|
+
}
|
|
5574
|
+
]
|
|
5575
|
+
};
|
|
5576
|
+
};
|
|
5577
|
+
var closeTrackedBrowsers = async (activeBrowsers) => {
|
|
5578
|
+
const browsers = Array.from(activeBrowsers || []);
|
|
5579
|
+
activeBrowsers?.clear?.();
|
|
5580
|
+
await Promise.allSettled(
|
|
5581
|
+
browsers.map(async (browser) => {
|
|
5582
|
+
if (!browser || typeof browser.isConnected !== "function" || !browser.isConnected()) {
|
|
5583
|
+
return;
|
|
5584
|
+
}
|
|
5585
|
+
await browser.close().catch(() => {
|
|
5586
|
+
});
|
|
5587
|
+
})
|
|
5588
|
+
);
|
|
5589
|
+
};
|
|
5590
|
+
var forceTerminateBrowsersByFingerprintArg = async (fingerprintArg) => {
|
|
5591
|
+
if (!fingerprintArg) {
|
|
5592
|
+
return;
|
|
5593
|
+
}
|
|
5594
|
+
await execFileAsync("pkill", ["-f", "--", fingerprintArg]).catch((error) => {
|
|
5595
|
+
if (error?.code === 1 || error?.code === "ENOENT") {
|
|
5596
|
+
return;
|
|
5597
|
+
}
|
|
5598
|
+
logger9.info(`\u5F3A\u5236\u5173\u95ED Cloak \u8FDB\u7A0B\u5931\u8D25\uFF08\u5FFD\u7565\uFF09: ${error?.message || String(error)}`);
|
|
5599
|
+
});
|
|
5600
|
+
};
|
|
5601
|
+
var CloakLaunch = {
|
|
5602
|
+
resolveProxyConfiguration(proxyConfiguration = {}) {
|
|
5603
|
+
return resolveCloakProxy(proxyConfiguration);
|
|
5604
|
+
},
|
|
5605
|
+
extractFingerprintArg(launchOptions = {}) {
|
|
5606
|
+
return extractFingerprintArg(launchOptions);
|
|
5607
|
+
},
|
|
5608
|
+
createStableGotoHook(recommendedGotoOptions = DEFAULT_CLOAK_GOTO_OPTIONS) {
|
|
5609
|
+
return createStableGotoHook(recommendedGotoOptions);
|
|
5610
|
+
},
|
|
5611
|
+
async getPlaywrightCrawlerOptions(options = {}) {
|
|
5612
|
+
const runtime2 = await CloakLaunch.createPlaywrightCrawlerRuntime(options);
|
|
5613
|
+
return Object.defineProperties(runtime2.crawlerOptions, {
|
|
5614
|
+
cleanup: {
|
|
5615
|
+
enumerable: false,
|
|
5616
|
+
value: runtime2.cleanup
|
|
5617
|
+
},
|
|
5618
|
+
closeActiveBrowsers: {
|
|
5619
|
+
enumerable: false,
|
|
5620
|
+
value: runtime2.closeActiveBrowsers
|
|
5621
|
+
},
|
|
5622
|
+
forceTerminateActiveProcesses: {
|
|
5623
|
+
enumerable: false,
|
|
5624
|
+
value: runtime2.forceTerminateActiveProcesses
|
|
5625
|
+
}
|
|
5626
|
+
});
|
|
5627
|
+
},
|
|
5628
|
+
async buildLaunchOptions(options = {}) {
|
|
5629
|
+
return await buildCloakLaunchOptions(options);
|
|
5630
|
+
},
|
|
5631
|
+
async createPlaywrightCrawlerRuntime(options = {}) {
|
|
5632
|
+
const normalizedOptions = normalizeObject2(options);
|
|
5633
|
+
const {
|
|
5634
|
+
proxyConfiguration = {},
|
|
5635
|
+
log: logOptions = null,
|
|
5636
|
+
debugMode = false,
|
|
5637
|
+
runInHeadfulMode = false,
|
|
5638
|
+
isRunningOnApify = false,
|
|
5639
|
+
launcher = null,
|
|
5640
|
+
runtimeState = null,
|
|
5641
|
+
fingerprintPlatform = "",
|
|
5642
|
+
cloakOptions = {},
|
|
5643
|
+
humanizeOptions = DEFAULT_CLOAK_HUMANIZE_OPTIONS,
|
|
5644
|
+
crawlerBaseOptions = {},
|
|
5645
|
+
browserPoolOptions = {},
|
|
5646
|
+
launchContext = {},
|
|
5647
|
+
preNavigationHooks = [],
|
|
5648
|
+
postNavigationHooks = [],
|
|
5649
|
+
recommendedGotoOptions = DEFAULT_CLOAK_GOTO_OPTIONS
|
|
5650
|
+
} = normalizedOptions;
|
|
5651
|
+
const normalizedCloakOptions = normalizeObject2(cloakOptions);
|
|
5652
|
+
const activeBrowsers = /* @__PURE__ */ new Set();
|
|
5653
|
+
const patchedBrowsers = /* @__PURE__ */ new WeakSet();
|
|
5654
|
+
const defaultArgs = isRunningOnApify ? ["--no-sandbox", "--disable-setuid-sandbox"] : [];
|
|
5655
|
+
const replayContext = resolveReplayableCloakProfile(runtimeState, {
|
|
5656
|
+
fingerprintPlatform,
|
|
5657
|
+
cloakOptions: normalizedCloakOptions
|
|
5658
|
+
});
|
|
5659
|
+
const fingerprintPlatformArg = resolveCloakFingerprintPlatformArg(
|
|
5660
|
+
replayContext.fingerprintPlatform,
|
|
5661
|
+
normalizedCloakOptions.args
|
|
5662
|
+
);
|
|
5663
|
+
const extraArgs = normalizeStringArray(normalizedCloakOptions.args).filter((value) => !value.startsWith(CLOAK_FINGERPRINT_PLATFORM_ARG_PREFIX));
|
|
5664
|
+
const replayFingerprintArg = !replayContext.hasExplicitFingerprintSeed && replayContext.fingerprintSeed > 0 ? buildFingerprintArg(replayContext.fingerprintSeed) : "";
|
|
5665
|
+
const hasExplicitProxy = hasOwn(normalizedCloakOptions, "proxy");
|
|
5666
|
+
const proxyLaunchState = hasExplicitProxy ? resolveLaunchTraffic({ proxyConfiguration, debugMode, useMeter: false }) : resolveLaunchTraffic({ proxyConfiguration, debugMode });
|
|
5667
|
+
const proxy = hasExplicitProxy ? normalizedCloakOptions.proxy : proxyLaunchState.launchProxy;
|
|
5668
|
+
const headless = hasOwn(normalizedCloakOptions, "headless") ? normalizedCloakOptions.headless : !runInHeadfulMode || isRunningOnApify;
|
|
5669
|
+
const enableByPassLogger = Boolean(logOptions && logOptions.enable);
|
|
5670
|
+
const mergedCloakOptions = {
|
|
5671
|
+
...normalizedCloakOptions,
|
|
5672
|
+
headless,
|
|
5673
|
+
proxy,
|
|
5674
|
+
...normalizedCloakOptions.timezoneId && !hasOwn(normalizedCloakOptions, "timezone") ? { timezone: normalizedCloakOptions.timezoneId } : {},
|
|
5675
|
+
...replayContext.timezone && !replayContext.hasExplicitTimezone ? { timezone: replayContext.timezone } : {},
|
|
5676
|
+
...replayContext.locale && !replayContext.hasExplicitLocale ? { locale: replayContext.locale } : {},
|
|
5677
|
+
args: [
|
|
5678
|
+
...defaultArgs,
|
|
5679
|
+
...replayFingerprintArg ? [replayFingerprintArg] : [],
|
|
5680
|
+
...extraArgs,
|
|
5681
|
+
fingerprintPlatformArg
|
|
5682
|
+
]
|
|
5683
|
+
};
|
|
5684
|
+
const launchOptions = await buildCloakLaunchOptions(mergedCloakOptions);
|
|
5685
|
+
const fingerprintArg = extractFingerprintArg(launchOptions);
|
|
5686
|
+
const internalPreNavigationHook = createStableGotoHook(recommendedGotoOptions);
|
|
5687
|
+
const trafficHook = createLaunchTrafficHook({
|
|
5688
|
+
byPassDomains: proxyLaunchState.byPassDomains,
|
|
5689
|
+
byPassRules: proxyLaunchState.byPassRules,
|
|
5690
|
+
enabled: enableByPassLogger,
|
|
5691
|
+
launchProxy: proxyLaunchState.launchProxy
|
|
5692
|
+
});
|
|
5693
|
+
const normalizedPreNavigationHooks = Array.isArray(preNavigationHooks) ? preNavigationHooks : [];
|
|
5694
|
+
const normalizedPostNavigationHooks = Array.isArray(postNavigationHooks) ? postNavigationHooks : [];
|
|
5695
|
+
logLaunchTraffic({
|
|
5696
|
+
...proxyLaunchState,
|
|
5697
|
+
debugMode,
|
|
5698
|
+
enabled: enableByPassLogger,
|
|
5699
|
+
explicitProxy: hasExplicitProxy
|
|
5700
|
+
});
|
|
5701
|
+
const crawlerOptions = {
|
|
5702
|
+
...DEFAULT_CLOAK_CRAWLER_BASE_OPTIONS,
|
|
5703
|
+
...normalizeObject2(crawlerBaseOptions),
|
|
5704
|
+
headless,
|
|
5705
|
+
launchContext: {
|
|
5706
|
+
useIncognitoPages: true,
|
|
5707
|
+
...normalizeObject2(launchContext),
|
|
5708
|
+
...launcher ? { launcher } : {},
|
|
5709
|
+
launchOptions
|
|
5710
|
+
},
|
|
5711
|
+
browserPoolOptions: attachCloakHumanizeHook({
|
|
5712
|
+
browserPoolOptions,
|
|
5713
|
+
activeBrowsers,
|
|
5714
|
+
patchedBrowsers,
|
|
5715
|
+
humanizeOptions
|
|
5716
|
+
}),
|
|
5717
|
+
preNavigationHooks: [
|
|
5718
|
+
async (crawlingContext, gotoOptions = {}) => {
|
|
5719
|
+
trafficHook(crawlingContext?.page);
|
|
5720
|
+
await internalPreNavigationHook(crawlingContext, gotoOptions);
|
|
5721
|
+
},
|
|
5722
|
+
...normalizedPreNavigationHooks
|
|
5723
|
+
],
|
|
5724
|
+
...normalizedPostNavigationHooks.length > 0 ? { postNavigationHooks: normalizedPostNavigationHooks } : {}
|
|
5725
|
+
};
|
|
5726
|
+
const closeActiveBrowsers = async () => {
|
|
5727
|
+
await closeTrackedBrowsers(activeBrowsers);
|
|
5728
|
+
};
|
|
5729
|
+
const forceTerminateActiveProcesses = async () => {
|
|
5730
|
+
await forceTerminateBrowsersByFingerprintArg(fingerprintArg);
|
|
5731
|
+
};
|
|
5732
|
+
const cleanup = async () => {
|
|
5733
|
+
await closeActiveBrowsers();
|
|
5734
|
+
await forceTerminateActiveProcesses();
|
|
5735
|
+
};
|
|
5736
|
+
return {
|
|
5737
|
+
headless,
|
|
5738
|
+
launchOptions,
|
|
5739
|
+
fingerprintArg,
|
|
5740
|
+
crawlerOptions,
|
|
5741
|
+
closeActiveBrowsers,
|
|
5742
|
+
forceTerminateActiveProcesses,
|
|
5743
|
+
cleanup
|
|
5744
|
+
};
|
|
5745
|
+
}
|
|
5746
|
+
};
|
|
5747
|
+
|
|
5748
|
+
// src/launch.js
|
|
5749
|
+
var launchStrategies = {
|
|
5750
|
+
[Mode.Default]: DefaultLaunch,
|
|
5751
|
+
[Mode.Cloak]: CloakLaunch
|
|
5752
|
+
};
|
|
5753
|
+
var Launch = withModeReflect("Launch", launchStrategies);
|
|
5754
|
+
|
|
5074
5755
|
// src/live-view.js
|
|
5075
5756
|
import express from "express";
|
|
5076
5757
|
import { Actor } from "apify";
|
|
5077
|
-
var
|
|
5758
|
+
var logger10 = createInternalLogger("LiveView");
|
|
5078
5759
|
async function startLiveViewServer(liveViewKey) {
|
|
5079
5760
|
const app = express();
|
|
5080
5761
|
app.get("/", async (req, res) => {
|
|
@@ -5099,13 +5780,13 @@ async function startLiveViewServer(liveViewKey) {
|
|
|
5099
5780
|
</html>
|
|
5100
5781
|
`);
|
|
5101
5782
|
} catch (error) {
|
|
5102
|
-
|
|
5783
|
+
logger10.fail("Live View Server", error);
|
|
5103
5784
|
res.status(500).send(`\u65E0\u6CD5\u52A0\u8F7D\u5C4F\u5E55\u622A\u56FE: ${error.message}`);
|
|
5104
5785
|
}
|
|
5105
5786
|
});
|
|
5106
5787
|
const port = process.env.APIFY_CONTAINER_PORT || 4321;
|
|
5107
5788
|
app.listen(port, () => {
|
|
5108
|
-
|
|
5789
|
+
logger10.success("startLiveViewServer", `\u76D1\u542C\u7AEF\u53E3 ${port}`);
|
|
5109
5790
|
});
|
|
5110
5791
|
}
|
|
5111
5792
|
async function takeLiveScreenshot(liveViewKey, page, logMessage) {
|
|
@@ -5113,10 +5794,10 @@ async function takeLiveScreenshot(liveViewKey, page, logMessage) {
|
|
|
5113
5794
|
const buffer = await capturePageScreenshot(page, { type: "png" });
|
|
5114
5795
|
await Actor.setValue(liveViewKey, buffer, { contentType: "image/png" });
|
|
5115
5796
|
if (logMessage) {
|
|
5116
|
-
|
|
5797
|
+
logger10.info(`(\u622A\u56FE): ${logMessage}`);
|
|
5117
5798
|
}
|
|
5118
5799
|
} catch (e) {
|
|
5119
|
-
|
|
5800
|
+
logger10.warn(`\u65E0\u6CD5\u6355\u83B7 Live View \u5C4F\u5E55\u622A\u56FE: ${e.message}`);
|
|
5120
5801
|
}
|
|
5121
5802
|
}
|
|
5122
5803
|
var useLiveView = (liveViewKey = PresetOfLiveViewKey) => {
|
|
@@ -5133,9 +5814,6 @@ var LiveView = {
|
|
|
5133
5814
|
useLiveView
|
|
5134
5815
|
};
|
|
5135
5816
|
|
|
5136
|
-
// src/chaptcha.js
|
|
5137
|
-
import { v4 as uuidv4 } from "uuid";
|
|
5138
|
-
|
|
5139
5817
|
// src/internals/captcha/bytedance.js
|
|
5140
5818
|
import { mkdir, writeFile } from "fs/promises";
|
|
5141
5819
|
import path2 from "path";
|
|
@@ -5225,7 +5903,7 @@ var dragCaptchaAction = async (page, sourceLocator, targetLocator, options = {})
|
|
|
5225
5903
|
};
|
|
5226
5904
|
|
|
5227
5905
|
// src/internals/captcha/bytedance.js
|
|
5228
|
-
var
|
|
5906
|
+
var logger11 = createInternalLogger("Captcha");
|
|
5229
5907
|
var DEFAULT_BYTEDANCE_CAPTCHA_OPTIONS = Object.freeze({
|
|
5230
5908
|
apiType: "31234",
|
|
5231
5909
|
maxRetries: 3,
|
|
@@ -5357,7 +6035,7 @@ var collectCaptchaDebugInfo = async (page, frame, iframeLocator, attempt, phase,
|
|
|
5357
6035
|
}
|
|
5358
6036
|
await writeFile(infoPath, JSON.stringify(payload, null, 2), "utf8");
|
|
5359
6037
|
}
|
|
5360
|
-
|
|
6038
|
+
logger11.info(`\u5DF2\u5199\u51FA\u9A8C\u8BC1\u7801\u8C03\u8BD5\u4EA7\u7269\uFF1A${debugDir}`);
|
|
5361
6039
|
};
|
|
5362
6040
|
var maybeCollectCaptchaDebugInfo = async (page, frame, iframeLocator, attempt, phase, options, extra = null) => {
|
|
5363
6041
|
if (!options.debugArtifacts) {
|
|
@@ -5394,14 +6072,14 @@ var getVerifycenterCaptchaContext = async (page, options) => {
|
|
|
5394
6072
|
if (!isContainerVisible) {
|
|
5395
6073
|
return null;
|
|
5396
6074
|
}
|
|
5397
|
-
|
|
6075
|
+
logger11.info("\u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\u5BB9\u5668\uFF0C\u5F00\u59CB\u7B49\u5F85 iframe \u52A0\u8F7D\u3002");
|
|
5398
6076
|
let iframeLocator = page.locator(options.iframeSelector).first();
|
|
5399
6077
|
let isIframeVisible = await waitForVisible(
|
|
5400
6078
|
iframeLocator,
|
|
5401
6079
|
options.iframeVisibleTimeoutMs
|
|
5402
6080
|
);
|
|
5403
6081
|
if (!isIframeVisible) {
|
|
5404
|
-
|
|
6082
|
+
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
6083
|
iframeLocator = captchaContainer.locator(options.iframeFallbackSelector).first();
|
|
5406
6084
|
isIframeVisible = await waitForVisible(
|
|
5407
6085
|
iframeLocator,
|
|
@@ -5411,7 +6089,7 @@ var getVerifycenterCaptchaContext = async (page, options) => {
|
|
|
5411
6089
|
if (!isIframeVisible) {
|
|
5412
6090
|
throw new Error("verifycenter iframe not found inside captcha container.");
|
|
5413
6091
|
}
|
|
5414
|
-
|
|
6092
|
+
logger11.info("\u9A8C\u8BC1\u7801 iframe \u5DF2\u53EF\u89C1\uFF0C\u5F00\u59CB\u89E3\u6790\u5185\u5BB9 frame\u3002");
|
|
5415
6093
|
const frame = await resolveContentFrame(page, iframeLocator, options);
|
|
5416
6094
|
if (!frame) {
|
|
5417
6095
|
throw new Error("Failed to resolve verifycenter iframe content frame.");
|
|
@@ -5527,11 +6205,11 @@ var refreshCaptcha = async (page, frame, options) => {
|
|
|
5527
6205
|
const clicked = await clickCaptchaAction(frame, options.refreshTexts, {
|
|
5528
6206
|
...options,
|
|
5529
6207
|
page,
|
|
5530
|
-
logger:
|
|
6208
|
+
logger: logger11,
|
|
5531
6209
|
forceMouse: true
|
|
5532
6210
|
}).catch(() => false);
|
|
5533
6211
|
if (!clicked) {
|
|
5534
|
-
|
|
6212
|
+
logger11.warn("Refresh button not found.");
|
|
5535
6213
|
return false;
|
|
5536
6214
|
}
|
|
5537
6215
|
await page.waitForTimeout(options.refreshWaitMs);
|
|
@@ -5562,24 +6240,24 @@ var waitForCaptchaChallengeReady = async (page, frame, options) => {
|
|
|
5562
6240
|
const hasGuideMaskVisible = options.guideMaskSelector ? await frame.locator(options.guideMaskSelector).first().isVisible({ timeout: options.loadingIndicatorVisibleTimeoutMs }).catch(() => false) : false;
|
|
5563
6241
|
hasSeenGuideMask = hasSeenGuideMask || hasGuideMaskVisible;
|
|
5564
6242
|
if (hasGuideMaskVisible && !hasLoggedGuideMask) {
|
|
5565
|
-
|
|
6243
|
+
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
6244
|
hasLoggedGuideMask = true;
|
|
5567
6245
|
}
|
|
5568
6246
|
if (!isLoadingVisible && hasVisibleSourceImage && hasVisibleDropTarget && !hasGuideMaskVisible) {
|
|
5569
|
-
|
|
6247
|
+
logger11.info(
|
|
5570
6248
|
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
6249
|
);
|
|
5572
6250
|
return;
|
|
5573
6251
|
}
|
|
5574
6252
|
if (hasErrorTextVisible) {
|
|
5575
|
-
|
|
6253
|
+
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
6254
|
await refreshCaptcha(page, frame, options);
|
|
5577
6255
|
refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
|
|
5578
6256
|
hasSeenLoading = false;
|
|
5579
6257
|
continue;
|
|
5580
6258
|
}
|
|
5581
6259
|
if ((!hasVisibleSourceImage || !hasVisibleDropTarget) && Date.now() >= refreshDeadline) {
|
|
5582
|
-
|
|
6260
|
+
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
6261
|
await refreshCaptcha(page, frame, options);
|
|
5584
6262
|
refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
|
|
5585
6263
|
hasSeenLoading = false;
|
|
@@ -5627,7 +6305,7 @@ var dragPromptCaptchaImage = async (page, frame, iframeLocator, sourceLocator, d
|
|
|
5627
6305
|
accepted
|
|
5628
6306
|
};
|
|
5629
6307
|
dragAttempts.push(attemptInfo);
|
|
5630
|
-
|
|
6308
|
+
logger11.info(
|
|
5631
6309
|
`\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
6310
|
);
|
|
5633
6311
|
if (accepted) {
|
|
@@ -5645,7 +6323,7 @@ var dragPromptCaptchaImage = async (page, frame, iframeLocator, sourceLocator, d
|
|
|
5645
6323
|
dragAttempts,
|
|
5646
6324
|
finalState: await readPromptCaptchaState(frame, options)
|
|
5647
6325
|
}).catch((error) => {
|
|
5648
|
-
|
|
6326
|
+
logger11.warn(`\u9A8C\u8BC1\u7801\u62D6\u62FD\u5931\u8D25\u8C03\u8BD5\u6293\u53D6\u5931\u8D25\uFF1A${error?.message || error}`);
|
|
5649
6327
|
});
|
|
5650
6328
|
return {
|
|
5651
6329
|
accepted: false,
|
|
@@ -5662,16 +6340,16 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
|
|
|
5662
6340
|
...options
|
|
5663
6341
|
};
|
|
5664
6342
|
if (!config.token) {
|
|
5665
|
-
|
|
6343
|
+
logger11.warn("\u7F3A\u5C11\u9A8C\u8BC1\u7801 token\uFF0C\u8DF3\u8FC7\u81EA\u52A8\u8BC6\u522B\u3002");
|
|
5666
6344
|
return false;
|
|
5667
6345
|
}
|
|
5668
|
-
|
|
6346
|
+
logger11.info("\u5F53\u524D\u4F7F\u7528\u672Ctool\u2014\u2014\u6D4B\u8BD5\u7248\u672C");
|
|
5669
6347
|
for (let attempt = 1; attempt <= config.maxRetries; attempt += 1) {
|
|
5670
|
-
|
|
6348
|
+
logger11.info(`\u5F00\u59CB\u7B2C ${attempt}/${config.maxRetries} \u6B21 verifycenter \u9A8C\u8BC1\u7801\u8BC6\u522B\u3002`);
|
|
5671
6349
|
try {
|
|
5672
6350
|
const captchaContext = await getVerifycenterCaptchaContext(page, config);
|
|
5673
6351
|
if (!captchaContext) {
|
|
5674
|
-
|
|
6352
|
+
logger11.info("Captcha container is not visible anymore.");
|
|
5675
6353
|
return true;
|
|
5676
6354
|
}
|
|
5677
6355
|
const { iframeLocator, frame } = captchaContext;
|
|
@@ -5684,7 +6362,7 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
|
|
|
5684
6362
|
"ready",
|
|
5685
6363
|
config
|
|
5686
6364
|
).catch((error) => {
|
|
5687
|
-
|
|
6365
|
+
logger11.warn(`\u9A8C\u8BC1\u7801\u8C03\u8BD5\u6293\u53D6\u5931\u8D25\uFF1A${error?.message || error}`);
|
|
5688
6366
|
});
|
|
5689
6367
|
await page.waitForTimeout(config.recognitionDelayMs);
|
|
5690
6368
|
const screenshotBuffer = await iframeLocator.screenshot();
|
|
@@ -5696,16 +6374,16 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
|
|
|
5696
6374
|
});
|
|
5697
6375
|
const serialNumbers = extractCaptchaSerialNumbers(apiResponse);
|
|
5698
6376
|
if (apiResponse?.code !== config.recognitionSuccessCode || serialNumbers.length === 0) {
|
|
5699
|
-
|
|
6377
|
+
logger11.warn(
|
|
5700
6378
|
`\u9A8C\u8BC1\u7801\u8BC6\u522B\u5931\u8D25\u3002code=${apiResponse?.code}, msg=${apiResponse?.msg || "unknown"}`
|
|
5701
6379
|
);
|
|
5702
6380
|
await refreshCaptcha(page, frame, config);
|
|
5703
6381
|
continue;
|
|
5704
6382
|
}
|
|
5705
|
-
|
|
6383
|
+
logger11.info(`\u9A8C\u8BC1\u7801\u8BC6\u522B\u6210\u529F\uFF0C\u5E8F\u53F7\uFF1A${serialNumbers.join(", ")}`);
|
|
5706
6384
|
const dropTarget = await findCaptchaDropTarget(frame, config);
|
|
5707
6385
|
if (!dropTarget) {
|
|
5708
|
-
|
|
6386
|
+
logger11.warn("\u672A\u627E\u5230\u9A8C\u8BC1\u7801\u62D6\u62FD\u76EE\u6807\u533A\u57DF\u3002");
|
|
5709
6387
|
await refreshCaptcha(page, frame, config);
|
|
5710
6388
|
continue;
|
|
5711
6389
|
}
|
|
@@ -5716,7 +6394,7 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
|
|
|
5716
6394
|
`Captcha image indexes could not be normalized. raw=${serialNumbers.join(", ")}, count=${orderedSourceImages.length}`
|
|
5717
6395
|
);
|
|
5718
6396
|
}
|
|
5719
|
-
|
|
6397
|
+
logger11.info(`\u9A8C\u8BC1\u7801\u89C6\u89C9\u4F4D\u5E8F\u6620\u5C04\uFF1A${normalizedIndexes.map((index) => index + 1).join(", ")}`);
|
|
5720
6398
|
for (const imageIndex of normalizedIndexes) {
|
|
5721
6399
|
if (imageIndex < 0 || imageIndex >= orderedSourceImages.length) {
|
|
5722
6400
|
throw new Error(
|
|
@@ -5748,52 +6426,55 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
|
|
|
5748
6426
|
}
|
|
5749
6427
|
}
|
|
5750
6428
|
const beforeSubmitState = await readPromptCaptchaState(frame, config);
|
|
5751
|
-
|
|
6429
|
+
logger11.info(
|
|
5752
6430
|
`\u63D0\u4EA4\u524D\u9A8C\u8BC1\u7801\u72B6\u6001\uFF1Abadge=${beforeSubmitState.badgeCount}, selected=${beforeSubmitState.selectedCount}, submitDisabled=${beforeSubmitState.submitDisabled}`
|
|
5753
6431
|
);
|
|
5754
6432
|
const submitted = await clickCaptchaAction(frame, config.submitTexts, {
|
|
5755
6433
|
...config,
|
|
5756
6434
|
page,
|
|
5757
|
-
logger:
|
|
6435
|
+
logger: logger11,
|
|
5758
6436
|
forceMouse: true,
|
|
5759
6437
|
actionVisibleTimeoutMs: config.submitReadyTimeoutMs
|
|
5760
6438
|
}).catch(() => false);
|
|
5761
6439
|
if (!submitted) {
|
|
5762
|
-
|
|
6440
|
+
logger11.warn("\u672A\u627E\u5230\u63D0\u4EA4\u6309\u94AE\uFF0C\u53EF\u80FD\u4F1A\u81EA\u52A8\u63D0\u4EA4\u3002");
|
|
5763
6441
|
}
|
|
5764
6442
|
await page.waitForTimeout(config.submitWaitMs);
|
|
5765
6443
|
const afterSubmitState = await readPromptCaptchaState(frame, config);
|
|
5766
|
-
|
|
6444
|
+
logger11.info(
|
|
5767
6445
|
`\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801\u72B6\u6001\uFF1Abadge=${afterSubmitState.badgeCount}, selected=${afterSubmitState.selectedCount}, submitDisabled=${afterSubmitState.submitDisabled}`
|
|
5768
6446
|
);
|
|
5769
6447
|
const stillVisible = await iframeLocator.isVisible({ timeout: config.containerVisibleTimeoutMs }).catch(() => false);
|
|
5770
6448
|
if (!stillVisible) {
|
|
5771
|
-
|
|
6449
|
+
logger11.info("\u9A8C\u8BC1\u7801\u8BC6\u522B\u5E76\u63D0\u4EA4\u6210\u529F\u3002");
|
|
5772
6450
|
return true;
|
|
5773
6451
|
}
|
|
5774
6452
|
await maybeCollectCaptchaDebugInfo(page, frame, iframeLocator, attempt, "submit-still-visible", config, {
|
|
5775
6453
|
beforeSubmitState,
|
|
5776
6454
|
afterSubmitState
|
|
5777
6455
|
}).catch((error) => {
|
|
5778
|
-
|
|
6456
|
+
logger11.warn(`\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801\u8C03\u8BD5\u6293\u53D6\u5931\u8D25\uFF1A${error?.message || error}`);
|
|
5779
6457
|
});
|
|
5780
|
-
|
|
6458
|
+
logger11.warn("\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801 iframe \u4ECD\u7136\u53EF\u89C1\uFF0C\u51C6\u5907\u5237\u65B0\u540E\u91CD\u8BD5\u3002");
|
|
5781
6459
|
await page.waitForTimeout(2e3);
|
|
5782
6460
|
await refreshCaptcha(page, frame, config);
|
|
5783
6461
|
} catch (error) {
|
|
5784
|
-
|
|
6462
|
+
logger11.error(`\u7B2C ${attempt}/${config.maxRetries} \u6B21\u9A8C\u8BC1\u7801\u8BC6\u522B\u5931\u8D25\uFF1A${error?.message || error}`);
|
|
5785
6463
|
}
|
|
5786
6464
|
if (attempt < config.maxRetries) {
|
|
5787
6465
|
await page.waitForTimeout(config.retryDelayBaseMs + attempt * config.retryDelayStepMs);
|
|
5788
6466
|
}
|
|
5789
6467
|
}
|
|
5790
|
-
|
|
6468
|
+
logger11.error(`\u91CD\u8BD5 ${config.maxRetries} \u6B21\u540E\uFF0C\u9A8C\u8BC1\u7801\u4ECD\u672A\u8BC6\u522B\u6210\u529F\u3002`);
|
|
5791
6469
|
return false;
|
|
5792
6470
|
}
|
|
5793
6471
|
var sloveCaptcha = solveCaptcha;
|
|
5794
6472
|
|
|
5795
6473
|
// src/chaptcha.js
|
|
5796
|
-
var
|
|
6474
|
+
var logger12 = createInternalLogger("Captcha");
|
|
6475
|
+
var DOM_MONITOR_WAIT_TIMEOUT_MS = 1e3;
|
|
6476
|
+
var DOM_MONITOR_POST_DETECT_HIDDEN_WAIT_MS = 300;
|
|
6477
|
+
var DOM_MONITOR_RECOVERY_WAIT_MS = 100;
|
|
5797
6478
|
var DEFAULT_CAPTCHA_RECOGNITION_OPTIONS = Object.freeze({
|
|
5798
6479
|
token: "eKJvBfwfN0YRav0-VD_44E2VBSfm7l0YtddUQ7cFySI",
|
|
5799
6480
|
apiUrl: "https://api.jfbym.com/api/YmServer/customApi"
|
|
@@ -5814,6 +6495,11 @@ var mergeDefinedOptions = (...sources) => {
|
|
|
5814
6495
|
}
|
|
5815
6496
|
return merged;
|
|
5816
6497
|
};
|
|
6498
|
+
var sleep = (ms) => new Promise((resolve) => {
|
|
6499
|
+
setTimeout(resolve, ms);
|
|
6500
|
+
});
|
|
6501
|
+
var getErrorMessage = (error) => String(error?.message || error || "");
|
|
6502
|
+
var isTimeoutError = (error) => error?.name === "TimeoutError" || getErrorMessage(error).includes("Timeout");
|
|
5817
6503
|
function useCaptchaMonitor(page, options) {
|
|
5818
6504
|
const { domSelector, urlPattern, onDetected } = options;
|
|
5819
6505
|
if (!domSelector && !urlPattern) {
|
|
@@ -5825,10 +6511,13 @@ function useCaptchaMonitor(page, options) {
|
|
|
5825
6511
|
let isStopped = false;
|
|
5826
6512
|
let isHandling = false;
|
|
5827
6513
|
let frameHandler = null;
|
|
5828
|
-
let
|
|
6514
|
+
let domMonitorTask = null;
|
|
6515
|
+
let lastTriggeredAt = 0;
|
|
5829
6516
|
const triggerDetected = async () => {
|
|
5830
|
-
|
|
6517
|
+
const now = Date.now();
|
|
6518
|
+
if (isStopped || isHandling || now - lastTriggeredAt < 250) return;
|
|
5831
6519
|
isHandling = true;
|
|
6520
|
+
lastTriggeredAt = now;
|
|
5832
6521
|
try {
|
|
5833
6522
|
await onDetected();
|
|
5834
6523
|
} finally {
|
|
@@ -5837,60 +6526,38 @@ function useCaptchaMonitor(page, options) {
|
|
|
5837
6526
|
};
|
|
5838
6527
|
const cleanupFns = [];
|
|
5839
6528
|
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 });
|
|
6529
|
+
domMonitorTask = (async () => {
|
|
6530
|
+
const locator = page.locator(domSelector).first();
|
|
6531
|
+
while (!isStopped) {
|
|
6532
|
+
try {
|
|
6533
|
+
await locator.waitFor({ state: "visible", timeout: DOM_MONITOR_WAIT_TIMEOUT_MS });
|
|
6534
|
+
if (isStopped) break;
|
|
6535
|
+
await triggerDetected();
|
|
6536
|
+
if (isStopped) break;
|
|
6537
|
+
await locator.waitFor({
|
|
6538
|
+
state: "hidden",
|
|
6539
|
+
timeout: DOM_MONITOR_POST_DETECT_HIDDEN_WAIT_MS
|
|
6540
|
+
}).catch(() => {
|
|
6541
|
+
});
|
|
6542
|
+
} catch (error) {
|
|
6543
|
+
if (isStopped) break;
|
|
6544
|
+
if (page?.isClosed?.()) break;
|
|
6545
|
+
if (isTimeoutError(error)) {
|
|
6546
|
+
await sleep(DOM_MONITOR_RECOVERY_WAIT_MS);
|
|
6547
|
+
continue;
|
|
5868
6548
|
}
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
6549
|
+
logger12.warning(
|
|
6550
|
+
"useCaptchaMonitor",
|
|
6551
|
+
`DOM \u76D1\u63A7\u51FA\u73B0\u5F02\u5E38\uFF08\u7EE7\u7EED\u91CD\u8BD5\uFF09: selector=${domSelector}, error=${getErrorMessage(error)}`
|
|
6552
|
+
);
|
|
6553
|
+
await sleep(DOM_MONITOR_RECOVERY_WAIT_MS);
|
|
5874
6554
|
}
|
|
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
6555
|
}
|
|
6556
|
+
})();
|
|
6557
|
+
logger12.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${domSelector}`);
|
|
6558
|
+
cleanupFns.push(async () => {
|
|
6559
|
+
await domMonitorTask?.catch(() => {
|
|
6560
|
+
});
|
|
5894
6561
|
});
|
|
5895
6562
|
}
|
|
5896
6563
|
if (urlPattern) {
|
|
@@ -5904,18 +6571,24 @@ function useCaptchaMonitor(page, options) {
|
|
|
5904
6571
|
}
|
|
5905
6572
|
};
|
|
5906
6573
|
page.on("framenavigated", frameHandler);
|
|
5907
|
-
|
|
6574
|
+
logger12.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${urlPattern}`);
|
|
6575
|
+
Promise.resolve().then(async () => {
|
|
6576
|
+
if (!isStopped && page.url().includes(urlPattern)) {
|
|
6577
|
+
await triggerDetected();
|
|
6578
|
+
}
|
|
6579
|
+
}).catch(() => {
|
|
6580
|
+
});
|
|
5908
6581
|
cleanupFns.push(async () => {
|
|
5909
6582
|
page.off("framenavigated", frameHandler);
|
|
5910
6583
|
});
|
|
5911
6584
|
}
|
|
5912
6585
|
return {
|
|
5913
6586
|
stop: async () => {
|
|
5914
|
-
|
|
6587
|
+
logger12.info("\u6B63\u5728\u505C\u6B62\u9A8C\u8BC1\u7801\u76D1\u63A7...");
|
|
6588
|
+
isStopped = true;
|
|
5915
6589
|
for (const fn of cleanupFns) {
|
|
5916
6590
|
await fn();
|
|
5917
6591
|
}
|
|
5918
|
-
isStopped = true;
|
|
5919
6592
|
}
|
|
5920
6593
|
};
|
|
5921
6594
|
}
|
|
@@ -5950,7 +6623,7 @@ async function solveCaptchaWithStrategy(strategyName, page, options = {}) {
|
|
|
5950
6623
|
);
|
|
5951
6624
|
return strategy.sloveCaptcha(page, resolvedOptions, {
|
|
5952
6625
|
callCaptchaRecognitionApi,
|
|
5953
|
-
logger:
|
|
6626
|
+
logger: logger12
|
|
5954
6627
|
});
|
|
5955
6628
|
}
|
|
5956
6629
|
var Captcha = {
|
|
@@ -5960,15 +6633,15 @@ var Captcha = {
|
|
|
5960
6633
|
|
|
5961
6634
|
// src/mutation.js
|
|
5962
6635
|
import { createHash } from "node:crypto";
|
|
5963
|
-
import { v4 as
|
|
5964
|
-
var
|
|
6636
|
+
import { v4 as uuidv4 } from "uuid";
|
|
6637
|
+
var logger13 = createInternalLogger("Mutation");
|
|
5965
6638
|
var MUTATION_MONITOR_MODE = Object.freeze({
|
|
5966
6639
|
Added: "added",
|
|
5967
6640
|
Changed: "changed",
|
|
5968
6641
|
All: "all"
|
|
5969
6642
|
});
|
|
5970
6643
|
function generateKey(prefix) {
|
|
5971
|
-
return `__${prefix}_${
|
|
6644
|
+
return `__${prefix}_${uuidv4().replace(/-/g, "_")}`;
|
|
5972
6645
|
}
|
|
5973
6646
|
var Mutation = {
|
|
5974
6647
|
Mode: MUTATION_MONITOR_MODE,
|
|
@@ -5994,14 +6667,14 @@ var Mutation = {
|
|
|
5994
6667
|
const stableTime = options.stableTime ?? 5 * 1e3;
|
|
5995
6668
|
const timeout = options.timeout ?? 120 * 1e3;
|
|
5996
6669
|
const onMutation = options.onMutation;
|
|
5997
|
-
|
|
6670
|
+
logger13.start("waitForStable", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);
|
|
5998
6671
|
if (initialTimeout > 0) {
|
|
5999
6672
|
const selectorQuery = selectorList.join(",");
|
|
6000
6673
|
try {
|
|
6001
6674
|
await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
|
|
6002
|
-
|
|
6675
|
+
logger13.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
|
|
6003
6676
|
} catch (e) {
|
|
6004
|
-
|
|
6677
|
+
logger13.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
|
|
6005
6678
|
throw e;
|
|
6006
6679
|
}
|
|
6007
6680
|
}
|
|
@@ -6017,7 +6690,7 @@ var Mutation = {
|
|
|
6017
6690
|
return "__CONTINUE__";
|
|
6018
6691
|
}
|
|
6019
6692
|
});
|
|
6020
|
-
|
|
6693
|
+
logger13.info("waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03");
|
|
6021
6694
|
} catch (e) {
|
|
6022
6695
|
}
|
|
6023
6696
|
}
|
|
@@ -6132,9 +6805,9 @@ var Mutation = {
|
|
|
6132
6805
|
{ selectorList, stableTime, timeout, callbackName, hasCallback: !!onMutation }
|
|
6133
6806
|
);
|
|
6134
6807
|
if (result.mutationCount === 0 && result.stableTime === 0) {
|
|
6135
|
-
|
|
6808
|
+
logger13.warning("waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
|
|
6136
6809
|
}
|
|
6137
|
-
|
|
6810
|
+
logger13.success("waitForStable", `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
|
|
6138
6811
|
return result;
|
|
6139
6812
|
},
|
|
6140
6813
|
/**
|
|
@@ -6158,7 +6831,7 @@ var Mutation = {
|
|
|
6158
6831
|
const overallTimeout = options.timeout ?? 180 * 1e3;
|
|
6159
6832
|
const onMutation = options.onMutation;
|
|
6160
6833
|
const pollInterval = 500;
|
|
6161
|
-
const
|
|
6834
|
+
const sleep2 = (ms) => new Promise((resolve) => {
|
|
6162
6835
|
setTimeout(resolve, ms);
|
|
6163
6836
|
});
|
|
6164
6837
|
const truncate = (value, max = 800) => {
|
|
@@ -6166,7 +6839,7 @@ var Mutation = {
|
|
|
6166
6839
|
if (text.length <= max) return text;
|
|
6167
6840
|
return `${text.slice(0, max)}...`;
|
|
6168
6841
|
};
|
|
6169
|
-
const
|
|
6842
|
+
const normalizeText3 = (value) => String(value || "").replace(/\s+/g, " ").trim();
|
|
6170
6843
|
const normalizeHtml = (value) => String(value || "").trim();
|
|
6171
6844
|
const hashSnapshot = (value) => createHash("sha256").update(String(value || "")).digest("hex");
|
|
6172
6845
|
const buildState = async () => {
|
|
@@ -6231,7 +6904,7 @@ var Mutation = {
|
|
|
6231
6904
|
if (frame) {
|
|
6232
6905
|
try {
|
|
6233
6906
|
const frameSnapshot = await readFrameSnapshot(frame);
|
|
6234
|
-
text =
|
|
6907
|
+
text = normalizeText3(frameSnapshot?.text || "");
|
|
6235
6908
|
html = normalizeHtml(frameSnapshot?.html || "");
|
|
6236
6909
|
frameUrl = String(frameSnapshot?.url || "").trim();
|
|
6237
6910
|
readyState = String(frameSnapshot?.readyState || "").trim();
|
|
@@ -6245,7 +6918,7 @@ var Mutation = {
|
|
|
6245
6918
|
} else {
|
|
6246
6919
|
try {
|
|
6247
6920
|
const elementSnapshot = await readElementSnapshot(handle);
|
|
6248
|
-
text =
|
|
6921
|
+
text = normalizeText3(elementSnapshot?.text || "");
|
|
6249
6922
|
html = normalizeHtml(elementSnapshot?.html || "");
|
|
6250
6923
|
} catch (error) {
|
|
6251
6924
|
source = "main-unreadable";
|
|
@@ -6306,29 +6979,29 @@ var Mutation = {
|
|
|
6306
6979
|
return "__CONTINUE__";
|
|
6307
6980
|
}
|
|
6308
6981
|
};
|
|
6309
|
-
|
|
6982
|
+
logger13.start(
|
|
6310
6983
|
"waitForStableAcrossRoots",
|
|
6311
6984
|
`\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668(\u8DE8 root), \u7A33\u5B9A\u65F6\u95F4=${waitForStableTime}ms`
|
|
6312
6985
|
);
|
|
6313
6986
|
if (initialTimeout > 0) {
|
|
6314
6987
|
try {
|
|
6315
6988
|
await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
|
|
6316
|
-
|
|
6989
|
+
logger13.info(`waitForStableAcrossRoots \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
|
|
6317
6990
|
} catch (e) {
|
|
6318
|
-
|
|
6991
|
+
logger13.warning(`waitForStableAcrossRoots \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
|
|
6319
6992
|
throw e;
|
|
6320
6993
|
}
|
|
6321
6994
|
}
|
|
6322
|
-
let
|
|
6323
|
-
if (!
|
|
6324
|
-
|
|
6995
|
+
let state2 = await buildState();
|
|
6996
|
+
if (!state2?.hasMatched) {
|
|
6997
|
+
logger13.warning("waitForStableAcrossRoots \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
|
|
6325
6998
|
return { mutationCount: 0, stableTime: 0, wasPaused: false };
|
|
6326
6999
|
}
|
|
6327
7000
|
let mutationCount = 0;
|
|
6328
7001
|
let stableSince = 0;
|
|
6329
7002
|
let isPaused = false;
|
|
6330
7003
|
let wasPaused = false;
|
|
6331
|
-
let lastSnapshotKey =
|
|
7004
|
+
let lastSnapshotKey = state2.snapshotKey;
|
|
6332
7005
|
const applyPauseSignal = (signal) => {
|
|
6333
7006
|
const nextPaused = signal === "__PAUSE__";
|
|
6334
7007
|
if (nextPaused) {
|
|
@@ -6342,15 +7015,15 @@ var Mutation = {
|
|
|
6342
7015
|
};
|
|
6343
7016
|
const initialSignal = await invokeMutationCallback({
|
|
6344
7017
|
mutationCount: 0,
|
|
6345
|
-
html:
|
|
6346
|
-
text:
|
|
6347
|
-
mutationNodes:
|
|
7018
|
+
html: state2.html || "",
|
|
7019
|
+
text: state2.text || "",
|
|
7020
|
+
mutationNodes: state2.mutationNodes || []
|
|
6348
7021
|
});
|
|
6349
7022
|
applyPauseSignal(initialSignal);
|
|
6350
7023
|
const deadline = Date.now() + overallTimeout;
|
|
6351
|
-
let lastState =
|
|
7024
|
+
let lastState = state2;
|
|
6352
7025
|
while (Date.now() < deadline) {
|
|
6353
|
-
await
|
|
7026
|
+
await sleep2(pollInterval);
|
|
6354
7027
|
lastState = await buildState();
|
|
6355
7028
|
if (!lastState?.hasMatched) {
|
|
6356
7029
|
continue;
|
|
@@ -6358,7 +7031,7 @@ var Mutation = {
|
|
|
6358
7031
|
if (lastState.snapshotKey !== lastSnapshotKey) {
|
|
6359
7032
|
lastSnapshotKey = lastState.snapshotKey;
|
|
6360
7033
|
mutationCount += 1;
|
|
6361
|
-
|
|
7034
|
+
logger13.info(
|
|
6362
7035
|
`waitForStableAcrossRoots \u53D8\u5316#${mutationCount}, len=${lastState.snapshotLength}, path=${lastState.primaryPath || "unknown"}, preview="${truncate(lastState.text, 120)}"`
|
|
6363
7036
|
);
|
|
6364
7037
|
const signal = await invokeMutationCallback({
|
|
@@ -6371,7 +7044,7 @@ var Mutation = {
|
|
|
6371
7044
|
continue;
|
|
6372
7045
|
}
|
|
6373
7046
|
if (!isPaused && stableSince > 0 && Date.now() - stableSince >= waitForStableTime) {
|
|
6374
|
-
|
|
7047
|
+
logger13.success("waitForStableAcrossRoots", `DOM \u7A33\u5B9A, \u603B\u5171 ${mutationCount} \u6B21\u53D8\u5316${wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
|
|
6375
7048
|
return {
|
|
6376
7049
|
mutationCount,
|
|
6377
7050
|
stableTime: waitForStableTime,
|
|
@@ -6397,8 +7070,8 @@ var Mutation = {
|
|
|
6397
7070
|
const selectorList = Array.isArray(selectors) ? selectors : [selectors];
|
|
6398
7071
|
const onMutation = options.onMutation;
|
|
6399
7072
|
const rawMode = String(options.mode || MUTATION_MONITOR_MODE.Added).toLowerCase();
|
|
6400
|
-
const
|
|
6401
|
-
|
|
7073
|
+
const mode2 = [MUTATION_MONITOR_MODE.Added, MUTATION_MONITOR_MODE.Changed, MUTATION_MONITOR_MODE.All].includes(rawMode) ? rawMode : MUTATION_MONITOR_MODE.Added;
|
|
7074
|
+
logger13.start("useMonitor", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode2}`);
|
|
6402
7075
|
const monitorKey = generateKey("pk_mon");
|
|
6403
7076
|
const callbackName = generateKey("pk_mon_cb");
|
|
6404
7077
|
const cleanerName = generateKey("pk_mon_clean");
|
|
@@ -6413,7 +7086,7 @@ var Mutation = {
|
|
|
6413
7086
|
} catch (e) {
|
|
6414
7087
|
}
|
|
6415
7088
|
}
|
|
6416
|
-
await page.evaluate(({ selectorList: selectorList2, monitorKey: monitorKey2, callbackName: callbackName2, cleanerName: cleanerName2, hasCallback, mode:
|
|
7089
|
+
await page.evaluate(({ selectorList: selectorList2, monitorKey: monitorKey2, callbackName: callbackName2, cleanerName: cleanerName2, hasCallback, mode: mode3 }) => {
|
|
6417
7090
|
const monitor = {
|
|
6418
7091
|
observers: [],
|
|
6419
7092
|
totalMutations: 0,
|
|
@@ -6457,7 +7130,7 @@ var Mutation = {
|
|
|
6457
7130
|
const collectMutationNodes = (mutations) => {
|
|
6458
7131
|
const mutationNodes = [];
|
|
6459
7132
|
for (const mutation of mutations) {
|
|
6460
|
-
if (
|
|
7133
|
+
if (mode3 === "added") {
|
|
6461
7134
|
if (mutation.type !== "childList") continue;
|
|
6462
7135
|
const added = Array.from(mutation.addedNodes || []);
|
|
6463
7136
|
for (const node of added) {
|
|
@@ -6465,7 +7138,7 @@ var Mutation = {
|
|
|
6465
7138
|
}
|
|
6466
7139
|
continue;
|
|
6467
7140
|
}
|
|
6468
|
-
if (
|
|
7141
|
+
if (mode3 === "changed") {
|
|
6469
7142
|
if (mutation.type === "attributes" || mutation.type === "characterData") {
|
|
6470
7143
|
mutationNodes.push(serializeNode(mutation.target, mutation.type));
|
|
6471
7144
|
} else if (mutation.type === "childList") {
|
|
@@ -6525,8 +7198,8 @@ var Mutation = {
|
|
|
6525
7198
|
observer.observe(element, {
|
|
6526
7199
|
childList: true,
|
|
6527
7200
|
subtree: true,
|
|
6528
|
-
characterData:
|
|
6529
|
-
attributes:
|
|
7201
|
+
characterData: mode3 !== "added",
|
|
7202
|
+
attributes: mode3 !== "added"
|
|
6530
7203
|
});
|
|
6531
7204
|
monitor.observers.push(observer);
|
|
6532
7205
|
});
|
|
@@ -6540,8 +7213,8 @@ var Mutation = {
|
|
|
6540
7213
|
delete window[cleanerName2];
|
|
6541
7214
|
return total;
|
|
6542
7215
|
};
|
|
6543
|
-
}, { selectorList, monitorKey, callbackName, cleanerName, hasCallback: !!onMutation, mode });
|
|
6544
|
-
|
|
7216
|
+
}, { selectorList, monitorKey, callbackName, cleanerName, hasCallback: !!onMutation, mode: mode2 });
|
|
7217
|
+
logger13.success("useMonitor", "\u76D1\u63A7\u5668\u5DF2\u542F\u52A8");
|
|
6545
7218
|
return {
|
|
6546
7219
|
stop: async () => {
|
|
6547
7220
|
let totalMutations = 0;
|
|
@@ -6554,7 +7227,7 @@ var Mutation = {
|
|
|
6554
7227
|
}, cleanerName);
|
|
6555
7228
|
} catch (e) {
|
|
6556
7229
|
}
|
|
6557
|
-
|
|
7230
|
+
logger13.success("useMonitor.stop", `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);
|
|
6558
7231
|
return { totalMutations };
|
|
6559
7232
|
}
|
|
6560
7233
|
};
|
|
@@ -7423,7 +8096,7 @@ var createTemplateLogger = (baseLogger = createBaseLogger()) => {
|
|
|
7423
8096
|
};
|
|
7424
8097
|
var getDefaultBaseLogger = () => createBaseLogger("");
|
|
7425
8098
|
var Logger = {
|
|
7426
|
-
setLogger: (
|
|
8099
|
+
setLogger: (logger17) => setDefaultLogger(logger17),
|
|
7427
8100
|
info: (message) => getDefaultBaseLogger().info(message),
|
|
7428
8101
|
success: (message) => getDefaultBaseLogger().success(message),
|
|
7429
8102
|
warning: (message) => getDefaultBaseLogger().warning(message),
|
|
@@ -7431,14 +8104,14 @@ var Logger = {
|
|
|
7431
8104
|
error: (message) => getDefaultBaseLogger().error(message),
|
|
7432
8105
|
debug: (message) => getDefaultBaseLogger().debug(message),
|
|
7433
8106
|
start: (message) => getDefaultBaseLogger().start(message),
|
|
7434
|
-
useTemplate: (
|
|
7435
|
-
if (
|
|
8107
|
+
useTemplate: (logger17) => {
|
|
8108
|
+
if (logger17) return createTemplateLogger(createBaseLogger("", logger17));
|
|
7436
8109
|
return createTemplateLogger();
|
|
7437
8110
|
}
|
|
7438
8111
|
};
|
|
7439
8112
|
|
|
7440
8113
|
// src/share.js
|
|
7441
|
-
import
|
|
8114
|
+
import delay5 from "delay";
|
|
7442
8115
|
|
|
7443
8116
|
// src/internals/watermarkify.js
|
|
7444
8117
|
var DEFAULT_TIMEZONE_OFFSET = 8;
|
|
@@ -7506,10 +8179,10 @@ var LOCATION_NETWORK_SUFFIX_PATTERNS = [
|
|
|
7506
8179
|
];
|
|
7507
8180
|
var cachedStripLogoSrcPromise = null;
|
|
7508
8181
|
var cachedEnrichmentByContext = /* @__PURE__ */ new WeakMap();
|
|
7509
|
-
var
|
|
7510
|
-
var
|
|
8182
|
+
var logger14 = createInternalLogger("Watermarkify");
|
|
8183
|
+
var normalizeText2 = (value) => String(value || "").trim();
|
|
7511
8184
|
var toInline = (value, maxLen = 200) => {
|
|
7512
|
-
const text =
|
|
8185
|
+
const text = normalizeText2(value);
|
|
7513
8186
|
if (!text) return "";
|
|
7514
8187
|
return text.replace(/\s+/g, " ").trim().slice(0, maxLen);
|
|
7515
8188
|
};
|
|
@@ -7569,7 +8242,7 @@ var pickHeaderValue = async (response, names = []) => {
|
|
|
7569
8242
|
if (!response || typeof response.headerValue !== "function") return "";
|
|
7570
8243
|
for (const name of names) {
|
|
7571
8244
|
const value = await response.headerValue(name).catch(() => null);
|
|
7572
|
-
const text =
|
|
8245
|
+
const text = normalizeText2(value);
|
|
7573
8246
|
if (text) return text;
|
|
7574
8247
|
}
|
|
7575
8248
|
return "";
|
|
@@ -7673,7 +8346,7 @@ var fetchAsDataUrl = async (url, timeoutMs = DEFAULT_LOGO_FETCH_TIMEOUT_MS) => {
|
|
|
7673
8346
|
if (!response?.ok) {
|
|
7674
8347
|
return "";
|
|
7675
8348
|
}
|
|
7676
|
-
const contentType =
|
|
8349
|
+
const contentType = normalizeText2(response.headers?.get?.("content-type")) || "image/png";
|
|
7677
8350
|
if (!/^image\//i.test(contentType)) {
|
|
7678
8351
|
return "";
|
|
7679
8352
|
}
|
|
@@ -7696,7 +8369,7 @@ var resolveStripLogoSrc = async () => {
|
|
|
7696
8369
|
})();
|
|
7697
8370
|
}
|
|
7698
8371
|
const resolved = await cachedStripLogoSrcPromise.catch(() => DEFAULT_STRIP_LOGO_URL);
|
|
7699
|
-
return
|
|
8372
|
+
return normalizeText2(resolved) || DEFAULT_STRIP_LOGO_URL;
|
|
7700
8373
|
};
|
|
7701
8374
|
var normalizeLayer = (value, defaults) => {
|
|
7702
8375
|
if (value === false) {
|
|
@@ -7748,9 +8421,9 @@ var resolveWithCustomResolver = async (page, baseMeta, options = {}) => {
|
|
|
7748
8421
|
location: toInline(resolved.location, 80)
|
|
7749
8422
|
};
|
|
7750
8423
|
if (enrichment.ip || enrichment.location) {
|
|
7751
|
-
|
|
8424
|
+
logger14.info(`\u81EA\u5B9A\u4E49 resolver \u547D\u4E2D: ip=${enrichment.ip || "-"}, loc=${enrichment.location || "-"}`);
|
|
7752
8425
|
} else {
|
|
7753
|
-
|
|
8426
|
+
logger14.warning("\u81EA\u5B9A\u4E49 resolver \u5DF2\u6267\u884C\uFF0C\u4F46\u672A\u8FD4\u56DE IP/Loc");
|
|
7754
8427
|
}
|
|
7755
8428
|
return enrichment;
|
|
7756
8429
|
} finally {
|
|
@@ -7934,14 +8607,17 @@ var buildWatermarkifyRenderHtml = ({ imageSrc, overlaySvg, width, height, imageH
|
|
|
7934
8607
|
</html>
|
|
7935
8608
|
`;
|
|
7936
8609
|
};
|
|
7937
|
-
var
|
|
8610
|
+
var normalizeWatermarkifyRenderMode = (value) => {
|
|
8611
|
+
return String(value || Mode.Default).trim().toLowerCase() === Mode.Cloak ? Mode.Cloak : Mode.Default;
|
|
8612
|
+
};
|
|
8613
|
+
var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageInfo = {}, options = {}) => {
|
|
7938
8614
|
if (!page || typeof page.context !== "function") {
|
|
7939
|
-
|
|
8615
|
+
logger14.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u7F3A\u5C11\u53EF\u7528 page");
|
|
7940
8616
|
return buffer;
|
|
7941
8617
|
}
|
|
7942
8618
|
const renderScope = await openProbePage(page);
|
|
7943
8619
|
if (!renderScope?.page) {
|
|
7944
|
-
|
|
8620
|
+
logger14.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA render page");
|
|
7945
8621
|
return buffer;
|
|
7946
8622
|
}
|
|
7947
8623
|
try {
|
|
@@ -7958,15 +8634,35 @@ var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageI
|
|
|
7958
8634
|
height: viewportHeight
|
|
7959
8635
|
}).catch(() => {
|
|
7960
8636
|
});
|
|
7961
|
-
|
|
7962
|
-
|
|
7963
|
-
|
|
7964
|
-
|
|
7965
|
-
|
|
7966
|
-
|
|
7967
|
-
|
|
7968
|
-
|
|
7969
|
-
|
|
8637
|
+
const renderMode = normalizeWatermarkifyRenderMode(options.mode);
|
|
8638
|
+
if (renderMode === Mode.Cloak) {
|
|
8639
|
+
const renderHtml = buildWatermarkifyRenderHtml({
|
|
8640
|
+
imageSrc: `data:${imageInfo.mimeType || "image/png"};base64,${buffer.toString("base64")}`,
|
|
8641
|
+
overlaySvg,
|
|
8642
|
+
width: safeWidth,
|
|
8643
|
+
height: safeHeight,
|
|
8644
|
+
imageHeight: safeImageHeight
|
|
8645
|
+
});
|
|
8646
|
+
await renderPage.goto("about:blank", {
|
|
8647
|
+
waitUntil: "commit"
|
|
8648
|
+
}).catch(() => {
|
|
8649
|
+
});
|
|
8650
|
+
await renderPage.evaluate((html) => {
|
|
8651
|
+
document.open();
|
|
8652
|
+
document.write(html);
|
|
8653
|
+
document.close();
|
|
8654
|
+
}, renderHtml);
|
|
8655
|
+
} else {
|
|
8656
|
+
await renderPage.setContent(buildWatermarkifyRenderHtml({
|
|
8657
|
+
imageSrc: `data:${imageInfo.mimeType || "image/png"};base64,${buffer.toString("base64")}`,
|
|
8658
|
+
overlaySvg,
|
|
8659
|
+
width: safeWidth,
|
|
8660
|
+
height: safeHeight,
|
|
8661
|
+
imageHeight: safeImageHeight
|
|
8662
|
+
}), {
|
|
8663
|
+
waitUntil: "load"
|
|
8664
|
+
});
|
|
8665
|
+
}
|
|
7970
8666
|
await renderPage.waitForFunction(() => {
|
|
7971
8667
|
const image = document.getElementById("pk-base-image");
|
|
7972
8668
|
return image instanceof HTMLImageElement && image.complete && image.naturalWidth > 0 && image.naturalHeight > 0;
|
|
@@ -7986,13 +8682,13 @@ var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageI
|
|
|
7986
8682
|
fullPage: true,
|
|
7987
8683
|
animations: "disabled"
|
|
7988
8684
|
}).catch((error) => {
|
|
7989
|
-
|
|
8685
|
+
logger14.warning(`watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
7990
8686
|
return null;
|
|
7991
8687
|
});
|
|
7992
8688
|
if (Buffer.isBuffer(composed) && composed.length > 0) {
|
|
7993
8689
|
return composed;
|
|
7994
8690
|
}
|
|
7995
|
-
|
|
8691
|
+
logger14.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: \u672A\u5F97\u5230\u6709\u6548\u622A\u56FE\u7ED3\u679C");
|
|
7996
8692
|
return buffer;
|
|
7997
8693
|
} finally {
|
|
7998
8694
|
await renderScope.close().catch(() => {
|
|
@@ -8005,7 +8701,7 @@ var resolveWithIpLookup = async (page, options = {}) => {
|
|
|
8005
8701
|
}
|
|
8006
8702
|
const probeScope = await openProbePage(page);
|
|
8007
8703
|
if (!probeScope?.page) {
|
|
8008
|
-
|
|
8704
|
+
logger14.warning("ipLookup \u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA probe page");
|
|
8009
8705
|
return null;
|
|
8010
8706
|
}
|
|
8011
8707
|
const timeoutMs = Math.max(
|
|
@@ -8014,16 +8710,16 @@ var resolveWithIpLookup = async (page, options = {}) => {
|
|
|
8014
8710
|
);
|
|
8015
8711
|
try {
|
|
8016
8712
|
const probePage = probeScope.page;
|
|
8017
|
-
|
|
8713
|
+
logger14.info(`ipLookup \u5C1D\u8BD5: url=${DEFAULT_IP_LOOKUP_URL}, timeoutMs=${timeoutMs}`);
|
|
8018
8714
|
const response = await probePage.goto(DEFAULT_IP_LOOKUP_URL, {
|
|
8019
8715
|
waitUntil: "commit",
|
|
8020
8716
|
timeout: timeoutMs
|
|
8021
8717
|
}).catch((error) => {
|
|
8022
|
-
|
|
8718
|
+
logger14.warning(`ipLookup \u8BF7\u6C42\u5931\u8D25: url=${DEFAULT_IP_LOOKUP_URL}, error=${error instanceof Error ? error.message : String(error)}`);
|
|
8023
8719
|
return null;
|
|
8024
8720
|
});
|
|
8025
8721
|
const status = response && typeof response.status === "function" ? response.status() : 0;
|
|
8026
|
-
const contentType =
|
|
8722
|
+
const contentType = normalizeText2(await pickHeaderValue(response, ["content-type"]));
|
|
8027
8723
|
let rawText = "";
|
|
8028
8724
|
if (response && typeof response.text === "function") {
|
|
8029
8725
|
rawText = String(await withTimeout2(
|
|
@@ -8041,13 +8737,13 @@ var resolveWithIpLookup = async (page, options = {}) => {
|
|
|
8041
8737
|
}
|
|
8042
8738
|
const parsed = parseIpIpJsonResponse(rawText);
|
|
8043
8739
|
if (parsed?.ip || parsed?.location) {
|
|
8044
|
-
|
|
8740
|
+
logger14.info(`ipLookup \u6210\u529F: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, ip=${parsed.ip || "-"}, loc=${parsed.location || "-"}`);
|
|
8045
8741
|
return parsed;
|
|
8046
8742
|
}
|
|
8047
|
-
|
|
8743
|
+
logger14.warning(`ipLookup \u672A\u89E3\u6790\u51FA IP/Loc: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, preview=${shortenTail(rawText, 120) || "[empty]"}`);
|
|
8048
8744
|
return null;
|
|
8049
8745
|
} catch (error) {
|
|
8050
|
-
|
|
8746
|
+
logger14.warning(`ipLookup \u6267\u884C\u5F02\u5E38\uFF0C\u672A\u83B7\u5F97 IP/Loc: ${error instanceof Error ? error.message : String(error)}`);
|
|
8051
8747
|
return null;
|
|
8052
8748
|
} finally {
|
|
8053
8749
|
await probeScope.close().catch(() => {
|
|
@@ -8061,10 +8757,10 @@ var resolveEnrichment = async (page, baseMeta, options) => {
|
|
|
8061
8757
|
ip: toInline(options.ip, 80),
|
|
8062
8758
|
location: toInline(options.location, 80)
|
|
8063
8759
|
};
|
|
8064
|
-
|
|
8760
|
+
logger14.info(`enrichment \u5F00\u59CB: host=${baseMeta.hostname || "-"}, hasPresetIp=${Boolean(merged.ip)}, hasPresetLoc=${Boolean(merged.location)}, ipLookup=${options.ipLookup !== false}`);
|
|
8065
8761
|
if (!merged.ip || !merged.location) {
|
|
8066
8762
|
if (cached?.ip || cached?.location) {
|
|
8067
|
-
|
|
8763
|
+
logger14.info(`enrichment \u547D\u4E2D\u4E0A\u4E0B\u6587\u7F13\u5B58: ip=${cached.ip || "-"}, loc=${cached.location || "-"}`);
|
|
8068
8764
|
}
|
|
8069
8765
|
fillEnrichment(merged, cached);
|
|
8070
8766
|
}
|
|
@@ -8088,15 +8784,15 @@ var resolveEnrichment = async (page, baseMeta, options) => {
|
|
|
8088
8784
|
"x-geo-country"
|
|
8089
8785
|
]), 80);
|
|
8090
8786
|
if (!merged.location || isWeakLocationValue(merged.location) && headerLocation) {
|
|
8091
|
-
|
|
8787
|
+
logger14.info(`enrichment \u4F7F\u7528\u54CD\u5E94\u5934\u8865\u5145 Loc: ${headerLocation || "-"}`);
|
|
8092
8788
|
merged.location = headerLocation || merged.location;
|
|
8093
8789
|
}
|
|
8094
8790
|
}
|
|
8095
8791
|
writeCachedEnrichment(page, merged);
|
|
8096
8792
|
if (merged.ip || merged.location) {
|
|
8097
|
-
|
|
8793
|
+
logger14.info(`enrichment \u5B8C\u6210: ip=${merged.ip || "-"}, loc=${merged.location || "-"}`);
|
|
8098
8794
|
} else {
|
|
8099
|
-
|
|
8795
|
+
logger14.warning("enrichment \u5B8C\u6210: \u672A\u83B7\u5F97 IP/Loc");
|
|
8100
8796
|
}
|
|
8101
8797
|
return merged;
|
|
8102
8798
|
};
|
|
@@ -8162,8 +8858,8 @@ var estimateTextWidth = (value, fontSize = 16) => {
|
|
|
8162
8858
|
return Math.ceil(width);
|
|
8163
8859
|
};
|
|
8164
8860
|
var resolvePromptFields = (options = {}, fallbackTitle = "") => {
|
|
8165
|
-
const query =
|
|
8166
|
-
const prompt = query ||
|
|
8861
|
+
const query = normalizeText2(options.query);
|
|
8862
|
+
const prompt = query || normalizeText2(options.prompt) || normalizeText2(fallbackTitle) || "\u672A\u63D0\u4F9B Prompt";
|
|
8167
8863
|
return {
|
|
8168
8864
|
prompt,
|
|
8169
8865
|
query: query || prompt
|
|
@@ -8217,8 +8913,8 @@ var normalizeScreenshotWatermarkify = (value) => {
|
|
|
8217
8913
|
enabled: source.enabled !== false,
|
|
8218
8914
|
timezoneOffsetHours: Number.isFinite(timezoneOffsetHoursRaw) ? timezoneOffsetHoursRaw : DEFAULT_TIMEZONE_OFFSET,
|
|
8219
8915
|
response: source.response ?? null,
|
|
8220
|
-
ip:
|
|
8221
|
-
location:
|
|
8916
|
+
ip: normalizeText2(source.ip),
|
|
8917
|
+
location: normalizeText2(source.location),
|
|
8222
8918
|
prompt: normalizeWhitespace(source.prompt),
|
|
8223
8919
|
query: normalizeWhitespace(source.query),
|
|
8224
8920
|
ipLookup: source.ipLookup !== false,
|
|
@@ -8236,8 +8932,8 @@ var normalizeScreenshotWatermarkify = (value) => {
|
|
|
8236
8932
|
};
|
|
8237
8933
|
var resolveScreenshotWatermarkifyMeta = async (page, options = {}) => {
|
|
8238
8934
|
const timezoneOffsetHours = options.timezoneOffsetHours ?? DEFAULT_TIMEZONE_OFFSET;
|
|
8239
|
-
const url =
|
|
8240
|
-
const title =
|
|
8935
|
+
const url = normalizeText2(page?.url?.()) || "about:blank";
|
|
8936
|
+
const title = normalizeText2(await page.title().catch(() => "")) || "\u672A\u547D\u540D\u9875\u9762";
|
|
8241
8937
|
const hostname = getHostname(url);
|
|
8242
8938
|
const { prompt, query } = resolvePromptFields(options, title);
|
|
8243
8939
|
const capturedAt = options.capturedAt instanceof Date ? options.capturedAt : new Date(options.capturedAt || Date.now());
|
|
@@ -8724,7 +9420,7 @@ var renderMobileStrip = ({ meta, width, baseHeight, fontFamily }) => {
|
|
|
8724
9420
|
`;
|
|
8725
9421
|
};
|
|
8726
9422
|
var buildWatermarkifySvg = (meta, imageWidth, imageHeight) => {
|
|
8727
|
-
const hasWatermark = meta?.watermark?.enabled !== false &&
|
|
9423
|
+
const hasWatermark = meta?.watermark?.enabled !== false && normalizeText2(meta?.watermarkText);
|
|
8728
9424
|
const hasStrip = meta?.strip?.enabled !== false && Array.isArray(meta?.stripSegments) && meta.stripSegments.length > 0;
|
|
8729
9425
|
if (!hasWatermark && !hasStrip) {
|
|
8730
9426
|
return "";
|
|
@@ -8735,7 +9431,7 @@ var buildWatermarkifySvg = (meta, imageWidth, imageHeight) => {
|
|
|
8735
9431
|
const fontFamily = escapeXml(buildFontFamily());
|
|
8736
9432
|
const parts = [];
|
|
8737
9433
|
if (hasWatermark) {
|
|
8738
|
-
const stampText = escapeXml(
|
|
9434
|
+
const stampText = escapeXml(normalizeText2(meta.watermarkText));
|
|
8739
9435
|
const cellWidth = Math.max(680, Number(meta.watermark?.cellWidth) || DEFAULT_WATERMARK_CELL_WIDTH);
|
|
8740
9436
|
const cellHeight = Math.max(260, Number(meta.watermark?.cellHeight) || DEFAULT_WATERMARK_CELL_HEIGHT);
|
|
8741
9437
|
const rotateDeg = Number(meta.watermark?.rotateDeg) || DEFAULT_WATERMARK_ROTATE_DEG;
|
|
@@ -8901,15 +9597,15 @@ var buildWatermarkifySvg = (meta, imageWidth, imageHeight) => {
|
|
|
8901
9597
|
</svg>
|
|
8902
9598
|
`;
|
|
8903
9599
|
};
|
|
8904
|
-
var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
|
|
8905
|
-
const hasWatermark = meta?.watermark?.enabled !== false &&
|
|
9600
|
+
var watermarkifyScreenshotBuffer = async (buffer, meta, page = null, options = {}) => {
|
|
9601
|
+
const hasWatermark = meta?.watermark?.enabled !== false && normalizeText2(meta?.watermarkText);
|
|
8906
9602
|
const hasStrip = meta?.strip?.enabled !== false && Array.isArray(meta?.stripSegments) && meta.stripSegments.length > 0;
|
|
8907
9603
|
if (!Buffer.isBuffer(buffer) || !meta || !hasWatermark && !hasStrip) {
|
|
8908
9604
|
return buffer;
|
|
8909
9605
|
}
|
|
8910
9606
|
const imageInfo = readImageInfo(buffer);
|
|
8911
9607
|
if (!imageInfo.width || !imageInfo.height || !imageInfo.mimeType) {
|
|
8912
|
-
|
|
9608
|
+
logger14.warning("watermarkify \u8DF3\u8FC7: \u65E0\u6CD5\u89E3\u6790\u622A\u56FE\u5C3A\u5BF8\u6216\u683C\u5F0F");
|
|
8913
9609
|
return buffer;
|
|
8914
9610
|
}
|
|
8915
9611
|
const isMobileStrip = normalizeDevice(meta.device) === Device.Mobile && hasStrip;
|
|
@@ -8922,12 +9618,12 @@ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
|
|
|
8922
9618
|
if (!overlaySvg) {
|
|
8923
9619
|
return buffer;
|
|
8924
9620
|
}
|
|
8925
|
-
return await composeScreenshotBufferWithBrowser(page, buffer, overlaySvg, outputImageInfo);
|
|
9621
|
+
return await composeScreenshotBufferWithBrowser(page, buffer, overlaySvg, outputImageInfo, options);
|
|
8926
9622
|
};
|
|
8927
9623
|
|
|
8928
9624
|
// src/internals/compression.js
|
|
8929
9625
|
import { Jimp, JimpMime, ResizeStrategy } from "jimp";
|
|
8930
|
-
var
|
|
9626
|
+
var logger15 = createInternalLogger("Compression");
|
|
8931
9627
|
var DEFAULT_SCREENSHOT_MAX_BYTES = 5 * 1024 * 1024;
|
|
8932
9628
|
var DEFAULT_SCREENSHOT_OUTPUT_TYPE = "jpeg";
|
|
8933
9629
|
var DEFAULT_SCREENSHOT_QUALITY = 0.72;
|
|
@@ -9046,18 +9742,18 @@ var compressImageBufferToBase64 = async (buffer, compression) => {
|
|
|
9046
9742
|
return buffer.toString("base64");
|
|
9047
9743
|
}
|
|
9048
9744
|
const result = await compressImageBuffer(buffer, compression).catch((error) => {
|
|
9049
|
-
|
|
9745
|
+
logger15.warning(`captureScreen \u538B\u7F29\u5931\u8D25\uFF0C\u8FD4\u56DE\u539F\u56FE: ${error instanceof Error ? error.message : String(error)}`);
|
|
9050
9746
|
return null;
|
|
9051
9747
|
});
|
|
9052
9748
|
if (!result?.buffer) {
|
|
9053
9749
|
return buffer.toString("base64");
|
|
9054
9750
|
}
|
|
9055
9751
|
if (result.withinLimit) {
|
|
9056
|
-
|
|
9752
|
+
logger15.info(
|
|
9057
9753
|
`captureScreen \u5DF2\u538B\u7F29: ${originalBytes} -> ${result.bytes} bytes, format=${result.format}, quality=${result.quality}, scale=${result.scale}, size=${result.width}x${result.height}`
|
|
9058
9754
|
);
|
|
9059
9755
|
} else {
|
|
9060
|
-
|
|
9756
|
+
logger15.warning(
|
|
9061
9757
|
`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
9758
|
);
|
|
9063
9759
|
}
|
|
@@ -9065,7 +9761,7 @@ var compressImageBufferToBase64 = async (buffer, compression) => {
|
|
|
9065
9761
|
};
|
|
9066
9762
|
|
|
9067
9763
|
// src/share.js
|
|
9068
|
-
var
|
|
9764
|
+
var logger16 = createInternalLogger("Share");
|
|
9069
9765
|
var DEFAULT_TIMEOUT_MS2 = 50 * 1e3;
|
|
9070
9766
|
var DEFAULT_PAYLOAD_SNAPSHOT_MAX_LEN = 500;
|
|
9071
9767
|
var DEFAULT_POLL_INTERVAL_MS = 120;
|
|
@@ -9135,9 +9831,9 @@ var normalizeXurl = (value) => {
|
|
|
9135
9831
|
var normalizeShare = (share) => {
|
|
9136
9832
|
const source = share && typeof share === "object" ? share : {};
|
|
9137
9833
|
const modeRaw = String(source.mode || "dom").trim().toLowerCase();
|
|
9138
|
-
const
|
|
9834
|
+
const mode2 = ["dom", "response", "custom"].includes(modeRaw) ? modeRaw : "dom";
|
|
9139
9835
|
return {
|
|
9140
|
-
mode,
|
|
9836
|
+
mode: mode2,
|
|
9141
9837
|
prefix: normalizePrefix(source.prefix),
|
|
9142
9838
|
xurl: normalizeXurl(source.xurl)
|
|
9143
9839
|
};
|
|
@@ -9198,13 +9894,13 @@ var parseJsonSafely = (text) => {
|
|
|
9198
9894
|
var createDomShareMonitor = async (page, options = {}) => {
|
|
9199
9895
|
const prefix = normalizePrefix(options.prefix);
|
|
9200
9896
|
const selectors = options.selectors ?? "html";
|
|
9201
|
-
const
|
|
9897
|
+
const mode2 = options.mode ?? Mutation.Mode.All;
|
|
9202
9898
|
const onMatch = typeof options.onMatch === "function" ? options.onMatch : null;
|
|
9203
9899
|
const onTelemetry = typeof options.onTelemetry === "function" ? options.onTelemetry : null;
|
|
9204
9900
|
let matched = false;
|
|
9205
|
-
|
|
9901
|
+
logger16.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode2}`);
|
|
9206
9902
|
const monitor = await Mutation.useMonitor(page, selectors, {
|
|
9207
|
-
mode,
|
|
9903
|
+
mode: mode2,
|
|
9208
9904
|
onMutation: (context = {}) => {
|
|
9209
9905
|
if (matched) return;
|
|
9210
9906
|
const mutationCount = Number(context.mutationCount || 0);
|
|
@@ -9220,12 +9916,12 @@ ${text}`;
|
|
|
9220
9916
|
});
|
|
9221
9917
|
}
|
|
9222
9918
|
if (mutationCount <= 5 || mutationCount % 50 === 0) {
|
|
9223
|
-
|
|
9919
|
+
logger16.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);
|
|
9224
9920
|
}
|
|
9225
9921
|
const [candidate] = Utils.parseLinks(rawDom, { prefix }) || [];
|
|
9226
9922
|
if (!candidate) return;
|
|
9227
9923
|
matched = true;
|
|
9228
|
-
|
|
9924
|
+
logger16.success("captureLink.domHit", `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);
|
|
9229
9925
|
if (onMatch) {
|
|
9230
9926
|
onMatch({
|
|
9231
9927
|
link: candidate,
|
|
@@ -9241,7 +9937,7 @@ ${text}`;
|
|
|
9241
9937
|
return {
|
|
9242
9938
|
stop: async () => {
|
|
9243
9939
|
const result = await monitor.stop();
|
|
9244
|
-
|
|
9940
|
+
logger16.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);
|
|
9245
9941
|
return result;
|
|
9246
9942
|
}
|
|
9247
9943
|
};
|
|
@@ -9290,8 +9986,8 @@ var Share = {
|
|
|
9290
9986
|
if (share.mode === "response" && apiMatchers.length === 0) {
|
|
9291
9987
|
throw new Error("Share.captureLink requires share.xurl[0] api matcher when mode=response");
|
|
9292
9988
|
}
|
|
9293
|
-
|
|
9294
|
-
|
|
9989
|
+
logger16.start("captureLink", `mode=${share.mode}, timeoutMs=${timeoutDisabled ? "disabled" : timeoutMs}, prefix=${share.prefix}`);
|
|
9990
|
+
logger16.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);
|
|
9295
9991
|
const stats = {
|
|
9296
9992
|
actionTimedOut: false,
|
|
9297
9993
|
domMutationCount: 0,
|
|
@@ -9303,7 +9999,7 @@ var Share = {
|
|
|
9303
9999
|
responseSampleUrls: []
|
|
9304
10000
|
};
|
|
9305
10001
|
if (isAborted()) {
|
|
9306
|
-
|
|
10002
|
+
logger16.warning(`captureLink \u5DF2\u53D6\u6D88: ${abortReason()}`);
|
|
9307
10003
|
return {
|
|
9308
10004
|
link: null,
|
|
9309
10005
|
payloadText: "",
|
|
@@ -9326,7 +10022,7 @@ var Share = {
|
|
|
9326
10022
|
link: validated,
|
|
9327
10023
|
payloadText: String(payloadText || "")
|
|
9328
10024
|
};
|
|
9329
|
-
|
|
10025
|
+
logger16.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);
|
|
9330
10026
|
return true;
|
|
9331
10027
|
};
|
|
9332
10028
|
const resolveResponseCandidate = (responseText) => {
|
|
@@ -9361,7 +10057,7 @@ var Share = {
|
|
|
9361
10057
|
try {
|
|
9362
10058
|
await monitor.stop();
|
|
9363
10059
|
} catch (error) {
|
|
9364
|
-
|
|
10060
|
+
logger16.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
9365
10061
|
}
|
|
9366
10062
|
};
|
|
9367
10063
|
const onResponse = async (response) => {
|
|
@@ -9375,29 +10071,29 @@ var Share = {
|
|
|
9375
10071
|
stats.responseSampleUrls.push(url);
|
|
9376
10072
|
}
|
|
9377
10073
|
if (stats.responseObserved <= 5) {
|
|
9378
|
-
|
|
10074
|
+
logger16.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);
|
|
9379
10075
|
}
|
|
9380
10076
|
if (!apiMatchers.some((matcher) => url.includes(matcher))) return;
|
|
9381
10077
|
stats.responseMatched += 1;
|
|
9382
10078
|
stats.lastMatchedUrl = url;
|
|
9383
|
-
|
|
10079
|
+
logger16.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);
|
|
9384
10080
|
const text = await response.text();
|
|
9385
10081
|
const hit = resolveResponseCandidate(text);
|
|
9386
10082
|
if (!hit?.link) {
|
|
9387
10083
|
if (stats.responseMatched <= 3) {
|
|
9388
|
-
|
|
10084
|
+
logger16.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);
|
|
9389
10085
|
}
|
|
9390
10086
|
return;
|
|
9391
10087
|
}
|
|
9392
10088
|
stats.responseResolved += 1;
|
|
9393
|
-
|
|
10089
|
+
logger16.success("captureLink.responseHit", `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);
|
|
9394
10090
|
setCandidate("response", hit.link, hit.payloadText);
|
|
9395
10091
|
} catch (error) {
|
|
9396
|
-
|
|
10092
|
+
logger16.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);
|
|
9397
10093
|
}
|
|
9398
10094
|
};
|
|
9399
10095
|
if (share.mode === "dom") {
|
|
9400
|
-
|
|
10096
|
+
logger16.info("\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C");
|
|
9401
10097
|
domMonitor = await createDomShareMonitor(page, {
|
|
9402
10098
|
prefix: share.prefix,
|
|
9403
10099
|
selectors: domSelectors,
|
|
@@ -9412,17 +10108,17 @@ var Share = {
|
|
|
9412
10108
|
});
|
|
9413
10109
|
}
|
|
9414
10110
|
if (share.mode === "response") {
|
|
9415
|
-
|
|
10111
|
+
logger16.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);
|
|
9416
10112
|
page.on("response", onResponse);
|
|
9417
10113
|
}
|
|
9418
10114
|
if (share.mode === "custom") {
|
|
9419
|
-
|
|
10115
|
+
logger16.info("\u5F53\u524D\u4E3A custom \u6A21\u5F0F\uFF0C\u5C06\u4F7F\u7528 performActions \u8FD4\u56DE\u503C");
|
|
9420
10116
|
}
|
|
9421
10117
|
const deadline = timeoutDisabled ? Infinity : Date.now() + timeoutMs;
|
|
9422
10118
|
const getRemainingMs = () => timeoutDisabled ? Infinity : Math.max(0, deadline - Date.now());
|
|
9423
10119
|
try {
|
|
9424
10120
|
const actionTimeout = getRemainingMs();
|
|
9425
|
-
|
|
10121
|
+
logger16.start("captureLink.performActions", `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${timeoutDisabled ? "disabled" : `${actionTimeout}ms`}`);
|
|
9426
10122
|
let actionValue;
|
|
9427
10123
|
if (!isAborted() && actionTimeout > 0) {
|
|
9428
10124
|
let timer = null;
|
|
@@ -9435,30 +10131,30 @@ var Share = {
|
|
|
9435
10131
|
]);
|
|
9436
10132
|
if (timer) clearTimeout(timer);
|
|
9437
10133
|
if (actionResult.type === "error") {
|
|
9438
|
-
|
|
10134
|
+
logger16.fail("captureLink.performActions", actionResult.error);
|
|
9439
10135
|
throw actionResult.error;
|
|
9440
10136
|
}
|
|
9441
10137
|
if (actionResult.type === "timeout") {
|
|
9442
10138
|
stats.actionTimedOut = true;
|
|
9443
|
-
|
|
10139
|
+
logger16.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);
|
|
9444
10140
|
} else {
|
|
9445
10141
|
actionValue = actionResult.result;
|
|
9446
|
-
|
|
10142
|
+
logger16.success("captureLink.performActions", "\u6267\u884C\u52A8\u4F5C\u5B8C\u6210");
|
|
9447
10143
|
}
|
|
9448
10144
|
}
|
|
9449
10145
|
if (share.mode === "custom") {
|
|
9450
10146
|
const customLink = typeof actionValue === "string" ? actionValue : actionValue?.link || actionValue?.payloadText;
|
|
9451
10147
|
const customPayloadText = typeof actionValue === "string" ? actionValue : actionValue?.payloadText;
|
|
9452
10148
|
if (setCandidate("custom", customLink, customPayloadText)) {
|
|
9453
|
-
|
|
10149
|
+
logger16.success("captureLink.customResult", `custom \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: link=${candidates.custom.link}`);
|
|
9454
10150
|
} else {
|
|
9455
|
-
|
|
10151
|
+
logger16.warning("performActions \u6267\u884C\u5B8C\u6210\u4F46\u672A\u8FD4\u56DE\u6709\u6548\u5206\u4EAB\u94FE\u63A5");
|
|
9456
10152
|
}
|
|
9457
10153
|
}
|
|
9458
10154
|
let nextProgressLogTs = Date.now() + 3e3;
|
|
9459
10155
|
while (true) {
|
|
9460
10156
|
if (isAborted()) {
|
|
9461
|
-
|
|
10157
|
+
logger16.warning(`captureLink \u5DF2\u53D6\u6D88: ${abortReason()}`);
|
|
9462
10158
|
return {
|
|
9463
10159
|
link: null,
|
|
9464
10160
|
payloadText: "",
|
|
@@ -9468,7 +10164,7 @@ var Share = {
|
|
|
9468
10164
|
}
|
|
9469
10165
|
const selected = candidates[share.mode];
|
|
9470
10166
|
if (selected?.link) {
|
|
9471
|
-
|
|
10167
|
+
logger16.success("captureLink", `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);
|
|
9472
10168
|
return {
|
|
9473
10169
|
link: selected.link,
|
|
9474
10170
|
payloadText: selected.payloadText,
|
|
@@ -9481,19 +10177,19 @@ var Share = {
|
|
|
9481
10177
|
if (remaining <= 0) break;
|
|
9482
10178
|
const now = Date.now();
|
|
9483
10179
|
if (now >= nextProgressLogTs) {
|
|
9484
|
-
|
|
10180
|
+
logger16.info(
|
|
9485
10181
|
`captureLink \u7B49\u5F85\u4E2D: remaining=${timeoutDisabled ? "disabled" : `${remaining}ms`}, domMutationCount=${stats.domMutationCount}, responseMatched=${stats.responseMatched}`
|
|
9486
10182
|
);
|
|
9487
10183
|
nextProgressLogTs = now + 5e3;
|
|
9488
10184
|
}
|
|
9489
|
-
await
|
|
10185
|
+
await delay5(Math.max(0, Math.min(DEFAULT_POLL_INTERVAL_MS, remaining)));
|
|
9490
10186
|
}
|
|
9491
10187
|
if (!timeoutDisabled && share.mode === "response" && stats.responseMatched === 0) {
|
|
9492
|
-
|
|
10188
|
+
logger16.warning(
|
|
9493
10189
|
`\u63A5\u53E3\u76D1\u542C\u672A\u547D\u4E2D: apiMatchers=${toJsonInline(apiMatchers, 220)}, \u54CD\u5E94\u6837\u672CURLs=${toJsonInline(stats.responseSampleUrls, 420)}`
|
|
9494
10190
|
);
|
|
9495
10191
|
}
|
|
9496
|
-
|
|
10192
|
+
logger16.warning(
|
|
9497
10193
|
`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
10194
|
);
|
|
9499
10195
|
return {
|
|
@@ -9505,7 +10201,7 @@ var Share = {
|
|
|
9505
10201
|
} finally {
|
|
9506
10202
|
if (share.mode === "response") {
|
|
9507
10203
|
page.off("response", onResponse);
|
|
9508
|
-
|
|
10204
|
+
logger16.info("response \u76D1\u542C\u5DF2\u5378\u8F7D");
|
|
9509
10205
|
}
|
|
9510
10206
|
await stopDomMonitor();
|
|
9511
10207
|
}
|
|
@@ -9520,12 +10216,14 @@ var Share = {
|
|
|
9520
10216
|
* @param {number} [options.maxBytes] 默认 5MiB,返回 base64 超过后会压缩
|
|
9521
10217
|
* @param {'jpeg'|'jpg'} [options.type] 压缩输出格式,默认 jpeg
|
|
9522
10218
|
* @param {boolean|Object} [options.compression] 传 false 可关闭压缩
|
|
10219
|
+
* @param {'default'|'cloak'} [options.mode] 截图水印合成模式,默认取当前 toolkit mode
|
|
9523
10220
|
* @returns {Promise<string>} base64 image
|
|
9524
10221
|
*/
|
|
9525
10222
|
async captureScreen(page, options = {}) {
|
|
9526
10223
|
const restore = options.restore ?? false;
|
|
9527
10224
|
const screenshotWatermarkify = resolveCaptureScreenWatermarkify(page, options.watermarkify);
|
|
9528
10225
|
const compression = resolveImageCompression(options);
|
|
10226
|
+
const screenshotMode = options.mode ?? getToolkitMode();
|
|
9529
10227
|
const captureOptions = {
|
|
9530
10228
|
restore,
|
|
9531
10229
|
maxHeight: options.maxHeight,
|
|
@@ -9540,7 +10238,9 @@ var Share = {
|
|
|
9540
10238
|
...screenshotWatermarkify,
|
|
9541
10239
|
capturedAt
|
|
9542
10240
|
});
|
|
9543
|
-
outputBuffer = await watermarkifyScreenshotBuffer(rawBuffer, watermarkifyMeta, page
|
|
10241
|
+
outputBuffer = await watermarkifyScreenshotBuffer(rawBuffer, watermarkifyMeta, page, {
|
|
10242
|
+
mode: screenshotMode
|
|
10243
|
+
});
|
|
9544
10244
|
}
|
|
9545
10245
|
return await compressImageBufferToBase64(outputBuffer, compression);
|
|
9546
10246
|
}
|
|
@@ -9548,8 +10248,13 @@ var Share = {
|
|
|
9548
10248
|
|
|
9549
10249
|
// entrys/node.js
|
|
9550
10250
|
Logger.setLogger(crawleeLog);
|
|
9551
|
-
var
|
|
9552
|
-
|
|
10251
|
+
var ToolkitMode = Object.freeze({
|
|
10252
|
+
default: Mode.Default,
|
|
10253
|
+
cloak: Mode.Cloak
|
|
10254
|
+
});
|
|
10255
|
+
var usePlaywrightToolKit = (mode2 = Mode.Default) => {
|
|
10256
|
+
setToolkitMode(mode2);
|
|
10257
|
+
const toolkit = {
|
|
9553
10258
|
ApifyKit,
|
|
9554
10259
|
AntiCheat,
|
|
9555
10260
|
DeviceInput,
|
|
@@ -9569,7 +10274,9 @@ var usePlaywrightToolKit = () => {
|
|
|
9569
10274
|
ByPass,
|
|
9570
10275
|
$Internals: { LOG_TEMPLATES, stripAnsi }
|
|
9571
10276
|
};
|
|
10277
|
+
return toolkit;
|
|
9572
10278
|
};
|
|
10279
|
+
usePlaywrightToolKit.Mode = ToolkitMode;
|
|
9573
10280
|
export {
|
|
9574
10281
|
usePlaywrightToolKit
|
|
9575
10282
|
};
|