@skrillex1224/playwright-toolkit 2.1.224 → 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 +10 -6
- package/dist/browser.js +43 -3
- package/dist/browser.js.map +2 -2
- package/dist/index.cjs +628 -141
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +628 -141
- package/dist/index.js.map +4 -4
- package/index.d.ts +25 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12,8 +12,10 @@ var constants_exports = {};
|
|
|
12
12
|
__export(constants_exports, {
|
|
13
13
|
ActorInfo: () => ActorInfo,
|
|
14
14
|
Code: () => Code,
|
|
15
|
+
Device: () => Device,
|
|
15
16
|
PresetOfLiveViewKey: () => PresetOfLiveViewKey,
|
|
16
|
-
Status: () => Status
|
|
17
|
+
Status: () => Status,
|
|
18
|
+
normalizeDevice: () => normalizeDevice
|
|
17
19
|
});
|
|
18
20
|
var Code = {
|
|
19
21
|
Success: 0,
|
|
@@ -29,6 +31,17 @@ var Status = {
|
|
|
29
31
|
Failed: "FAILED"
|
|
30
32
|
};
|
|
31
33
|
var PresetOfLiveViewKey = "LIVE_VIEW_SCREENSHOT";
|
|
34
|
+
var Device = Object.freeze({
|
|
35
|
+
Desktop: "desktop",
|
|
36
|
+
Mobile: "mobile"
|
|
37
|
+
});
|
|
38
|
+
var normalizeDevice = (value, fallback = Device.Desktop) => {
|
|
39
|
+
const normalizedFallback = String(fallback || "").trim().toLowerCase() === Device.Mobile ? Device.Mobile : Device.Desktop;
|
|
40
|
+
const raw = String(value || "").trim().toLowerCase();
|
|
41
|
+
if (raw === Device.Mobile) return Device.Mobile;
|
|
42
|
+
if (raw === Device.Desktop) return Device.Desktop;
|
|
43
|
+
return normalizedFallback;
|
|
44
|
+
};
|
|
32
45
|
var createActorInfo = (info) => {
|
|
33
46
|
const normalizeDomain = (value) => {
|
|
34
47
|
if (!value) return "";
|
|
@@ -106,12 +119,14 @@ var createActorInfo = (info) => {
|
|
|
106
119
|
const domain = normalizeDomain(info.domain);
|
|
107
120
|
const path2 = normalizePath(info.path);
|
|
108
121
|
const share = normalizeShare2(info.share);
|
|
122
|
+
const device = normalizeDevice(info.device);
|
|
109
123
|
return {
|
|
110
124
|
...info,
|
|
111
125
|
protocol,
|
|
112
126
|
domain,
|
|
113
127
|
path: path2,
|
|
114
128
|
share,
|
|
129
|
+
device,
|
|
115
130
|
get icon() {
|
|
116
131
|
if (info.icon) return info.icon;
|
|
117
132
|
return buildIcon(this);
|
|
@@ -163,6 +178,7 @@ var ActorInfo = {
|
|
|
163
178
|
name: "\u8C46\u5305",
|
|
164
179
|
domain: "www.doubao.com",
|
|
165
180
|
path: "/",
|
|
181
|
+
device: Device.Mobile,
|
|
166
182
|
share: {
|
|
167
183
|
mode: "response",
|
|
168
184
|
prefix: "https://www.doubao.com/thread/",
|
|
@@ -178,6 +194,7 @@ var ActorInfo = {
|
|
|
178
194
|
name: "DeepSeek",
|
|
179
195
|
domain: "chat.deepseek.com",
|
|
180
196
|
path: "/",
|
|
197
|
+
device: Device.Mobile,
|
|
181
198
|
share: {
|
|
182
199
|
mode: "response",
|
|
183
200
|
prefix: "https://chat.deepseek.com/share/",
|
|
@@ -334,18 +351,18 @@ var fallbackLog = {
|
|
|
334
351
|
error: (...args) => console.error(...args),
|
|
335
352
|
debug: (...args) => console.debug ? console.debug(...args) : console.log(...args)
|
|
336
353
|
};
|
|
337
|
-
var resolveLogMethod = (
|
|
338
|
-
if (
|
|
339
|
-
return
|
|
354
|
+
var resolveLogMethod = (logger16, name) => {
|
|
355
|
+
if (logger16 && typeof logger16[name] === "function") {
|
|
356
|
+
return logger16[name].bind(logger16);
|
|
340
357
|
}
|
|
341
|
-
if (name === "warning" &&
|
|
342
|
-
return
|
|
358
|
+
if (name === "warning" && logger16 && typeof logger16.warn === "function") {
|
|
359
|
+
return logger16.warn.bind(logger16);
|
|
343
360
|
}
|
|
344
361
|
return fallbackLog[name];
|
|
345
362
|
};
|
|
346
363
|
var defaultLogger = null;
|
|
347
|
-
var setDefaultLogger = (
|
|
348
|
-
defaultLogger =
|
|
364
|
+
var setDefaultLogger = (logger16) => {
|
|
365
|
+
defaultLogger = logger16;
|
|
349
366
|
};
|
|
350
367
|
var resolveLogger = (explicitLogger) => {
|
|
351
368
|
if (explicitLogger && typeof explicitLogger.info === "function") {
|
|
@@ -372,8 +389,8 @@ var colorize = (text, color) => {
|
|
|
372
389
|
var createBaseLogger = (prefix = "", explicitLogger) => {
|
|
373
390
|
const name = prefix ? String(prefix) : "";
|
|
374
391
|
const dispatch = (methodName, icon, message, color) => {
|
|
375
|
-
const
|
|
376
|
-
const logFn = resolveLogMethod(
|
|
392
|
+
const logger16 = resolveLogger(explicitLogger);
|
|
393
|
+
const logFn = resolveLogMethod(logger16, methodName);
|
|
377
394
|
const timestamp = colorize(`[${formatTimestamp()}]`, ANSI.gray);
|
|
378
395
|
const line = formatLine(name, icon, message);
|
|
379
396
|
const coloredLine = colorize(line, color);
|
|
@@ -972,6 +989,12 @@ var PageRuntimeStateKey = "__playwright_toolkit_runtime_state__";
|
|
|
972
989
|
var BROWSER_PROFILE_SCHEMA_VERSION = 1;
|
|
973
990
|
var rememberedRuntimeState = null;
|
|
974
991
|
var isPlainObject = (value) => value && typeof value === "object" && !Array.isArray(value);
|
|
992
|
+
var normalizeKnownDevice = (value) => {
|
|
993
|
+
const raw = String(value || "").trim().toLowerCase();
|
|
994
|
+
if (raw === Device.Mobile) return Device.Mobile;
|
|
995
|
+
if (raw === Device.Desktop) return Device.Desktop;
|
|
996
|
+
return "";
|
|
997
|
+
};
|
|
975
998
|
var deepClone = (value) => {
|
|
976
999
|
if (value == null) return value;
|
|
977
1000
|
try {
|
|
@@ -1323,6 +1346,10 @@ var normalizeObservedBrowserProfile = (value) => {
|
|
|
1323
1346
|
var normalizeBrowserProfileCore = (value) => {
|
|
1324
1347
|
const source = isPlainObject(value) ? value : {};
|
|
1325
1348
|
const profile = {};
|
|
1349
|
+
const device = normalizeKnownDevice(source.device);
|
|
1350
|
+
if (device) {
|
|
1351
|
+
profile.device = device;
|
|
1352
|
+
}
|
|
1326
1353
|
if (isPlainObject(source.fingerprint) && Object.keys(source.fingerprint).length > 0) {
|
|
1327
1354
|
profile.fingerprint = deepClone(source.fingerprint);
|
|
1328
1355
|
}
|
|
@@ -1380,9 +1407,11 @@ var mergeBrowserProfilePayload = (target = {}, source = {}) => {
|
|
|
1380
1407
|
if (Object.keys(mergedCore).length === 0 && Object.keys(incomingCore).length > 0) {
|
|
1381
1408
|
mergedCore = incomingCore;
|
|
1382
1409
|
} else if (Object.keys(incomingCore).length > 0) {
|
|
1410
|
+
const currentDevice = normalizeKnownDevice(currentCore.device);
|
|
1411
|
+
const incomingDevice = normalizeKnownDevice(incomingCore.device);
|
|
1383
1412
|
const currentVersion = Number(currentCore.browser_major_version || 0);
|
|
1384
1413
|
const incomingVersion = Number(incomingCore.browser_major_version || 0);
|
|
1385
|
-
if (currentVersion > 0 && incomingVersion > 0 && currentVersion !== incomingVersion) {
|
|
1414
|
+
if (incomingDevice && currentDevice !== incomingDevice || currentVersion > 0 && incomingVersion > 0 && currentVersion !== incomingVersion) {
|
|
1386
1415
|
mergedCore = incomingCore;
|
|
1387
1416
|
}
|
|
1388
1417
|
}
|
|
@@ -1433,8 +1462,13 @@ var normalizeRuntimeState = (source = {}, actor = "") => {
|
|
|
1433
1462
|
}
|
|
1434
1463
|
return RuntimeEnv.parseInput(source, actor);
|
|
1435
1464
|
};
|
|
1465
|
+
var resolveInputDevice = (input = {}, runtime2 = {}, actor = "") => {
|
|
1466
|
+
const actorDevice = ActorInfo?.[actor]?.device;
|
|
1467
|
+
return normalizeDevice(actorDevice ?? input?.device ?? runtime2?.device);
|
|
1468
|
+
};
|
|
1436
1469
|
var RuntimeEnv = {
|
|
1437
1470
|
tryParseJSON,
|
|
1471
|
+
normalizeDevice,
|
|
1438
1472
|
normalizeCookies,
|
|
1439
1473
|
normalizeLocalStorage,
|
|
1440
1474
|
normalizeSessionStorage,
|
|
@@ -1460,6 +1494,7 @@ var RuntimeEnv = {
|
|
|
1460
1494
|
parseInput(input = {}, actor = "") {
|
|
1461
1495
|
const runtime2 = tryParseJSON(input?.runtime) || {};
|
|
1462
1496
|
const resolvedActor = String(actor || input?.actor || "").trim();
|
|
1497
|
+
const device = resolveInputDevice(input, runtime2, resolvedActor);
|
|
1463
1498
|
const query = String(input?.query || "").trim();
|
|
1464
1499
|
const cookies = normalizeCookies(runtime2?.cookies);
|
|
1465
1500
|
const cookieMap = buildCookieMap(cookies);
|
|
@@ -1479,6 +1514,7 @@ var RuntimeEnv = {
|
|
|
1479
1514
|
}
|
|
1480
1515
|
const state = {
|
|
1481
1516
|
actor: resolvedActor,
|
|
1517
|
+
device,
|
|
1482
1518
|
runtime: normalizedRuntime,
|
|
1483
1519
|
envId,
|
|
1484
1520
|
query,
|
|
@@ -1524,7 +1560,10 @@ var RuntimeEnv = {
|
|
|
1524
1560
|
},
|
|
1525
1561
|
setBrowserProfileCore(source = {}, core = {}, actor = "") {
|
|
1526
1562
|
const state = normalizeRuntimeState(source, actor);
|
|
1527
|
-
const normalizedCore = normalizeBrowserProfileCore(
|
|
1563
|
+
const normalizedCore = normalizeBrowserProfileCore({
|
|
1564
|
+
...core,
|
|
1565
|
+
device: normalizeKnownDevice(core?.device) || state.device
|
|
1566
|
+
});
|
|
1528
1567
|
state.browserProfileCore = normalizedCore;
|
|
1529
1568
|
state.browserProfile = buildBrowserProfilePayload(normalizedCore, state.browserProfileObserved);
|
|
1530
1569
|
if (Object.keys(state.browserProfile).length > 0) {
|
|
@@ -1999,15 +2038,25 @@ var DEFAULT_LAUNCH_ARGS = [
|
|
|
1999
2038
|
"--disable-setuid-sandbox",
|
|
2000
2039
|
"--window-position=0,0"
|
|
2001
2040
|
];
|
|
2002
|
-
function buildFingerprintOptions({ locale = BASE_CONFIG.locale, browserMajorVersion = 0 } = {}) {
|
|
2041
|
+
function buildFingerprintOptions({ locale = BASE_CONFIG.locale, browserMajorVersion = 0, device = Device.Desktop } = {}) {
|
|
2042
|
+
const resolvedDevice = normalizeDevice(device);
|
|
2003
2043
|
const normalizedBrowserMajorVersion = Number(browserMajorVersion || 0);
|
|
2004
2044
|
const browserDescriptor = normalizedBrowserMajorVersion > 0 ? [{ name: "chrome", minVersion: normalizedBrowserMajorVersion, maxVersion: normalizedBrowserMajorVersion }] : [{ name: "chrome", minVersion: 110 }];
|
|
2005
|
-
|
|
2045
|
+
const options = {
|
|
2006
2046
|
browsers: browserDescriptor,
|
|
2007
|
-
devices: [
|
|
2008
|
-
operatingSystems: ["windows", "macos", "linux"],
|
|
2047
|
+
devices: [resolvedDevice],
|
|
2048
|
+
operatingSystems: resolvedDevice === Device.Mobile ? ["android"] : ["windows", "macos", "linux"],
|
|
2009
2049
|
locales: [locale]
|
|
2010
2050
|
};
|
|
2051
|
+
if (resolvedDevice === Device.Mobile) {
|
|
2052
|
+
options.screen = {
|
|
2053
|
+
minWidth: 320,
|
|
2054
|
+
maxWidth: 480,
|
|
2055
|
+
minHeight: 640,
|
|
2056
|
+
maxHeight: 1100
|
|
2057
|
+
};
|
|
2058
|
+
}
|
|
2059
|
+
return options;
|
|
2011
2060
|
}
|
|
2012
2061
|
var AntiCheat = {
|
|
2013
2062
|
/**
|
|
@@ -2017,7 +2066,7 @@ var AntiCheat = {
|
|
|
2017
2066
|
return { ...BASE_CONFIG };
|
|
2018
2067
|
},
|
|
2019
2068
|
/**
|
|
2020
|
-
* 用于 Crawlee fingerprint generator
|
|
2069
|
+
* 用于 Crawlee fingerprint generator 的统一配置。
|
|
2021
2070
|
*/
|
|
2022
2071
|
getFingerprintGeneratorOptions(options = {}) {
|
|
2023
2072
|
return buildFingerprintOptions(options);
|
|
@@ -2030,10 +2079,10 @@ var AntiCheat = {
|
|
|
2030
2079
|
return [...DEFAULT_LAUNCH_ARGS, `--lang=${locale}`];
|
|
2031
2080
|
},
|
|
2032
2081
|
/**
|
|
2033
|
-
* 为 got-scraping 生成与浏览器一致的 TLS
|
|
2082
|
+
* 为 got-scraping 生成与浏览器一致的 TLS 指纹配置。
|
|
2034
2083
|
*/
|
|
2035
|
-
getTlsFingerprintOptions(userAgent = "", acceptLanguage = "") {
|
|
2036
|
-
return buildFingerprintOptions();
|
|
2084
|
+
getTlsFingerprintOptions(userAgent = "", acceptLanguage = "", options = {}) {
|
|
2085
|
+
return buildFingerprintOptions(options);
|
|
2037
2086
|
},
|
|
2038
2087
|
/**
|
|
2039
2088
|
* 规范化请求头
|
|
@@ -2046,7 +2095,7 @@ var AntiCheat = {
|
|
|
2046
2095
|
}
|
|
2047
2096
|
};
|
|
2048
2097
|
|
|
2049
|
-
// src/humanize.js
|
|
2098
|
+
// src/internals/humanize/desktop.js
|
|
2050
2099
|
import delay from "delay";
|
|
2051
2100
|
import { createCursor } from "ghost-cursor-playwright";
|
|
2052
2101
|
var logger6 = createInternalLogger("Humanize");
|
|
@@ -2351,7 +2400,9 @@ var Humanize = {
|
|
|
2351
2400
|
const y = box.y + box.height / 2 + (Math.random() - 0.5) * box.height * 0.3;
|
|
2352
2401
|
await cursor.actions.move({ x, y });
|
|
2353
2402
|
await delay(this.jitterMs(reactionDelay, 0.4));
|
|
2354
|
-
await
|
|
2403
|
+
await page.mouse.click(x, y, {
|
|
2404
|
+
delay: this.jitterMs(45, 0.45)
|
|
2405
|
+
});
|
|
2355
2406
|
await restoreOnce();
|
|
2356
2407
|
logger6.success("humanClick");
|
|
2357
2408
|
return true;
|
|
@@ -2524,6 +2575,379 @@ var Humanize = {
|
|
|
2524
2575
|
}
|
|
2525
2576
|
};
|
|
2526
2577
|
|
|
2578
|
+
// src/internals/humanize/shared.js
|
|
2579
|
+
import delay2 from "delay";
|
|
2580
|
+
var jitterMs = (base, jitterPercent = 0.3) => {
|
|
2581
|
+
const jitter = Number(base || 0) * Number(jitterPercent || 0) * (Math.random() * 2 - 1);
|
|
2582
|
+
return Math.max(10, Math.round(Number(base || 0) + jitter));
|
|
2583
|
+
};
|
|
2584
|
+
var randomPointInBox = (box, paddingRatio = 0.24) => {
|
|
2585
|
+
const safePaddingX = Math.max(2, Math.min(box.width * paddingRatio, box.width / 2));
|
|
2586
|
+
const safePaddingY = Math.max(2, Math.min(box.height * paddingRatio, box.height / 2));
|
|
2587
|
+
const x = box.x + safePaddingX + Math.random() * Math.max(1, box.width - safePaddingX * 2);
|
|
2588
|
+
const y = box.y + safePaddingY + Math.random() * Math.max(1, box.height - safePaddingY * 2);
|
|
2589
|
+
return { x, y };
|
|
2590
|
+
};
|
|
2591
|
+
var resolveElement = async (page, target, { throwOnMissing = true } = {}) => {
|
|
2592
|
+
if (target == null) return null;
|
|
2593
|
+
let element = target;
|
|
2594
|
+
if (typeof target === "string") {
|
|
2595
|
+
element = await page.$(target);
|
|
2596
|
+
}
|
|
2597
|
+
if (!element) {
|
|
2598
|
+
if (throwOnMissing) {
|
|
2599
|
+
throw new Error(`\u627E\u4E0D\u5230\u5143\u7D20 ${String(target)}`);
|
|
2600
|
+
}
|
|
2601
|
+
return null;
|
|
2602
|
+
}
|
|
2603
|
+
return element;
|
|
2604
|
+
};
|
|
2605
|
+
var waitJitter = (base, jitterPercent = 0.3) => delay2(jitterMs(base, jitterPercent));
|
|
2606
|
+
|
|
2607
|
+
// src/internals/humanize/mobile.js
|
|
2608
|
+
var logger7 = createInternalLogger("Humanize.Mobile");
|
|
2609
|
+
var initializedPages = /* @__PURE__ */ new WeakSet();
|
|
2610
|
+
var clamp = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
2611
|
+
var resolveViewport = (page) => page?.viewportSize?.() || { width: 390, height: 844 };
|
|
2612
|
+
var checkElementVisibility = async (element) => {
|
|
2613
|
+
return element.evaluate((el) => {
|
|
2614
|
+
const rect = el.getBoundingClientRect();
|
|
2615
|
+
if (!rect || rect.width <= 0 || rect.height <= 0) {
|
|
2616
|
+
return { code: "ZERO_DIMENSIONS", direction: "down" };
|
|
2617
|
+
}
|
|
2618
|
+
const viewW = window.innerWidth;
|
|
2619
|
+
const viewH = window.innerHeight;
|
|
2620
|
+
const cx = rect.left + rect.width / 2;
|
|
2621
|
+
const cy = rect.top + rect.height / 2;
|
|
2622
|
+
let isFixed = false;
|
|
2623
|
+
for (let node = el; node && node !== document.body; node = node.parentElement) {
|
|
2624
|
+
const style = window.getComputedStyle(node);
|
|
2625
|
+
if (style && (style.position === "fixed" || style.position === "sticky")) {
|
|
2626
|
+
isFixed = true;
|
|
2627
|
+
break;
|
|
2628
|
+
}
|
|
2629
|
+
}
|
|
2630
|
+
if ((isFixed ? cy < 0 || cy > viewH : cy < 12 || cy > viewH - 12) || cx < 0 || cx > viewW) {
|
|
2631
|
+
return {
|
|
2632
|
+
code: "OUT_OF_VIEWPORT",
|
|
2633
|
+
direction: cy < viewH / 2 ? "up" : "down",
|
|
2634
|
+
cy,
|
|
2635
|
+
viewH,
|
|
2636
|
+
isFixed
|
|
2637
|
+
};
|
|
2638
|
+
}
|
|
2639
|
+
const pointElement = document.elementFromPoint(cx, cy);
|
|
2640
|
+
if (pointElement && !el.contains(pointElement) && !pointElement.contains(el)) {
|
|
2641
|
+
return {
|
|
2642
|
+
code: "OBSTRUCTED",
|
|
2643
|
+
direction: cy > viewH / 2 ? "down" : "up",
|
|
2644
|
+
cy,
|
|
2645
|
+
viewH,
|
|
2646
|
+
isFixed
|
|
2647
|
+
};
|
|
2648
|
+
}
|
|
2649
|
+
return { code: "VISIBLE", isFixed };
|
|
2650
|
+
});
|
|
2651
|
+
};
|
|
2652
|
+
var dispatchTouchSwipe = async (page, deltaY, options = {}) => {
|
|
2653
|
+
const viewport = resolveViewport(page);
|
|
2654
|
+
const distance = clamp(Math.abs(deltaY), 80, Math.max(120, viewport.height * 0.72));
|
|
2655
|
+
const direction = deltaY >= 0 ? 1 : -1;
|
|
2656
|
+
const startX = clamp(
|
|
2657
|
+
viewport.width * (0.45 + Math.random() * 0.1),
|
|
2658
|
+
24,
|
|
2659
|
+
viewport.width - 24
|
|
2660
|
+
);
|
|
2661
|
+
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);
|
|
2662
|
+
const endY = clamp(startY - direction * distance, 24, viewport.height - 24);
|
|
2663
|
+
const steps = Math.max(4, Math.round(Number(options.steps || 6)));
|
|
2664
|
+
const durationMs = jitterMs(options.durationMs || 320, 0.35);
|
|
2665
|
+
let client = null;
|
|
2666
|
+
const scrollBefore = await page.evaluate(() => ({ x: window.scrollX, y: window.scrollY })).catch(() => null);
|
|
2667
|
+
try {
|
|
2668
|
+
if (page.context && typeof page.context().newCDPSession === "function") {
|
|
2669
|
+
client = await page.context().newCDPSession(page);
|
|
2670
|
+
}
|
|
2671
|
+
if (!client) throw new Error("CDP session unavailable");
|
|
2672
|
+
await client.send("Input.synthesizeScrollGesture", {
|
|
2673
|
+
x: startX,
|
|
2674
|
+
y: startY,
|
|
2675
|
+
yDistance: -direction * distance,
|
|
2676
|
+
xOverscroll: (Math.random() - 0.5) * 4,
|
|
2677
|
+
yOverscroll: (Math.random() - 0.5) * 8,
|
|
2678
|
+
speed: 700 + Math.round(Math.random() * 350),
|
|
2679
|
+
gestureSourceType: "touch"
|
|
2680
|
+
});
|
|
2681
|
+
await waitJitter(160, 0.35);
|
|
2682
|
+
const scrollAfterSynth = await page.evaluate(() => ({ x: window.scrollX, y: window.scrollY })).catch(() => null);
|
|
2683
|
+
if (scrollBefore && scrollAfterSynth && (Math.abs(scrollAfterSynth.y - scrollBefore.y) > 2 || Math.abs(scrollAfterSynth.x - scrollBefore.x) > 2)) {
|
|
2684
|
+
return true;
|
|
2685
|
+
}
|
|
2686
|
+
await client.send("Input.dispatchTouchEvent", {
|
|
2687
|
+
type: "touchStart",
|
|
2688
|
+
touchPoints: [{ x: startX, y: startY, id: 1 }]
|
|
2689
|
+
});
|
|
2690
|
+
for (let i = 1; i <= steps; i += 1) {
|
|
2691
|
+
const progress = i / steps;
|
|
2692
|
+
const eased = 1 - Math.pow(1 - progress, 2);
|
|
2693
|
+
const x = startX + (Math.random() - 0.5) * 3;
|
|
2694
|
+
const y = startY + (endY - startY) * eased + (Math.random() - 0.5) * 5;
|
|
2695
|
+
await waitJitter(durationMs / steps, 0.25);
|
|
2696
|
+
await client.send("Input.dispatchTouchEvent", {
|
|
2697
|
+
type: "touchMove",
|
|
2698
|
+
touchPoints: [{ x, y, id: 1 }]
|
|
2699
|
+
});
|
|
2700
|
+
}
|
|
2701
|
+
await client.send("Input.dispatchTouchEvent", {
|
|
2702
|
+
type: "touchEnd",
|
|
2703
|
+
touchPoints: []
|
|
2704
|
+
});
|
|
2705
|
+
await waitJitter(120, 0.35);
|
|
2706
|
+
const scrollAfterTouch = await page.evaluate(() => ({ x: window.scrollX, y: window.scrollY })).catch(() => null);
|
|
2707
|
+
if (scrollBefore && scrollAfterTouch && Math.abs(scrollAfterTouch.y - scrollBefore.y) <= 2 && Math.abs(scrollAfterTouch.x - scrollBefore.x) <= 2) {
|
|
2708
|
+
await page.evaluate((amount) => window.scrollBy(0, amount), deltaY);
|
|
2709
|
+
await waitJitter(120, 0.35);
|
|
2710
|
+
}
|
|
2711
|
+
return true;
|
|
2712
|
+
} catch (error) {
|
|
2713
|
+
logger7.debug(`touch swipe fallback: ${error?.message || error}`);
|
|
2714
|
+
try {
|
|
2715
|
+
await page.evaluate((amount) => window.scrollBy(0, amount), deltaY);
|
|
2716
|
+
await waitJitter(120, 0.35);
|
|
2717
|
+
return true;
|
|
2718
|
+
} catch {
|
|
2719
|
+
await page.mouse.wheel(0, deltaY);
|
|
2720
|
+
await waitJitter(120, 0.35);
|
|
2721
|
+
return true;
|
|
2722
|
+
}
|
|
2723
|
+
} finally {
|
|
2724
|
+
if (client && typeof client.detach === "function") {
|
|
2725
|
+
try {
|
|
2726
|
+
await client.detach();
|
|
2727
|
+
} catch {
|
|
2728
|
+
}
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
};
|
|
2732
|
+
var tapPoint = async (page, point) => {
|
|
2733
|
+
if (page.touchscreen && typeof page.touchscreen.tap === "function") {
|
|
2734
|
+
await page.touchscreen.tap(point.x, point.y);
|
|
2735
|
+
return;
|
|
2736
|
+
}
|
|
2737
|
+
await page.mouse.click(point.x, point.y);
|
|
2738
|
+
};
|
|
2739
|
+
var MobileHumanize = {
|
|
2740
|
+
jitterMs,
|
|
2741
|
+
async initializeCursor(page) {
|
|
2742
|
+
if (initializedPages.has(page)) return;
|
|
2743
|
+
initializedPages.add(page);
|
|
2744
|
+
logger7.debug("initializeCursor: mobile mode uses touch gestures, cursor init skipped");
|
|
2745
|
+
},
|
|
2746
|
+
async humanMove(page, target) {
|
|
2747
|
+
logger7.debug(`humanMove: mobile no-op target=${typeof target === "string" ? target : "element/coords"}`);
|
|
2748
|
+
if (typeof target === "string" || target && typeof target.boundingBox === "function") {
|
|
2749
|
+
const element = await resolveElement(page, target, { throwOnMissing: false });
|
|
2750
|
+
if (!element) {
|
|
2751
|
+
return false;
|
|
2752
|
+
}
|
|
2753
|
+
}
|
|
2754
|
+
await waitJitter(80, 0.4);
|
|
2755
|
+
return true;
|
|
2756
|
+
},
|
|
2757
|
+
async humanScroll(page, target, options = {}) {
|
|
2758
|
+
const {
|
|
2759
|
+
maxSteps = 12,
|
|
2760
|
+
minStep = 180,
|
|
2761
|
+
maxStep = 520,
|
|
2762
|
+
maxDurationMs = maxSteps * 280 + 1200,
|
|
2763
|
+
throwOnMissing = false
|
|
2764
|
+
} = options;
|
|
2765
|
+
const element = await resolveElement(page, target, { throwOnMissing });
|
|
2766
|
+
if (!element) {
|
|
2767
|
+
return { element: null, didScroll: false, restore: null };
|
|
2768
|
+
}
|
|
2769
|
+
const startTime = Date.now();
|
|
2770
|
+
let didScroll = false;
|
|
2771
|
+
for (let i = 0; i < maxSteps; i += 1) {
|
|
2772
|
+
const status = await checkElementVisibility(element);
|
|
2773
|
+
if (status.code === "VISIBLE") {
|
|
2774
|
+
return { element, didScroll, restore: null };
|
|
2775
|
+
}
|
|
2776
|
+
if (Date.now() - startTime > maxDurationMs) {
|
|
2777
|
+
logger7.warn(`humanScroll | mobile timeout (${maxDurationMs}ms)`);
|
|
2778
|
+
return { element, didScroll, restore: null };
|
|
2779
|
+
}
|
|
2780
|
+
const distance = minStep + Math.random() * Math.max(1, maxStep - minStep);
|
|
2781
|
+
const deltaY = status.direction === "up" ? -distance : distance;
|
|
2782
|
+
await dispatchTouchSwipe(page, deltaY);
|
|
2783
|
+
didScroll = true;
|
|
2784
|
+
}
|
|
2785
|
+
return { element, didScroll, restore: null };
|
|
2786
|
+
},
|
|
2787
|
+
async humanClick(page, target, options = {}) {
|
|
2788
|
+
const {
|
|
2789
|
+
reactionDelay = 220,
|
|
2790
|
+
throwOnMissing = true,
|
|
2791
|
+
scrollIfNeeded = true
|
|
2792
|
+
} = options;
|
|
2793
|
+
if (target == null) {
|
|
2794
|
+
const viewport = resolveViewport(page);
|
|
2795
|
+
await waitJitter(reactionDelay, 0.45);
|
|
2796
|
+
await tapPoint(page, {
|
|
2797
|
+
x: viewport.width * (0.45 + Math.random() * 0.1),
|
|
2798
|
+
y: viewport.height * (0.48 + Math.random() * 0.12)
|
|
2799
|
+
});
|
|
2800
|
+
return true;
|
|
2801
|
+
}
|
|
2802
|
+
const element = await resolveElement(page, target, { throwOnMissing });
|
|
2803
|
+
if (!element) return false;
|
|
2804
|
+
if (scrollIfNeeded) {
|
|
2805
|
+
await MobileHumanize.humanScroll(page, element, { throwOnMissing });
|
|
2806
|
+
}
|
|
2807
|
+
const box = await element.boundingBox();
|
|
2808
|
+
if (!box) {
|
|
2809
|
+
if (throwOnMissing) throw new Error("\u65E0\u6CD5\u83B7\u53D6\u5143\u7D20\u4F4D\u7F6E");
|
|
2810
|
+
return false;
|
|
2811
|
+
}
|
|
2812
|
+
await waitJitter(reactionDelay, 0.45);
|
|
2813
|
+
await tapPoint(page, randomPointInBox(box, 0.2));
|
|
2814
|
+
await waitJitter(120, 0.35);
|
|
2815
|
+
return true;
|
|
2816
|
+
},
|
|
2817
|
+
async randomSleep(baseMs, jitterPercent = 0.3) {
|
|
2818
|
+
await waitJitter(baseMs, jitterPercent);
|
|
2819
|
+
},
|
|
2820
|
+
async simulateGaze(page, baseDurationMs = 2500) {
|
|
2821
|
+
const durationMs = jitterMs(baseDurationMs, 0.4);
|
|
2822
|
+
const startTime = Date.now();
|
|
2823
|
+
while (Date.now() - startTime < durationMs) {
|
|
2824
|
+
if (Math.random() < 0.28) {
|
|
2825
|
+
const distance = 70 + Math.random() * 120;
|
|
2826
|
+
await dispatchTouchSwipe(page, Math.random() < 0.7 ? distance : -distance, {
|
|
2827
|
+
durationMs: 180,
|
|
2828
|
+
steps: 4
|
|
2829
|
+
});
|
|
2830
|
+
} else {
|
|
2831
|
+
await waitJitter(420, 0.55);
|
|
2832
|
+
}
|
|
2833
|
+
}
|
|
2834
|
+
},
|
|
2835
|
+
async humanType(page, selector, text, options = {}) {
|
|
2836
|
+
const {
|
|
2837
|
+
baseDelay = 160,
|
|
2838
|
+
pauseProbability = 0.08,
|
|
2839
|
+
pauseBase = 700
|
|
2840
|
+
} = options;
|
|
2841
|
+
await MobileHumanize.humanClick(page, selector, { scrollIfNeeded: true });
|
|
2842
|
+
await waitJitter(220, 0.45);
|
|
2843
|
+
for (let i = 0; i < String(text).length; i += 1) {
|
|
2844
|
+
const char = String(text)[i];
|
|
2845
|
+
const charDelay = /[,.!?;:,。!?;:]/.test(char) ? jitterMs(baseDelay * 1.45, 0.4) : jitterMs(char === " " ? baseDelay * 0.65 : baseDelay, 0.4);
|
|
2846
|
+
await page.keyboard.type(char);
|
|
2847
|
+
await waitJitter(charDelay, 0.15);
|
|
2848
|
+
if (Math.random() < pauseProbability && i < String(text).length - 1) {
|
|
2849
|
+
await waitJitter(pauseBase, 0.5);
|
|
2850
|
+
}
|
|
2851
|
+
}
|
|
2852
|
+
},
|
|
2853
|
+
async humanClear(page, selector) {
|
|
2854
|
+
const locator = page.locator(selector);
|
|
2855
|
+
await MobileHumanize.humanClick(page, locator, { scrollIfNeeded: true });
|
|
2856
|
+
await waitJitter(160, 0.4);
|
|
2857
|
+
await locator.evaluate((el) => {
|
|
2858
|
+
if ("value" in el) {
|
|
2859
|
+
el.value = "";
|
|
2860
|
+
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
2861
|
+
el.dispatchEvent(new Event("change", { bubbles: true }));
|
|
2862
|
+
return;
|
|
2863
|
+
}
|
|
2864
|
+
el.textContent = "";
|
|
2865
|
+
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
2866
|
+
});
|
|
2867
|
+
},
|
|
2868
|
+
async warmUpBrowsing(page, baseDuration = 3500) {
|
|
2869
|
+
const durationMs = jitterMs(baseDuration, 0.4);
|
|
2870
|
+
const startTime = Date.now();
|
|
2871
|
+
while (Date.now() - startTime < durationMs) {
|
|
2872
|
+
const action = Math.random();
|
|
2873
|
+
if (action < 0.5) {
|
|
2874
|
+
await dispatchTouchSwipe(page, 120 + Math.random() * 220, {
|
|
2875
|
+
durationMs: 240,
|
|
2876
|
+
steps: 5
|
|
2877
|
+
});
|
|
2878
|
+
} else if (action < 0.7) {
|
|
2879
|
+
await dispatchTouchSwipe(page, -(80 + Math.random() * 160), {
|
|
2880
|
+
durationMs: 220,
|
|
2881
|
+
steps: 4
|
|
2882
|
+
});
|
|
2883
|
+
} else {
|
|
2884
|
+
await waitJitter(560, 0.55);
|
|
2885
|
+
}
|
|
2886
|
+
}
|
|
2887
|
+
},
|
|
2888
|
+
async naturalScroll(page, direction = "down", distance = 300, baseSteps = 5) {
|
|
2889
|
+
const steps = Math.max(3, baseSteps + Math.floor(Math.random() * 3) - 1);
|
|
2890
|
+
const actualDistance = jitterMs(distance, 0.15);
|
|
2891
|
+
const sign = direction === "down" ? 1 : -1;
|
|
2892
|
+
for (let i = 0; i < steps; i += 1) {
|
|
2893
|
+
const factor = 1 - i / steps * 0.45;
|
|
2894
|
+
await dispatchTouchSwipe(page, actualDistance / steps * factor * sign, {
|
|
2895
|
+
durationMs: 150 + i * 20,
|
|
2896
|
+
steps: 4
|
|
2897
|
+
});
|
|
2898
|
+
}
|
|
2899
|
+
}
|
|
2900
|
+
};
|
|
2901
|
+
|
|
2902
|
+
// src/humanize.js
|
|
2903
|
+
var resolveDeviceFromPage = (page) => normalizeDevice(page?.[PageRuntimeStateKey]?.device);
|
|
2904
|
+
var resolveDelegate = (page) => {
|
|
2905
|
+
return resolveDeviceFromPage(page) === Device.Mobile ? MobileHumanize : Humanize;
|
|
2906
|
+
};
|
|
2907
|
+
var callDelegate = (method, page, args) => {
|
|
2908
|
+
const delegate = resolveDelegate(page);
|
|
2909
|
+
return delegate[method](page, ...args);
|
|
2910
|
+
};
|
|
2911
|
+
var Humanize2 = {
|
|
2912
|
+
jitterMs(base, jitterPercent = 0.3) {
|
|
2913
|
+
return Humanize.jitterMs(base, jitterPercent);
|
|
2914
|
+
},
|
|
2915
|
+
initializeCursor(page) {
|
|
2916
|
+
return callDelegate("initializeCursor", page, []);
|
|
2917
|
+
},
|
|
2918
|
+
humanMove(page, target) {
|
|
2919
|
+
return callDelegate("humanMove", page, [target]);
|
|
2920
|
+
},
|
|
2921
|
+
humanScroll(page, target, options = {}) {
|
|
2922
|
+
return callDelegate("humanScroll", page, [target, options]);
|
|
2923
|
+
},
|
|
2924
|
+
humanClick(page, target, options = {}) {
|
|
2925
|
+
return callDelegate("humanClick", page, [target, options]);
|
|
2926
|
+
},
|
|
2927
|
+
randomSleep(pageOrBaseMs, maybeBaseMs, maybeJitterPercent) {
|
|
2928
|
+
if (pageOrBaseMs && typeof pageOrBaseMs === "object" && typeof pageOrBaseMs.evaluate === "function") {
|
|
2929
|
+
const delegate = resolveDelegate(pageOrBaseMs);
|
|
2930
|
+
return delegate.randomSleep(maybeBaseMs, maybeJitterPercent);
|
|
2931
|
+
}
|
|
2932
|
+
return Humanize.randomSleep(pageOrBaseMs, maybeBaseMs);
|
|
2933
|
+
},
|
|
2934
|
+
simulateGaze(page, baseDurationMs = 2500) {
|
|
2935
|
+
return callDelegate("simulateGaze", page, [baseDurationMs]);
|
|
2936
|
+
},
|
|
2937
|
+
humanType(page, selector, text, options = {}) {
|
|
2938
|
+
return callDelegate("humanType", page, [selector, text, options]);
|
|
2939
|
+
},
|
|
2940
|
+
humanClear(page, selector) {
|
|
2941
|
+
return callDelegate("humanClear", page, [selector]);
|
|
2942
|
+
},
|
|
2943
|
+
warmUpBrowsing(page, baseDuration = 3500) {
|
|
2944
|
+
return callDelegate("warmUpBrowsing", page, [baseDuration]);
|
|
2945
|
+
},
|
|
2946
|
+
naturalScroll(page, direction = "down", distance = 300, baseSteps = 5) {
|
|
2947
|
+
return callDelegate("naturalScroll", page, [direction, distance, baseSteps]);
|
|
2948
|
+
}
|
|
2949
|
+
};
|
|
2950
|
+
|
|
2527
2951
|
// src/launch.js
|
|
2528
2952
|
import { execFileSync } from "node:child_process";
|
|
2529
2953
|
import { FingerprintGenerator } from "fingerprint-generator";
|
|
@@ -2610,7 +3034,7 @@ var ByPass = {
|
|
|
2610
3034
|
};
|
|
2611
3035
|
|
|
2612
3036
|
// src/launch.js
|
|
2613
|
-
var
|
|
3037
|
+
var logger8 = createInternalLogger("Launch");
|
|
2614
3038
|
var REQUEST_HOOK_FLAG = Symbol("playwright-toolkit-request-hook");
|
|
2615
3039
|
var injectedContexts = /* @__PURE__ */ new WeakSet();
|
|
2616
3040
|
var browserMajorVersionCache = /* @__PURE__ */ new Map();
|
|
@@ -2662,20 +3086,29 @@ var detectBrowserMajorVersion = (launcher) => {
|
|
|
2662
3086
|
});
|
|
2663
3087
|
detectedVersion = parseChromeMajorVersion(rawVersion);
|
|
2664
3088
|
} catch (error) {
|
|
2665
|
-
|
|
3089
|
+
logger8.warn(`\u8BFB\u53D6\u6D4F\u89C8\u5668\u7248\u672C\u5931\u8D25: ${error?.message || error}`);
|
|
2666
3090
|
}
|
|
2667
3091
|
browserMajorVersionCache.set(executablePath, detectedVersion);
|
|
2668
3092
|
return detectedVersion;
|
|
2669
3093
|
};
|
|
2670
|
-
var
|
|
3094
|
+
var resolveRuntimeDevice = (runtimeState = {}) => normalizeDevice(runtimeState?.device);
|
|
3095
|
+
var resolveCoreDevice = (core = {}) => {
|
|
3096
|
+
const raw = String(core?.device || "").trim().toLowerCase();
|
|
3097
|
+
if (raw === Device.Mobile) return Device.Mobile;
|
|
3098
|
+
if (raw === Device.Desktop) return Device.Desktop;
|
|
3099
|
+
return "";
|
|
3100
|
+
};
|
|
3101
|
+
var buildFingerprintGenerator = ({ locale, browserMajorVersion, device }) => {
|
|
2671
3102
|
return new FingerprintGenerator(
|
|
2672
3103
|
AntiCheat.getFingerprintGeneratorOptions({
|
|
2673
3104
|
locale,
|
|
2674
|
-
browserMajorVersion
|
|
3105
|
+
browserMajorVersion,
|
|
3106
|
+
device
|
|
2675
3107
|
})
|
|
2676
3108
|
);
|
|
2677
3109
|
};
|
|
2678
3110
|
var buildReplayableBrowserProfile = (runtimeState, launcher) => {
|
|
3111
|
+
const device = resolveRuntimeDevice(runtimeState);
|
|
2679
3112
|
if (!runtimeState || !RuntimeEnv.hasLoginState(runtimeState)) {
|
|
2680
3113
|
return { runtimeState, browserProfileCore: null };
|
|
2681
3114
|
}
|
|
@@ -2685,29 +3118,34 @@ var buildReplayableBrowserProfile = (runtimeState, launcher) => {
|
|
|
2685
3118
|
const locale = DEFAULT_LOCALE;
|
|
2686
3119
|
const currentBrowserMajorVersion = detectBrowserMajorVersion(launcher);
|
|
2687
3120
|
const storedBrowserMajorVersion = Number(browserProfileCore?.browser_major_version || 0);
|
|
2688
|
-
const
|
|
3121
|
+
const storedDevice = resolveCoreDevice(browserProfileCore);
|
|
3122
|
+
const needsDeviceRebuild = storedDevice ? storedDevice !== device : device === Device.Mobile;
|
|
3123
|
+
const needsRebuild = !browserProfileCore?.fingerprint || Object.keys(browserProfileCore.fingerprint || {}).length === 0 || needsDeviceRebuild || currentBrowserMajorVersion > 0 && storedBrowserMajorVersion > 0 && storedBrowserMajorVersion !== currentBrowserMajorVersion;
|
|
2689
3124
|
if (needsRebuild) {
|
|
2690
3125
|
const generator = buildFingerprintGenerator({
|
|
2691
3126
|
locale,
|
|
2692
|
-
browserMajorVersion: currentBrowserMajorVersion
|
|
3127
|
+
browserMajorVersion: currentBrowserMajorVersion,
|
|
3128
|
+
device
|
|
2693
3129
|
});
|
|
2694
3130
|
const fingerprint = generator.getFingerprint();
|
|
2695
3131
|
const fingerprintBrowserMajorVersion = parseChromeMajorVersion(fingerprint?.fingerprint?.navigator?.userAgent || "");
|
|
2696
3132
|
browserProfileCore = {
|
|
2697
3133
|
fingerprint,
|
|
3134
|
+
device,
|
|
2698
3135
|
timezone_id: timezoneId,
|
|
2699
3136
|
locale,
|
|
2700
3137
|
browser_major_version: currentBrowserMajorVersion > 0 ? currentBrowserMajorVersion : fingerprintBrowserMajorVersion,
|
|
2701
3138
|
schema_version: DEFAULT_BROWSER_PROFILE_SCHEMA_VERSION
|
|
2702
3139
|
};
|
|
2703
3140
|
nextState = RuntimeEnv.setBrowserProfileCore(nextState, browserProfileCore);
|
|
2704
|
-
|
|
2705
|
-
`\u5DF2\u751F\u6210\u6D4F\u89C8\u5668\u6307\u7EB9\u771F\u6E90 | env=${String(nextState.envId || "-")} | version=${browserProfileCore.browser_major_version || "-"} | timezone=${timezoneId}`
|
|
3141
|
+
logger8.info(
|
|
3142
|
+
`\u5DF2\u751F\u6210\u6D4F\u89C8\u5668\u6307\u7EB9\u771F\u6E90 | env=${String(nextState.envId || "-")} | device=${device} | version=${browserProfileCore.browser_major_version || "-"} | timezone=${timezoneId}`
|
|
2706
3143
|
);
|
|
2707
3144
|
return { runtimeState: nextState, browserProfileCore };
|
|
2708
3145
|
}
|
|
2709
3146
|
const normalizedBrowserProfileCore = {
|
|
2710
3147
|
...browserProfileCore,
|
|
3148
|
+
device,
|
|
2711
3149
|
timezone_id: timezoneId,
|
|
2712
3150
|
locale,
|
|
2713
3151
|
schema_version: Number(browserProfileCore.schema_version || 0) > 0 ? Number(browserProfileCore.schema_version || 0) : DEFAULT_BROWSER_PROFILE_SCHEMA_VERSION,
|
|
@@ -2723,6 +3161,35 @@ var buildReplayableBrowserProfile = (runtimeState, launcher) => {
|
|
|
2723
3161
|
browserProfileCore: normalizedBrowserProfileCore
|
|
2724
3162
|
};
|
|
2725
3163
|
};
|
|
3164
|
+
var applyDevicePageOptions = (pageOptions = {}, { device = Device.Desktop, fingerprint = null } = {}) => {
|
|
3165
|
+
if (!pageOptions || typeof pageOptions !== "object") return;
|
|
3166
|
+
const resolvedDevice = normalizeDevice(device);
|
|
3167
|
+
const screen = fingerprint?.screen || {};
|
|
3168
|
+
const dpr = Number(screen.devicePixelRatio || 0);
|
|
3169
|
+
if (resolvedDevice === Device.Mobile) {
|
|
3170
|
+
pageOptions.isMobile = true;
|
|
3171
|
+
pageOptions.hasTouch = true;
|
|
3172
|
+
pageOptions.deviceScaleFactor = dpr > 0 ? dpr : 2;
|
|
3173
|
+
if (!pageOptions.viewport) {
|
|
3174
|
+
pageOptions.viewport = {
|
|
3175
|
+
width: Number(screen.width || 390),
|
|
3176
|
+
height: Number(screen.height || 844)
|
|
3177
|
+
};
|
|
3178
|
+
}
|
|
3179
|
+
if (!pageOptions.screen) {
|
|
3180
|
+
pageOptions.screen = {
|
|
3181
|
+
width: Number(screen.width || pageOptions.viewport.width || 390),
|
|
3182
|
+
height: Number(screen.height || pageOptions.viewport.height || 844)
|
|
3183
|
+
};
|
|
3184
|
+
}
|
|
3185
|
+
return;
|
|
3186
|
+
}
|
|
3187
|
+
pageOptions.isMobile = false;
|
|
3188
|
+
pageOptions.hasTouch = false;
|
|
3189
|
+
if (!pageOptions.deviceScaleFactor) {
|
|
3190
|
+
pageOptions.deviceScaleFactor = dpr > 0 ? dpr : 1;
|
|
3191
|
+
}
|
|
3192
|
+
};
|
|
2726
3193
|
var buildReplayBrowserPoolOptions = (browserProfileCore) => {
|
|
2727
3194
|
const fingerprintWithHeaders = browserProfileCore?.fingerprint;
|
|
2728
3195
|
const fingerprint = fingerprintWithHeaders?.fingerprint;
|
|
@@ -2755,6 +3222,10 @@ var buildReplayBrowserPoolOptions = (browserProfileCore) => {
|
|
|
2755
3222
|
if (browserProfileCore.timezone_id) {
|
|
2756
3223
|
pageOptions.timezoneId = browserProfileCore.timezone_id;
|
|
2757
3224
|
}
|
|
3225
|
+
applyDevicePageOptions(pageOptions, {
|
|
3226
|
+
device: browserProfileCore.device,
|
|
3227
|
+
fingerprint
|
|
3228
|
+
});
|
|
2758
3229
|
}
|
|
2759
3230
|
],
|
|
2760
3231
|
postPageCreateHooks: [
|
|
@@ -2784,6 +3255,7 @@ var Launch = {
|
|
|
2784
3255
|
postNavigationHooks = [],
|
|
2785
3256
|
runtimeState = null
|
|
2786
3257
|
} = normalizedOptions;
|
|
3258
|
+
const device = resolveRuntimeDevice(runtimeState);
|
|
2787
3259
|
const { byPassDomains, enableProxy, proxyUrl } = resolveProxyLaunchOptions(proxyConfiguration);
|
|
2788
3260
|
const byPassRules = ByPass.buildByPassDomainRules(byPassDomains);
|
|
2789
3261
|
const proxyMeter = enableProxy && proxyUrl ? ProxyMeterRuntime.startProxyMeter({ proxyUrl, debugMode }) : null;
|
|
@@ -2812,18 +3284,18 @@ var Launch = {
|
|
|
2812
3284
|
upstreamLabel = `${parsedProxyUrl.protocol}//${parsedProxyUrl.host}`;
|
|
2813
3285
|
} catch {
|
|
2814
3286
|
}
|
|
2815
|
-
|
|
3287
|
+
logger8.info(
|
|
2816
3288
|
`[\u4EE3\u7406\u5DF2\u542F\u7528] \u672C\u5730=${launchProxy.server} \u4E0A\u6E38=${upstreamLabel || "-"} \u76F4\u8FDE\u57DF\u540D=${(byPassDomains || []).join(",")}`
|
|
2817
3289
|
);
|
|
2818
|
-
|
|
3290
|
+
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`);
|
|
2819
3291
|
} else if (enableByPassLogger && enableProxy && !launchProxy) {
|
|
2820
|
-
|
|
2821
|
-
|
|
3292
|
+
logger8.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=true \u4F46 proxy_url \u4E3A\u7A7A");
|
|
3293
|
+
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`);
|
|
2822
3294
|
} else if (enableByPassLogger && !enableProxy && proxyUrl) {
|
|
2823
|
-
|
|
2824
|
-
|
|
3295
|
+
logger8.info("[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=false \u4E14 proxy_url \u5DF2\u914D\u7F6E");
|
|
3296
|
+
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`);
|
|
2825
3297
|
} else if (enableByPassLogger) {
|
|
2826
|
-
|
|
3298
|
+
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`);
|
|
2827
3299
|
}
|
|
2828
3300
|
const onPageCreated = (page) => {
|
|
2829
3301
|
const recommendedGotoOptions = {
|
|
@@ -2845,7 +3317,7 @@ var Launch = {
|
|
|
2845
3317
|
}
|
|
2846
3318
|
if (!enableByPassLogger || byPassDomains.length === 0) return;
|
|
2847
3319
|
if (!matched || !matched.rule) return;
|
|
2848
|
-
|
|
3320
|
+
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}`);
|
|
2849
3321
|
};
|
|
2850
3322
|
page.on("request", requestHandler);
|
|
2851
3323
|
return recommendedGotoOptions;
|
|
@@ -2864,8 +3336,23 @@ var Launch = {
|
|
|
2864
3336
|
browserPoolOptions: replayBrowserPoolOptions || {
|
|
2865
3337
|
useFingerprints: true,
|
|
2866
3338
|
fingerprintOptions: {
|
|
2867
|
-
fingerprintGeneratorOptions: AntiCheat.getFingerprintGeneratorOptions(
|
|
2868
|
-
|
|
3339
|
+
fingerprintGeneratorOptions: AntiCheat.getFingerprintGeneratorOptions({
|
|
3340
|
+
locale: launchLocale,
|
|
3341
|
+
device
|
|
3342
|
+
})
|
|
3343
|
+
},
|
|
3344
|
+
prePageCreateHooks: [
|
|
3345
|
+
(_pageId, _browserController, pageOptions = {}) => {
|
|
3346
|
+
applyDevicePageOptions(pageOptions, { device });
|
|
3347
|
+
if (launchLocale) {
|
|
3348
|
+
pageOptions.locale = launchLocale;
|
|
3349
|
+
}
|
|
3350
|
+
const timezoneId = AntiCheat.getBaseConfig().timezoneId;
|
|
3351
|
+
if (timezoneId) {
|
|
3352
|
+
pageOptions.timezoneId = timezoneId;
|
|
3353
|
+
}
|
|
3354
|
+
}
|
|
3355
|
+
]
|
|
2869
3356
|
},
|
|
2870
3357
|
launchContext
|
|
2871
3358
|
};
|
|
@@ -2888,7 +3375,7 @@ var Launch = {
|
|
|
2888
3375
|
// src/live-view.js
|
|
2889
3376
|
import express from "express";
|
|
2890
3377
|
import { Actor } from "apify";
|
|
2891
|
-
var
|
|
3378
|
+
var logger9 = createInternalLogger("LiveView");
|
|
2892
3379
|
async function startLiveViewServer(liveViewKey) {
|
|
2893
3380
|
const app = express();
|
|
2894
3381
|
app.get("/", async (req, res) => {
|
|
@@ -2913,13 +3400,13 @@ async function startLiveViewServer(liveViewKey) {
|
|
|
2913
3400
|
</html>
|
|
2914
3401
|
`);
|
|
2915
3402
|
} catch (error) {
|
|
2916
|
-
|
|
3403
|
+
logger9.fail("Live View Server", error);
|
|
2917
3404
|
res.status(500).send(`\u65E0\u6CD5\u52A0\u8F7D\u5C4F\u5E55\u622A\u56FE: ${error.message}`);
|
|
2918
3405
|
}
|
|
2919
3406
|
});
|
|
2920
3407
|
const port = process.env.APIFY_CONTAINER_PORT || 4321;
|
|
2921
3408
|
app.listen(port, () => {
|
|
2922
|
-
|
|
3409
|
+
logger9.success("startLiveViewServer", `\u76D1\u542C\u7AEF\u53E3 ${port}`);
|
|
2923
3410
|
});
|
|
2924
3411
|
}
|
|
2925
3412
|
async function takeLiveScreenshot(liveViewKey, page, logMessage) {
|
|
@@ -2927,10 +3414,10 @@ async function takeLiveScreenshot(liveViewKey, page, logMessage) {
|
|
|
2927
3414
|
const buffer = await capturePageScreenshot(page, { type: "png" });
|
|
2928
3415
|
await Actor.setValue(liveViewKey, buffer, { contentType: "image/png" });
|
|
2929
3416
|
if (logMessage) {
|
|
2930
|
-
|
|
3417
|
+
logger9.info(`(\u622A\u56FE): ${logMessage}`);
|
|
2931
3418
|
}
|
|
2932
3419
|
} catch (e) {
|
|
2933
|
-
|
|
3420
|
+
logger9.warn(`\u65E0\u6CD5\u6355\u83B7 Live View \u5C4F\u5E55\u622A\u56FE: ${e.message}`);
|
|
2934
3421
|
}
|
|
2935
3422
|
}
|
|
2936
3423
|
var useLiveView = (liveViewKey = PresetOfLiveViewKey) => {
|
|
@@ -3030,7 +3517,7 @@ var dragCaptchaWithMouse = async (page, sourceLocator, targetLocator) => {
|
|
|
3030
3517
|
};
|
|
3031
3518
|
|
|
3032
3519
|
// src/internals/captcha/bytedance.js
|
|
3033
|
-
var
|
|
3520
|
+
var logger10 = createInternalLogger("Captcha");
|
|
3034
3521
|
var DEFAULT_BYTEDANCE_CAPTCHA_OPTIONS = Object.freeze({
|
|
3035
3522
|
apiType: "31234",
|
|
3036
3523
|
maxRetries: 3,
|
|
@@ -3097,14 +3584,14 @@ var getVerifycenterCaptchaContext = async (page, options) => {
|
|
|
3097
3584
|
if (!isContainerVisible) {
|
|
3098
3585
|
return null;
|
|
3099
3586
|
}
|
|
3100
|
-
|
|
3587
|
+
logger10.info("\u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\u5BB9\u5668\uFF0C\u5F00\u59CB\u7B49\u5F85 iframe \u52A0\u8F7D\u3002");
|
|
3101
3588
|
let iframeLocator = page.locator(options.iframeSelector).first();
|
|
3102
3589
|
let isIframeVisible = await waitForVisible(
|
|
3103
3590
|
iframeLocator,
|
|
3104
3591
|
options.iframeVisibleTimeoutMs
|
|
3105
3592
|
);
|
|
3106
3593
|
if (!isIframeVisible) {
|
|
3107
|
-
|
|
3594
|
+
logger10.warn("\u672A\u5728\u9884\u671F\u9009\u62E9\u5668\u4E2D\u627E\u5230 verifycenter iframe\uFF0C\u5C1D\u8BD5\u5BB9\u5668\u5185\u4EFB\u610F iframe\u3002");
|
|
3108
3595
|
iframeLocator = captchaContainer.locator(options.iframeFallbackSelector).first();
|
|
3109
3596
|
isIframeVisible = await waitForVisible(
|
|
3110
3597
|
iframeLocator,
|
|
@@ -3114,7 +3601,7 @@ var getVerifycenterCaptchaContext = async (page, options) => {
|
|
|
3114
3601
|
if (!isIframeVisible) {
|
|
3115
3602
|
throw new Error("verifycenter iframe not found inside captcha container.");
|
|
3116
3603
|
}
|
|
3117
|
-
|
|
3604
|
+
logger10.info("\u9A8C\u8BC1\u7801 iframe \u5DF2\u53EF\u89C1\uFF0C\u5F00\u59CB\u89E3\u6790\u5185\u5BB9 frame\u3002");
|
|
3118
3605
|
const frame = await resolveContentFrame(page, iframeLocator, options);
|
|
3119
3606
|
if (!frame) {
|
|
3120
3607
|
throw new Error("Failed to resolve verifycenter iframe content frame.");
|
|
@@ -3124,7 +3611,7 @@ var getVerifycenterCaptchaContext = async (page, options) => {
|
|
|
3124
3611
|
var refreshCaptcha = async (page, frame, options) => {
|
|
3125
3612
|
const clicked = await clickCaptchaAction(frame, options.refreshTexts, options).catch(() => false);
|
|
3126
3613
|
if (!clicked) {
|
|
3127
|
-
|
|
3614
|
+
logger10.warn("Refresh button not found.");
|
|
3128
3615
|
return false;
|
|
3129
3616
|
}
|
|
3130
3617
|
await page.waitForTimeout(options.refreshWaitMs);
|
|
@@ -3165,18 +3652,18 @@ var waitForCaptchaChallengeReady = async (page, frame, options) => {
|
|
|
3165
3652
|
const imageCount = await sourceImages.count().catch(() => 0);
|
|
3166
3653
|
const hasVisibleSourceImage = imageCount > 0 ? await sourceImages.first().isVisible({ timeout: options.loadingIndicatorVisibleTimeoutMs }).catch(() => false) : false;
|
|
3167
3654
|
if (!isLoadingVisible && hasVisibleSourceImage) {
|
|
3168
|
-
|
|
3655
|
+
logger10.info(hasSeenLoading ? "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u52A0\u8F7D\u5B8C\u6210\u3002" : "\u9A8C\u8BC1\u7801\u56FE\u7247\u5DF2\u5C31\u7EEA\u3002");
|
|
3169
3656
|
return;
|
|
3170
3657
|
}
|
|
3171
3658
|
if (hasErrorTextVisible) {
|
|
3172
|
-
|
|
3659
|
+
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");
|
|
3173
3660
|
await refreshCaptcha(page, frame, options);
|
|
3174
3661
|
refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
|
|
3175
3662
|
hasSeenLoading = false;
|
|
3176
3663
|
continue;
|
|
3177
3664
|
}
|
|
3178
3665
|
if (!hasVisibleSourceImage && Date.now() >= refreshDeadline) {
|
|
3179
|
-
|
|
3666
|
+
logger10.warn(`\u9A8C\u8BC1\u7801\u56FE\u7247\u8D85\u8FC7 ${options.challengeReadyRefreshTimeoutMs}ms \u4ECD\u672A\u51FA\u73B0\uFF0C\u5C1D\u8BD5\u5237\u65B0\u9898\u76EE\u3002`);
|
|
3180
3667
|
await refreshCaptcha(page, frame, options);
|
|
3181
3668
|
refreshDeadline = Date.now() + options.challengeReadyRefreshTimeoutMs;
|
|
3182
3669
|
hasSeenLoading = false;
|
|
@@ -3196,16 +3683,16 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
|
|
|
3196
3683
|
...options
|
|
3197
3684
|
};
|
|
3198
3685
|
if (!config.token) {
|
|
3199
|
-
|
|
3686
|
+
logger10.warn("\u7F3A\u5C11\u9A8C\u8BC1\u7801 token\uFF0C\u8DF3\u8FC7\u81EA\u52A8\u8BC6\u522B\u3002");
|
|
3200
3687
|
return false;
|
|
3201
3688
|
}
|
|
3202
|
-
|
|
3689
|
+
logger10.info("\u5F53\u524D\u4F7F\u7528\u672Ctool\u2014\u2014\u6D4B\u8BD5\u7248\u672C");
|
|
3203
3690
|
for (let attempt = 1; attempt <= config.maxRetries; attempt++) {
|
|
3204
|
-
|
|
3691
|
+
logger10.info(`\u5F00\u59CB\u7B2C ${attempt}/${config.maxRetries} \u6B21 verifycenter \u9A8C\u8BC1\u7801\u8BC6\u522B\u3002`);
|
|
3205
3692
|
try {
|
|
3206
3693
|
const captchaContext = await getVerifycenterCaptchaContext(page, config);
|
|
3207
3694
|
if (!captchaContext) {
|
|
3208
|
-
|
|
3695
|
+
logger10.info("Captcha container is not visible anymore.");
|
|
3209
3696
|
return true;
|
|
3210
3697
|
}
|
|
3211
3698
|
const { iframeLocator, frame } = captchaContext;
|
|
@@ -3220,16 +3707,16 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
|
|
|
3220
3707
|
});
|
|
3221
3708
|
const serialNumbers = extractCaptchaSerialNumbers(apiResponse);
|
|
3222
3709
|
if (apiResponse?.code !== config.recognitionSuccessCode || serialNumbers.length === 0) {
|
|
3223
|
-
|
|
3710
|
+
logger10.warn(
|
|
3224
3711
|
`\u9A8C\u8BC1\u7801\u8BC6\u522B\u5931\u8D25\u3002code=${apiResponse?.code}, msg=${apiResponse?.msg || "unknown"}`
|
|
3225
3712
|
);
|
|
3226
3713
|
await refreshCaptcha(page, frame, config);
|
|
3227
3714
|
continue;
|
|
3228
3715
|
}
|
|
3229
|
-
|
|
3716
|
+
logger10.info(`\u9A8C\u8BC1\u7801\u8BC6\u522B\u6210\u529F\uFF0C\u5E8F\u53F7\uFF1A${serialNumbers.join(", ")}`);
|
|
3230
3717
|
const dropTarget = await findCaptchaDropTarget(frame, config);
|
|
3231
3718
|
if (!dropTarget) {
|
|
3232
|
-
|
|
3719
|
+
logger10.warn("\u672A\u627E\u5230\u9A8C\u8BC1\u7801\u62D6\u62FD\u76EE\u6807\u533A\u57DF\u3002");
|
|
3233
3720
|
await refreshCaptcha(page, frame, config);
|
|
3234
3721
|
continue;
|
|
3235
3722
|
}
|
|
@@ -3252,31 +3739,31 @@ async function solveCaptcha(page, options = {}, dependencies = {}) {
|
|
|
3252
3739
|
}
|
|
3253
3740
|
const submitted = await clickCaptchaAction(frame, config.submitTexts, config).catch(() => false);
|
|
3254
3741
|
if (!submitted) {
|
|
3255
|
-
|
|
3742
|
+
logger10.warn("\u672A\u627E\u5230\u63D0\u4EA4\u6309\u94AE\uFF0C\u53EF\u80FD\u4F1A\u81EA\u52A8\u63D0\u4EA4\u3002");
|
|
3256
3743
|
}
|
|
3257
3744
|
await page.waitForTimeout(config.submitWaitMs);
|
|
3258
3745
|
const stillVisible = await iframeLocator.isVisible({ timeout: config.containerVisibleTimeoutMs }).catch(() => false);
|
|
3259
3746
|
if (!stillVisible) {
|
|
3260
|
-
|
|
3747
|
+
logger10.info("\u9A8C\u8BC1\u7801\u8BC6\u522B\u5E76\u63D0\u4EA4\u6210\u529F\u3002");
|
|
3261
3748
|
return true;
|
|
3262
3749
|
}
|
|
3263
|
-
|
|
3750
|
+
logger10.warn("\u63D0\u4EA4\u540E\u9A8C\u8BC1\u7801 iframe \u4ECD\u7136\u53EF\u89C1\uFF0C\u51C6\u5907\u5237\u65B0\u540E\u91CD\u8BD5\u3002");
|
|
3264
3751
|
await page.waitForTimeout(2e3);
|
|
3265
3752
|
await refreshCaptcha(page, frame, config);
|
|
3266
3753
|
} catch (error) {
|
|
3267
|
-
|
|
3754
|
+
logger10.error(`\u7B2C ${attempt}/${config.maxRetries} \u6B21\u9A8C\u8BC1\u7801\u8BC6\u522B\u5931\u8D25\uFF1A${error?.message || error}`);
|
|
3268
3755
|
}
|
|
3269
3756
|
if (attempt < config.maxRetries) {
|
|
3270
3757
|
await page.waitForTimeout(config.retryDelayBaseMs + attempt * config.retryDelayStepMs);
|
|
3271
3758
|
}
|
|
3272
3759
|
}
|
|
3273
|
-
|
|
3760
|
+
logger10.error(`\u91CD\u8BD5 ${config.maxRetries} \u6B21\u540E\uFF0C\u9A8C\u8BC1\u7801\u4ECD\u672A\u8BC6\u522B\u6210\u529F\u3002`);
|
|
3274
3761
|
return false;
|
|
3275
3762
|
}
|
|
3276
3763
|
var sloveCaptcha = solveCaptcha;
|
|
3277
3764
|
|
|
3278
3765
|
// src/chaptcha.js
|
|
3279
|
-
var
|
|
3766
|
+
var logger11 = createInternalLogger("Captcha");
|
|
3280
3767
|
var DEFAULT_CAPTCHA_RECOGNITION_OPTIONS = Object.freeze({
|
|
3281
3768
|
token: "eKJvBfwfN0YRav0-VD_44E2VBSfm7l0YtddUQ7cFySI",
|
|
3282
3769
|
apiUrl: "https://api.jfbym.com/api/YmServer/customApi"
|
|
@@ -3363,7 +3850,7 @@ function useCaptchaMonitor(page, options) {
|
|
|
3363
3850
|
};
|
|
3364
3851
|
})();
|
|
3365
3852
|
}, { selector: domSelector, callbackName: exposedFunctionName, cleanerName });
|
|
3366
|
-
|
|
3853
|
+
logger11.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${domSelector}`);
|
|
3367
3854
|
cleanupFns.push(async () => {
|
|
3368
3855
|
try {
|
|
3369
3856
|
await page.evaluate((name) => {
|
|
@@ -3387,14 +3874,14 @@ function useCaptchaMonitor(page, options) {
|
|
|
3387
3874
|
}
|
|
3388
3875
|
};
|
|
3389
3876
|
page.on("framenavigated", frameHandler);
|
|
3390
|
-
|
|
3877
|
+
logger11.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${urlPattern}`);
|
|
3391
3878
|
cleanupFns.push(async () => {
|
|
3392
3879
|
page.off("framenavigated", frameHandler);
|
|
3393
3880
|
});
|
|
3394
3881
|
}
|
|
3395
3882
|
return {
|
|
3396
3883
|
stop: async () => {
|
|
3397
|
-
|
|
3884
|
+
logger11.info("\u6B63\u5728\u505C\u6B62\u9A8C\u8BC1\u7801\u76D1\u63A7...");
|
|
3398
3885
|
for (const fn of cleanupFns) {
|
|
3399
3886
|
await fn();
|
|
3400
3887
|
}
|
|
@@ -3433,7 +3920,7 @@ async function solveCaptchaWithStrategy(strategyName, page, options = {}) {
|
|
|
3433
3920
|
);
|
|
3434
3921
|
return strategy.sloveCaptcha(page, resolvedOptions, {
|
|
3435
3922
|
callCaptchaRecognitionApi,
|
|
3436
|
-
logger:
|
|
3923
|
+
logger: logger11
|
|
3437
3924
|
});
|
|
3438
3925
|
}
|
|
3439
3926
|
var Captcha = {
|
|
@@ -3444,7 +3931,7 @@ var Captcha = {
|
|
|
3444
3931
|
// src/mutation.js
|
|
3445
3932
|
import { createHash } from "node:crypto";
|
|
3446
3933
|
import { v4 as uuidv42 } from "uuid";
|
|
3447
|
-
var
|
|
3934
|
+
var logger12 = createInternalLogger("Mutation");
|
|
3448
3935
|
var MUTATION_MONITOR_MODE = Object.freeze({
|
|
3449
3936
|
Added: "added",
|
|
3450
3937
|
Changed: "changed",
|
|
@@ -3477,14 +3964,14 @@ var Mutation = {
|
|
|
3477
3964
|
const stableTime = options.stableTime ?? 5 * 1e3;
|
|
3478
3965
|
const timeout = options.timeout ?? 120 * 1e3;
|
|
3479
3966
|
const onMutation = options.onMutation;
|
|
3480
|
-
|
|
3967
|
+
logger12.start("waitForStable", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);
|
|
3481
3968
|
if (initialTimeout > 0) {
|
|
3482
3969
|
const selectorQuery = selectorList.join(",");
|
|
3483
3970
|
try {
|
|
3484
3971
|
await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
|
|
3485
|
-
|
|
3972
|
+
logger12.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
|
|
3486
3973
|
} catch (e) {
|
|
3487
|
-
|
|
3974
|
+
logger12.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
|
|
3488
3975
|
throw e;
|
|
3489
3976
|
}
|
|
3490
3977
|
}
|
|
@@ -3500,7 +3987,7 @@ var Mutation = {
|
|
|
3500
3987
|
return "__CONTINUE__";
|
|
3501
3988
|
}
|
|
3502
3989
|
});
|
|
3503
|
-
|
|
3990
|
+
logger12.info("waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03");
|
|
3504
3991
|
} catch (e) {
|
|
3505
3992
|
}
|
|
3506
3993
|
}
|
|
@@ -3615,9 +4102,9 @@ var Mutation = {
|
|
|
3615
4102
|
{ selectorList, stableTime, timeout, callbackName, hasCallback: !!onMutation }
|
|
3616
4103
|
);
|
|
3617
4104
|
if (result.mutationCount === 0 && result.stableTime === 0) {
|
|
3618
|
-
|
|
4105
|
+
logger12.warning("waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
|
|
3619
4106
|
}
|
|
3620
|
-
|
|
4107
|
+
logger12.success("waitForStable", `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
|
|
3621
4108
|
return result;
|
|
3622
4109
|
},
|
|
3623
4110
|
/**
|
|
@@ -3789,22 +4276,22 @@ var Mutation = {
|
|
|
3789
4276
|
return "__CONTINUE__";
|
|
3790
4277
|
}
|
|
3791
4278
|
};
|
|
3792
|
-
|
|
4279
|
+
logger12.start(
|
|
3793
4280
|
"waitForStableAcrossRoots",
|
|
3794
4281
|
`\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668(\u8DE8 root), \u7A33\u5B9A\u65F6\u95F4=${waitForStableTime}ms`
|
|
3795
4282
|
);
|
|
3796
4283
|
if (initialTimeout > 0) {
|
|
3797
4284
|
try {
|
|
3798
4285
|
await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
|
|
3799
|
-
|
|
4286
|
+
logger12.info(`waitForStableAcrossRoots \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
|
|
3800
4287
|
} catch (e) {
|
|
3801
|
-
|
|
4288
|
+
logger12.warning(`waitForStableAcrossRoots \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
|
|
3802
4289
|
throw e;
|
|
3803
4290
|
}
|
|
3804
4291
|
}
|
|
3805
4292
|
let state = await buildState();
|
|
3806
4293
|
if (!state?.hasMatched) {
|
|
3807
|
-
|
|
4294
|
+
logger12.warning("waitForStableAcrossRoots \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
|
|
3808
4295
|
return { mutationCount: 0, stableTime: 0, wasPaused: false };
|
|
3809
4296
|
}
|
|
3810
4297
|
let mutationCount = 0;
|
|
@@ -3841,7 +4328,7 @@ var Mutation = {
|
|
|
3841
4328
|
if (lastState.snapshotKey !== lastSnapshotKey) {
|
|
3842
4329
|
lastSnapshotKey = lastState.snapshotKey;
|
|
3843
4330
|
mutationCount += 1;
|
|
3844
|
-
|
|
4331
|
+
logger12.info(
|
|
3845
4332
|
`waitForStableAcrossRoots \u53D8\u5316#${mutationCount}, len=${lastState.snapshotLength}, path=${lastState.primaryPath || "unknown"}, preview="${truncate(lastState.text, 120)}"`
|
|
3846
4333
|
);
|
|
3847
4334
|
const signal = await invokeMutationCallback({
|
|
@@ -3854,7 +4341,7 @@ var Mutation = {
|
|
|
3854
4341
|
continue;
|
|
3855
4342
|
}
|
|
3856
4343
|
if (!isPaused && stableSince > 0 && Date.now() - stableSince >= waitForStableTime) {
|
|
3857
|
-
|
|
4344
|
+
logger12.success("waitForStableAcrossRoots", `DOM \u7A33\u5B9A, \u603B\u5171 ${mutationCount} \u6B21\u53D8\u5316${wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
|
|
3858
4345
|
return {
|
|
3859
4346
|
mutationCount,
|
|
3860
4347
|
stableTime: waitForStableTime,
|
|
@@ -3881,7 +4368,7 @@ var Mutation = {
|
|
|
3881
4368
|
const onMutation = options.onMutation;
|
|
3882
4369
|
const rawMode = String(options.mode || MUTATION_MONITOR_MODE.Added).toLowerCase();
|
|
3883
4370
|
const mode = [MUTATION_MONITOR_MODE.Added, MUTATION_MONITOR_MODE.Changed, MUTATION_MONITOR_MODE.All].includes(rawMode) ? rawMode : MUTATION_MONITOR_MODE.Added;
|
|
3884
|
-
|
|
4371
|
+
logger12.start("useMonitor", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode}`);
|
|
3885
4372
|
const monitorKey = generateKey("pk_mon");
|
|
3886
4373
|
const callbackName = generateKey("pk_mon_cb");
|
|
3887
4374
|
const cleanerName = generateKey("pk_mon_clean");
|
|
@@ -4024,7 +4511,7 @@ var Mutation = {
|
|
|
4024
4511
|
return total;
|
|
4025
4512
|
};
|
|
4026
4513
|
}, { selectorList, monitorKey, callbackName, cleanerName, hasCallback: !!onMutation, mode });
|
|
4027
|
-
|
|
4514
|
+
logger12.success("useMonitor", "\u76D1\u63A7\u5668\u5DF2\u542F\u52A8");
|
|
4028
4515
|
return {
|
|
4029
4516
|
stop: async () => {
|
|
4030
4517
|
let totalMutations = 0;
|
|
@@ -4037,7 +4524,7 @@ var Mutation = {
|
|
|
4037
4524
|
}, cleanerName);
|
|
4038
4525
|
} catch (e) {
|
|
4039
4526
|
}
|
|
4040
|
-
|
|
4527
|
+
logger12.success("useMonitor.stop", `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);
|
|
4041
4528
|
return { totalMutations };
|
|
4042
4529
|
}
|
|
4043
4530
|
};
|
|
@@ -4906,7 +5393,7 @@ var createTemplateLogger = (baseLogger = createBaseLogger()) => {
|
|
|
4906
5393
|
};
|
|
4907
5394
|
var getDefaultBaseLogger = () => createBaseLogger("");
|
|
4908
5395
|
var Logger = {
|
|
4909
|
-
setLogger: (
|
|
5396
|
+
setLogger: (logger16) => setDefaultLogger(logger16),
|
|
4910
5397
|
info: (message) => getDefaultBaseLogger().info(message),
|
|
4911
5398
|
success: (message) => getDefaultBaseLogger().success(message),
|
|
4912
5399
|
warning: (message) => getDefaultBaseLogger().warning(message),
|
|
@@ -4914,14 +5401,14 @@ var Logger = {
|
|
|
4914
5401
|
error: (message) => getDefaultBaseLogger().error(message),
|
|
4915
5402
|
debug: (message) => getDefaultBaseLogger().debug(message),
|
|
4916
5403
|
start: (message) => getDefaultBaseLogger().start(message),
|
|
4917
|
-
useTemplate: (
|
|
4918
|
-
if (
|
|
5404
|
+
useTemplate: (logger16) => {
|
|
5405
|
+
if (logger16) return createTemplateLogger(createBaseLogger("", logger16));
|
|
4919
5406
|
return createTemplateLogger();
|
|
4920
5407
|
}
|
|
4921
5408
|
};
|
|
4922
5409
|
|
|
4923
5410
|
// src/share.js
|
|
4924
|
-
import
|
|
5411
|
+
import delay3 from "delay";
|
|
4925
5412
|
|
|
4926
5413
|
// src/internals/watermarkify.js
|
|
4927
5414
|
var DEFAULT_TIMEZONE_OFFSET = 8;
|
|
@@ -4980,7 +5467,7 @@ var LOCATION_NETWORK_SUFFIX_PATTERNS = [
|
|
|
4980
5467
|
];
|
|
4981
5468
|
var cachedStripLogoSrcPromise = null;
|
|
4982
5469
|
var cachedEnrichmentByContext = /* @__PURE__ */ new WeakMap();
|
|
4983
|
-
var
|
|
5470
|
+
var logger13 = createInternalLogger("Watermarkify");
|
|
4984
5471
|
var normalizeText = (value) => String(value || "").trim();
|
|
4985
5472
|
var toInline = (value, maxLen = 200) => {
|
|
4986
5473
|
const text = normalizeText(value);
|
|
@@ -5222,9 +5709,9 @@ var resolveWithCustomResolver = async (page, baseMeta, options = {}) => {
|
|
|
5222
5709
|
location: toInline(resolved.location, 80)
|
|
5223
5710
|
};
|
|
5224
5711
|
if (enrichment.ip || enrichment.location) {
|
|
5225
|
-
|
|
5712
|
+
logger13.info(`\u81EA\u5B9A\u4E49 resolver \u547D\u4E2D: ip=${enrichment.ip || "-"}, loc=${enrichment.location || "-"}`);
|
|
5226
5713
|
} else {
|
|
5227
|
-
|
|
5714
|
+
logger13.warning("\u81EA\u5B9A\u4E49 resolver \u5DF2\u6267\u884C\uFF0C\u4F46\u672A\u8FD4\u56DE IP/Loc");
|
|
5228
5715
|
}
|
|
5229
5716
|
return enrichment;
|
|
5230
5717
|
} finally {
|
|
@@ -5408,12 +5895,12 @@ var buildWatermarkifyRenderHtml = ({ imageSrc, overlaySvg, width, height }) => {
|
|
|
5408
5895
|
};
|
|
5409
5896
|
var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageInfo = {}) => {
|
|
5410
5897
|
if (!page || typeof page.context !== "function") {
|
|
5411
|
-
|
|
5898
|
+
logger13.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u7F3A\u5C11\u53EF\u7528 page");
|
|
5412
5899
|
return buffer;
|
|
5413
5900
|
}
|
|
5414
5901
|
const renderScope = await openProbePage(page);
|
|
5415
5902
|
if (!renderScope?.page) {
|
|
5416
|
-
|
|
5903
|
+
logger13.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA render page");
|
|
5417
5904
|
return buffer;
|
|
5418
5905
|
}
|
|
5419
5906
|
try {
|
|
@@ -5456,13 +5943,13 @@ var composeScreenshotBufferWithBrowser = async (page, buffer, overlaySvg, imageI
|
|
|
5456
5943
|
fullPage: true,
|
|
5457
5944
|
animations: "disabled"
|
|
5458
5945
|
}).catch((error) => {
|
|
5459
|
-
|
|
5946
|
+
logger13.warning(`watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
5460
5947
|
return null;
|
|
5461
5948
|
});
|
|
5462
5949
|
if (Buffer.isBuffer(composed) && composed.length > 0) {
|
|
5463
5950
|
return composed;
|
|
5464
5951
|
}
|
|
5465
|
-
|
|
5952
|
+
logger13.warning("watermarkify \u6D4F\u89C8\u5668\u5408\u6210\u5931\u8D25: \u672A\u5F97\u5230\u6709\u6548\u622A\u56FE\u7ED3\u679C");
|
|
5466
5953
|
return buffer;
|
|
5467
5954
|
} finally {
|
|
5468
5955
|
await renderScope.close().catch(() => {
|
|
@@ -5475,7 +5962,7 @@ var resolveWithIpLookup = async (page, options = {}) => {
|
|
|
5475
5962
|
}
|
|
5476
5963
|
const probeScope = await openProbePage(page);
|
|
5477
5964
|
if (!probeScope?.page) {
|
|
5478
|
-
|
|
5965
|
+
logger13.warning("ipLookup \u8DF3\u8FC7: \u65E0\u6CD5\u521B\u5EFA probe page");
|
|
5479
5966
|
return null;
|
|
5480
5967
|
}
|
|
5481
5968
|
const timeoutMs = Math.max(
|
|
@@ -5484,12 +5971,12 @@ var resolveWithIpLookup = async (page, options = {}) => {
|
|
|
5484
5971
|
);
|
|
5485
5972
|
try {
|
|
5486
5973
|
const probePage = probeScope.page;
|
|
5487
|
-
|
|
5974
|
+
logger13.info(`ipLookup \u5C1D\u8BD5: url=${DEFAULT_IP_LOOKUP_URL}, timeoutMs=${timeoutMs}`);
|
|
5488
5975
|
const response = await probePage.goto(DEFAULT_IP_LOOKUP_URL, {
|
|
5489
5976
|
waitUntil: "commit",
|
|
5490
5977
|
timeout: timeoutMs
|
|
5491
5978
|
}).catch((error) => {
|
|
5492
|
-
|
|
5979
|
+
logger13.warning(`ipLookup \u8BF7\u6C42\u5931\u8D25: url=${DEFAULT_IP_LOOKUP_URL}, error=${error instanceof Error ? error.message : String(error)}`);
|
|
5493
5980
|
return null;
|
|
5494
5981
|
});
|
|
5495
5982
|
const status = response && typeof response.status === "function" ? response.status() : 0;
|
|
@@ -5511,13 +5998,13 @@ var resolveWithIpLookup = async (page, options = {}) => {
|
|
|
5511
5998
|
}
|
|
5512
5999
|
const parsed = parseIpIpJsonResponse(rawText);
|
|
5513
6000
|
if (parsed?.ip || parsed?.location) {
|
|
5514
|
-
|
|
6001
|
+
logger13.info(`ipLookup \u6210\u529F: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, ip=${parsed.ip || "-"}, loc=${parsed.location || "-"}`);
|
|
5515
6002
|
return parsed;
|
|
5516
6003
|
}
|
|
5517
|
-
|
|
6004
|
+
logger13.warning(`ipLookup \u672A\u89E3\u6790\u51FA IP/Loc: url=${DEFAULT_IP_LOOKUP_URL}, status=${status || "-"}, contentType=${contentType || "-"}, preview=${shortenTail(rawText, 120) || "[empty]"}`);
|
|
5518
6005
|
return null;
|
|
5519
6006
|
} catch (error) {
|
|
5520
|
-
|
|
6007
|
+
logger13.warning(`ipLookup \u6267\u884C\u5F02\u5E38\uFF0C\u672A\u83B7\u5F97 IP/Loc: ${error instanceof Error ? error.message : String(error)}`);
|
|
5521
6008
|
return null;
|
|
5522
6009
|
} finally {
|
|
5523
6010
|
await probeScope.close().catch(() => {
|
|
@@ -5531,10 +6018,10 @@ var resolveEnrichment = async (page, baseMeta, options) => {
|
|
|
5531
6018
|
ip: toInline(options.ip, 80),
|
|
5532
6019
|
location: toInline(options.location, 80)
|
|
5533
6020
|
};
|
|
5534
|
-
|
|
6021
|
+
logger13.info(`enrichment \u5F00\u59CB: host=${baseMeta.hostname || "-"}, hasPresetIp=${Boolean(merged.ip)}, hasPresetLoc=${Boolean(merged.location)}, ipLookup=${options.ipLookup !== false}`);
|
|
5535
6022
|
if (!merged.ip || !merged.location) {
|
|
5536
6023
|
if (cached?.ip || cached?.location) {
|
|
5537
|
-
|
|
6024
|
+
logger13.info(`enrichment \u547D\u4E2D\u4E0A\u4E0B\u6587\u7F13\u5B58: ip=${cached.ip || "-"}, loc=${cached.location || "-"}`);
|
|
5538
6025
|
}
|
|
5539
6026
|
fillEnrichment(merged, cached);
|
|
5540
6027
|
}
|
|
@@ -5558,15 +6045,15 @@ var resolveEnrichment = async (page, baseMeta, options) => {
|
|
|
5558
6045
|
"x-geo-country"
|
|
5559
6046
|
]), 80);
|
|
5560
6047
|
if (!merged.location || isWeakLocationValue(merged.location) && headerLocation) {
|
|
5561
|
-
|
|
6048
|
+
logger13.info(`enrichment \u4F7F\u7528\u54CD\u5E94\u5934\u8865\u5145 Loc: ${headerLocation || "-"}`);
|
|
5562
6049
|
merged.location = headerLocation || merged.location;
|
|
5563
6050
|
}
|
|
5564
6051
|
}
|
|
5565
6052
|
writeCachedEnrichment(page, merged);
|
|
5566
6053
|
if (merged.ip || merged.location) {
|
|
5567
|
-
|
|
6054
|
+
logger13.info(`enrichment \u5B8C\u6210: ip=${merged.ip || "-"}, loc=${merged.location || "-"}`);
|
|
5568
6055
|
} else {
|
|
5569
|
-
|
|
6056
|
+
logger13.warning("enrichment \u5B8C\u6210: \u672A\u83B7\u5F97 IP/Loc");
|
|
5570
6057
|
}
|
|
5571
6058
|
return merged;
|
|
5572
6059
|
};
|
|
@@ -6234,7 +6721,7 @@ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
|
|
|
6234
6721
|
}
|
|
6235
6722
|
const imageInfo = readImageInfo(buffer);
|
|
6236
6723
|
if (!imageInfo.width || !imageInfo.height || !imageInfo.mimeType) {
|
|
6237
|
-
|
|
6724
|
+
logger13.warning("watermarkify \u8DF3\u8FC7: \u65E0\u6CD5\u89E3\u6790\u622A\u56FE\u5C3A\u5BF8\u6216\u683C\u5F0F");
|
|
6238
6725
|
return buffer;
|
|
6239
6726
|
}
|
|
6240
6727
|
const overlaySvg = buildWatermarkifySvg(meta, imageInfo.width, imageInfo.height);
|
|
@@ -6246,7 +6733,7 @@ var watermarkifyScreenshotBuffer = async (buffer, meta, page = null) => {
|
|
|
6246
6733
|
|
|
6247
6734
|
// src/internals/screenshot-compression.js
|
|
6248
6735
|
import { Jimp, JimpMime, ResizeStrategy } from "jimp";
|
|
6249
|
-
var
|
|
6736
|
+
var logger14 = createInternalLogger("ScreenshotCompression");
|
|
6250
6737
|
var DEFAULT_SCREENSHOT_MAX_BYTES = 5 * 1024 * 1024;
|
|
6251
6738
|
var DEFAULT_SCREENSHOT_OUTPUT_TYPE = "jpeg";
|
|
6252
6739
|
var DEFAULT_SCREENSHOT_QUALITY = 0.72;
|
|
@@ -6365,18 +6852,18 @@ var compressScreenshotBufferToBase64 = async (buffer, compression) => {
|
|
|
6365
6852
|
return buffer.toString("base64");
|
|
6366
6853
|
}
|
|
6367
6854
|
const result = await compressScreenshotBuffer(buffer, compression).catch((error) => {
|
|
6368
|
-
|
|
6855
|
+
logger14.warning(`captureScreen \u538B\u7F29\u5931\u8D25\uFF0C\u8FD4\u56DE\u539F\u56FE: ${error instanceof Error ? error.message : String(error)}`);
|
|
6369
6856
|
return null;
|
|
6370
6857
|
});
|
|
6371
6858
|
if (!result?.buffer) {
|
|
6372
6859
|
return buffer.toString("base64");
|
|
6373
6860
|
}
|
|
6374
6861
|
if (result.withinLimit) {
|
|
6375
|
-
|
|
6862
|
+
logger14.info(
|
|
6376
6863
|
`captureScreen \u5DF2\u538B\u7F29: ${originalBytes} -> ${result.bytes} bytes, format=${result.format}, quality=${result.quality}, scale=${result.scale}, size=${result.width}x${result.height}`
|
|
6377
6864
|
);
|
|
6378
6865
|
} else {
|
|
6379
|
-
|
|
6866
|
+
logger14.warning(
|
|
6380
6867
|
`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}`
|
|
6381
6868
|
);
|
|
6382
6869
|
}
|
|
@@ -6384,7 +6871,7 @@ var compressScreenshotBufferToBase64 = async (buffer, compression) => {
|
|
|
6384
6871
|
};
|
|
6385
6872
|
|
|
6386
6873
|
// src/share.js
|
|
6387
|
-
var
|
|
6874
|
+
var logger15 = createInternalLogger("Share");
|
|
6388
6875
|
var DEFAULT_TIMEOUT_MS2 = 50 * 1e3;
|
|
6389
6876
|
var DEFAULT_PAYLOAD_SNAPSHOT_MAX_LEN = 500;
|
|
6390
6877
|
var DEFAULT_POLL_INTERVAL_MS = 120;
|
|
@@ -6521,7 +7008,7 @@ var createDomShareMonitor = async (page, options = {}) => {
|
|
|
6521
7008
|
const onMatch = typeof options.onMatch === "function" ? options.onMatch : null;
|
|
6522
7009
|
const onTelemetry = typeof options.onTelemetry === "function" ? options.onTelemetry : null;
|
|
6523
7010
|
let matched = false;
|
|
6524
|
-
|
|
7011
|
+
logger15.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode}`);
|
|
6525
7012
|
const monitor = await Mutation.useMonitor(page, selectors, {
|
|
6526
7013
|
mode,
|
|
6527
7014
|
onMutation: (context = {}) => {
|
|
@@ -6539,12 +7026,12 @@ ${text}`;
|
|
|
6539
7026
|
});
|
|
6540
7027
|
}
|
|
6541
7028
|
if (mutationCount <= 5 || mutationCount % 50 === 0) {
|
|
6542
|
-
|
|
7029
|
+
logger15.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);
|
|
6543
7030
|
}
|
|
6544
7031
|
const [candidate] = Utils.parseLinks(rawDom, { prefix }) || [];
|
|
6545
7032
|
if (!candidate) return;
|
|
6546
7033
|
matched = true;
|
|
6547
|
-
|
|
7034
|
+
logger15.success("captureLink.domHit", `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);
|
|
6548
7035
|
if (onMatch) {
|
|
6549
7036
|
onMatch({
|
|
6550
7037
|
link: candidate,
|
|
@@ -6560,7 +7047,7 @@ ${text}`;
|
|
|
6560
7047
|
return {
|
|
6561
7048
|
stop: async () => {
|
|
6562
7049
|
const result = await monitor.stop();
|
|
6563
|
-
|
|
7050
|
+
logger15.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);
|
|
6564
7051
|
return result;
|
|
6565
7052
|
}
|
|
6566
7053
|
};
|
|
@@ -6600,8 +7087,8 @@ var Share = {
|
|
|
6600
7087
|
if (share.mode === "response" && apiMatchers.length === 0) {
|
|
6601
7088
|
throw new Error("Share.captureLink requires share.xurl[0] api matcher when mode=response");
|
|
6602
7089
|
}
|
|
6603
|
-
|
|
6604
|
-
|
|
7090
|
+
logger15.start("captureLink", `mode=${share.mode}, timeoutMs=${timeoutMs}, prefix=${share.prefix}`);
|
|
7091
|
+
logger15.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);
|
|
6605
7092
|
const stats = {
|
|
6606
7093
|
actionTimedOut: false,
|
|
6607
7094
|
domMutationCount: 0,
|
|
@@ -6626,7 +7113,7 @@ var Share = {
|
|
|
6626
7113
|
link: validated,
|
|
6627
7114
|
payloadText: String(payloadText || "")
|
|
6628
7115
|
};
|
|
6629
|
-
|
|
7116
|
+
logger15.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);
|
|
6630
7117
|
return true;
|
|
6631
7118
|
};
|
|
6632
7119
|
const resolveResponseCandidate = (responseText) => {
|
|
@@ -6661,7 +7148,7 @@ var Share = {
|
|
|
6661
7148
|
try {
|
|
6662
7149
|
await monitor.stop();
|
|
6663
7150
|
} catch (error) {
|
|
6664
|
-
|
|
7151
|
+
logger15.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
6665
7152
|
}
|
|
6666
7153
|
};
|
|
6667
7154
|
const onResponse = async (response) => {
|
|
@@ -6674,29 +7161,29 @@ var Share = {
|
|
|
6674
7161
|
stats.responseSampleUrls.push(url);
|
|
6675
7162
|
}
|
|
6676
7163
|
if (stats.responseObserved <= 5) {
|
|
6677
|
-
|
|
7164
|
+
logger15.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);
|
|
6678
7165
|
}
|
|
6679
7166
|
if (!apiMatchers.some((matcher) => url.includes(matcher))) return;
|
|
6680
7167
|
stats.responseMatched += 1;
|
|
6681
7168
|
stats.lastMatchedUrl = url;
|
|
6682
|
-
|
|
7169
|
+
logger15.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);
|
|
6683
7170
|
const text = await response.text();
|
|
6684
7171
|
const hit = resolveResponseCandidate(text);
|
|
6685
7172
|
if (!hit?.link) {
|
|
6686
7173
|
if (stats.responseMatched <= 3) {
|
|
6687
|
-
|
|
7174
|
+
logger15.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);
|
|
6688
7175
|
}
|
|
6689
7176
|
return;
|
|
6690
7177
|
}
|
|
6691
7178
|
stats.responseResolved += 1;
|
|
6692
|
-
|
|
7179
|
+
logger15.success("captureLink.responseHit", `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);
|
|
6693
7180
|
setCandidate("response", hit.link, hit.payloadText);
|
|
6694
7181
|
} catch (error) {
|
|
6695
|
-
|
|
7182
|
+
logger15.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);
|
|
6696
7183
|
}
|
|
6697
7184
|
};
|
|
6698
7185
|
if (share.mode === "dom") {
|
|
6699
|
-
|
|
7186
|
+
logger15.info("\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C");
|
|
6700
7187
|
domMonitor = await createDomShareMonitor(page, {
|
|
6701
7188
|
prefix: share.prefix,
|
|
6702
7189
|
selectors: domSelectors,
|
|
@@ -6711,14 +7198,14 @@ var Share = {
|
|
|
6711
7198
|
});
|
|
6712
7199
|
}
|
|
6713
7200
|
if (share.mode === "response") {
|
|
6714
|
-
|
|
7201
|
+
logger15.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);
|
|
6715
7202
|
page.on("response", onResponse);
|
|
6716
7203
|
}
|
|
6717
7204
|
const deadline = Date.now() + timeoutMs;
|
|
6718
7205
|
const getRemainingMs = () => Math.max(0, deadline - Date.now());
|
|
6719
7206
|
try {
|
|
6720
7207
|
const actionTimeout = getRemainingMs();
|
|
6721
|
-
|
|
7208
|
+
logger15.start("captureLink.performActions", `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${actionTimeout}ms`);
|
|
6722
7209
|
if (actionTimeout > 0) {
|
|
6723
7210
|
let timer = null;
|
|
6724
7211
|
let actionError = null;
|
|
@@ -6732,21 +7219,21 @@ var Share = {
|
|
|
6732
7219
|
const actionResult = await Promise.race([actionPromise, timeoutPromise]);
|
|
6733
7220
|
if (timer) clearTimeout(timer);
|
|
6734
7221
|
if (actionResult === "__ACTION_ERROR__") {
|
|
6735
|
-
|
|
7222
|
+
logger15.fail("captureLink.performActions", actionError);
|
|
6736
7223
|
throw actionError;
|
|
6737
7224
|
}
|
|
6738
7225
|
if (actionResult === "__ACTION_TIMEOUT__") {
|
|
6739
7226
|
stats.actionTimedOut = true;
|
|
6740
|
-
|
|
7227
|
+
logger15.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);
|
|
6741
7228
|
} else {
|
|
6742
|
-
|
|
7229
|
+
logger15.success("captureLink.performActions", "\u6267\u884C\u52A8\u4F5C\u5B8C\u6210");
|
|
6743
7230
|
}
|
|
6744
7231
|
}
|
|
6745
7232
|
let nextProgressLogTs = Date.now() + 3e3;
|
|
6746
7233
|
while (true) {
|
|
6747
7234
|
const selected = share.mode === "dom" ? candidates.dom : candidates.response;
|
|
6748
7235
|
if (selected?.link) {
|
|
6749
|
-
|
|
7236
|
+
logger15.success("captureLink", `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);
|
|
6750
7237
|
return {
|
|
6751
7238
|
link: selected.link,
|
|
6752
7239
|
payloadText: selected.payloadText,
|
|
@@ -6758,19 +7245,19 @@ var Share = {
|
|
|
6758
7245
|
if (remaining <= 0) break;
|
|
6759
7246
|
const now = Date.now();
|
|
6760
7247
|
if (now >= nextProgressLogTs) {
|
|
6761
|
-
|
|
7248
|
+
logger15.info(
|
|
6762
7249
|
`captureLink \u7B49\u5F85\u4E2D: remaining=${remaining}ms, domMutationCount=${stats.domMutationCount}, responseMatched=${stats.responseMatched}`
|
|
6763
7250
|
);
|
|
6764
7251
|
nextProgressLogTs = now + 5e3;
|
|
6765
7252
|
}
|
|
6766
|
-
await
|
|
7253
|
+
await delay3(Math.max(0, Math.min(DEFAULT_POLL_INTERVAL_MS, remaining)));
|
|
6767
7254
|
}
|
|
6768
7255
|
if (share.mode === "response" && stats.responseMatched === 0) {
|
|
6769
|
-
|
|
7256
|
+
logger15.warning(
|
|
6770
7257
|
`\u63A5\u53E3\u76D1\u542C\u672A\u547D\u4E2D: apiMatchers=${toJsonInline(apiMatchers, 220)}, \u54CD\u5E94\u6837\u672CURLs=${toJsonInline(stats.responseSampleUrls, 420)}`
|
|
6771
7258
|
);
|
|
6772
7259
|
}
|
|
6773
|
-
|
|
7260
|
+
logger15.warning(
|
|
6774
7261
|
`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"}`
|
|
6775
7262
|
);
|
|
6776
7263
|
return {
|
|
@@ -6782,7 +7269,7 @@ var Share = {
|
|
|
6782
7269
|
} finally {
|
|
6783
7270
|
if (share.mode === "response") {
|
|
6784
7271
|
page.off("response", onResponse);
|
|
6785
|
-
|
|
7272
|
+
logger15.info("response \u76D1\u542C\u5DF2\u5378\u8F7D");
|
|
6786
7273
|
}
|
|
6787
7274
|
await stopDomMonitor();
|
|
6788
7275
|
}
|
|
@@ -6834,7 +7321,7 @@ var Share = {
|
|
|
6834
7321
|
width: originalViewport.width,
|
|
6835
7322
|
height: targetHeight
|
|
6836
7323
|
});
|
|
6837
|
-
await
|
|
7324
|
+
await delay3(1e3);
|
|
6838
7325
|
const capturedAt = /* @__PURE__ */ new Date();
|
|
6839
7326
|
const rawBuffer = await capturePageScreenshot(page, {
|
|
6840
7327
|
fullPage: true,
|
|
@@ -6875,7 +7362,7 @@ var usePlaywrightToolKit = () => {
|
|
|
6875
7362
|
return {
|
|
6876
7363
|
ApifyKit,
|
|
6877
7364
|
AntiCheat,
|
|
6878
|
-
Humanize,
|
|
7365
|
+
Humanize: Humanize2,
|
|
6879
7366
|
Launch,
|
|
6880
7367
|
LiveView,
|
|
6881
7368
|
Constants: constants_exports,
|