@skrillex1224/playwright-toolkit 2.1.158 → 2.1.160
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/dist/index.cjs +239 -143
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +239 -143
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -335,18 +335,18 @@ var fallbackLog = {
|
|
|
335
335
|
error: (...args) => console.error(...args),
|
|
336
336
|
debug: (...args) => console.debug ? console.debug(...args) : console.log(...args)
|
|
337
337
|
};
|
|
338
|
-
var resolveLogMethod = (
|
|
339
|
-
if (
|
|
340
|
-
return
|
|
338
|
+
var resolveLogMethod = (logger13, name) => {
|
|
339
|
+
if (logger13 && typeof logger13[name] === "function") {
|
|
340
|
+
return logger13[name].bind(logger13);
|
|
341
341
|
}
|
|
342
|
-
if (name === "warning" &&
|
|
343
|
-
return
|
|
342
|
+
if (name === "warning" && logger13 && typeof logger13.warn === "function") {
|
|
343
|
+
return logger13.warn.bind(logger13);
|
|
344
344
|
}
|
|
345
345
|
return fallbackLog[name];
|
|
346
346
|
};
|
|
347
347
|
var defaultLogger = null;
|
|
348
|
-
var setDefaultLogger = (
|
|
349
|
-
defaultLogger =
|
|
348
|
+
var setDefaultLogger = (logger13) => {
|
|
349
|
+
defaultLogger = logger13;
|
|
350
350
|
};
|
|
351
351
|
var resolveLogger = (explicitLogger) => {
|
|
352
352
|
if (explicitLogger && typeof explicitLogger.info === "function") {
|
|
@@ -373,8 +373,8 @@ var colorize = (text, color) => {
|
|
|
373
373
|
var createBaseLogger = (prefix = "", explicitLogger) => {
|
|
374
374
|
const name = prefix ? String(prefix) : "";
|
|
375
375
|
const dispatch = (methodName, icon, message, color) => {
|
|
376
|
-
const
|
|
377
|
-
const logFn = resolveLogMethod(
|
|
376
|
+
const logger13 = resolveLogger(explicitLogger);
|
|
377
|
+
const logFn = resolveLogMethod(logger13, methodName);
|
|
378
378
|
const timestamp = colorize(`[${formatTimestamp()}]`, ANSI.gray);
|
|
379
379
|
const line = formatLine(name, icon, message);
|
|
380
380
|
const coloredLine = colorize(line, color);
|
|
@@ -420,6 +420,97 @@ function createInternalLogger(moduleName, explicitLogger) {
|
|
|
420
420
|
};
|
|
421
421
|
}
|
|
422
422
|
|
|
423
|
+
// src/internals/screenshot.js
|
|
424
|
+
var logger = createInternalLogger("Screenshot");
|
|
425
|
+
var DEFAULT_TIMEOUT_MS = 5e3;
|
|
426
|
+
var SUPPORTED_TYPES = /* @__PURE__ */ new Set(["png", "jpeg", "webp"]);
|
|
427
|
+
var toPositiveNumber = (value, fallback = 0) => {
|
|
428
|
+
const n = Number(value);
|
|
429
|
+
if (!Number.isFinite(n) || n <= 0) return fallback;
|
|
430
|
+
return n;
|
|
431
|
+
};
|
|
432
|
+
var normalizeType = (value) => {
|
|
433
|
+
const raw = String(value || "png").trim().toLowerCase();
|
|
434
|
+
if (!SUPPORTED_TYPES.has(raw)) return "png";
|
|
435
|
+
return raw;
|
|
436
|
+
};
|
|
437
|
+
var normalizeQuality = (value, type) => {
|
|
438
|
+
if (type !== "jpeg" && type !== "webp") return void 0;
|
|
439
|
+
const n = Number(value);
|
|
440
|
+
if (!Number.isFinite(n)) return void 0;
|
|
441
|
+
const rounded = Math.round(n);
|
|
442
|
+
if (rounded < 0 || rounded > 100) return void 0;
|
|
443
|
+
return rounded;
|
|
444
|
+
};
|
|
445
|
+
var buildFullPageClip = (metrics, viewport, maxClipHeight) => {
|
|
446
|
+
const contentSize = metrics && typeof metrics === "object" ? metrics.contentSize || null : null;
|
|
447
|
+
const width = Math.max(1, Math.ceil(contentSize?.width || viewport.width || 1));
|
|
448
|
+
let height = Math.max(1, Math.ceil(contentSize?.height || viewport.height || 1));
|
|
449
|
+
if (maxClipHeight > 0) {
|
|
450
|
+
height = Math.min(height, maxClipHeight);
|
|
451
|
+
}
|
|
452
|
+
return {
|
|
453
|
+
x: 0,
|
|
454
|
+
y: 0,
|
|
455
|
+
width,
|
|
456
|
+
height,
|
|
457
|
+
scale: 1
|
|
458
|
+
};
|
|
459
|
+
};
|
|
460
|
+
var capturePageScreenshot = async (page, options = {}) => {
|
|
461
|
+
const type = normalizeType(options.type);
|
|
462
|
+
const quality = normalizeQuality(options.quality, type);
|
|
463
|
+
const fullPage = Boolean(options.fullPage);
|
|
464
|
+
const timeout = toPositiveNumber(options.timeout, DEFAULT_TIMEOUT_MS);
|
|
465
|
+
const maxClipHeight = Math.round(toPositiveNumber(options.maxClipHeight, 0));
|
|
466
|
+
const fallbackOptions = {
|
|
467
|
+
type: type === "webp" ? "png" : type,
|
|
468
|
+
fullPage
|
|
469
|
+
};
|
|
470
|
+
if (quality !== void 0 && fallbackOptions.type === "jpeg") {
|
|
471
|
+
fallbackOptions.quality = quality;
|
|
472
|
+
}
|
|
473
|
+
if (timeout > 0) {
|
|
474
|
+
fallbackOptions.timeout = timeout;
|
|
475
|
+
}
|
|
476
|
+
try {
|
|
477
|
+
const context = page && typeof page.context === "function" ? page.context() : null;
|
|
478
|
+
if (!context || typeof context.newCDPSession !== "function") {
|
|
479
|
+
throw new Error("CDP session is not available");
|
|
480
|
+
}
|
|
481
|
+
const session = await context.newCDPSession(page);
|
|
482
|
+
try {
|
|
483
|
+
const metrics = await session.send("Page.getLayoutMetrics");
|
|
484
|
+
const viewport = page.viewportSize() || { width: 1280, height: 720 };
|
|
485
|
+
const captureParams = {
|
|
486
|
+
format: type,
|
|
487
|
+
fromSurface: true,
|
|
488
|
+
captureBeyondViewport: fullPage,
|
|
489
|
+
optimizeForSpeed: true
|
|
490
|
+
};
|
|
491
|
+
if (quality !== void 0) {
|
|
492
|
+
captureParams.quality = quality;
|
|
493
|
+
}
|
|
494
|
+
if (fullPage) {
|
|
495
|
+
captureParams.clip = buildFullPageClip(metrics, viewport, maxClipHeight);
|
|
496
|
+
}
|
|
497
|
+
const result = await session.send("Page.captureScreenshot", captureParams);
|
|
498
|
+
if (!result || typeof result.data !== "string" || !result.data) {
|
|
499
|
+
throw new Error("CDP returned empty screenshot data");
|
|
500
|
+
}
|
|
501
|
+
return Buffer.from(result.data, "base64");
|
|
502
|
+
} finally {
|
|
503
|
+
if (typeof session.detach === "function") {
|
|
504
|
+
await session.detach().catch(() => {
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
} catch (error) {
|
|
509
|
+
logger.warning(`CDP \u622A\u56FE\u5931\u8D25\uFF0C\u56DE\u9000 page.screenshot: ${error?.message || error}`);
|
|
510
|
+
return await page.screenshot(fallbackOptions);
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
|
|
423
514
|
// src/errors.js
|
|
424
515
|
var errors_exports = {};
|
|
425
516
|
__export(errors_exports, {
|
|
@@ -493,7 +584,7 @@ var getTrafficSnapshot = () => {
|
|
|
493
584
|
};
|
|
494
585
|
|
|
495
586
|
// src/apify-kit.js
|
|
496
|
-
var
|
|
587
|
+
var logger2 = createInternalLogger("ApifyKit");
|
|
497
588
|
async function createApifyKit() {
|
|
498
589
|
let apify = null;
|
|
499
590
|
try {
|
|
@@ -521,29 +612,29 @@ async function createApifyKit() {
|
|
|
521
612
|
const { times: retryTimes = 0, mode: retryMode = "direct", before: beforeRetry } = retry;
|
|
522
613
|
const executeAction = async (attemptNumber) => {
|
|
523
614
|
const attemptLabel = attemptNumber > 0 ? ` (\u91CD\u8BD5 #${attemptNumber})` : "";
|
|
524
|
-
|
|
615
|
+
logger2.start(`[Step] ${step}${attemptLabel}`);
|
|
525
616
|
try {
|
|
526
617
|
const result = await actionFn();
|
|
527
|
-
|
|
618
|
+
logger2.success(`[Step] ${step}${attemptLabel}`);
|
|
528
619
|
return { success: true, result };
|
|
529
620
|
} catch (error) {
|
|
530
|
-
|
|
621
|
+
logger2.fail(`[Step] ${step}${attemptLabel}`, error);
|
|
531
622
|
return { success: false, error };
|
|
532
623
|
}
|
|
533
624
|
};
|
|
534
625
|
const prepareForRetry = async (attemptNumber) => {
|
|
535
626
|
if (typeof beforeRetry === "function") {
|
|
536
|
-
|
|
627
|
+
logger2.start(`[RetryStep] \u6267\u884C\u81EA\u5B9A\u4E49 before \u94A9\u5B50 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);
|
|
537
628
|
await beforeRetry(page, attemptNumber);
|
|
538
|
-
|
|
629
|
+
logger2.success(`[RetryStep] before \u94A9\u5B50\u5B8C\u6210`);
|
|
539
630
|
} else if (retryMode === "refresh") {
|
|
540
|
-
|
|
631
|
+
logger2.start(`[RetryStep] \u5237\u65B0\u9875\u9762 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);
|
|
541
632
|
await page.reload({ waitUntil: "domcontentloaded" });
|
|
542
|
-
|
|
633
|
+
logger2.success(`[RetryStep] \u9875\u9762\u5237\u65B0\u5B8C\u6210`);
|
|
543
634
|
} else {
|
|
544
|
-
|
|
635
|
+
logger2.start(`[RetryStep] \u7B49\u5F85 3 \u79D2 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);
|
|
545
636
|
await new Promise((resolve) => setTimeout(resolve, 3e3));
|
|
546
|
-
|
|
637
|
+
logger2.success(`[RetryStep] \u7B49\u5F85\u5B8C\u6210`);
|
|
547
638
|
}
|
|
548
639
|
};
|
|
549
640
|
let lastResult = await executeAction(0);
|
|
@@ -551,11 +642,11 @@ async function createApifyKit() {
|
|
|
551
642
|
return lastResult.result;
|
|
552
643
|
}
|
|
553
644
|
for (let attempt = 1; attempt <= retryTimes; attempt++) {
|
|
554
|
-
|
|
645
|
+
logger2.start(`[RetryStep] \u51C6\u5907\u7B2C ${attempt}/${retryTimes} \u6B21\u91CD\u8BD5: ${step}`);
|
|
555
646
|
try {
|
|
556
647
|
await prepareForRetry(attempt);
|
|
557
648
|
} catch (prepareError) {
|
|
558
|
-
|
|
649
|
+
logger2.warn(`[RetryStep] \u91CD\u8BD5\u51C6\u5907\u5931\u8D25: ${prepareError.message}`);
|
|
559
650
|
continue;
|
|
560
651
|
}
|
|
561
652
|
lastResult = await executeAction(attempt);
|
|
@@ -568,11 +659,15 @@ async function createApifyKit() {
|
|
|
568
659
|
let base64 = "\u622A\u56FE\u5931\u8D25";
|
|
569
660
|
try {
|
|
570
661
|
if (page) {
|
|
571
|
-
const buffer = await page
|
|
662
|
+
const buffer = await capturePageScreenshot(page, {
|
|
663
|
+
fullPage: true,
|
|
664
|
+
type: "jpeg",
|
|
665
|
+
quality: 60
|
|
666
|
+
});
|
|
572
667
|
base64 = `data:image/jpeg;base64,${buffer.toString("base64")}`;
|
|
573
668
|
}
|
|
574
669
|
} catch (snapErr) {
|
|
575
|
-
|
|
670
|
+
logger2.warn(`\u622A\u56FE\u751F\u6210\u5931\u8D25: ${snapErr.message}`);
|
|
576
671
|
}
|
|
577
672
|
await this.pushFailed(finalError, {
|
|
578
673
|
step,
|
|
@@ -615,7 +710,7 @@ async function createApifyKit() {
|
|
|
615
710
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
616
711
|
data
|
|
617
712
|
});
|
|
618
|
-
|
|
713
|
+
logger2.success("pushSuccess", "Data pushed");
|
|
619
714
|
},
|
|
620
715
|
/**
|
|
621
716
|
* 推送失败数据的通用方法(私有方法,仅供runStep内部使用)
|
|
@@ -639,7 +734,7 @@ async function createApifyKit() {
|
|
|
639
734
|
context,
|
|
640
735
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
641
736
|
});
|
|
642
|
-
|
|
737
|
+
logger2.success("pushFailed", "Error data pushed");
|
|
643
738
|
}
|
|
644
739
|
};
|
|
645
740
|
}
|
|
@@ -655,7 +750,7 @@ var ApifyKit = {
|
|
|
655
750
|
};
|
|
656
751
|
|
|
657
752
|
// src/internals/utils.js
|
|
658
|
-
var
|
|
753
|
+
var logger3 = createInternalLogger("InternalUtils");
|
|
659
754
|
var parseCookies = (cookieString, domain) => {
|
|
660
755
|
const cookies = [];
|
|
661
756
|
const pairs = cookieString.split(";").map((c) => c.trim());
|
|
@@ -673,7 +768,7 @@ var parseCookies = (cookieString, domain) => {
|
|
|
673
768
|
cookies.push(cookie);
|
|
674
769
|
}
|
|
675
770
|
}
|
|
676
|
-
|
|
771
|
+
logger3.success("parseCookies", `parsed ${cookies.length} cookies`);
|
|
677
772
|
return cookies;
|
|
678
773
|
};
|
|
679
774
|
|
|
@@ -716,7 +811,7 @@ var Utils = {
|
|
|
716
811
|
};
|
|
717
812
|
|
|
718
813
|
// src/anti-cheat.js
|
|
719
|
-
var
|
|
814
|
+
var logger4 = createInternalLogger("AntiCheat");
|
|
720
815
|
var BASE_CONFIG = Object.freeze({
|
|
721
816
|
locale: "zh-CN",
|
|
722
817
|
acceptLanguage: "zh-CN,zh;q=0.9",
|
|
@@ -778,7 +873,7 @@ var AntiCheat = {
|
|
|
778
873
|
// src/humanize.js
|
|
779
874
|
var import_delay = __toESM(require("delay"), 1);
|
|
780
875
|
var import_ghost_cursor_playwright = require("ghost-cursor-playwright");
|
|
781
|
-
var
|
|
876
|
+
var logger5 = createInternalLogger("Humanize");
|
|
782
877
|
var $CursorWeakMap = /* @__PURE__ */ new WeakMap();
|
|
783
878
|
function $GetCursor(page) {
|
|
784
879
|
const cursor = $CursorWeakMap.get(page);
|
|
@@ -806,13 +901,13 @@ var Humanize = {
|
|
|
806
901
|
*/
|
|
807
902
|
async initializeCursor(page) {
|
|
808
903
|
if ($CursorWeakMap.has(page)) {
|
|
809
|
-
|
|
904
|
+
logger5.debug("initializeCursor: cursor already exists, skipping");
|
|
810
905
|
return;
|
|
811
906
|
}
|
|
812
|
-
|
|
907
|
+
logger5.start("initializeCursor", "creating cursor");
|
|
813
908
|
const cursor = await (0, import_ghost_cursor_playwright.createCursor)(page);
|
|
814
909
|
$CursorWeakMap.set(page, cursor);
|
|
815
|
-
|
|
910
|
+
logger5.success("initializeCursor", "cursor initialized");
|
|
816
911
|
},
|
|
817
912
|
/**
|
|
818
913
|
* 人类化鼠标移动 - 使用 ghost-cursor 移动到指定位置或元素
|
|
@@ -822,17 +917,17 @@ var Humanize = {
|
|
|
822
917
|
*/
|
|
823
918
|
async humanMove(page, target) {
|
|
824
919
|
const cursor = $GetCursor(page);
|
|
825
|
-
|
|
920
|
+
logger5.start("humanMove", `target=${typeof target === "string" ? target : "element/coords"}`);
|
|
826
921
|
try {
|
|
827
922
|
if (typeof target === "string") {
|
|
828
923
|
const element = await page.$(target);
|
|
829
924
|
if (!element) {
|
|
830
|
-
|
|
925
|
+
logger5.warn(`humanMove: \u5143\u7D20\u4E0D\u5B58\u5728 ${target}`);
|
|
831
926
|
return false;
|
|
832
927
|
}
|
|
833
928
|
const box = await element.boundingBox();
|
|
834
929
|
if (!box) {
|
|
835
|
-
|
|
930
|
+
logger5.warn(`humanMove: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E ${target}`);
|
|
836
931
|
return false;
|
|
837
932
|
}
|
|
838
933
|
const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.2;
|
|
@@ -848,10 +943,10 @@ var Humanize = {
|
|
|
848
943
|
await cursor.actions.move({ x, y });
|
|
849
944
|
}
|
|
850
945
|
}
|
|
851
|
-
|
|
946
|
+
logger5.success("humanMove");
|
|
852
947
|
return true;
|
|
853
948
|
} catch (error) {
|
|
854
|
-
|
|
949
|
+
logger5.fail("humanMove", error);
|
|
855
950
|
throw error;
|
|
856
951
|
}
|
|
857
952
|
},
|
|
@@ -875,12 +970,12 @@ var Humanize = {
|
|
|
875
970
|
maxDurationMs = maxSteps * 220 + 800
|
|
876
971
|
} = options;
|
|
877
972
|
const targetDesc = typeof target === "string" ? target : "ElementHandle";
|
|
878
|
-
|
|
973
|
+
logger5.start("humanScroll", `target=${targetDesc}`);
|
|
879
974
|
let element;
|
|
880
975
|
if (typeof target === "string") {
|
|
881
976
|
element = await page.$(target);
|
|
882
977
|
if (!element) {
|
|
883
|
-
|
|
978
|
+
logger5.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${target}`);
|
|
884
979
|
return { element: null, didScroll: false };
|
|
885
980
|
}
|
|
886
981
|
} else {
|
|
@@ -955,26 +1050,26 @@ var Humanize = {
|
|
|
955
1050
|
try {
|
|
956
1051
|
for (let i = 0; i < maxSteps; i++) {
|
|
957
1052
|
if (Date.now() - startTime > maxDurationMs) {
|
|
958
|
-
|
|
1053
|
+
logger5.warn(`humanScroll | \u8D85\u65F6\u4FDD\u62A4\u89E6\u53D1 (${maxDurationMs}ms)`);
|
|
959
1054
|
return { element, didScroll };
|
|
960
1055
|
}
|
|
961
1056
|
const status = await checkVisibility();
|
|
962
1057
|
if (status.code === "VISIBLE") {
|
|
963
1058
|
if (status.isFixed) {
|
|
964
|
-
|
|
1059
|
+
logger5.info("humanScroll | fixed \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
|
|
965
1060
|
} else {
|
|
966
|
-
|
|
1061
|
+
logger5.debug("humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321");
|
|
967
1062
|
}
|
|
968
|
-
|
|
1063
|
+
logger5.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
|
|
969
1064
|
return { element, didScroll };
|
|
970
1065
|
}
|
|
971
|
-
|
|
1066
|
+
logger5.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason} ${status.direction ? `(${status.direction})` : ""}`);
|
|
972
1067
|
if (status.code === "OBSTRUCTED" && status.obstruction) {
|
|
973
|
-
|
|
1068
|
+
logger5.debug(`humanScroll | \u88AB\u4EE5\u4E0B\u5143\u7D20\u906E\u6321 <${status.obstruction.tag} id="${status.obstruction.id}">`);
|
|
974
1069
|
}
|
|
975
1070
|
const scrollRect = await getScrollableRect();
|
|
976
1071
|
if (!scrollRect && status.isFixed) {
|
|
977
|
-
|
|
1072
|
+
logger5.warn("humanScroll | fixed \u5BB9\u5668\u5185\u4E14\u65E0\u53EF\u6EDA\u52A8\u7956\u5148\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
|
|
978
1073
|
return { element, didScroll };
|
|
979
1074
|
}
|
|
980
1075
|
const stepMin = scrollRect ? Math.min(minStep, Math.max(60, scrollRect.height * 0.4)) : minStep;
|
|
@@ -1010,10 +1105,10 @@ var Humanize = {
|
|
|
1010
1105
|
didScroll = true;
|
|
1011
1106
|
await (0, import_delay.default)(this.jitterMs(20 + Math.random() * 40, 0.2));
|
|
1012
1107
|
}
|
|
1013
|
-
|
|
1108
|
+
logger5.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);
|
|
1014
1109
|
return { element, didScroll };
|
|
1015
1110
|
} catch (error) {
|
|
1016
|
-
|
|
1111
|
+
logger5.fail("humanScroll", error);
|
|
1017
1112
|
throw error;
|
|
1018
1113
|
}
|
|
1019
1114
|
},
|
|
@@ -1031,7 +1126,7 @@ var Humanize = {
|
|
|
1031
1126
|
const cursor = $GetCursor(page);
|
|
1032
1127
|
const { reactionDelay = 250, throwOnMissing = true, scrollIfNeeded = true, restore = false } = options;
|
|
1033
1128
|
const targetDesc = target == null ? "Current Position" : typeof target === "string" ? target : "ElementHandle";
|
|
1034
|
-
|
|
1129
|
+
logger5.start("humanClick", `target=${targetDesc}`);
|
|
1035
1130
|
const restoreOnce = async () => {
|
|
1036
1131
|
if (restoreOnce.restored) return;
|
|
1037
1132
|
restoreOnce.restored = true;
|
|
@@ -1040,14 +1135,14 @@ var Humanize = {
|
|
|
1040
1135
|
await (0, import_delay.default)(this.jitterMs(1e3));
|
|
1041
1136
|
await restoreOnce.do();
|
|
1042
1137
|
} catch (restoreError) {
|
|
1043
|
-
|
|
1138
|
+
logger5.warn(`humanClick: \u6062\u590D\u6EDA\u52A8\u4F4D\u7F6E\u5931\u8D25: ${restoreError.message}`);
|
|
1044
1139
|
}
|
|
1045
1140
|
};
|
|
1046
1141
|
try {
|
|
1047
1142
|
if (target == null) {
|
|
1048
1143
|
await (0, import_delay.default)(this.jitterMs(reactionDelay, 0.4));
|
|
1049
1144
|
await cursor.actions.click();
|
|
1050
|
-
|
|
1145
|
+
logger5.success("humanClick", "Clicked current position");
|
|
1051
1146
|
return true;
|
|
1052
1147
|
}
|
|
1053
1148
|
let element;
|
|
@@ -1057,7 +1152,7 @@ var Humanize = {
|
|
|
1057
1152
|
if (throwOnMissing) {
|
|
1058
1153
|
throw new Error(`\u627E\u4E0D\u5230\u5143\u7D20 ${target}`);
|
|
1059
1154
|
}
|
|
1060
|
-
|
|
1155
|
+
logger5.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${target}`);
|
|
1061
1156
|
return false;
|
|
1062
1157
|
}
|
|
1063
1158
|
} else {
|
|
@@ -1073,7 +1168,7 @@ var Humanize = {
|
|
|
1073
1168
|
if (throwOnMissing) {
|
|
1074
1169
|
throw new Error("\u65E0\u6CD5\u83B7\u53D6\u5143\u7D20\u4F4D\u7F6E");
|
|
1075
1170
|
}
|
|
1076
|
-
|
|
1171
|
+
logger5.warn("humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB");
|
|
1077
1172
|
return false;
|
|
1078
1173
|
}
|
|
1079
1174
|
const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.3;
|
|
@@ -1082,11 +1177,11 @@ var Humanize = {
|
|
|
1082
1177
|
await (0, import_delay.default)(this.jitterMs(reactionDelay, 0.4));
|
|
1083
1178
|
await cursor.actions.click();
|
|
1084
1179
|
await restoreOnce();
|
|
1085
|
-
|
|
1180
|
+
logger5.success("humanClick");
|
|
1086
1181
|
return true;
|
|
1087
1182
|
} catch (error) {
|
|
1088
1183
|
await restoreOnce();
|
|
1089
|
-
|
|
1184
|
+
logger5.fail("humanClick", error);
|
|
1090
1185
|
throw error;
|
|
1091
1186
|
}
|
|
1092
1187
|
},
|
|
@@ -1097,9 +1192,9 @@ var Humanize = {
|
|
|
1097
1192
|
*/
|
|
1098
1193
|
async randomSleep(baseMs, jitterPercent = 0.3) {
|
|
1099
1194
|
const ms = this.jitterMs(baseMs, jitterPercent);
|
|
1100
|
-
|
|
1195
|
+
logger5.start("randomSleep", `base=${baseMs}, actual=${ms}ms`);
|
|
1101
1196
|
await (0, import_delay.default)(ms);
|
|
1102
|
-
|
|
1197
|
+
logger5.success("randomSleep");
|
|
1103
1198
|
},
|
|
1104
1199
|
/**
|
|
1105
1200
|
* 模拟人类"注视"或"阅读"行为:鼠标在页面上随机微动
|
|
@@ -1109,7 +1204,7 @@ var Humanize = {
|
|
|
1109
1204
|
async simulateGaze(page, baseDurationMs = 2500) {
|
|
1110
1205
|
const cursor = $GetCursor(page);
|
|
1111
1206
|
const durationMs = this.jitterMs(baseDurationMs, 0.4);
|
|
1112
|
-
|
|
1207
|
+
logger5.start("simulateGaze", `duration=${durationMs}ms`);
|
|
1113
1208
|
const startTime = Date.now();
|
|
1114
1209
|
const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };
|
|
1115
1210
|
while (Date.now() - startTime < durationMs) {
|
|
@@ -1118,7 +1213,7 @@ var Humanize = {
|
|
|
1118
1213
|
await cursor.actions.move({ x, y });
|
|
1119
1214
|
await (0, import_delay.default)(this.jitterMs(600, 0.5));
|
|
1120
1215
|
}
|
|
1121
|
-
|
|
1216
|
+
logger5.success("simulateGaze");
|
|
1122
1217
|
},
|
|
1123
1218
|
/**
|
|
1124
1219
|
* 人类化输入 - 带节奏变化(快-慢-停顿-偶尔加速)
|
|
@@ -1131,7 +1226,7 @@ var Humanize = {
|
|
|
1131
1226
|
* @param {number} [options.pauseBase=800] - 停顿时长基础值 (ms),实际 ±50% 抖动
|
|
1132
1227
|
*/
|
|
1133
1228
|
async humanType(page, selector, text, options = {}) {
|
|
1134
|
-
|
|
1229
|
+
logger5.start("humanType", `selector=${selector}, textLen=${text.length}`);
|
|
1135
1230
|
const {
|
|
1136
1231
|
baseDelay = 180,
|
|
1137
1232
|
pauseProbability = 0.08,
|
|
@@ -1155,13 +1250,13 @@ var Humanize = {
|
|
|
1155
1250
|
await (0, import_delay.default)(charDelay);
|
|
1156
1251
|
if (Math.random() < pauseProbability && i < text.length - 1) {
|
|
1157
1252
|
const pauseTime = this.jitterMs(pauseBase, 0.5);
|
|
1158
|
-
|
|
1253
|
+
logger5.debug(`\u505C\u987F ${pauseTime}ms...`);
|
|
1159
1254
|
await (0, import_delay.default)(pauseTime);
|
|
1160
1255
|
}
|
|
1161
1256
|
}
|
|
1162
|
-
|
|
1257
|
+
logger5.success("humanType");
|
|
1163
1258
|
} catch (error) {
|
|
1164
|
-
|
|
1259
|
+
logger5.fail("humanType", error);
|
|
1165
1260
|
throw error;
|
|
1166
1261
|
}
|
|
1167
1262
|
},
|
|
@@ -1171,22 +1266,22 @@ var Humanize = {
|
|
|
1171
1266
|
* @param {string} selector - 输入框选择器
|
|
1172
1267
|
*/
|
|
1173
1268
|
async humanClear(page, selector) {
|
|
1174
|
-
|
|
1269
|
+
logger5.start("humanClear", `selector=${selector}`);
|
|
1175
1270
|
try {
|
|
1176
1271
|
const locator = page.locator(selector);
|
|
1177
1272
|
await locator.click();
|
|
1178
1273
|
await (0, import_delay.default)(this.jitterMs(200, 0.4));
|
|
1179
1274
|
const currentValue = await locator.inputValue();
|
|
1180
1275
|
if (!currentValue || currentValue.length === 0) {
|
|
1181
|
-
|
|
1276
|
+
logger5.success("humanClear", "already empty");
|
|
1182
1277
|
return;
|
|
1183
1278
|
}
|
|
1184
1279
|
await page.keyboard.press("Meta+A");
|
|
1185
1280
|
await (0, import_delay.default)(this.jitterMs(100, 0.4));
|
|
1186
1281
|
await page.keyboard.press("Backspace");
|
|
1187
|
-
|
|
1282
|
+
logger5.success("humanClear");
|
|
1188
1283
|
} catch (error) {
|
|
1189
|
-
|
|
1284
|
+
logger5.fail("humanClear", error);
|
|
1190
1285
|
throw error;
|
|
1191
1286
|
}
|
|
1192
1287
|
},
|
|
@@ -1198,7 +1293,7 @@ var Humanize = {
|
|
|
1198
1293
|
async warmUpBrowsing(page, baseDuration = 3500) {
|
|
1199
1294
|
const cursor = $GetCursor(page);
|
|
1200
1295
|
const durationMs = this.jitterMs(baseDuration, 0.4);
|
|
1201
|
-
|
|
1296
|
+
logger5.start("warmUpBrowsing", `duration=${durationMs}ms`);
|
|
1202
1297
|
const startTime = Date.now();
|
|
1203
1298
|
const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };
|
|
1204
1299
|
try {
|
|
@@ -1217,9 +1312,9 @@ var Humanize = {
|
|
|
1217
1312
|
await (0, import_delay.default)(this.jitterMs(800, 0.5));
|
|
1218
1313
|
}
|
|
1219
1314
|
}
|
|
1220
|
-
|
|
1315
|
+
logger5.success("warmUpBrowsing");
|
|
1221
1316
|
} catch (error) {
|
|
1222
|
-
|
|
1317
|
+
logger5.fail("warmUpBrowsing", error);
|
|
1223
1318
|
throw error;
|
|
1224
1319
|
}
|
|
1225
1320
|
},
|
|
@@ -1233,7 +1328,7 @@ var Humanize = {
|
|
|
1233
1328
|
async naturalScroll(page, direction = "down", distance = 300, baseSteps = 5) {
|
|
1234
1329
|
const steps = Math.max(3, baseSteps + Math.floor(Math.random() * 3) - 1);
|
|
1235
1330
|
const actualDistance = this.jitterMs(distance, 0.15);
|
|
1236
|
-
|
|
1331
|
+
logger5.start("naturalScroll", `dir=${direction}, dist=${actualDistance}, steps=${steps}`);
|
|
1237
1332
|
const sign = direction === "down" ? 1 : -1;
|
|
1238
1333
|
const stepDistance = actualDistance / steps;
|
|
1239
1334
|
try {
|
|
@@ -1245,9 +1340,9 @@ var Humanize = {
|
|
|
1245
1340
|
const baseDelay = 60 + i * 25;
|
|
1246
1341
|
await (0, import_delay.default)(this.jitterMs(baseDelay, 0.3));
|
|
1247
1342
|
}
|
|
1248
|
-
|
|
1343
|
+
logger5.success("naturalScroll");
|
|
1249
1344
|
} catch (error) {
|
|
1250
|
-
|
|
1345
|
+
logger5.fail("naturalScroll", error);
|
|
1251
1346
|
throw error;
|
|
1252
1347
|
}
|
|
1253
1348
|
}
|
|
@@ -1315,7 +1410,7 @@ var resolveRouteByProxy = ({
|
|
|
1315
1410
|
};
|
|
1316
1411
|
|
|
1317
1412
|
// src/traffic-meter.js
|
|
1318
|
-
var
|
|
1413
|
+
var logger6 = createInternalLogger("TrafficMeter");
|
|
1319
1414
|
var encoder = new TextEncoder();
|
|
1320
1415
|
var toSafeNumber = (value) => {
|
|
1321
1416
|
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return 0;
|
|
@@ -1485,7 +1580,7 @@ var createTrafficMeter = ({
|
|
|
1485
1580
|
session.on("Network.webSocketFrameSent", recordWebSocketFrameSent);
|
|
1486
1581
|
session.on("Network.webSocketFrameReceived", recordWebSocketFrameReceived);
|
|
1487
1582
|
} catch (error) {
|
|
1488
|
-
|
|
1583
|
+
logger6.warn(`CDP \u76D1\u542C\u6CE8\u518C\u5931\u8D25: ${error?.message || error}`);
|
|
1489
1584
|
}
|
|
1490
1585
|
};
|
|
1491
1586
|
const snapshot = () => {
|
|
@@ -1521,7 +1616,7 @@ var createTrafficMeter = ({
|
|
|
1521
1616
|
};
|
|
1522
1617
|
|
|
1523
1618
|
// src/launch.js
|
|
1524
|
-
var
|
|
1619
|
+
var logger7 = createInternalLogger("Launch");
|
|
1525
1620
|
var resolveProxyLaunchOptions = (proxyConfiguration = {}) => {
|
|
1526
1621
|
const config = proxyConfiguration && typeof proxyConfiguration === "object" && !Array.isArray(proxyConfiguration) ? proxyConfiguration : {};
|
|
1527
1622
|
const proxyUrl = String(config.proxy_url || "").trim();
|
|
@@ -1573,15 +1668,15 @@ var Launch = {
|
|
|
1573
1668
|
}
|
|
1574
1669
|
const enableByPassLogger = Boolean(logOptions && logOptions.enable);
|
|
1575
1670
|
if (enableByPassLogger && launchProxy) {
|
|
1576
|
-
|
|
1671
|
+
logger7.info(
|
|
1577
1672
|
`[\u4EE3\u7406\u5DF2\u542F\u7528] \u4EE3\u7406\u670D\u52A1=${launchProxy.server} \u76F4\u8FDE\u57DF\u540D=${(byPassDomains || []).join(",")}`
|
|
1578
1673
|
);
|
|
1579
1674
|
} else if (enableByPassLogger && enableProxy && !launchProxy) {
|
|
1580
|
-
|
|
1675
|
+
logger7.info(
|
|
1581
1676
|
`[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=true \u4F46 proxy_url \u4E3A\u7A7A`
|
|
1582
1677
|
);
|
|
1583
1678
|
} else if (enableByPassLogger && !enableProxy && proxyUrl) {
|
|
1584
|
-
|
|
1679
|
+
logger7.info(
|
|
1585
1680
|
`[\u4EE3\u7406\u672A\u542F\u7528] enable_proxy=false \u4E14 proxy_url \u5DF2\u914D\u7F6E`
|
|
1586
1681
|
);
|
|
1587
1682
|
}
|
|
@@ -1599,7 +1694,7 @@ var Launch = {
|
|
|
1599
1694
|
const requestUrl = req.url();
|
|
1600
1695
|
const matched = findMatchedByPassRule(byPassRules, requestUrl);
|
|
1601
1696
|
if (!matched || !matched.rule) return;
|
|
1602
|
-
|
|
1697
|
+
logger7.info(`[\u76F4\u8FDE\u547D\u4E2D] \u89C4\u5219=${matched.rule.pattern} \u57DF\u540D=${matched.hostname} \u8D44\u6E90\u7C7B\u578B=${req.resourceType()} \u65B9\u6CD5=${req.method()} \u5730\u5740=${requestUrl}`);
|
|
1603
1698
|
};
|
|
1604
1699
|
page.on("request", requestHandler);
|
|
1605
1700
|
return recommendedGotoOptions;
|
|
@@ -1618,7 +1713,7 @@ var Launch = {
|
|
|
1618
1713
|
// src/live-view.js
|
|
1619
1714
|
var import_express = __toESM(require("express"), 1);
|
|
1620
1715
|
var import_apify = require("apify");
|
|
1621
|
-
var
|
|
1716
|
+
var logger8 = createInternalLogger("LiveView");
|
|
1622
1717
|
async function startLiveViewServer(liveViewKey) {
|
|
1623
1718
|
const app = (0, import_express.default)();
|
|
1624
1719
|
app.get("/", async (req, res) => {
|
|
@@ -1643,24 +1738,24 @@ async function startLiveViewServer(liveViewKey) {
|
|
|
1643
1738
|
</html>
|
|
1644
1739
|
`);
|
|
1645
1740
|
} catch (error) {
|
|
1646
|
-
|
|
1741
|
+
logger8.fail("Live View Server", error);
|
|
1647
1742
|
res.status(500).send(`\u65E0\u6CD5\u52A0\u8F7D\u5C4F\u5E55\u622A\u56FE: ${error.message}`);
|
|
1648
1743
|
}
|
|
1649
1744
|
});
|
|
1650
1745
|
const port = process.env.APIFY_CONTAINER_PORT || 4321;
|
|
1651
1746
|
app.listen(port, () => {
|
|
1652
|
-
|
|
1747
|
+
logger8.success("startLiveViewServer", `\u76D1\u542C\u7AEF\u53E3 ${port}`);
|
|
1653
1748
|
});
|
|
1654
1749
|
}
|
|
1655
1750
|
async function takeLiveScreenshot(liveViewKey, page, logMessage) {
|
|
1656
1751
|
try {
|
|
1657
|
-
const buffer = await page
|
|
1752
|
+
const buffer = await capturePageScreenshot(page, { type: "png" });
|
|
1658
1753
|
await import_apify.Actor.setValue(liveViewKey, buffer, { contentType: "image/png" });
|
|
1659
1754
|
if (logMessage) {
|
|
1660
|
-
|
|
1755
|
+
logger8.info(`(\u622A\u56FE): ${logMessage}`);
|
|
1661
1756
|
}
|
|
1662
1757
|
} catch (e) {
|
|
1663
|
-
|
|
1758
|
+
logger8.warn(`\u65E0\u6CD5\u6355\u83B7 Live View \u5C4F\u5E55\u622A\u56FE: ${e.message}`);
|
|
1664
1759
|
}
|
|
1665
1760
|
}
|
|
1666
1761
|
var useLiveView = (liveViewKey = PresetOfLiveViewKey) => {
|
|
@@ -1679,7 +1774,7 @@ var LiveView = {
|
|
|
1679
1774
|
|
|
1680
1775
|
// src/captcha-monitor.js
|
|
1681
1776
|
var import_uuid = require("uuid");
|
|
1682
|
-
var
|
|
1777
|
+
var logger9 = createInternalLogger("Captcha");
|
|
1683
1778
|
function useCaptchaMonitor(page, options) {
|
|
1684
1779
|
const { domSelector, urlPattern, onDetected } = options;
|
|
1685
1780
|
if (!domSelector && !urlPattern) {
|
|
@@ -1752,7 +1847,7 @@ function useCaptchaMonitor(page, options) {
|
|
|
1752
1847
|
};
|
|
1753
1848
|
})();
|
|
1754
1849
|
}, { selector: domSelector, callbackName: exposedFunctionName, cleanerName });
|
|
1755
|
-
|
|
1850
|
+
logger9.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528: ${domSelector}`);
|
|
1756
1851
|
cleanupFns.push(async () => {
|
|
1757
1852
|
try {
|
|
1758
1853
|
await page.evaluate((name) => {
|
|
@@ -1775,14 +1870,14 @@ function useCaptchaMonitor(page, options) {
|
|
|
1775
1870
|
}
|
|
1776
1871
|
};
|
|
1777
1872
|
page.on("framenavigated", frameHandler);
|
|
1778
|
-
|
|
1873
|
+
logger9.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528: ${urlPattern}`);
|
|
1779
1874
|
cleanupFns.push(async () => {
|
|
1780
1875
|
page.off("framenavigated", frameHandler);
|
|
1781
1876
|
});
|
|
1782
1877
|
}
|
|
1783
1878
|
return {
|
|
1784
1879
|
stop: async () => {
|
|
1785
|
-
|
|
1880
|
+
logger9.info("useCaptchaMonitor", "\u6B63\u5728\u505C\u6B62\u76D1\u63A7...");
|
|
1786
1881
|
for (const fn of cleanupFns) {
|
|
1787
1882
|
await fn();
|
|
1788
1883
|
}
|
|
@@ -1797,7 +1892,7 @@ var Captcha = {
|
|
|
1797
1892
|
// src/sse.js
|
|
1798
1893
|
var import_https = __toESM(require("https"), 1);
|
|
1799
1894
|
var import_url = require("url");
|
|
1800
|
-
var
|
|
1895
|
+
var logger10 = createInternalLogger("Sse");
|
|
1801
1896
|
var Sse = {
|
|
1802
1897
|
/**
|
|
1803
1898
|
* 解析 SSE 流文本
|
|
@@ -1816,11 +1911,11 @@ var Sse = {
|
|
|
1816
1911
|
events.push(JSON.parse(jsonContent));
|
|
1817
1912
|
}
|
|
1818
1913
|
} catch (e) {
|
|
1819
|
-
|
|
1914
|
+
logger10.debug("parseSseStream", `JSON \u89E3\u6790\u5931\u8D25: ${e.message}, line: ${line.substring(0, 100)}...`);
|
|
1820
1915
|
}
|
|
1821
1916
|
}
|
|
1822
1917
|
}
|
|
1823
|
-
|
|
1918
|
+
logger10.success("parseSseStream", `\u89E3\u6790\u5B8C\u6210, events \u6570\u91CF: ${events.length}`);
|
|
1824
1919
|
return events;
|
|
1825
1920
|
},
|
|
1826
1921
|
/**
|
|
@@ -1870,7 +1965,7 @@ var Sse = {
|
|
|
1870
1965
|
if (!autoUnroute) return;
|
|
1871
1966
|
if (unrouteRequested) return;
|
|
1872
1967
|
unrouteRequested = true;
|
|
1873
|
-
|
|
1968
|
+
logger10.info("[MITM] autoUnroute: \u53D6\u6D88\u540E\u7EED\u62E6\u622A");
|
|
1874
1969
|
page.unroute(urlPattern, routeHandler).catch(() => {
|
|
1875
1970
|
});
|
|
1876
1971
|
};
|
|
@@ -1890,19 +1985,19 @@ var Sse = {
|
|
|
1890
1985
|
};
|
|
1891
1986
|
const routeHandler = async (route) => {
|
|
1892
1987
|
if (firstMatchOnly && hasMatchedOnce) {
|
|
1893
|
-
|
|
1988
|
+
logger10.info(`[MITM] firstMatchOnly: \u653E\u884C\u540E\u7EED\u8BF7\u6C42: ${route.request().url()}`);
|
|
1894
1989
|
route.continue().catch(() => {
|
|
1895
1990
|
});
|
|
1896
1991
|
return;
|
|
1897
1992
|
}
|
|
1898
1993
|
if (firstMatchOnly && !hasMatchedOnce) {
|
|
1899
1994
|
hasMatchedOnce = true;
|
|
1900
|
-
|
|
1995
|
+
logger10.info("[MITM] firstMatchOnly: \u547D\u4E2D\u9996\u4E2A\u8BF7\u6C42\uFF0C\u53D6\u6D88\u540E\u7EED\u62E6\u622A");
|
|
1901
1996
|
page.unroute(urlPattern, routeHandler).catch(() => {
|
|
1902
1997
|
});
|
|
1903
1998
|
}
|
|
1904
1999
|
const request = route.request();
|
|
1905
|
-
|
|
2000
|
+
logger10.info(`[MITM] \u5DF2\u62E6\u622A\u8BF7\u6C42: ${request.url()}`);
|
|
1906
2001
|
try {
|
|
1907
2002
|
const headers = await request.allHeaders();
|
|
1908
2003
|
const postData = request.postData();
|
|
@@ -1927,7 +2022,7 @@ var Sse = {
|
|
|
1927
2022
|
clearTimeout(initialTimer);
|
|
1928
2023
|
initialTimer = null;
|
|
1929
2024
|
}
|
|
1930
|
-
|
|
2025
|
+
logger10.debug("[Intercept] \u5DF2\u63A5\u6536\u521D\u59CB\u6570\u636E");
|
|
1931
2026
|
}
|
|
1932
2027
|
chunks.push(chunk);
|
|
1933
2028
|
const textChunk = chunk.toString("utf-8");
|
|
@@ -1936,18 +2031,18 @@ var Sse = {
|
|
|
1936
2031
|
try {
|
|
1937
2032
|
onData(textChunk, safeResolve, accumulatedText);
|
|
1938
2033
|
} catch (e) {
|
|
1939
|
-
|
|
2034
|
+
logger10.fail(`onData \u9519\u8BEF`, e);
|
|
1940
2035
|
}
|
|
1941
2036
|
}
|
|
1942
2037
|
});
|
|
1943
2038
|
res.on("end", () => {
|
|
1944
|
-
|
|
2039
|
+
logger10.info("[MITM] \u4E0A\u6E38\u54CD\u5E94\u7ED3\u675F");
|
|
1945
2040
|
clearAllTimers();
|
|
1946
2041
|
if (onEnd) {
|
|
1947
2042
|
try {
|
|
1948
2043
|
onEnd(accumulatedText, safeResolve);
|
|
1949
2044
|
} catch (e) {
|
|
1950
|
-
|
|
2045
|
+
logger10.fail(`onEnd \u9519\u8BEF`, e);
|
|
1951
2046
|
}
|
|
1952
2047
|
} else if (!onData) {
|
|
1953
2048
|
safeResolve(accumulatedText);
|
|
@@ -2028,7 +2123,7 @@ var Sse = {
|
|
|
2028
2123
|
|
|
2029
2124
|
// src/mutation.js
|
|
2030
2125
|
var import_uuid2 = require("uuid");
|
|
2031
|
-
var
|
|
2126
|
+
var logger11 = createInternalLogger("Mutation");
|
|
2032
2127
|
var MUTATION_MONITOR_MODE = Object.freeze({
|
|
2033
2128
|
Added: "added",
|
|
2034
2129
|
Changed: "changed",
|
|
@@ -2061,14 +2156,14 @@ var Mutation = {
|
|
|
2061
2156
|
const stableTime = options.stableTime ?? 5 * 1e3;
|
|
2062
2157
|
const timeout = options.timeout ?? 120 * 1e3;
|
|
2063
2158
|
const onMutation = options.onMutation;
|
|
2064
|
-
|
|
2159
|
+
logger11.start("waitForStable", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);
|
|
2065
2160
|
if (initialTimeout > 0) {
|
|
2066
2161
|
const selectorQuery = selectorList.join(",");
|
|
2067
2162
|
try {
|
|
2068
2163
|
await page.waitForSelector(selectorQuery, { timeout: initialTimeout });
|
|
2069
|
-
|
|
2164
|
+
logger11.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
|
|
2070
2165
|
} catch (e) {
|
|
2071
|
-
|
|
2166
|
+
logger11.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
|
|
2072
2167
|
throw e;
|
|
2073
2168
|
}
|
|
2074
2169
|
}
|
|
@@ -2084,7 +2179,7 @@ var Mutation = {
|
|
|
2084
2179
|
return "__CONTINUE__";
|
|
2085
2180
|
}
|
|
2086
2181
|
});
|
|
2087
|
-
|
|
2182
|
+
logger11.info("waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03");
|
|
2088
2183
|
} catch (e) {
|
|
2089
2184
|
}
|
|
2090
2185
|
}
|
|
@@ -2199,9 +2294,9 @@ var Mutation = {
|
|
|
2199
2294
|
{ selectorList, stableTime, timeout, callbackName, hasCallback: !!onMutation }
|
|
2200
2295
|
);
|
|
2201
2296
|
if (result.mutationCount === 0 && result.stableTime === 0) {
|
|
2202
|
-
|
|
2297
|
+
logger11.warning("waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
|
|
2203
2298
|
}
|
|
2204
|
-
|
|
2299
|
+
logger11.success("waitForStable", `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
|
|
2205
2300
|
return result;
|
|
2206
2301
|
},
|
|
2207
2302
|
/**
|
|
@@ -2221,7 +2316,7 @@ var Mutation = {
|
|
|
2221
2316
|
const onMutation = options.onMutation;
|
|
2222
2317
|
const rawMode = String(options.mode || MUTATION_MONITOR_MODE.Added).toLowerCase();
|
|
2223
2318
|
const mode = [MUTATION_MONITOR_MODE.Added, MUTATION_MONITOR_MODE.Changed, MUTATION_MONITOR_MODE.All].includes(rawMode) ? rawMode : MUTATION_MONITOR_MODE.Added;
|
|
2224
|
-
|
|
2319
|
+
logger11.start("useMonitor", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode}`);
|
|
2225
2320
|
const monitorKey = generateKey("pk_mon");
|
|
2226
2321
|
const callbackName = generateKey("pk_mon_cb");
|
|
2227
2322
|
const cleanerName = generateKey("pk_mon_clean");
|
|
@@ -2364,7 +2459,7 @@ var Mutation = {
|
|
|
2364
2459
|
return total;
|
|
2365
2460
|
};
|
|
2366
2461
|
}, { selectorList, monitorKey, callbackName, cleanerName, hasCallback: !!onMutation, mode });
|
|
2367
|
-
|
|
2462
|
+
logger11.success("useMonitor", "\u76D1\u63A7\u5668\u5DF2\u542F\u52A8");
|
|
2368
2463
|
return {
|
|
2369
2464
|
stop: async () => {
|
|
2370
2465
|
let totalMutations = 0;
|
|
@@ -2377,7 +2472,7 @@ var Mutation = {
|
|
|
2377
2472
|
}, cleanerName);
|
|
2378
2473
|
} catch (e) {
|
|
2379
2474
|
}
|
|
2380
|
-
|
|
2475
|
+
logger11.success("useMonitor.stop", `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);
|
|
2381
2476
|
return { totalMutations };
|
|
2382
2477
|
}
|
|
2383
2478
|
};
|
|
@@ -3246,7 +3341,7 @@ var createTemplateLogger = (baseLogger = createBaseLogger()) => {
|
|
|
3246
3341
|
};
|
|
3247
3342
|
var getDefaultBaseLogger = () => createBaseLogger("");
|
|
3248
3343
|
var Logger = {
|
|
3249
|
-
setLogger: (
|
|
3344
|
+
setLogger: (logger13) => setDefaultLogger(logger13),
|
|
3250
3345
|
info: (message) => getDefaultBaseLogger().info(message),
|
|
3251
3346
|
success: (message) => getDefaultBaseLogger().success(message),
|
|
3252
3347
|
warning: (message) => getDefaultBaseLogger().warning(message),
|
|
@@ -3254,16 +3349,16 @@ var Logger = {
|
|
|
3254
3349
|
error: (message) => getDefaultBaseLogger().error(message),
|
|
3255
3350
|
debug: (message) => getDefaultBaseLogger().debug(message),
|
|
3256
3351
|
start: (message) => getDefaultBaseLogger().start(message),
|
|
3257
|
-
useTemplate: (
|
|
3258
|
-
if (
|
|
3352
|
+
useTemplate: (logger13) => {
|
|
3353
|
+
if (logger13) return createTemplateLogger(createBaseLogger("", logger13));
|
|
3259
3354
|
return createTemplateLogger();
|
|
3260
3355
|
}
|
|
3261
3356
|
};
|
|
3262
3357
|
|
|
3263
3358
|
// src/share.js
|
|
3264
3359
|
var import_delay2 = __toESM(require("delay"), 1);
|
|
3265
|
-
var
|
|
3266
|
-
var
|
|
3360
|
+
var logger12 = createInternalLogger("Share");
|
|
3361
|
+
var DEFAULT_TIMEOUT_MS2 = 50 * 1e3;
|
|
3267
3362
|
var DEFAULT_PAYLOAD_SNAPSHOT_MAX_LEN = 500;
|
|
3268
3363
|
var DEFAULT_POLL_INTERVAL_MS = 120;
|
|
3269
3364
|
var normalizePrefix = (value) => value == null ? void 0 : String(value).trim();
|
|
@@ -3382,7 +3477,7 @@ var createDomShareMonitor = async (page, options = {}) => {
|
|
|
3382
3477
|
const onMatch = typeof options.onMatch === "function" ? options.onMatch : null;
|
|
3383
3478
|
const onTelemetry = typeof options.onTelemetry === "function" ? options.onTelemetry : null;
|
|
3384
3479
|
let matched = false;
|
|
3385
|
-
|
|
3480
|
+
logger12.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode}`);
|
|
3386
3481
|
const monitor = await Mutation.useMonitor(page, selectors, {
|
|
3387
3482
|
mode,
|
|
3388
3483
|
onMutation: (context = {}) => {
|
|
@@ -3400,12 +3495,12 @@ ${text}`;
|
|
|
3400
3495
|
});
|
|
3401
3496
|
}
|
|
3402
3497
|
if (mutationCount <= 5 || mutationCount % 50 === 0) {
|
|
3403
|
-
|
|
3498
|
+
logger12.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);
|
|
3404
3499
|
}
|
|
3405
3500
|
const [candidate] = Utils.parseLinks(rawDom, { prefix }) || [];
|
|
3406
3501
|
if (!candidate) return;
|
|
3407
3502
|
matched = true;
|
|
3408
|
-
|
|
3503
|
+
logger12.success("captureLink.domHit", `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);
|
|
3409
3504
|
if (onMatch) {
|
|
3410
3505
|
onMatch({
|
|
3411
3506
|
link: candidate,
|
|
@@ -3421,7 +3516,7 @@ ${text}`;
|
|
|
3421
3516
|
return {
|
|
3422
3517
|
stop: async () => {
|
|
3423
3518
|
const result = await monitor.stop();
|
|
3424
|
-
|
|
3519
|
+
logger12.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);
|
|
3425
3520
|
return result;
|
|
3426
3521
|
}
|
|
3427
3522
|
};
|
|
@@ -3444,7 +3539,7 @@ var Share = {
|
|
|
3444
3539
|
*/
|
|
3445
3540
|
async captureLink(page, options = {}) {
|
|
3446
3541
|
const share = normalizeShare(options.share);
|
|
3447
|
-
const timeoutMs = Math.max(0, Number(options.timeoutMs ??
|
|
3542
|
+
const timeoutMs = Math.max(0, Number(options.timeoutMs ?? DEFAULT_TIMEOUT_MS2) || 0);
|
|
3448
3543
|
const payloadSnapshotMaxLen = options.payloadSnapshotMaxLen ?? DEFAULT_PAYLOAD_SNAPSHOT_MAX_LEN;
|
|
3449
3544
|
const domSelectors = options.domSelectors ?? "html";
|
|
3450
3545
|
const domMode = options.domMode ?? Mutation.Mode.All;
|
|
@@ -3461,8 +3556,8 @@ var Share = {
|
|
|
3461
3556
|
if (share.mode === "response" && apiMatchers.length === 0) {
|
|
3462
3557
|
throw new Error("Share.captureLink requires share.xurl[0] api matcher when mode=response");
|
|
3463
3558
|
}
|
|
3464
|
-
|
|
3465
|
-
|
|
3559
|
+
logger12.start("captureLink", `mode=${share.mode}, timeoutMs=${timeoutMs}, prefix=${share.prefix}`);
|
|
3560
|
+
logger12.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);
|
|
3466
3561
|
const stats = {
|
|
3467
3562
|
actionTimedOut: false,
|
|
3468
3563
|
domMutationCount: 0,
|
|
@@ -3487,7 +3582,7 @@ var Share = {
|
|
|
3487
3582
|
link: validated,
|
|
3488
3583
|
payloadText: String(payloadText || "")
|
|
3489
3584
|
};
|
|
3490
|
-
|
|
3585
|
+
logger12.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);
|
|
3491
3586
|
return true;
|
|
3492
3587
|
};
|
|
3493
3588
|
const resolveResponseCandidate = (responseText) => {
|
|
@@ -3522,7 +3617,7 @@ var Share = {
|
|
|
3522
3617
|
try {
|
|
3523
3618
|
await monitor.stop();
|
|
3524
3619
|
} catch (error) {
|
|
3525
|
-
|
|
3620
|
+
logger12.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
3526
3621
|
}
|
|
3527
3622
|
};
|
|
3528
3623
|
const onResponse = async (response) => {
|
|
@@ -3535,29 +3630,29 @@ var Share = {
|
|
|
3535
3630
|
stats.responseSampleUrls.push(url);
|
|
3536
3631
|
}
|
|
3537
3632
|
if (stats.responseObserved <= 5) {
|
|
3538
|
-
|
|
3633
|
+
logger12.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);
|
|
3539
3634
|
}
|
|
3540
3635
|
if (!apiMatchers.some((matcher) => url.includes(matcher))) return;
|
|
3541
3636
|
stats.responseMatched += 1;
|
|
3542
3637
|
stats.lastMatchedUrl = url;
|
|
3543
|
-
|
|
3638
|
+
logger12.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);
|
|
3544
3639
|
const text = await response.text();
|
|
3545
3640
|
const hit = resolveResponseCandidate(text);
|
|
3546
3641
|
if (!hit?.link) {
|
|
3547
3642
|
if (stats.responseMatched <= 3) {
|
|
3548
|
-
|
|
3643
|
+
logger12.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);
|
|
3549
3644
|
}
|
|
3550
3645
|
return;
|
|
3551
3646
|
}
|
|
3552
3647
|
stats.responseResolved += 1;
|
|
3553
|
-
|
|
3648
|
+
logger12.success("captureLink.responseHit", `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);
|
|
3554
3649
|
setCandidate("response", hit.link, hit.payloadText);
|
|
3555
3650
|
} catch (error) {
|
|
3556
|
-
|
|
3651
|
+
logger12.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);
|
|
3557
3652
|
}
|
|
3558
3653
|
};
|
|
3559
3654
|
if (share.mode === "dom") {
|
|
3560
|
-
|
|
3655
|
+
logger12.info("\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C");
|
|
3561
3656
|
domMonitor = await createDomShareMonitor(page, {
|
|
3562
3657
|
prefix: share.prefix,
|
|
3563
3658
|
selectors: domSelectors,
|
|
@@ -3572,14 +3667,14 @@ var Share = {
|
|
|
3572
3667
|
});
|
|
3573
3668
|
}
|
|
3574
3669
|
if (share.mode === "response") {
|
|
3575
|
-
|
|
3670
|
+
logger12.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);
|
|
3576
3671
|
page.on("response", onResponse);
|
|
3577
3672
|
}
|
|
3578
3673
|
const deadline = Date.now() + timeoutMs;
|
|
3579
3674
|
const getRemainingMs = () => Math.max(0, deadline - Date.now());
|
|
3580
3675
|
try {
|
|
3581
3676
|
const actionTimeout = getRemainingMs();
|
|
3582
|
-
|
|
3677
|
+
logger12.start("captureLink.performActions", `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${actionTimeout}ms`);
|
|
3583
3678
|
if (actionTimeout > 0) {
|
|
3584
3679
|
let timer = null;
|
|
3585
3680
|
let actionError = null;
|
|
@@ -3593,21 +3688,21 @@ var Share = {
|
|
|
3593
3688
|
const actionResult = await Promise.race([actionPromise, timeoutPromise]);
|
|
3594
3689
|
if (timer) clearTimeout(timer);
|
|
3595
3690
|
if (actionResult === "__ACTION_ERROR__") {
|
|
3596
|
-
|
|
3691
|
+
logger12.fail("captureLink.performActions", actionError);
|
|
3597
3692
|
throw actionError;
|
|
3598
3693
|
}
|
|
3599
3694
|
if (actionResult === "__ACTION_TIMEOUT__") {
|
|
3600
3695
|
stats.actionTimedOut = true;
|
|
3601
|
-
|
|
3696
|
+
logger12.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);
|
|
3602
3697
|
} else {
|
|
3603
|
-
|
|
3698
|
+
logger12.success("captureLink.performActions", "\u6267\u884C\u52A8\u4F5C\u5B8C\u6210");
|
|
3604
3699
|
}
|
|
3605
3700
|
}
|
|
3606
3701
|
let nextProgressLogTs = Date.now() + 3e3;
|
|
3607
3702
|
while (true) {
|
|
3608
3703
|
const selected = share.mode === "dom" ? candidates.dom : candidates.response;
|
|
3609
3704
|
if (selected?.link) {
|
|
3610
|
-
|
|
3705
|
+
logger12.success("captureLink", `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);
|
|
3611
3706
|
return {
|
|
3612
3707
|
link: selected.link,
|
|
3613
3708
|
payloadText: selected.payloadText,
|
|
@@ -3619,7 +3714,7 @@ var Share = {
|
|
|
3619
3714
|
if (remaining <= 0) break;
|
|
3620
3715
|
const now = Date.now();
|
|
3621
3716
|
if (now >= nextProgressLogTs) {
|
|
3622
|
-
|
|
3717
|
+
logger12.info(
|
|
3623
3718
|
`captureLink \u7B49\u5F85\u4E2D: remaining=${remaining}ms, domMutationCount=${stats.domMutationCount}, responseMatched=${stats.responseMatched}`
|
|
3624
3719
|
);
|
|
3625
3720
|
nextProgressLogTs = now + 5e3;
|
|
@@ -3627,11 +3722,11 @@ var Share = {
|
|
|
3627
3722
|
await (0, import_delay2.default)(Math.max(0, Math.min(DEFAULT_POLL_INTERVAL_MS, remaining)));
|
|
3628
3723
|
}
|
|
3629
3724
|
if (share.mode === "response" && stats.responseMatched === 0) {
|
|
3630
|
-
|
|
3725
|
+
logger12.warning(
|
|
3631
3726
|
`\u63A5\u53E3\u76D1\u542C\u672A\u547D\u4E2D: apiMatchers=${toJsonInline(apiMatchers, 220)}, \u54CD\u5E94\u6837\u672CURLs=${toJsonInline(stats.responseSampleUrls, 420)}`
|
|
3632
3727
|
);
|
|
3633
3728
|
}
|
|
3634
|
-
|
|
3729
|
+
logger12.warning(
|
|
3635
3730
|
`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"}`
|
|
3636
3731
|
);
|
|
3637
3732
|
return {
|
|
@@ -3643,7 +3738,7 @@ var Share = {
|
|
|
3643
3738
|
} finally {
|
|
3644
3739
|
if (share.mode === "response") {
|
|
3645
3740
|
page.off("response", onResponse);
|
|
3646
|
-
|
|
3741
|
+
logger12.info("response \u76D1\u542C\u5DF2\u5378\u8F7D");
|
|
3647
3742
|
}
|
|
3648
3743
|
await stopDomMonitor();
|
|
3649
3744
|
}
|
|
@@ -3691,9 +3786,10 @@ var Share = {
|
|
|
3691
3786
|
height: targetHeight
|
|
3692
3787
|
});
|
|
3693
3788
|
await (0, import_delay2.default)(1e3);
|
|
3694
|
-
const buffer_ = await page
|
|
3789
|
+
const buffer_ = await capturePageScreenshot(page, {
|
|
3695
3790
|
fullPage: true,
|
|
3696
|
-
type: "png"
|
|
3791
|
+
type: "png",
|
|
3792
|
+
maxClipHeight: targetHeight
|
|
3697
3793
|
});
|
|
3698
3794
|
return buffer_.toString("base64");
|
|
3699
3795
|
} finally {
|