@skrillex1224/playwright-toolkit 2.1.223 → 2.1.225
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/README.md +11 -7
- package/dist/browser.js +43 -3
- package/dist/browser.js.map +2 -2
- package/dist/index.cjs +630 -143
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +630 -143
- package/dist/index.js.map +4 -4
- package/index.d.ts +27 -7
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -39,8 +39,10 @@ var constants_exports = {};
|
|
|
39
39
|
__export(constants_exports, {
|
|
40
40
|
ActorInfo: () => ActorInfo,
|
|
41
41
|
Code: () => Code,
|
|
42
|
+
Device: () => Device,
|
|
42
43
|
PresetOfLiveViewKey: () => PresetOfLiveViewKey,
|
|
43
|
-
Status: () => Status
|
|
44
|
+
Status: () => Status,
|
|
45
|
+
normalizeDevice: () => normalizeDevice
|
|
44
46
|
});
|
|
45
47
|
var Code = {
|
|
46
48
|
Success: 0,
|
|
@@ -56,6 +58,17 @@ var Status = {
|
|
|
56
58
|
Failed: "FAILED"
|
|
57
59
|
};
|
|
58
60
|
var PresetOfLiveViewKey = "LIVE_VIEW_SCREENSHOT";
|
|
61
|
+
var Device = Object.freeze({
|
|
62
|
+
Desktop: "desktop",
|
|
63
|
+
Mobile: "mobile"
|
|
64
|
+
});
|
|
65
|
+
var normalizeDevice = (value, fallback = Device.Desktop) => {
|
|
66
|
+
const normalizedFallback = String(fallback || "").trim().toLowerCase() === Device.Mobile ? Device.Mobile : Device.Desktop;
|
|
67
|
+
const raw = String(value || "").trim().toLowerCase();
|
|
68
|
+
if (raw === Device.Mobile) return Device.Mobile;
|
|
69
|
+
if (raw === Device.Desktop) return Device.Desktop;
|
|
70
|
+
return normalizedFallback;
|
|
71
|
+
};
|
|
59
72
|
var createActorInfo = (info) => {
|
|
60
73
|
const normalizeDomain = (value) => {
|
|
61
74
|
if (!value) return "";
|
|
@@ -133,12 +146,14 @@ var createActorInfo = (info) => {
|
|
|
133
146
|
const domain = normalizeDomain(info.domain);
|
|
134
147
|
const path2 = normalizePath(info.path);
|
|
135
148
|
const share = normalizeShare2(info.share);
|
|
149
|
+
const device = normalizeDevice(info.device);
|
|
136
150
|
return {
|
|
137
151
|
...info,
|
|
138
152
|
protocol,
|
|
139
153
|
domain,
|
|
140
154
|
path: path2,
|
|
141
155
|
share,
|
|
156
|
+
device,
|
|
142
157
|
get icon() {
|
|
143
158
|
if (info.icon) return info.icon;
|
|
144
159
|
return buildIcon(this);
|
|
@@ -190,6 +205,7 @@ var ActorInfo = {
|
|
|
190
205
|
name: "\u8C46\u5305",
|
|
191
206
|
domain: "www.doubao.com",
|
|
192
207
|
path: "/",
|
|
208
|
+
device: Device.Mobile,
|
|
193
209
|
share: {
|
|
194
210
|
mode: "response",
|
|
195
211
|
prefix: "https://www.doubao.com/thread/",
|
|
@@ -205,6 +221,7 @@ var ActorInfo = {
|
|
|
205
221
|
name: "DeepSeek",
|
|
206
222
|
domain: "chat.deepseek.com",
|
|
207
223
|
path: "/",
|
|
224
|
+
device: Device.Mobile,
|
|
208
225
|
share: {
|
|
209
226
|
mode: "response",
|
|
210
227
|
prefix: "https://chat.deepseek.com/share/",
|
|
@@ -361,18 +378,18 @@ var fallbackLog = {
|
|
|
361
378
|
error: (...args) => console.error(...args),
|
|
362
379
|
debug: (...args) => console.debug ? console.debug(...args) : console.log(...args)
|
|
363
380
|
};
|
|
364
|
-
var resolveLogMethod = (
|
|
365
|
-
if (
|
|
366
|
-
return
|
|
381
|
+
var resolveLogMethod = (logger16, name) => {
|
|
382
|
+
if (logger16 && typeof logger16[name] === "function") {
|
|
383
|
+
return logger16[name].bind(logger16);
|
|
367
384
|
}
|
|
368
|
-
if (name === "warning" &&
|
|
369
|
-
return
|
|
385
|
+
if (name === "warning" && logger16 && typeof logger16.warn === "function") {
|
|
386
|
+
return logger16.warn.bind(logger16);
|
|
370
387
|
}
|
|
371
388
|
return fallbackLog[name];
|
|
372
389
|
};
|
|
373
390
|
var defaultLogger = null;
|
|
374
|
-
var setDefaultLogger = (
|
|
375
|
-
defaultLogger =
|
|
391
|
+
var setDefaultLogger = (logger16) => {
|
|
392
|
+
defaultLogger = logger16;
|
|
376
393
|
};
|
|
377
394
|
var resolveLogger = (explicitLogger) => {
|
|
378
395
|
if (explicitLogger && typeof explicitLogger.info === "function") {
|
|
@@ -399,8 +416,8 @@ var colorize = (text, color) => {
|
|
|
399
416
|
var createBaseLogger = (prefix = "", explicitLogger) => {
|
|
400
417
|
const name = prefix ? String(prefix) : "";
|
|
401
418
|
const dispatch = (methodName, icon, message, color) => {
|
|
402
|
-
const
|
|
403
|
-
const logFn = resolveLogMethod(
|
|
419
|
+
const logger16 = resolveLogger(explicitLogger);
|
|
420
|
+
const logFn = resolveLogMethod(logger16, methodName);
|
|
404
421
|
const timestamp = colorize(`[${formatTimestamp()}]`, ANSI.gray);
|
|
405
422
|
const line = formatLine(name, icon, message);
|
|
406
423
|
const coloredLine = colorize(line, color);
|
|
@@ -1000,6 +1017,12 @@ var PageRuntimeStateKey = "__playwright_toolkit_runtime_state__";
|
|
|
1000
1017
|
var BROWSER_PROFILE_SCHEMA_VERSION = 1;
|
|
1001
1018
|
var rememberedRuntimeState = null;
|
|
1002
1019
|
var isPlainObject = (value) => value && typeof value === "object" && !Array.isArray(value);
|
|
1020
|
+
var normalizeKnownDevice = (value) => {
|
|
1021
|
+
const raw = String(value || "").trim().toLowerCase();
|
|
1022
|
+
if (raw === Device.Mobile) return Device.Mobile;
|
|
1023
|
+
if (raw === Device.Desktop) return Device.Desktop;
|
|
1024
|
+
return "";
|
|
1025
|
+
};
|
|
1003
1026
|
var deepClone = (value) => {
|
|
1004
1027
|
if (value == null) return value;
|
|
1005
1028
|
try {
|
|
@@ -1351,6 +1374,10 @@ var normalizeObservedBrowserProfile = (value) => {
|
|
|
1351
1374
|
var normalizeBrowserProfileCore = (value) => {
|
|
1352
1375
|
const source = isPlainObject(value) ? value : {};
|
|
1353
1376
|
const profile = {};
|
|
1377
|
+
const device = normalizeKnownDevice(source.device);
|
|
1378
|
+
if (device) {
|
|
1379
|
+
profile.device = device;
|
|
1380
|
+
}
|
|
1354
1381
|
if (isPlainObject(source.fingerprint) && Object.keys(source.fingerprint).length > 0) {
|
|
1355
1382
|
profile.fingerprint = deepClone(source.fingerprint);
|
|
1356
1383
|
}
|
|
@@ -1408,9 +1435,11 @@ var mergeBrowserProfilePayload = (target = {}, source = {}) => {
|
|
|
1408
1435
|
if (Object.keys(mergedCore).length === 0 && Object.keys(incomingCore).length > 0) {
|
|
1409
1436
|
mergedCore = incomingCore;
|
|
1410
1437
|
} else if (Object.keys(incomingCore).length > 0) {
|
|
1438
|
+
const currentDevice = normalizeKnownDevice(currentCore.device);
|
|
1439
|
+
const incomingDevice = normalizeKnownDevice(incomingCore.device);
|
|
1411
1440
|
const currentVersion = Number(currentCore.browser_major_version || 0);
|
|
1412
1441
|
const incomingVersion = Number(incomingCore.browser_major_version || 0);
|
|
1413
|
-
if (currentVersion > 0 && incomingVersion > 0 && currentVersion !== incomingVersion) {
|
|
1442
|
+
if (incomingDevice && currentDevice !== incomingDevice || currentVersion > 0 && incomingVersion > 0 && currentVersion !== incomingVersion) {
|
|
1414
1443
|
mergedCore = incomingCore;
|
|
1415
1444
|
}
|
|
1416
1445
|
}
|
|
@@ -1461,8 +1490,13 @@ var normalizeRuntimeState = (source = {}, actor = "") => {
|
|
|
1461
1490
|
}
|
|
1462
1491
|
return RuntimeEnv.parseInput(source, actor);
|
|
1463
1492
|
};
|
|
1493
|
+
var resolveInputDevice = (input = {}, runtime2 = {}, actor = "") => {
|
|
1494
|
+
const actorDevice = ActorInfo?.[actor]?.device;
|
|
1495
|
+
return normalizeDevice(actorDevice ?? input?.device ?? runtime2?.device);
|
|
1496
|
+
};
|
|
1464
1497
|
var RuntimeEnv = {
|
|
1465
1498
|
tryParseJSON,
|
|
1499
|
+
normalizeDevice,
|
|
1466
1500
|
normalizeCookies,
|
|
1467
1501
|
normalizeLocalStorage,
|
|
1468
1502
|
normalizeSessionStorage,
|
|
@@ -1488,6 +1522,7 @@ var RuntimeEnv = {
|
|
|
1488
1522
|
parseInput(input = {}, actor = "") {
|
|
1489
1523
|
const runtime2 = tryParseJSON(input?.runtime) || {};
|
|
1490
1524
|
const resolvedActor = String(actor || input?.actor || "").trim();
|
|
1525
|
+
const device = resolveInputDevice(input, runtime2, resolvedActor);
|
|
1491
1526
|
const query = String(input?.query || "").trim();
|
|
1492
1527
|
const cookies = normalizeCookies(runtime2?.cookies);
|
|
1493
1528
|
const cookieMap = buildCookieMap(cookies);
|
|
@@ -1507,6 +1542,7 @@ var RuntimeEnv = {
|
|
|
1507
1542
|
}
|
|
1508
1543
|
const state = {
|
|
1509
1544
|
actor: resolvedActor,
|
|
1545
|
+
device,
|
|
1510
1546
|
runtime: normalizedRuntime,
|
|
1511
1547
|
envId,
|
|
1512
1548
|
query,
|
|
@@ -1552,7 +1588,10 @@ var RuntimeEnv = {
|
|
|
1552
1588
|
},
|
|
1553
1589
|
setBrowserProfileCore(source = {}, core = {}, actor = "") {
|
|
1554
1590
|
const state = normalizeRuntimeState(source, actor);
|
|
1555
|
-
const normalizedCore = normalizeBrowserProfileCore(
|
|
1591
|
+
const normalizedCore = normalizeBrowserProfileCore({
|
|
1592
|
+
...core,
|
|
1593
|
+
device: normalizeKnownDevice(core?.device) || state.device
|
|
1594
|
+
});
|
|
1556
1595
|
state.browserProfileCore = normalizedCore;
|
|
1557
1596
|
state.browserProfile = buildBrowserProfilePayload(normalizedCore, state.browserProfileObserved);
|
|
1558
1597
|
if (Object.keys(state.browserProfile).length > 0) {
|
|
@@ -2027,15 +2066,25 @@ var DEFAULT_LAUNCH_ARGS = [
|
|
|
2027
2066
|
"--disable-setuid-sandbox",
|
|
2028
2067
|
"--window-position=0,0"
|
|
2029
2068
|
];
|
|
2030
|
-
function buildFingerprintOptions({ locale = BASE_CONFIG.locale, browserMajorVersion = 0 } = {}) {
|
|
2069
|
+
function buildFingerprintOptions({ locale = BASE_CONFIG.locale, browserMajorVersion = 0, device = Device.Desktop } = {}) {
|
|
2070
|
+
const resolvedDevice = normalizeDevice(device);
|
|
2031
2071
|
const normalizedBrowserMajorVersion = Number(browserMajorVersion || 0);
|
|
2032
2072
|
const browserDescriptor = normalizedBrowserMajorVersion > 0 ? [{ name: "chrome", minVersion: normalizedBrowserMajorVersion, maxVersion: normalizedBrowserMajorVersion }] : [{ name: "chrome", minVersion: 110 }];
|
|
2033
|
-
|
|
2073
|
+
const options = {
|
|
2034
2074
|
browsers: browserDescriptor,
|
|
2035
|
-
devices: [
|
|
2036
|
-
operatingSystems: ["windows", "macos", "linux"],
|
|
2075
|
+
devices: [resolvedDevice],
|
|
2076
|
+
operatingSystems: resolvedDevice === Device.Mobile ? ["android"] : ["windows", "macos", "linux"],
|
|
2037
2077
|
locales: [locale]
|
|
2038
2078
|
};
|
|
2079
|
+
if (resolvedDevice === Device.Mobile) {
|
|
2080
|
+
options.screen = {
|
|
2081
|
+
minWidth: 320,
|
|
2082
|
+
maxWidth: 480,
|
|
2083
|
+
minHeight: 640,
|
|
2084
|
+
maxHeight: 1100
|
|
2085
|
+
};
|
|
2086
|
+
}
|
|
2087
|
+
return options;
|
|
2039
2088
|
}
|
|
2040
2089
|
var AntiCheat = {
|
|
2041
2090
|
/**
|
|
@@ -2045,7 +2094,7 @@ var AntiCheat = {
|
|
|
2045
2094
|
return { ...BASE_CONFIG };
|
|
2046
2095
|
},
|
|
2047
2096
|
/**
|
|
2048
|
-
* 用于 Crawlee fingerprint generator
|
|
2097
|
+
* 用于 Crawlee fingerprint generator 的统一配置。
|
|
2049
2098
|
*/
|
|
2050
2099
|
getFingerprintGeneratorOptions(options = {}) {
|
|
2051
2100
|
return buildFingerprintOptions(options);
|
|
@@ -2058,10 +2107,10 @@ var AntiCheat = {
|
|
|
2058
2107
|
return [...DEFAULT_LAUNCH_ARGS, `--lang=${locale}`];
|
|
2059
2108
|
},
|
|
2060
2109
|
/**
|
|
2061
|
-
* 为 got-scraping 生成与浏览器一致的 TLS
|
|
2110
|
+
* 为 got-scraping 生成与浏览器一致的 TLS 指纹配置。
|
|
2062
2111
|
*/
|
|
2063
|
-
getTlsFingerprintOptions(userAgent = "", acceptLanguage = "") {
|
|
2064
|
-
return buildFingerprintOptions();
|
|
2112
|
+
getTlsFingerprintOptions(userAgent = "", acceptLanguage = "", options = {}) {
|
|
2113
|
+
return buildFingerprintOptions(options);
|
|
2065
2114
|
},
|
|
2066
2115
|
/**
|
|
2067
2116
|
* 规范化请求头
|
|
@@ -2074,7 +2123,7 @@ var AntiCheat = {
|
|
|
2074
2123
|
}
|
|
2075
2124
|
};
|
|
2076
2125
|
|
|
2077
|
-
// src/humanize.js
|
|
2126
|
+
// src/internals/humanize/desktop.js
|
|
2078
2127
|
var import_delay = __toESM(require("delay"), 1);
|
|
2079
2128
|
var import_ghost_cursor_playwright = require("ghost-cursor-playwright");
|
|
2080
2129
|
var logger6 = createInternalLogger("Humanize");
|
|
@@ -2379,7 +2428,9 @@ var Humanize = {
|
|
|
2379
2428
|
const y = box.y + box.height / 2 + (Math.random() - 0.5) * box.height * 0.3;
|
|
2380
2429
|
await cursor.actions.move({ x, y });
|
|
2381
2430
|
await (0, import_delay.default)(this.jitterMs(reactionDelay, 0.4));
|
|
2382
|
-
await
|
|
2431
|
+
await page.mouse.click(x, y, {
|
|
2432
|
+
delay: this.jitterMs(45, 0.45)
|
|
2433
|
+
});
|
|
2383
2434
|
await restoreOnce();
|
|
2384
2435
|
logger6.success("humanClick");
|
|
2385
2436
|
return true;
|
|
@@ -2552,6 +2603,379 @@ var Humanize = {
|
|
|
2552
2603
|
}
|
|
2553
2604
|
};
|
|
2554
2605
|
|
|
2606
|
+
// src/internals/humanize/shared.js
|
|
2607
|
+
var import_delay2 = __toESM(require("delay"), 1);
|
|
2608
|
+
var jitterMs = (base, jitterPercent = 0.3) => {
|
|
2609
|
+
const jitter = Number(base || 0) * Number(jitterPercent || 0) * (Math.random() * 2 - 1);
|
|
2610
|
+
return Math.max(10, Math.round(Number(base || 0) + jitter));
|
|
2611
|
+
};
|
|
2612
|
+
var randomPointInBox = (box, paddingRatio = 0.24) => {
|
|
2613
|
+
const safePaddingX = Math.max(2, Math.min(box.width * paddingRatio, box.width / 2));
|
|
2614
|
+
const safePaddingY = Math.max(2, Math.min(box.height * paddingRatio, box.height / 2));
|
|
2615
|
+
const x = box.x + safePaddingX + Math.random() * Math.max(1, box.width - safePaddingX * 2);
|
|
2616
|
+
const y = box.y + safePaddingY + Math.random() * Math.max(1, box.height - safePaddingY * 2);
|
|
2617
|
+
return { x, y };
|
|
2618
|
+
};
|
|
2619
|
+
var resolveElement = async (page, target, { throwOnMissing = true } = {}) => {
|
|
2620
|
+
if (target == null) return null;
|
|
2621
|
+
let element = target;
|
|
2622
|
+
if (typeof target === "string") {
|
|
2623
|
+
element = await page.$(target);
|
|
2624
|
+
}
|
|
2625
|
+
if (!element) {
|
|
2626
|
+
if (throwOnMissing) {
|
|
2627
|
+
throw new Error(`\u627E\u4E0D\u5230\u5143\u7D20 ${String(target)}`);
|
|
2628
|
+
}
|
|
2629
|
+
return null;
|
|
2630
|
+
}
|
|
2631
|
+
return element;
|
|
2632
|
+
};
|
|
2633
|
+
var waitJitter = (base, jitterPercent = 0.3) => (0, import_delay2.default)(jitterMs(base, jitterPercent));
|
|
2634
|
+
|
|
2635
|
+
// src/internals/humanize/mobile.js
|
|
2636
|
+
var logger7 = createInternalLogger("Humanize.Mobile");
|
|
2637
|
+
var initializedPages = /* @__PURE__ */ new WeakSet();
|
|
2638
|
+
var clamp = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
2639
|
+
var resolveViewport = (page) => page?.viewportSize?.() || { width: 390, height: 844 };
|
|
2640
|
+
var checkElementVisibility = async (element) => {
|
|
2641
|
+
return element.evaluate((el) => {
|
|
2642
|
+
const rect = el.getBoundingClientRect();
|
|
2643
|
+
if (!rect || rect.width <= 0 || rect.height <= 0) {
|
|
2644
|
+
return { code: "ZERO_DIMENSIONS", direction: "down" };
|
|
2645
|
+
}
|
|
2646
|
+
const viewW = window.innerWidth;
|
|
2647
|
+
const viewH = window.innerHeight;
|
|
2648
|
+
const cx = rect.left + rect.width / 2;
|
|
2649
|
+
const cy = rect.top + rect.height / 2;
|
|
2650
|
+
let isFixed = false;
|
|
2651
|
+
for (let node = el; node && node !== document.body; node = node.parentElement) {
|
|
2652
|
+
const style = window.getComputedStyle(node);
|
|
2653
|
+
if (style && (style.position === "fixed" || style.position === "sticky")) {
|
|
2654
|
+
isFixed = true;
|
|
2655
|
+
break;
|
|
2656
|
+
}
|
|
2657
|
+
}
|
|
2658
|
+
if ((isFixed ? cy < 0 || cy > viewH : cy < 12 || cy > viewH - 12) || cx < 0 || cx > viewW) {
|
|
2659
|
+
return {
|
|
2660
|
+
code: "OUT_OF_VIEWPORT",
|
|
2661
|
+
direction: cy < viewH / 2 ? "up" : "down",
|
|
2662
|
+
cy,
|
|
2663
|
+
viewH,
|
|
2664
|
+
isFixed
|
|
2665
|
+
};
|
|
2666
|
+
}
|
|
2667
|
+
const pointElement = document.elementFromPoint(cx, cy);
|
|
2668
|
+
if (pointElement && !el.contains(pointElement) && !pointElement.contains(el)) {
|
|
2669
|
+
return {
|
|
2670
|
+
code: "OBSTRUCTED",
|
|
2671
|
+
direction: cy > viewH / 2 ? "down" : "up",
|
|
2672
|
+
cy,
|
|
2673
|
+
viewH,
|
|
2674
|
+
isFixed
|
|
2675
|
+
};
|
|
2676
|
+
}
|
|
2677
|
+
return { code: "VISIBLE", isFixed };
|
|
2678
|
+
});
|
|
2679
|
+
};
|
|
2680
|
+
var dispatchTouchSwipe = async (page, deltaY, options = {}) => {
|
|
2681
|
+
const viewport = resolveViewport(page);
|
|
2682
|
+
const distance = clamp(Math.abs(deltaY), 80, Math.max(120, viewport.height * 0.72));
|
|
2683
|
+
const direction = deltaY >= 0 ? 1 : -1;
|
|
2684
|
+
const startX = clamp(
|
|
2685
|
+
viewport.width * (0.45 + Math.random() * 0.1),
|
|
2686
|
+
24,
|
|
2687
|
+
viewport.width - 24
|
|
2688
|
+
);
|
|
2689
|
+
const startY = direction > 0 ? clamp(viewport.height * (0.72 + Math.random() * 0.1), 80, viewport.height - 32) : clamp(viewport.height * (0.28 + Math.random() * 0.1), 32, viewport.height - 80);
|
|
2690
|
+
const endY = clamp(startY - direction * distance, 24, viewport.height - 24);
|
|
2691
|
+
const steps = Math.max(4, Math.round(Number(options.steps || 6)));
|
|
2692
|
+
const durationMs = jitterMs(options.durationMs || 320, 0.35);
|
|
2693
|
+
let client = null;
|
|
2694
|
+
const scrollBefore = await page.evaluate(() => ({ x: window.scrollX, y: window.scrollY })).catch(() => null);
|
|
2695
|
+
try {
|
|
2696
|
+
if (page.context && typeof page.context().newCDPSession === "function") {
|
|
2697
|
+
client = await page.context().newCDPSession(page);
|
|
2698
|
+
}
|
|
2699
|
+
if (!client) throw new Error("CDP session unavailable");
|
|
2700
|
+
await client.send("Input.synthesizeScrollGesture", {
|
|
2701
|
+
x: startX,
|
|
2702
|
+
y: startY,
|
|
2703
|
+
yDistance: -direction * distance,
|
|
2704
|
+
xOverscroll: (Math.random() - 0.5) * 4,
|
|
2705
|
+
yOverscroll: (Math.random() - 0.5) * 8,
|
|
2706
|
+
speed: 700 + Math.round(Math.random() * 350),
|
|
2707
|
+
gestureSourceType: "touch"
|
|
2708
|
+
});
|
|
2709
|
+
await waitJitter(160, 0.35);
|
|
2710
|
+
const scrollAfterSynth = await page.evaluate(() => ({ x: window.scrollX, y: window.scrollY })).catch(() => null);
|
|
2711
|
+
if (scrollBefore && scrollAfterSynth && (Math.abs(scrollAfterSynth.y - scrollBefore.y) > 2 || Math.abs(scrollAfterSynth.x - scrollBefore.x) > 2)) {
|
|
2712
|
+
return true;
|
|
2713
|
+
}
|
|
2714
|
+
await client.send("Input.dispatchTouchEvent", {
|
|
2715
|
+
type: "touchStart",
|
|
2716
|
+
touchPoints: [{ x: startX, y: startY, id: 1 }]
|
|
2717
|
+
});
|
|
2718
|
+
for (let i = 1; i <= steps; i += 1) {
|
|
2719
|
+
const progress = i / steps;
|
|
2720
|
+
const eased = 1 - Math.pow(1 - progress, 2);
|
|
2721
|
+
const x = startX + (Math.random() - 0.5) * 3;
|
|
2722
|
+
const y = startY + (endY - startY) * eased + (Math.random() - 0.5) * 5;
|
|
2723
|
+
await waitJitter(durationMs / steps, 0.25);
|
|
2724
|
+
await client.send("Input.dispatchTouchEvent", {
|
|
2725
|
+
type: "touchMove",
|
|
2726
|
+
touchPoints: [{ x, y, id: 1 }]
|
|
2727
|
+
});
|
|
2728
|
+
}
|
|
2729
|
+
await client.send("Input.dispatchTouchEvent", {
|
|
2730
|
+
type: "touchEnd",
|
|
2731
|
+
touchPoints: []
|
|
2732
|
+
});
|
|
2733
|
+
await waitJitter(120, 0.35);
|
|
2734
|
+
const scrollAfterTouch = await page.evaluate(() => ({ x: window.scrollX, y: window.scrollY })).catch(() => null);
|
|
2735
|
+
if (scrollBefore && scrollAfterTouch && Math.abs(scrollAfterTouch.y - scrollBefore.y) <= 2 && Math.abs(scrollAfterTouch.x - scrollBefore.x) <= 2) {
|
|
2736
|
+
await page.evaluate((amount) => window.scrollBy(0, amount), deltaY);
|
|
2737
|
+
await waitJitter(120, 0.35);
|
|
2738
|
+
}
|
|
2739
|
+
return true;
|
|
2740
|
+
} catch (error) {
|
|
2741
|
+
logger7.debug(`touch swipe fallback: ${error?.message || error}`);
|
|
2742
|
+
try {
|
|
2743
|
+
await page.evaluate((amount) => window.scrollBy(0, amount), deltaY);
|
|
2744
|
+
await waitJitter(120, 0.35);
|
|
2745
|
+
return true;
|
|
2746
|
+
} catch {
|
|
2747
|
+
await page.mouse.wheel(0, deltaY);
|
|
2748
|
+
await waitJitter(120, 0.35);
|
|
2749
|
+
return true;
|
|
2750
|
+
}
|
|
2751
|
+
} finally {
|
|
2752
|
+
if (client && typeof client.detach === "function") {
|
|
2753
|
+
try {
|
|
2754
|
+
await client.detach();
|
|
2755
|
+
} catch {
|
|
2756
|
+
}
|
|
2757
|
+
}
|
|
2758
|
+
}
|
|
2759
|
+
};
|
|
2760
|
+
var tapPoint = async (page, point) => {
|
|
2761
|
+
if (page.touchscreen && typeof page.touchscreen.tap === "function") {
|
|
2762
|
+
await page.touchscreen.tap(point.x, point.y);
|
|
2763
|
+
return;
|
|
2764
|
+
}
|
|
2765
|
+
await page.mouse.click(point.x, point.y);
|
|
2766
|
+
};
|
|
2767
|
+
var MobileHumanize = {
|
|
2768
|
+
jitterMs,
|
|
2769
|
+
async initializeCursor(page) {
|
|
2770
|
+
if (initializedPages.has(page)) return;
|
|
2771
|
+
initializedPages.add(page);
|
|
2772
|
+
logger7.debug("initializeCursor: mobile mode uses touch gestures, cursor init skipped");
|
|
2773
|
+
},
|
|
2774
|
+
async humanMove(page, target) {
|
|
2775
|
+
logger7.debug(`humanMove: mobile no-op target=${typeof target === "string" ? target : "element/coords"}`);
|
|
2776
|
+
if (typeof target === "string" || target && typeof target.boundingBox === "function") {
|
|
2777
|
+
const element = await resolveElement(page, target, { throwOnMissing: false });
|
|
2778
|
+
if (!element) {
|
|
2779
|
+
return false;
|
|
2780
|
+
}
|
|
2781
|
+
}
|
|
2782
|
+
await waitJitter(80, 0.4);
|
|
2783
|
+
return true;
|
|
2784
|
+
},
|
|
2785
|
+
async humanScroll(page, target, options = {}) {
|
|
2786
|
+
const {
|
|
2787
|
+
maxSteps = 12,
|
|
2788
|
+
minStep = 180,
|
|
2789
|
+
maxStep = 520,
|
|
2790
|
+
maxDurationMs = maxSteps * 280 + 1200,
|
|
2791
|
+
throwOnMissing = false
|
|
2792
|
+
} = options;
|
|
2793
|
+
const element = await resolveElement(page, target, { throwOnMissing });
|
|
2794
|
+
if (!element) {
|
|
2795
|
+
return { element: null, didScroll: false, restore: null };
|
|
2796
|
+
}
|
|
2797
|
+
const startTime = Date.now();
|
|
2798
|
+
let didScroll = false;
|
|
2799
|
+
for (let i = 0; i < maxSteps; i += 1) {
|
|
2800
|
+
const status = await checkElementVisibility(element);
|
|
2801
|
+
if (status.code === "VISIBLE") {
|
|
2802
|
+
return { element, didScroll, restore: null };
|
|
2803
|
+
}
|
|
2804
|
+
if (Date.now() - startTime > maxDurationMs) {
|
|
2805
|
+
logger7.warn(`humanScroll | mobile timeout (${maxDurationMs}ms)`);
|
|
2806
|
+
return { element, didScroll, restore: null };
|
|
2807
|
+
}
|
|
2808
|
+
const distance = minStep + Math.random() * Math.max(1, maxStep - minStep);
|
|
2809
|
+
const deltaY = status.direction === "up" ? -distance : distance;
|
|
2810
|
+
await dispatchTouchSwipe(page, deltaY);
|
|
2811
|
+
didScroll = true;
|
|
2812
|
+
}
|
|
2813
|
+
return { element, didScroll, restore: null };
|
|
2814
|
+
},
|
|
2815
|
+
async humanClick(page, target, options = {}) {
|
|
2816
|
+
const {
|
|
2817
|
+
reactionDelay = 220,
|
|
2818
|
+
throwOnMissing = true,
|
|
2819
|
+
scrollIfNeeded = true
|
|
2820
|
+
} = options;
|
|
2821
|
+
if (target == null) {
|
|
2822
|
+
const viewport = resolveViewport(page);
|
|
2823
|
+
await waitJitter(reactionDelay, 0.45);
|
|
2824
|
+
await tapPoint(page, {
|
|
2825
|
+
x: viewport.width * (0.45 + Math.random() * 0.1),
|
|
2826
|
+
y: viewport.height * (0.48 + Math.random() * 0.12)
|
|
2827
|
+
});
|
|
2828
|
+
return true;
|
|
2829
|
+
}
|
|
2830
|
+
const element = await resolveElement(page, target, { throwOnMissing });
|
|
2831
|
+
if (!element) return false;
|
|
2832
|
+
if (scrollIfNeeded) {
|
|
2833
|
+
await MobileHumanize.humanScroll(page, element, { throwOnMissing });
|
|
2834
|
+
}
|
|
2835
|
+
const box = await element.boundingBox();
|
|
2836
|
+
if (!box) {
|
|
2837
|
+
if (throwOnMissing) throw new Error("\u65E0\u6CD5\u83B7\u53D6\u5143\u7D20\u4F4D\u7F6E");
|
|
2838
|
+
return false;
|
|
2839
|
+
}
|
|
2840
|
+
await waitJitter(reactionDelay, 0.45);
|
|
2841
|
+
await tapPoint(page, randomPointInBox(box, 0.2));
|
|
2842
|
+
await waitJitter(120, 0.35);
|
|
2843
|
+
return true;
|
|
2844
|
+
},
|
|
2845
|
+
async randomSleep(baseMs, jitterPercent = 0.3) {
|
|
2846
|
+
await waitJitter(baseMs, jitterPercent);
|
|
2847
|
+
},
|
|
2848
|
+
async simulateGaze(page, baseDurationMs = 2500) {
|
|
2849
|
+
const durationMs = jitterMs(baseDurationMs, 0.4);
|
|
2850
|
+
const startTime = Date.now();
|
|
2851
|
+
while (Date.now() - startTime < durationMs) {
|
|
2852
|
+
if (Math.random() < 0.28) {
|
|
2853
|
+
const distance = 70 + Math.random() * 120;
|
|
2854
|
+
await dispatchTouchSwipe(page, Math.random() < 0.7 ? distance : -distance, {
|
|
2855
|
+
durationMs: 180,
|
|
2856
|
+
steps: 4
|
|
2857
|
+
});
|
|
2858
|
+
} else {
|
|
2859
|
+
await waitJitter(420, 0.55);
|
|
2860
|
+
}
|
|
2861
|
+
}
|
|
2862
|
+
},
|
|
2863
|
+
async humanType(page, selector, text, options = {}) {
|
|
2864
|
+
const {
|
|
2865
|
+
baseDelay = 160,
|
|
2866
|
+
pauseProbability = 0.08,
|
|
2867
|
+
pauseBase = 700
|
|
2868
|
+
} = options;
|
|
2869
|
+
await MobileHumanize.humanClick(page, selector, { scrollIfNeeded: true });
|
|
2870
|
+
await waitJitter(220, 0.45);
|
|
2871
|
+
for (let i = 0; i < String(text).length; i += 1) {
|
|
2872
|
+
const char = String(text)[i];
|
|
2873
|
+
const charDelay = /[,.!?;:,。!?;:]/.test(char) ? jitterMs(baseDelay * 1.45, 0.4) : jitterMs(char === " " ? baseDelay * 0.65 : baseDelay, 0.4);
|
|
2874
|
+
await page.keyboard.type(char);
|
|
2875
|
+
await waitJitter(charDelay, 0.15);
|
|
2876
|
+
if (Math.random() < pauseProbability && i < String(text).length - 1) {
|
|
2877
|
+
await waitJitter(pauseBase, 0.5);
|
|
2878
|
+
}
|
|
2879
|
+
}
|
|
2880
|
+
},
|
|
2881
|
+
async humanClear(page, selector) {
|
|
2882
|
+
const locator = page.locator(selector);
|
|
2883
|
+
await MobileHumanize.humanClick(page, locator, { scrollIfNeeded: true });
|
|
2884
|
+
await waitJitter(160, 0.4);
|
|
2885
|
+
await locator.evaluate((el) => {
|
|
2886
|
+
if ("value" in el) {
|
|
2887
|
+
el.value = "";
|
|
2888
|
+
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
2889
|
+
el.dispatchEvent(new Event("change", { bubbles: true }));
|
|
2890
|
+
return;
|
|
2891
|
+
}
|
|
2892
|
+
el.textContent = "";
|
|
2893
|
+
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
2894
|
+
});
|
|
2895
|
+
},
|
|
2896
|
+
async warmUpBrowsing(page, baseDuration = 3500) {
|
|
2897
|
+
const durationMs = jitterMs(baseDuration, 0.4);
|
|
2898
|
+
const startTime = Date.now();
|
|
2899
|
+
while (Date.now() - startTime < durationMs) {
|
|
2900
|
+
const action = Math.random();
|
|
2901
|
+
if (action < 0.5) {
|
|
2902
|
+
await dispatchTouchSwipe(page, 120 + Math.random() * 220, {
|
|
2903
|
+
durationMs: 240,
|
|
2904
|
+
steps: 5
|
|
2905
|
+
});
|
|
2906
|
+
} else if (action < 0.7) {
|
|
2907
|
+
await dispatchTouchSwipe(page, -(80 + Math.random() * 160), {
|
|
2908
|
+
durationMs: 220,
|
|
2909
|
+
steps: 4
|
|
2910
|
+
});
|
|
2911
|
+
} else {
|
|
2912
|
+
await waitJitter(560, 0.55);
|
|
2913
|
+
}
|
|
2914
|
+
}
|
|
2915
|
+
},
|
|
2916
|
+
async naturalScroll(page, direction = "down", distance = 300, baseSteps = 5) {
|
|
2917
|
+
const steps = Math.max(3, baseSteps + Math.floor(Math.random() * 3) - 1);
|
|
2918
|
+
const actualDistance = jitterMs(distance, 0.15);
|
|
2919
|
+
const sign = direction === "down" ? 1 : -1;
|
|
2920
|
+
for (let i = 0; i < steps; i += 1) {
|
|
2921
|
+
const factor = 1 - i / steps * 0.45;
|
|
2922
|
+
await dispatchTouchSwipe(page, actualDistance / steps * factor * sign, {
|
|
2923
|
+
durationMs: 150 + i * 20,
|
|
2924
|
+
steps: 4
|
|
2925
|
+
});
|
|
2926
|
+
}
|
|
2927
|
+
}
|
|
2928
|
+
};
|
|
2929
|
+
|
|
2930
|
+
// src/humanize.js
|
|
2931
|
+
var resolveDeviceFromPage = (page) => normalizeDevice(page?.[PageRuntimeStateKey]?.device);
|
|
2932
|
+
var resolveDelegate = (page) => {
|
|
2933
|
+
return resolveDeviceFromPage(page) === Device.Mobile ? MobileHumanize : Humanize;
|
|
2934
|
+
};
|
|
2935
|
+
var callDelegate = (method, page, args) => {
|
|
2936
|
+
const delegate = resolveDelegate(page);
|
|
2937
|
+
return delegate[method](page, ...args);
|
|
2938
|
+
};
|
|
2939
|
+
var Humanize2 = {
|
|
2940
|
+
jitterMs(base, jitterPercent = 0.3) {
|
|
2941
|
+
return Humanize.jitterMs(base, jitterPercent);
|
|
2942
|
+
},
|
|
2943
|
+
initializeCursor(page) {
|
|
2944
|
+
return callDelegate("initializeCursor", page, []);
|
|
2945
|
+
},
|
|
2946
|
+
humanMove(page, target) {
|
|
2947
|
+
return callDelegate("humanMove", page, [target]);
|
|
2948
|
+
},
|
|
2949
|
+
humanScroll(page, target, options = {}) {
|
|
2950
|
+
return callDelegate("humanScroll", page, [target, options]);
|
|
2951
|
+
},
|
|
2952
|
+
humanClick(page, target, options = {}) {
|
|
2953
|
+
return callDelegate("humanClick", page, [target, options]);
|
|
2954
|
+
},
|
|
2955
|
+
randomSleep(pageOrBaseMs, maybeBaseMs, maybeJitterPercent) {
|
|
2956
|
+
if (pageOrBaseMs && typeof pageOrBaseMs === "object" && typeof pageOrBaseMs.evaluate === "function") {
|
|
2957
|
+
const delegate = resolveDelegate(pageOrBaseMs);
|
|
2958
|
+
return delegate.randomSleep(maybeBaseMs, maybeJitterPercent);
|
|
2959
|
+
}
|
|
2960
|
+
return Humanize.randomSleep(pageOrBaseMs, maybeBaseMs);
|
|
2961
|
+
},
|
|
2962
|
+
simulateGaze(page, baseDurationMs = 2500) {
|
|
2963
|
+
return callDelegate("simulateGaze", page, [baseDurationMs]);
|
|
2964
|
+
},
|
|
2965
|
+
humanType(page, selector, text, options = {}) {
|
|
2966
|
+
return callDelegate("humanType", page, [selector, text, options]);
|
|
2967
|
+
},
|
|
2968
|
+
humanClear(page, selector) {
|
|
2969
|
+
return callDelegate("humanClear", page, [selector]);
|
|
2970
|
+
},
|
|
2971
|
+
warmUpBrowsing(page, baseDuration = 3500) {
|
|
2972
|
+
return callDelegate("warmUpBrowsing", page, [baseDuration]);
|
|
2973
|
+
},
|
|
2974
|
+
naturalScroll(page, direction = "down", distance = 300, baseSteps = 5) {
|
|
2975
|
+
return callDelegate("naturalScroll", page, [direction, distance, baseSteps]);
|
|
2976
|
+
}
|
|
2977
|
+
};
|
|
2978
|
+
|
|
2555
2979
|
// src/launch.js
|
|
2556
2980
|
var import_node_child_process = require("node:child_process");
|
|
2557
2981
|
var import_fingerprint_generator = require("fingerprint-generator");
|
|
@@ -2638,7 +3062,7 @@ var ByPass = {
|
|
|
2638
3062
|
};
|
|
2639
3063
|
|
|
2640
3064
|
// src/launch.js
|
|
2641
|
-
var
|
|
3065
|
+
var logger8 = createInternalLogger("Launch");
|
|
2642
3066
|
var REQUEST_HOOK_FLAG = Symbol("playwright-toolkit-request-hook");
|
|
2643
3067
|
var injectedContexts = /* @__PURE__ */ new WeakSet();
|
|
2644
3068
|
var browserMajorVersionCache = /* @__PURE__ */ new Map();
|
|
@@ -2690,20 +3114,29 @@ var detectBrowserMajorVersion = (launcher) => {
|
|
|
2690
3114
|
});
|
|
2691
3115
|
detectedVersion = parseChromeMajorVersion(rawVersion);
|
|
2692
3116
|
} catch (error) {
|
|
2693
|
-
|
|
3117
|
+
logger8.warn(`\u8BFB\u53D6\u6D4F\u89C8\u5668\u7248\u672C\u5931\u8D25: ${error?.message || error}`);
|
|
2694
3118
|
}
|
|
2695
3119
|
browserMajorVersionCache.set(executablePath, detectedVersion);
|
|
2696
3120
|
return detectedVersion;
|
|
2697
3121
|
};
|
|
2698
|
-
var
|
|
3122
|
+
var resolveRuntimeDevice = (runtimeState = {}) => normalizeDevice(runtimeState?.device);
|
|
3123
|
+
var resolveCoreDevice = (core = {}) => {
|
|
3124
|
+
const raw = String(core?.device || "").trim().toLowerCase();
|
|
3125
|
+
if (raw === Device.Mobile) return Device.Mobile;
|
|
3126
|
+
if (raw === Device.Desktop) return Device.Desktop;
|
|
3127
|
+
return "";
|
|
3128
|
+
};
|
|
3129
|
+
var buildFingerprintGenerator = ({ locale, browserMajorVersion, device }) => {
|
|
2699
3130
|
return new import_fingerprint_generator.FingerprintGenerator(
|
|
2700
3131
|
AntiCheat.getFingerprintGeneratorOptions({
|
|
2701
3132
|
locale,
|
|
2702
|
-
browserMajorVersion
|
|
3133
|
+
browserMajorVersion,
|
|
3134
|
+
device
|
|
2703
3135
|
})
|
|
2704
3136
|
);
|
|
2705
3137
|
};
|
|
2706
3138
|
var buildReplayableBrowserProfile = (runtimeState, launcher) => {
|
|
3139
|
+
const device = resolveRuntimeDevice(runtimeState);
|
|
2707
3140
|
if (!runtimeState || !RuntimeEnv.hasLoginState(runtimeState)) {
|
|
2708
3141
|
return { runtimeState, browserProfileCore: null };
|
|
2709
3142
|
}
|
|
@@ -2713,29 +3146,34 @@ var buildReplayableBrowserProfile = (runtimeState, launcher) => {
|
|
|
2713
3146
|
const locale = DEFAULT_LOCALE;
|
|
2714
3147
|
const currentBrowserMajorVersion = detectBrowserMajorVersion(launcher);
|
|
2715
3148
|
const storedBrowserMajorVersion = Number(browserProfileCore?.browser_major_version || 0);
|
|
2716
|
-
const
|
|
3149
|
+
const storedDevice = resolveCoreDevice(browserProfileCore);
|
|
3150
|
+
const needsDeviceRebuild = storedDevice ? storedDevice !== device : device === Device.Mobile;
|
|
3151
|
+
const needsRebuild = !browserProfileCore?.fingerprint || Object.keys(browserProfileCore.fingerprint || {}).length === 0 || needsDeviceRebuild || currentBrowserMajorVersion > 0 && storedBrowserMajorVersion > 0 && storedBrowserMajorVersion !== currentBrowserMajorVersion;
|
|
2717
3152
|
if (needsRebuild) {
|
|
2718
3153
|
const generator = buildFingerprintGenerator({
|
|
2719
3154
|
locale,
|
|
2720
|
-
browserMajorVersion: currentBrowserMajorVersion
|
|
3155
|
+
browserMajorVersion: currentBrowserMajorVersion,
|
|
3156
|
+
device
|
|
2721
3157
|
});
|
|
2722
3158
|
const fingerprint = generator.getFingerprint();
|
|
2723
3159
|
const fingerprintBrowserMajorVersion = parseChromeMajorVersion(fingerprint?.fingerprint?.navigator?.userAgent || "");
|
|
2724
3160
|
browserProfileCore = {
|
|
2725
3161
|
fingerprint,
|
|
3162
|
+
device,
|
|
2726
3163
|
timezone_id: timezoneId,
|
|
2727
3164
|
locale,
|
|
2728
3165
|
browser_major_version: currentBrowserMajorVersion > 0 ? currentBrowserMajorVersion : fingerprintBrowserMajorVersion,
|
|
2729
3166
|
schema_version: DEFAULT_BROWSER_PROFILE_SCHEMA_VERSION
|
|
2730
3167
|
};
|
|
2731
3168
|
nextState = RuntimeEnv.setBrowserProfileCore(nextState, browserProfileCore);
|
|
2732
|
-
|
|
2733
|
-
`\u5DF2\u751F\u6210\u6D4F\u89C8\u5668\u6307\u7EB9\u771F\u6E90 | env=${String(nextState.envId || "-")} | version=${browserProfileCore.browser_major_version || "-"} | timezone=${timezoneId}`
|
|
3169
|
+
logger8.info(
|
|
3170
|
+
`\u5DF2\u751F\u6210\u6D4F\u89C8\u5668\u6307\u7EB9\u771F\u6E90 | env=${String(nextState.envId || "-")} | device=${device} | version=${browserProfileCore.browser_major_version || "-"} | timezone=${timezoneId}`
|
|
2734
3171
|
);
|
|
2735
3172
|
return { runtimeState: nextState, browserProfileCore };
|
|
2736
3173
|
}
|
|
2737
3174
|
const normalizedBrowserProfileCore = {
|
|
2738
3175
|
...browserProfileCore,
|
|
3176
|
+
device,
|
|
2739
3177
|
timezone_id: timezoneId,
|
|
2740
3178
|
locale,
|
|
2741
3179
|
schema_version: Number(browserProfileCore.schema_version || 0) > 0 ? Number(browserProfileCore.schema_version || 0) : DEFAULT_BROWSER_PROFILE_SCHEMA_VERSION,
|
|
@@ -2751,6 +3189,35 @@ var buildReplayableBrowserProfile = (runtimeState, launcher) => {
|
|
|
2751
3189
|
browserProfileCore: normalizedBrowserProfileCore
|
|
2752
3190
|
};
|
|
2753
3191
|
};
|
|
3192
|
+
var applyDevicePageOptions = (pageOptions = {}, { device = Device.Desktop, fingerprint = null } = {}) => {
|
|
3193
|
+
if (!pageOptions || typeof pageOptions !== "object") return;
|
|
3194
|
+
const resolvedDevice = normalizeDevice(device);
|
|
3195
|
+
const screen = fingerprint?.screen || {};
|
|
3196
|
+
const dpr = Number(screen.devicePixelRatio || 0);
|
|
3197
|
+
if (resolvedDevice === Device.Mobile) {
|
|
3198
|
+
pageOptions.isMobile = true;
|
|
3199
|
+
pageOptions.hasTouch = true;
|
|
3200
|
+
pageOptions.deviceScaleFactor = dpr > 0 ? dpr : 2;
|
|
3201
|
+
if (!pageOptions.viewport) {
|
|
3202
|
+
pageOptions.viewport = {
|
|
3203
|
+
width: Number(screen.width || 390),
|
|
3204
|
+
height: Number(screen.height || 844)
|
|
3205
|
+
};
|
|
3206
|
+
}
|
|
3207
|
+
if (!pageOptions.screen) {
|
|
3208
|
+
pageOptions.screen = {
|
|
3209
|
+
width: Number(screen.width || pageOptions.viewport.width || 390),
|
|
3210
|
+
height: Number(screen.height || pageOptions.viewport.height || 844)
|
|
3211
|
+
};
|
|
3212
|
+
}
|
|
3213
|
+
return;
|
|
3214
|
+
}
|
|
3215
|
+
pageOptions.isMobile = false;
|
|
3216
|
+
pageOptions.hasTouch = false;
|
|
3217
|
+
if (!pageOptions.deviceScaleFactor) {
|
|
3218
|
+
pageOptions.deviceScaleFactor = dpr > 0 ? dpr : 1;
|
|
3219
|
+
}
|
|
3220
|
+
};
|
|
2754
3221
|
var buildReplayBrowserPoolOptions = (browserProfileCore) => {
|
|
2755
3222
|
const fingerprintWithHeaders = browserProfileCore?.fingerprint;
|
|
2756
3223
|
const fingerprint = fingerprintWithHeaders?.fingerprint;
|
|
@@ -2783,6 +3250,10 @@ var buildReplayBrowserPoolOptions = (browserProfileCore) => {
|
|
|
2783
3250
|
if (browserProfileCore.timezone_id) {
|
|
2784
3251
|
pageOptions.timezoneId = browserProfileCore.timezone_id;
|
|
2785
3252
|
}
|
|
3253
|
+
applyDevicePageOptions(pageOptions, {
|
|
3254
|
+
device: browserProfileCore.device,
|
|
3255
|
+
fingerprint
|
|
3256
|
+
});
|
|
2786
3257
|
}
|
|
2787
3258
|
],
|
|
2788
3259
|
postPageCreateHooks: [
|
|
@@ -2812,6 +3283,7 @@ var Launch = {
|
|
|
2812
3283
|
postNavigationHooks = [],
|
|
2813
3284
|
runtimeState = null
|
|
2814
3285
|
} = normalizedOptions;
|
|
3286
|
+
const device = resolveRuntimeDevice(runtimeState);
|
|
2815
3287
|
const { byPassDomains, enableProxy, proxyUrl } = resolveProxyLaunchOptions(proxyConfiguration);
|
|
2816
3288
|
const byPassRules = ByPass.buildByPassDomainRules(byPassDomains);
|
|
2817
3289
|
const proxyMeter = enableProxy && proxyUrl ? ProxyMeterRuntime.startProxyMeter({ proxyUrl, debugMode }) : null;
|
|
@@ -2840,18 +3312,18 @@ var Launch = {
|
|
|
2840
3312
|
upstreamLabel = `${parsedProxyUrl.protocol}//${parsedProxyUrl.host}`;
|
|
2841
3313
|
} catch {
|
|
2842
3314
|
}
|
|
2843
|
-
|
|
3315
|
+
logger8.info(
|
|
2844
3316
|
`[\u4EE3\u7406\u5DF2\u542F\u7528] \u672C\u5730=${launchProxy.server} \u4E0A\u6E38=${upstreamLabel || "-"} \u76F4\u8FDE\u57DF\u540D=${(byPassDomains || []).join(",")}`
|
|
2845
3317
|
);
|
|
2846
|
-
|
|
3318
|
+
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`);
|
|
2847
3319
|
} else if (enableByPassLogger && enableProxy && !launchProxy) {
|
|
2848
|
-
|
|
2849
|
-
|
|
3320
|
+
logger8.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=true \u4F46 proxy_url \u4E3A\u7A7A");
|
|
3321
|
+
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`);
|
|
2850
3322
|
} else if (enableByPassLogger && !enableProxy && proxyUrl) {
|
|
2851
|
-
|
|
2852
|
-
|
|
3323
|
+
logger8.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=false \u4E14 proxy_url \u5DF2\u914D\u7F6E");
|
|
3324
|
+
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`);
|
|
2853
3325
|
} else if (enableByPassLogger) {
|
|
2854
|
-
|
|
3326
|
+
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`);
|
|
2855
3327
|
}
|
|
2856
3328
|
const onPageCreated = (page) => {
|
|
2857
3329
|
const recommendedGotoOptions = {
|
|
@@ -2873,7 +3345,7 @@ var Launch = {
|
|
|
2873
3345
|
}
|
|
2874
3346
|
if (!enableByPassLogger || byPassDomains.length === 0) return;
|
|
2875
3347
|
if (!matched || !matched.rule) return;
|
|
2876
|
-
|
|
3348
|
+
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}`);
|
|
2877
3349
|
};
|
|
2878
3350
|
page.on("request", requestHandler);
|
|
2879
3351
|
return recommendedGotoOptions;
|
|
@@ -2892,8 +3364,23 @@ var Launch = {
|
|
|
2892
3364
|
browserPoolOptions: replayBrowserPoolOptions || {
|
|
2893
3365
|
useFingerprints: true,
|
|
2894
3366
|
fingerprintOptions: {
|
|
2895
|
-
fingerprintGeneratorOptions: AntiCheat.getFingerprintGeneratorOptions(
|
|
2896
|
-
|
|
3367
|
+
fingerprintGeneratorOptions: AntiCheat.getFingerprintGeneratorOptions({
|
|
3368
|
+
locale: launchLocale,
|
|
3369
|
+
device
|
|
3370
|
+
})
|
|
3371
|
+
},
|
|
3372
|
+
prePageCreateHooks: [
|
|
3373
|
+
(_pageId, _browserController, pageOptions = {}) => {
|
|
3374
|
+
applyDevicePageOptions(pageOptions, { device });
|
|
3375
|
+
if (launchLocale) {
|
|
3376
|
+
pageOptions.locale = launchLocale;
|
|
3377
|
+
}
|
|
3378
|
+
const timezoneId = AntiCheat.getBaseConfig().timezoneId;
|
|
3379
|
+
if (timezoneId) {
|
|
3380
|
+
pageOptions.timezoneId = timezoneId;
|
|
3381
|
+
}
|
|
3382
|
+
}
|
|
3383
|
+
]
|
|
2897
3384
|
},
|
|
2898
3385
|
launchContext
|
|
2899
3386
|
};
|
|
@@ -2916,7 +3403,7 @@ var Launch = {
|
|
|
2916
3403
|
// src/live-view.js
|
|
2917
3404
|
var import_express = __toESM(require("express"), 1);
|
|
2918
3405
|
var import_apify = require("apify");
|
|
2919
|
-
var
|
|
3406
|
+
var logger9 = createInternalLogger("LiveView");
|
|
2920
3407
|
async function startLiveViewServer(liveViewKey) {
|
|
2921
3408
|
const app = (0, import_express.default)();
|
|
2922
3409
|
app.get("/", async (req, res) => {
|
|
@@ -2941,13 +3428,13 @@ async function startLiveViewServer(liveViewKey) {
|
|
|
2941
3428
|
</html>
|
|
2942
3429
|
`);
|
|
2943
3430
|
} catch (error) {
|
|
2944
|
-
|
|
3431
|
+
logger9.fail("Live View Server", error);
|
|
2945
3432
|
res.status(500).send(`\u65E0\u6CD5\u52A0\u8F7D\u5C4F\u5E55\u622A\u56FE: ${error.message}`);
|
|
2946
3433
|
}
|
|
2947
3434
|
});
|
|
2948
3435
|
const port = process.env.APIFY_CONTAINER_PORT || 4321;
|
|
2949
3436
|
app.listen(port, () => {
|
|
2950
|
-
|
|
3437
|
+
logger9.success("startLiveViewServer", `\u76D1\u542C\u7AEF\u53E3 ${port}`);
|
|
2951
3438
|
});
|
|
2952
3439
|
}
|
|
2953
3440
|
async function takeLiveScreenshot(liveViewKey, page, logMessage) {
|
|
@@ -2955,10 +3442,10 @@ async function takeLiveScreenshot(liveViewKey, page, logMessage) {
|
|
|
2955
3442
|
const buffer = await capturePageScreenshot(page, { type: "png" });
|
|
2956
3443
|
await import_apify.Actor.setValue(liveViewKey, buffer, { contentType: "image/png" });
|
|
2957
3444
|
if (logMessage) {
|
|
2958
|
-
|
|
3445
|
+
logger9.info(`(\u622A\u56FE): ${logMessage}`);
|
|
2959
3446
|
}
|
|
2960
3447
|
} catch (e) {
|
|
2961
|
-
|
|
3448
|
+
logger9.warn(`\u65E0\u6CD5\u6355\u83B7 Live View \u5C4F\u5E55\u622A\u56FE: ${e.message}`);
|
|
2962
3449
|
}
|
|
2963
3450
|
}
|
|
2964
3451
|
var useLiveView = (liveViewKey = PresetOfLiveViewKey) => {
|
|
@@ -3058,7 +3545,7 @@ var dragCaptchaWithMouse = async (page, sourceLocator, targetLocator) => {
|
|
|
3058
3545
|
};
|
|
3059
3546
|
|
|
3060
3547
|
// src/internals/captcha/bytedance.js
|
|
3061
|
-
var
|
|
3548
|
+
var logger10 = createInternalLogger("Captcha");
|
|
3062
3549
|
var DEFAULT_BYTEDANCE_CAPTCHA_OPTIONS = Object.freeze({
|
|
3063
3550
|
apiType: "31234",
|
|
3064
3551
|
maxRetries: 3,
|
|
@@ -3125,14 +3612,14 @@ var getVerifycenterCaptchaContext = async (page, options) => {
|
|
|
3125
3612
|
if (!isContainerVisible) {
|
|
3126
3613
|
return null;
|
|
3127
3614
|
}
|
|
3128
|
-
|
|
3615
|
+
logger10.info("\u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\u5BB9\u5668\uFF0C\u5F00\u59CB\u7B49\u5F85 iframe \u52A0\u8F7D\u3002");
|
|
3129
3616
|
let iframeLocator = page.locator(options.iframeSelector).first();
|
|
3130
3617
|
let isIframeVisible = await waitForVisible(
|
|
3131
3618
|
iframeLocator,
|
|
3132
3619
|
options.iframeVisibleTimeoutMs
|
|
3133
3620
|
);
|
|
3134
3621
|
if (!isIframeVisible) {
|
|
3135
|
-
|
|
3622
|
+
logger10.warn("\u672A\u5728\u9884\u671F\u9009\u62E9\u5668\u4E2D\u627E\u5230 verifycenter iframe\uFF0C\u5C1D\u8BD5\u5BB9\u5668\u5185\u4EFB\u610F iframe\u3002");
|
|
3136
3623
|
iframeLocator = captchaContainer.locator(options.iframeFallbackSelector).first();
|
|
3137
3624
|
isIframeVisible = await waitForVisible(
|
|
3138
3625
|
iframeLocator,
|
|
@@ -3142,7 +3629,7 @@ var getVerifycenterCaptchaContext = async (page, options) => {
|
|
|
3142
3629
|
if (!isIframeVisible) {
|
|
3143
3630
|
throw new Error("verifycenter iframe not found inside captcha container.");
|
|
3144
3631
|
}
|
|
3145
|
-
|
|
3632
|
+
logger10.info("\u9A8C\u8BC1\u7801 iframe \u5DF2\u53EF\u89C1\uFF0C\u5F00\u59CB\u89E3\u6790\u5185\u5BB9 frame\u3002");
|
|
3146
3633
|
const frame = await resolveContentFrame(page, iframeLocator, options);
|
|
3147
3634
|
if (!frame) {
|
|
3148
3635
|
throw new Error("Failed to resolve verifycenter iframe content frame.");
|
|
@@ -3152,7 +3639,7 @@ var getVerifycenterCaptchaContext = async (page, options) => {
|
|
|
3152
3639
|
var refreshCaptcha = async (page, frame, options) => {
|
|
3153
3640
|
const clicked = await clickCaptchaAction(frame, options.refreshTexts, options).catch(() => false);
|
|
3154
3641
|
if (!clicked) {
|
|
3155
|
-
|
|
3642
|
+
logger10.warn("Refresh button not found.");
|
|
3156
3643
|
return false;
|
|
3157
3644
|
}
|
|
3158
3645
|
await page.waitForTimeout(options.refreshWaitMs);
|
|
@@ -3193,18 +3680,18 @@ var waitForCaptchaChallengeReady = async (page, frame, options) => {
|
|
|
3193
3680
|
const imageCount = await sourceImages.count().catch(() => 0);
|
|
3194
3681
|
const hasVisibleSourceImage = imageCount > 0 ? await sourceImages.first().isVisible({ timeout: options.loadingIndicatorVisibleTimeoutMs }).catch(() => false) : false;
|
|
3195
3682
|
if (!isLoadingVisible && hasVisibleSourceImage) {
|
|
3196
|
-
|
|
3683
|
+
logger10.info(hasSeenLoading ? "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u52A0\u8F7D\u5B8C\u6210\u3002" : "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u5C31\u7EEA\u3002");
|
|
3197
3684
|
return;
|
|
3198
3685
|
}
|
|
3199
3686
|
if (hasErrorTextVisible) {
|
|
3200
|
-
|
|
3687
|
+
logger10.warn("\u9A8C\u8BC1\u7801\u9762\u677F\u51FA\u73B0\u7F51\u7EDC\u5F02\u5E38\u6587\u6848\uFF0C\u5C1D\u8BD5\u7ACB\u5373\u5237\u65B0\u9898\u76EE\u3002");
|
|
3201
3688
|
await refreshCaptcha(page, frame, options);
|
|
3202
3689
|
refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
|
|
3203
3690
|
hasSeenLoading = false;
|
|
3204
3691
|
continue;
|
|
3205
3692
|
}
|
|
3206
3693
|
if (!hasVisibleSourceImage && Date.now() >= refreshDeadline) {
|
|
3207
|
-
|
|
3694
|
+
logger10.warn(`\u9A8C\u8BC1\u7801\u56FE\u7247\u8D85\u8FC7 ${options.challengeReadyRefreshTimeoutMs}ms \u4ECD\u672A\u51FA\u73B0\uFF0C\u5C1D\u8BD5\u5237\u65B0\u9898\u76EE\u3002`);
|
|
3208
3695
|
await refreshCaptcha(page, frame, options);
|
|
3209
3696
|
refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
|
|
3210
3697
|
hasSeenLoading = false;
|
|
@@ -3224,16 +3711,16 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
|
|
|
3224
3711
|
...options
|
|
3225
3712
|
};
|
|
3226
3713
|
if (!config.token) {
|
|
3227
|
-
|
|
3714
|
+
logger10.warn("\u7F3A\u5C11\u9A8C\u8BC1\u7801 token\uFF0C\u8DF3\u8FC7\u81EA\u52A8\u8BC6\u522B\u3002");
|
|
3228
3715
|
return false;
|
|
3229
3716
|
}
|
|
3230
|
-
|
|
3717
|
+
logger10.info("\u5F53\u524D\u4F7F\u7528\u672Ctool\u2014\u2014\u6D4B\u8BD5\u7248\u672C");
|
|
3231
3718
|
for (let attempt = 1; attempt <= config.maxRetries; attempt++) {
|
|
3232
|
-
|
|
3719
|
+
logger10.info(`\u5F00\u59CB\u7B2C ${attempt}/${config.maxRetries} \u6B21 verifycenter \u9A8C\u8BC1\u7801\u8BC6\u522B\u3002`);
|
|
3233
3720
|
try {
|
|
3234
3721
|
const captchaContext = await getVerifycenterCaptchaContext(page, config);
|
|
3235
3722
|
if (!captchaContext) {
|
|
3236
|
-
|
|
3723
|
+
logger10.info("Captcha container is not visible anymore.");
|
|
3237
3724
|
return true;
|
|
3238
3725
|
}
|
|
3239
3726
|
const { iframeLocator, frame } = captchaContext;
|
|
@@ -3248,16 +3735,16 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
|
|
|
3248
3735
|
});
|
|
3249
3736
|
const serialNumbers = extractCaptchaSerialNumbers(apiResponse);
|
|
3250
3737
|
if (apiResponse?.code !== config.recognitionSuccessCode || serialNumbers.length === 0) {
|
|
3251
|
-
|
|
3738
|
+
logger10.warn(
|
|
3252
3739
|
`\u9A8C\u8BC1\u7801\u8BC6\u522B\u5931\u8D25\u3002code=${apiResponse?.code}, msg=${apiResponse?.msg || "unknown"}`
|
|
3253
3740
|
);
|
|
3254
3741
|
await refreshCaptcha(page, frame, config);
|
|
3255
3742
|
continue;
|
|
3256
3743
|
}
|
|
3257
|
-
|
|
3744
|
+
logger10.info(`\u9A8C\u8BC1\u7801\u8BC6\u522B\u6210\u529F\uFF0C\u5E8F\u53F7\uFF1A${serialNumbers.join(", ")}`);
|
|
3258
3745
|
const dropTarget = await findCaptchaDropTarget(frame, config);
|
|
3259
3746
|
if (!dropTarget) {
|
|
3260
|
-
|
|
3747
|
+
logger10.warn("\u672A\u627E\u5230\u9A8C\u8BC1\u7801\u62D6\u62FD\u76EE\u6807\u533A\u57DF\u3002");
|
|
3261
3748
|
await refreshCaptcha(page, frame, config);
|
|
3262
3749
|
continue;
|
|
3263
3750
|
}
|
|
@@ -3280,31 +3767,31 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
|
|
|
3280
3767
|
}
|
|
3281
3768
|
const submitted = await clickCaptchaAction(frame, config.submitTexts, config).catch(() => false);
|
|
3282
3769
|
if (!submitted) {
|
|
3283
|
-
|
|
3770
|
+
logger10.warn("\u672A\u627E\u5230\u63D0\u4EA4\u6309\u94AE\uFF0C\u53EF\u80FD\u4F1A\u81EA\u52A8\u63D0\u4EA4\u3002");
|
|
3284
3771
|
}
|
|
3285
3772
|
await page.waitForTimeout(config.submitWaitMs);
|
|
3286
3773
|
const stillVisible = await iframeLocator.isVisible({ timeout: config.containerVisibleTimeoutMs }).catch(() => false);
|
|
3287
3774
|
if (!stillVisible) {
|
|
3288
|
-
|
|
3775
|
+
logger10.info("\u9A8C\u8BC1\u7801\u8BC6\u522B\u5E76\u63D0\u4EA4\u6210\u529F\u3002");
|
|
3289
3776
|
return true;
|
|
3290
3777
|
}
|
|
3291
|
-
|
|
3778
|
+
logger10.warn("\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801 iframe \u4ECD\u7136\u53EF\u89C1\uFF0C\u51C6\u5907\u5237\u65B0\u540E\u91CD\u8BD5\u3002");
|
|
3292
3779
|
await page.waitForTimeout(2e3);
|
|
3293
3780
|
await refreshCaptcha(page, frame, config);
|
|
3294
3781
|
} catch (error) {
|
|
3295
|
-
|
|
3782
|
+
logger10.error(`\u7B2C ${attempt}/${config.maxRetries} \u6B21\u9A8C\u8BC1\u7801\u8BC6\u522B\u5931\u8D25\uFF1A${error?.message || error}`);
|
|
3296
3783
|
}
|
|
3297
3784
|
if (attempt < config.maxRetries) {
|
|
3298
3785
|
await page.waitForTimeout(config.retryDelayBaseMs + attempt * config.retryDelayStepMs);
|
|
3299
3786
|
}
|
|
3300
3787
|
}
|
|
3301
|
-
|
|
3788
|
+
logger10.error(`\u91CD\u8BD5 ${config.maxRetries} \u6B21\u540E\uFF0C\u9A8C\u8BC1\u7801\u4ECD\u672A\u8BC6\u522B\u6210\u529F\u3002`);
|
|
3302
3789
|
return false;
|
|
3303
3790
|
}
|
|
3304
3791
|
var sloveCaptcha = solveCaptcha;
|
|
3305
3792
|
|
|
3306
3793
|
// src/chaptcha.js
|
|
3307
|
-
var
|
|
3794
|
+
var logger11 = createInternalLogger("Captcha");
|
|
3308
3795
|
var DEFAULT_CAPTCHA_RECOGNITION_OPTIONS = Object.freeze({
|
|
3309
3796
|
token: "eKJvBfwfN0YRav0-VD_44E2VBSfm7l0YtddUQ7cFySI",
|
|
3310
3797
|
apiUrl: "https://api.jfbym.com/api/YmServer/customApi"
|
|
@@ -3391,7 +3878,7 @@ function useCaptchaMonitor(page, options) {
|
|
|
3391
3878
|
};
|
|
3392
3879
|
})();
|
|
3393
3880
|
}, { selector: domSelector, callbackName: exposedFunctionName, cleanerName });
|
|
3394
|
-
|
|
3881
|
+
logger11.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${domSelector}`);
|
|
3395
3882
|
cleanupFns.push(async () => {
|
|
3396
3883
|
try {
|
|
3397
3884
|
await page.evaluate((name) => {
|
|
@@ -3415,14 +3902,14 @@ function useCaptchaMonitor(page, options) {
|
|
|
3415
3902
|
}
|
|
3416
3903
|
};
|
|
3417
3904
|
page.on("framenavigated", frameHandler);
|
|
3418
|
-
|
|
3905
|
+
logger11.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${urlPattern}`);
|
|
3419
3906
|
cleanupFns.push(async () => {
|
|
3420
3907
|
page.off("framenavigated", frameHandler);
|
|
3421
3908
|
});
|
|
3422
3909
|
}
|
|
3423
3910
|
return {
|
|
3424
3911
|
stop: async () => {
|
|
3425
|
-
|
|
3912
|
+
logger11.info("\u6B63\u5728\u505C\u6B62\u9A8C\u8BC1\u7801\u76D1\u63A7...");
|
|
3426
3913
|
for (const fn of cleanupFns) {
|
|
3427
3914
|
await fn();
|
|
3428
3915
|
}
|
|
@@ -3461,7 +3948,7 @@ async function solveCaptchaWithStrategy(strategyName, page, options = {}) {
|
|
|
3461
3948
|
);
|
|
3462
3949
|
return strategy.sloveCaptcha(page, resolvedOptions, {
|
|
3463
3950
|
callCaptchaRecognitionApi,
|
|
3464
|
-
logger:
|
|
3951
|
+
logger: logger11
|
|
3465
3952
|
});
|
|
3466
3953
|
}
|
|
3467
3954
|
var Captcha = {
|
|
@@ -3472,7 +3959,7 @@ var Captcha = {
|
|
|
3472
3959
|
// src/mutation.js
|
|
3473
3960
|
var import_node_crypto = require("node:crypto");
|
|
3474
3961
|
var import_uuid2 = require("uuid");
|
|
3475
|
-
var
|
|
3962
|
+
var logger12 = createInternalLogger("Mutation");
|
|
3476
3963
|
var MUTATION_MONITOR_MODE = Object.freeze({
|
|
3477
3964
|
Added: "added",
|
|
3478
3965
|
Changed: "changed",
|
|
@@ -3505,14 +3992,14 @@ var Mutation = {
|
|
|
3505
3992
|
const stableTime = options.stableTime ?? 5 * 1e3;
|
|
3506
3993
|
const timeout = options.timeout ?? 120 * 1e3;
|
|
3507
3994
|
const onMutation = options.onMutation;
|
|
3508
|
-
|
|
3995
|
+
logger12.start("waitForStable", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);
|
|
3509
3996
|
if (initialTimeout > 0) {
|
|
3510
3997
|
const selectorQuery = selectorList.join(",");
|
|
3511
3998
|
try {
|
|
3512
3999
|
await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
|
|
3513
|
-
|
|
4000
|
+
logger12.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
|
|
3514
4001
|
} catch (e) {
|
|
3515
|
-
|
|
4002
|
+
logger12.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
|
|
3516
4003
|
throw e;
|
|
3517
4004
|
}
|
|
3518
4005
|
}
|
|
@@ -3528,7 +4015,7 @@ var Mutation = {
|
|
|
3528
4015
|
return "__CONTINUE__";
|
|
3529
4016
|
}
|
|
3530
4017
|
});
|
|
3531
|
-
|
|
4018
|
+
logger12.info("waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03");
|
|
3532
4019
|
} catch (e) {
|
|
3533
4020
|
}
|
|
3534
4021
|
}
|
|
@@ -3643,9 +4130,9 @@ var Mutation = {
|
|
|
3643
4130
|
{ selectorList, stableTime, timeout, callbackName, hasCallback: !!onMutation }
|
|
3644
4131
|
);
|
|
3645
4132
|
if (result.mutationCount === 0 && result.stableTime === 0) {
|
|
3646
|
-
|
|
4133
|
+
logger12.warning("waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
|
|
3647
4134
|
}
|
|
3648
|
-
|
|
4135
|
+
logger12.success("waitForStable", `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
|
|
3649
4136
|
return result;
|
|
3650
4137
|
},
|
|
3651
4138
|
/**
|
|
@@ -3817,22 +4304,22 @@ var Mutation = {
|
|
|
3817
4304
|
return "__CONTINUE__";
|
|
3818
4305
|
}
|
|
3819
4306
|
};
|
|
3820
|
-
|
|
4307
|
+
logger12.start(
|
|
3821
4308
|
"waitForStableAcrossRoots",
|
|
3822
4309
|
`\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668(\u8DE8 root), \u7A33\u5B9A\u65F6\u95F4=${waitForStableTime}ms`
|
|
3823
4310
|
);
|
|
3824
4311
|
if (initialTimeout > 0) {
|
|
3825
4312
|
try {
|
|
3826
4313
|
await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
|
|
3827
|
-
|
|
4314
|
+
logger12.info(`waitForStableAcrossRoots \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
|
|
3828
4315
|
} catch (e) {
|
|
3829
|
-
|
|
4316
|
+
logger12.warning(`waitForStableAcrossRoots \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
|
|
3830
4317
|
throw e;
|
|
3831
4318
|
}
|
|
3832
4319
|
}
|
|
3833
4320
|
let state = await buildState();
|
|
3834
4321
|
if (!state?.hasMatched) {
|
|
3835
|
-
|
|
4322
|
+
logger12.warning("waitForStableAcrossRoots \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
|
|
3836
4323
|
return { mutationCount: 0, stableTime: 0, wasPaused: false };
|
|
3837
4324
|
}
|
|
3838
4325
|
let mutationCount = 0;
|
|
@@ -3869,7 +4356,7 @@ var Mutation = {
|
|
|
3869
4356
|
if (lastState.snapshotKey !== lastSnapshotKey) {
|
|
3870
4357
|
lastSnapshotKey = lastState.snapshotKey;
|
|
3871
4358
|
mutationCount += 1;
|
|
3872
|
-
|
|
4359
|
+
logger12.info(
|
|
3873
4360
|
`waitForStableAcrossRoots \u53D8\u5316#${mutationCount}, len=${lastState.snapshotLength}, path=${lastState.primaryPath || "unknown"}, preview="${truncate(lastState.text, 120)}"`
|
|
3874
4361
|
);
|
|
3875
4362
|
const signal = await invokeMutationCallback({
|
|
@@ -3882,7 +4369,7 @@ var Mutation = {
|
|
|
3882
4369
|
continue;
|
|
3883
4370
|
}
|
|
3884
4371
|
if (!isPaused && stableSince > 0 && Date.now() - stableSince >= waitForStableTime) {
|
|
3885
|
-
|
|
4372
|
+
logger12.success("waitForStableAcrossRoots", `DOM \u7A33\u5B9A, \u603B\u5171 ${mutationCount} \u6B21\u53D8\u5316${wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
|
|
3886
4373
|
return {
|
|
3887
4374
|
mutationCount,
|
|
3888
4375
|
stableTime: waitForStableTime,
|
|
@@ -3909,7 +4396,7 @@ var Mutation = {
|
|
|
3909
4396
|
const onMutation = options.onMutation;
|
|
3910
4397
|
const rawMode = String(options.mode || MUTATION_MONITOR_MODE.Added).toLowerCase();
|
|
3911
4398
|
const mode = [MUTATION_MONITOR_MODE.Added, MUTATION_MONITOR_MODE.Changed, MUTATION_MONITOR_MODE.All].includes(rawMode) ? rawMode : MUTATION_MONITOR_MODE.Added;
|
|
3912
|
-
|
|
4399
|
+
logger12.start("useMonitor", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode}`);
|
|
3913
4400
|
const monitorKey = generateKey("pk_mon");
|
|
3914
4401
|
const callbackName = generateKey("pk_mon_cb");
|
|
3915
4402
|
const cleanerName = generateKey("pk_mon_clean");
|
|
@@ -4052,7 +4539,7 @@ var Mutation = {
|
|
|
4052
4539
|
return total;
|
|
4053
4540
|
};
|
|
4054
4541
|
}, { selectorList, monitorKey, callbackName, cleanerName, hasCallback: !!onMutation, mode });
|
|
4055
|
-
|
|
4542
|
+
logger12.success("useMonitor", "\u76D1\u63A7\u5668\u5DF2\u542F\u52A8");
|
|
4056
4543
|
return {
|
|
4057
4544
|
stop: async () => {
|
|
4058
4545
|
let totalMutations = 0;
|
|
@@ -4065,7 +4552,7 @@ var Mutation = {
|
|
|
4065
4552
|
}, cleanerName);
|
|
4066
4553
|
} catch (e) {
|
|
4067
4554
|
}
|
|
4068
|
-
|
|
4555
|
+
logger12.success("useMonitor.stop", `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);
|
|
4069
4556
|
return { totalMutations };
|
|
4070
4557
|
}
|
|
4071
4558
|
};
|
|
@@ -4934,7 +5421,7 @@ var createTemplateLogger = (baseLogger = createBaseLogger()) => {
|
|
|
4934
5421
|
};
|
|
4935
5422
|
var getDefaultBaseLogger = () => createBaseLogger("");
|
|
4936
5423
|
var Logger = {
|
|
4937
|
-
setLogger: (
|
|
5424
|
+
setLogger: (logger16) => setDefaultLogger(logger16),
|
|
4938
5425
|
info: (message) => getDefaultBaseLogger().info(message),
|
|
4939
5426
|
success: (message) => getDefaultBaseLogger().success(message),
|
|
4940
5427
|
warning: (message) => getDefaultBaseLogger().warning(message),
|
|
@@ -4942,14 +5429,14 @@ var Logger = {
|
|
|
4942
5429
|
error: (message) => getDefaultBaseLogger().error(message),
|
|
4943
5430
|
debug: (message) => getDefaultBaseLogger().debug(message),
|
|
4944
5431
|
start: (message) => getDefaultBaseLogger().start(message),
|
|
4945
|
-
useTemplate: (
|
|
4946
|
-
if (
|
|
5432
|
+
useTemplate: (logger16) => {
|
|
5433
|
+
if (logger16) return createTemplateLogger(createBaseLogger("", logger16));
|
|
4947
5434
|
return createTemplateLogger();
|
|
4948
5435
|
}
|
|
4949
5436
|
};
|
|
4950
5437
|
|
|
4951
5438
|
// src/share.js
|
|
4952
|
-
var
|
|
5439
|
+
var import_delay3 = __toESM(require("delay"), 1);
|
|
4953
5440
|
|
|
4954
5441
|
// src/internals/watermarkify.js
|
|
4955
5442
|
var DEFAULT_TIMEZONE_OFFSET = 8;
|
|
@@ -5008,7 +5495,7 @@ var LOCATION_NETWORK_SUFFIX_PATTERNS = [
|
|
|
5008
5495
|
];
|
|
5009
5496
|
var cachedStripLogoSrcPromise = null;
|
|
5010
5497
|
var cachedEnrichmentByContext = /* @__PURE__ */ new WeakMap();
|
|
5011
|
-
var
|
|
5498
|
+
var logger13 = createInternalLogger("Watermarkify");
|
|
5012
5499
|
var normalizeText = (value) => String(value || "").trim();
|
|
5013
5500
|
var toInline = (value, maxLen = 200) => {
|
|
5014
5501
|
const text = normalizeText(value);
|
|
@@ -5250,9 +5737,9 @@ var resolveWithCustomResolver = async (page, baseMeta, options = {}) => {
|
|
|
5250
5737
|
location: toInline(resolved.location, 80)
|
|
5251
5738
|
};
|
|
5252
5739
|
if (enrichment.ip || enrichment.location) {
|
|
5253
|
-
|
|
5740
|
+
logger13.info(`\u81EA\u5B9A\u4E49 resolver \u547D\u4E2D: ip=${enrichment.ip || "-"}, loc=${enrichment.location || "-"}`);
|
|
5254
5741
|
} else {
|
|
5255
|
-
|
|
5742
|
+
logger13.warning("\u81EA\u5B9A\u4E49 resolver \u5DF2\u6267\u884C\uFF0C\u4F46\u672A\u8FD4\u56DE IP/Loc");
|
|
5256
5743
|
}
|
|
5257
5744
|
return enrichment;
|
|
5258
5745
|
} finally {
|
|
@@ -5436,12 +5923,12 @@ var buildWatermarkifyRenderHtml = ({ imageSrc, overlaySvg, width, height }) => {
|
|
|
5436
5923
|
};
|
|
5437
5924
|
var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageInfo = {}) => {
|
|
5438
5925
|
if (!page || typeof page.context !== "function") {
|
|
5439
|
-
|
|
5926
|
+
logger13.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u7F3A\u5C11\u53EF\u7528 page");
|
|
5440
5927
|
return buffer;
|
|
5441
5928
|
}
|
|
5442
5929
|
const renderScope = await openProbePage(page);
|
|
5443
5930
|
if (!renderScope?.page) {
|
|
5444
|
-
|
|
5931
|
+
logger13.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA render page");
|
|
5445
5932
|
return buffer;
|
|
5446
5933
|
}
|
|
5447
5934
|
try {
|
|
@@ -5484,13 +5971,13 @@ var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageI
|
|
|
5484
5971
|
fullPage: true,
|
|
5485
5972
|
animations: "disabled"
|
|
5486
5973
|
}).catch((error) => {
|
|
5487
|
-
|
|
5974
|
+
logger13.warning(`watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
5488
5975
|
return null;
|
|
5489
5976
|
});
|
|
5490
5977
|
if (Buffer.isBuffer(composed) && composed.length > 0) {
|
|
5491
5978
|
return composed;
|
|
5492
5979
|
}
|
|
5493
|
-
|
|
5980
|
+
logger13.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: \u672A\u5F97\u5230\u6709\u6548\u622A\u56FE\u7ED3\u679C");
|
|
5494
5981
|
return buffer;
|
|
5495
5982
|
} finally {
|
|
5496
5983
|
await renderScope.close().catch(() => {
|
|
@@ -5503,7 +5990,7 @@ var resolveWithIpLookup = async (page, options = {}) => {
|
|
|
5503
5990
|
}
|
|
5504
5991
|
const probeScope = await openProbePage(page);
|
|
5505
5992
|
if (!probeScope?.page) {
|
|
5506
|
-
|
|
5993
|
+
logger13.warning("ipLookup \u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA probe page");
|
|
5507
5994
|
return null;
|
|
5508
5995
|
}
|
|
5509
5996
|
const timeoutMs = Math.max(
|
|
@@ -5512,12 +5999,12 @@ var resolveWithIpLookup = async (page, options = {}) => {
|
|
|
5512
5999
|
);
|
|
5513
6000
|
try {
|
|
5514
6001
|
const probePage = probeScope.page;
|
|
5515
|
-
|
|
6002
|
+
logger13.info(`ipLookup \u5C1D\u8BD5: url=${DEFAULT_IP_LOOKUP_URL}, timeoutMs=${timeoutMs}`);
|
|
5516
6003
|
const response = await probePage.goto(DEFAULT_IP_LOOKUP_URL, {
|
|
5517
6004
|
waitUntil: "commit",
|
|
5518
6005
|
timeout: timeoutMs
|
|
5519
6006
|
}).catch((error) => {
|
|
5520
|
-
|
|
6007
|
+
logger13.warning(`ipLookup \u8BF7\u6C42\u5931\u8D25: url=${DEFAULT_IP_LOOKUP_URL}, error=${error instanceof Error ? error.message : String(error)}`);
|
|
5521
6008
|
return null;
|
|
5522
6009
|
});
|
|
5523
6010
|
const status = response && typeof response.status === "function" ? response.status() : 0;
|
|
@@ -5539,13 +6026,13 @@ var resolveWithIpLookup = async (page, options = {}) => {
|
|
|
5539
6026
|
}
|
|
5540
6027
|
const parsed = parseIpIpJsonResponse(rawText);
|
|
5541
6028
|
if (parsed?.ip || parsed?.location) {
|
|
5542
|
-
|
|
6029
|
+
logger13.info(`ipLookup \u6210\u529F: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, ip=${parsed.ip || "-"}, loc=${parsed.location || "-"}`);
|
|
5543
6030
|
return parsed;
|
|
5544
6031
|
}
|
|
5545
|
-
|
|
6032
|
+
logger13.warning(`ipLookup \u672A\u89E3\u6790\u51FA IP/Loc: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, preview=${shortenTail(rawText, 120) || "[empty]"}`);
|
|
5546
6033
|
return null;
|
|
5547
6034
|
} catch (error) {
|
|
5548
|
-
|
|
6035
|
+
logger13.warning(`ipLookup \u6267\u884C\u5F02\u5E38\uFF0C\u672A\u83B7\u5F97 IP/Loc: ${error instanceof Error ? error.message : String(error)}`);
|
|
5549
6036
|
return null;
|
|
5550
6037
|
} finally {
|
|
5551
6038
|
await probeScope.close().catch(() => {
|
|
@@ -5559,10 +6046,10 @@ var resolveEnrichment = async (page, baseMeta, options) => {
|
|
|
5559
6046
|
ip: toInline(options.ip, 80),
|
|
5560
6047
|
location: toInline(options.location, 80)
|
|
5561
6048
|
};
|
|
5562
|
-
|
|
6049
|
+
logger13.info(`enrichment \u5F00\u59CB: host=${baseMeta.hostname || "-"}, hasPresetIp=${Boolean(merged.ip)}, hasPresetLoc=${Boolean(merged.location)}, ipLookup=${options.ipLookup !== false}`);
|
|
5563
6050
|
if (!merged.ip || !merged.location) {
|
|
5564
6051
|
if (cached?.ip || cached?.location) {
|
|
5565
|
-
|
|
6052
|
+
logger13.info(`enrichment \u547D\u4E2D\u4E0A\u4E0B\u6587\u7F13\u5B58: ip=${cached.ip || "-"}, loc=${cached.location || "-"}`);
|
|
5566
6053
|
}
|
|
5567
6054
|
fillEnrichment(merged, cached);
|
|
5568
6055
|
}
|
|
@@ -5586,15 +6073,15 @@ var resolveEnrichment = async (page, baseMeta, options) => {
|
|
|
5586
6073
|
"x-geo-country"
|
|
5587
6074
|
]), 80);
|
|
5588
6075
|
if (!merged.location || isWeakLocationValue(merged.location) && headerLocation) {
|
|
5589
|
-
|
|
6076
|
+
logger13.info(`enrichment \u4F7F\u7528\u54CD\u5E94\u5934\u8865\u5145 Loc: ${headerLocation || "-"}`);
|
|
5590
6077
|
merged.location = headerLocation || merged.location;
|
|
5591
6078
|
}
|
|
5592
6079
|
}
|
|
5593
6080
|
writeCachedEnrichment(page, merged);
|
|
5594
6081
|
if (merged.ip || merged.location) {
|
|
5595
|
-
|
|
6082
|
+
logger13.info(`enrichment \u5B8C\u6210: ip=${merged.ip || "-"}, loc=${merged.location || "-"}`);
|
|
5596
6083
|
} else {
|
|
5597
|
-
|
|
6084
|
+
logger13.warning("enrichment \u5B8C\u6210: \u672A\u83B7\u5F97 IP/Loc");
|
|
5598
6085
|
}
|
|
5599
6086
|
return merged;
|
|
5600
6087
|
};
|
|
@@ -6262,7 +6749,7 @@ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
|
|
|
6262
6749
|
}
|
|
6263
6750
|
const imageInfo = readImageInfo(buffer);
|
|
6264
6751
|
if (!imageInfo.width || !imageInfo.height || !imageInfo.mimeType) {
|
|
6265
|
-
|
|
6752
|
+
logger13.warning("watermarkify \u8DF3\u8FC7: \u65E0\u6CD5\u89E3\u6790\u622A\u56FE\u5C3A\u5BF8\u6216\u683C\u5F0F");
|
|
6266
6753
|
return buffer;
|
|
6267
6754
|
}
|
|
6268
6755
|
const overlaySvg = buildWatermarkifySvg(meta, imageInfo.width, imageInfo.height);
|
|
@@ -6274,8 +6761,8 @@ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
|
|
|
6274
6761
|
|
|
6275
6762
|
// src/internals/screenshot-compression.js
|
|
6276
6763
|
var import_jimp = require("jimp");
|
|
6277
|
-
var
|
|
6278
|
-
var DEFAULT_SCREENSHOT_MAX_BYTES =
|
|
6764
|
+
var logger14 = createInternalLogger("ScreenshotCompression");
|
|
6765
|
+
var DEFAULT_SCREENSHOT_MAX_BYTES = 5 * 1024 * 1024;
|
|
6279
6766
|
var DEFAULT_SCREENSHOT_OUTPUT_TYPE = "jpeg";
|
|
6280
6767
|
var DEFAULT_SCREENSHOT_QUALITY = 0.72;
|
|
6281
6768
|
var DEFAULT_SCREENSHOT_MIN_QUALITY = 0.38;
|
|
@@ -6393,18 +6880,18 @@ var compressScreenshotBufferToBase64 = async (buffer, compression) => {
|
|
|
6393
6880
|
return buffer.toString("base64");
|
|
6394
6881
|
}
|
|
6395
6882
|
const result = await compressScreenshotBuffer(buffer, compression).catch((error) => {
|
|
6396
|
-
|
|
6883
|
+
logger14.warning(`captureScreen \u538B\u7F29\u5931\u8D25\uFF0C\u8FD4\u56DE\u539F\u56FE: ${error instanceof Error ? error.message : String(error)}`);
|
|
6397
6884
|
return null;
|
|
6398
6885
|
});
|
|
6399
6886
|
if (!result?.buffer) {
|
|
6400
6887
|
return buffer.toString("base64");
|
|
6401
6888
|
}
|
|
6402
6889
|
if (result.withinLimit) {
|
|
6403
|
-
|
|
6890
|
+
logger14.info(
|
|
6404
6891
|
`captureScreen \u5DF2\u538B\u7F29: ${originalBytes} -> ${result.bytes} bytes, format=${result.format}, quality=${result.quality}, scale=${result.scale}, size=${result.width}x${result.height}`
|
|
6405
6892
|
);
|
|
6406
6893
|
} else {
|
|
6407
|
-
|
|
6894
|
+
logger14.warning(
|
|
6408
6895
|
`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}`
|
|
6409
6896
|
);
|
|
6410
6897
|
}
|
|
@@ -6412,7 +6899,7 @@ var compressScreenshotBufferToBase64 = async (buffer, compression) => {
|
|
|
6412
6899
|
};
|
|
6413
6900
|
|
|
6414
6901
|
// src/share.js
|
|
6415
|
-
var
|
|
6902
|
+
var logger15 = createInternalLogger("Share");
|
|
6416
6903
|
var DEFAULT_TIMEOUT_MS2 = 50 * 1e3;
|
|
6417
6904
|
var DEFAULT_PAYLOAD_SNAPSHOT_MAX_LEN = 500;
|
|
6418
6905
|
var DEFAULT_POLL_INTERVAL_MS = 120;
|
|
@@ -6549,7 +7036,7 @@ var createDomShareMonitor = async (page, options = {}) => {
|
|
|
6549
7036
|
const onMatch = typeof options.onMatch === "function" ? options.onMatch : null;
|
|
6550
7037
|
const onTelemetry = typeof options.onTelemetry === "function" ? options.onTelemetry : null;
|
|
6551
7038
|
let matched = false;
|
|
6552
|
-
|
|
7039
|
+
logger15.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode}`);
|
|
6553
7040
|
const monitor = await Mutation.useMonitor(page, selectors, {
|
|
6554
7041
|
mode,
|
|
6555
7042
|
onMutation: (context = {}) => {
|
|
@@ -6567,12 +7054,12 @@ ${text}`;
|
|
|
6567
7054
|
});
|
|
6568
7055
|
}
|
|
6569
7056
|
if (mutationCount <= 5 || mutationCount % 50 === 0) {
|
|
6570
|
-
|
|
7057
|
+
logger15.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);
|
|
6571
7058
|
}
|
|
6572
7059
|
const [candidate] = Utils.parseLinks(rawDom, { prefix }) || [];
|
|
6573
7060
|
if (!candidate) return;
|
|
6574
7061
|
matched = true;
|
|
6575
|
-
|
|
7062
|
+
logger15.success("captureLink.domHit", `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);
|
|
6576
7063
|
if (onMatch) {
|
|
6577
7064
|
onMatch({
|
|
6578
7065
|
link: candidate,
|
|
@@ -6588,7 +7075,7 @@ ${text}`;
|
|
|
6588
7075
|
return {
|
|
6589
7076
|
stop: async () => {
|
|
6590
7077
|
const result = await monitor.stop();
|
|
6591
|
-
|
|
7078
|
+
logger15.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);
|
|
6592
7079
|
return result;
|
|
6593
7080
|
}
|
|
6594
7081
|
};
|
|
@@ -6628,8 +7115,8 @@ var Share = {
|
|
|
6628
7115
|
if (share.mode === "response" && apiMatchers.length === 0) {
|
|
6629
7116
|
throw new Error("Share.captureLink requires share.xurl[0] api matcher when mode=response");
|
|
6630
7117
|
}
|
|
6631
|
-
|
|
6632
|
-
|
|
7118
|
+
logger15.start("captureLink", `mode=${share.mode}, timeoutMs=${timeoutMs}, prefix=${share.prefix}`);
|
|
7119
|
+
logger15.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);
|
|
6633
7120
|
const stats = {
|
|
6634
7121
|
actionTimedOut: false,
|
|
6635
7122
|
domMutationCount: 0,
|
|
@@ -6654,7 +7141,7 @@ var Share = {
|
|
|
6654
7141
|
link: validated,
|
|
6655
7142
|
payloadText: String(payloadText || "")
|
|
6656
7143
|
};
|
|
6657
|
-
|
|
7144
|
+
logger15.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);
|
|
6658
7145
|
return true;
|
|
6659
7146
|
};
|
|
6660
7147
|
const resolveResponseCandidate = (responseText) => {
|
|
@@ -6689,7 +7176,7 @@ var Share = {
|
|
|
6689
7176
|
try {
|
|
6690
7177
|
await monitor.stop();
|
|
6691
7178
|
} catch (error) {
|
|
6692
|
-
|
|
7179
|
+
logger15.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
6693
7180
|
}
|
|
6694
7181
|
};
|
|
6695
7182
|
const onResponse = async (response) => {
|
|
@@ -6702,29 +7189,29 @@ var Share = {
|
|
|
6702
7189
|
stats.responseSampleUrls.push(url);
|
|
6703
7190
|
}
|
|
6704
7191
|
if (stats.responseObserved <= 5) {
|
|
6705
|
-
|
|
7192
|
+
logger15.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);
|
|
6706
7193
|
}
|
|
6707
7194
|
if (!apiMatchers.some((matcher) => url.includes(matcher))) return;
|
|
6708
7195
|
stats.responseMatched += 1;
|
|
6709
7196
|
stats.lastMatchedUrl = url;
|
|
6710
|
-
|
|
7197
|
+
logger15.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);
|
|
6711
7198
|
const text = await response.text();
|
|
6712
7199
|
const hit = resolveResponseCandidate(text);
|
|
6713
7200
|
if (!hit?.link) {
|
|
6714
7201
|
if (stats.responseMatched <= 3) {
|
|
6715
|
-
|
|
7202
|
+
logger15.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);
|
|
6716
7203
|
}
|
|
6717
7204
|
return;
|
|
6718
7205
|
}
|
|
6719
7206
|
stats.responseResolved += 1;
|
|
6720
|
-
|
|
7207
|
+
logger15.success("captureLink.responseHit", `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);
|
|
6721
7208
|
setCandidate("response", hit.link, hit.payloadText);
|
|
6722
7209
|
} catch (error) {
|
|
6723
|
-
|
|
7210
|
+
logger15.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);
|
|
6724
7211
|
}
|
|
6725
7212
|
};
|
|
6726
7213
|
if (share.mode === "dom") {
|
|
6727
|
-
|
|
7214
|
+
logger15.info("\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C");
|
|
6728
7215
|
domMonitor = await createDomShareMonitor(page, {
|
|
6729
7216
|
prefix: share.prefix,
|
|
6730
7217
|
selectors: domSelectors,
|
|
@@ -6739,14 +7226,14 @@ var Share = {
|
|
|
6739
7226
|
});
|
|
6740
7227
|
}
|
|
6741
7228
|
if (share.mode === "response") {
|
|
6742
|
-
|
|
7229
|
+
logger15.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);
|
|
6743
7230
|
page.on("response", onResponse);
|
|
6744
7231
|
}
|
|
6745
7232
|
const deadline = Date.now() + timeoutMs;
|
|
6746
7233
|
const getRemainingMs = () => Math.max(0, deadline - Date.now());
|
|
6747
7234
|
try {
|
|
6748
7235
|
const actionTimeout = getRemainingMs();
|
|
6749
|
-
|
|
7236
|
+
logger15.start("captureLink.performActions", `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${actionTimeout}ms`);
|
|
6750
7237
|
if (actionTimeout > 0) {
|
|
6751
7238
|
let timer = null;
|
|
6752
7239
|
let actionError = null;
|
|
@@ -6760,21 +7247,21 @@ var Share = {
|
|
|
6760
7247
|
const actionResult = await Promise.race([actionPromise, timeoutPromise]);
|
|
6761
7248
|
if (timer) clearTimeout(timer);
|
|
6762
7249
|
if (actionResult === "__ACTION_ERROR__") {
|
|
6763
|
-
|
|
7250
|
+
logger15.fail("captureLink.performActions", actionError);
|
|
6764
7251
|
throw actionError;
|
|
6765
7252
|
}
|
|
6766
7253
|
if (actionResult === "__ACTION_TIMEOUT__") {
|
|
6767
7254
|
stats.actionTimedOut = true;
|
|
6768
|
-
|
|
7255
|
+
logger15.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);
|
|
6769
7256
|
} else {
|
|
6770
|
-
|
|
7257
|
+
logger15.success("captureLink.performActions", "\u6267\u884C\u52A8\u4F5C\u5B8C\u6210");
|
|
6771
7258
|
}
|
|
6772
7259
|
}
|
|
6773
7260
|
let nextProgressLogTs = Date.now() + 3e3;
|
|
6774
7261
|
while (true) {
|
|
6775
7262
|
const selected = share.mode === "dom" ? candidates.dom : candidates.response;
|
|
6776
7263
|
if (selected?.link) {
|
|
6777
|
-
|
|
7264
|
+
logger15.success("captureLink", `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);
|
|
6778
7265
|
return {
|
|
6779
7266
|
link: selected.link,
|
|
6780
7267
|
payloadText: selected.payloadText,
|
|
@@ -6786,19 +7273,19 @@ var Share = {
|
|
|
6786
7273
|
if (remaining <= 0) break;
|
|
6787
7274
|
const now = Date.now();
|
|
6788
7275
|
if (now >= nextProgressLogTs) {
|
|
6789
|
-
|
|
7276
|
+
logger15.info(
|
|
6790
7277
|
`captureLink \u7B49\u5F85\u4E2D: remaining=${remaining}ms, domMutationCount=${stats.domMutationCount}, responseMatched=${stats.responseMatched}`
|
|
6791
7278
|
);
|
|
6792
7279
|
nextProgressLogTs = now + 5e3;
|
|
6793
7280
|
}
|
|
6794
|
-
await (0,
|
|
7281
|
+
await (0, import_delay3.default)(Math.max(0, Math.min(DEFAULT_POLL_INTERVAL_MS, remaining)));
|
|
6795
7282
|
}
|
|
6796
7283
|
if (share.mode === "response" && stats.responseMatched === 0) {
|
|
6797
|
-
|
|
7284
|
+
logger15.warning(
|
|
6798
7285
|
`\u63A5\u53E3\u76D1\u542C\u672A\u547D\u4E2D: apiMatchers=${toJsonInline(apiMatchers, 220)}, \u54CD\u5E94\u6837\u672CURLs=${toJsonInline(stats.responseSampleUrls, 420)}`
|
|
6799
7286
|
);
|
|
6800
7287
|
}
|
|
6801
|
-
|
|
7288
|
+
logger15.warning(
|
|
6802
7289
|
`captureLink \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"}`
|
|
6803
7290
|
);
|
|
6804
7291
|
return {
|
|
@@ -6810,7 +7297,7 @@ var Share = {
|
|
|
6810
7297
|
} finally {
|
|
6811
7298
|
if (share.mode === "response") {
|
|
6812
7299
|
page.off("response", onResponse);
|
|
6813
|
-
|
|
7300
|
+
logger15.info("response \u76D1\u542C\u5DF2\u5378\u8F7D");
|
|
6814
7301
|
}
|
|
6815
7302
|
await stopDomMonitor();
|
|
6816
7303
|
}
|
|
@@ -6823,7 +7310,7 @@ var Share = {
|
|
|
6823
7310
|
* @param {number} [options.buffer]
|
|
6824
7311
|
* @param {boolean} [options.restore]
|
|
6825
7312
|
* @param {number} [options.maxHeight]
|
|
6826
|
-
* @param {number} [options.maxBytes] 默认
|
|
7313
|
+
* @param {number} [options.maxBytes] 默认 5MiB,返回 base64 超过后会压缩
|
|
6827
7314
|
* @param {'jpeg'|'jpg'} [options.type] 压缩输出格式,默认 jpeg
|
|
6828
7315
|
* @param {boolean|Object} [options.compression] 传 false 可关闭压缩
|
|
6829
7316
|
* @returns {Promise<string>} base64 image
|
|
@@ -6862,7 +7349,7 @@ var Share = {
|
|
|
6862
7349
|
width: originalViewport.width,
|
|
6863
7350
|
height: targetHeight
|
|
6864
7351
|
});
|
|
6865
|
-
await (0,
|
|
7352
|
+
await (0, import_delay3.default)(1e3);
|
|
6866
7353
|
const capturedAt = /* @__PURE__ */ new Date();
|
|
6867
7354
|
const rawBuffer = await capturePageScreenshot(page, {
|
|
6868
7355
|
fullPage: true,
|
|
@@ -6903,7 +7390,7 @@ var usePlaywrightToolKit = () => {
|
|
|
6903
7390
|
return {
|
|
6904
7391
|
ApifyKit,
|
|
6905
7392
|
AntiCheat,
|
|
6906
|
-
Humanize,
|
|
7393
|
+
Humanize: Humanize2,
|
|
6907
7394
|
Launch,
|
|
6908
7395
|
LiveView,
|
|
6909
7396
|
Constants: constants_exports,
|