@skrillex1224/playwright-toolkit 2.1.159 → 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 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 = (logger12, name) => {
339
- if (logger12 && typeof logger12[name] === "function") {
340
- return logger12[name].bind(logger12);
338
+ var resolveLogMethod = (logger13, name) => {
339
+ if (logger13 && typeof logger13[name] === "function") {
340
+ return logger13[name].bind(logger13);
341
341
  }
342
- if (name === "warning" && logger12 && typeof logger12.warn === "function") {
343
- return logger12.warn.bind(logger12);
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 = (logger12) => {
349
- defaultLogger = logger12;
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 logger12 = resolveLogger(explicitLogger);
377
- const logFn = resolveLogMethod(logger12, methodName);
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 logger = createInternalLogger("ApifyKit");
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
- logger.start(`[Step] ${step}${attemptLabel}`);
615
+ logger2.start(`[Step] ${step}${attemptLabel}`);
525
616
  try {
526
617
  const result = await actionFn();
527
- logger.success(`[Step] ${step}${attemptLabel}`);
618
+ logger2.success(`[Step] ${step}${attemptLabel}`);
528
619
  return { success: true, result };
529
620
  } catch (error) {
530
- logger.fail(`[Step] ${step}${attemptLabel}`, error);
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
- logger.start(`[RetryStep] \u6267\u884C\u81EA\u5B9A\u4E49 before \u94A9\u5B50 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);
627
+ logger2.start(`[RetryStep] \u6267\u884C\u81EA\u5B9A\u4E49 before \u94A9\u5B50 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);
537
628
  await beforeRetry(page, attemptNumber);
538
- logger.success(`[RetryStep] before \u94A9\u5B50\u5B8C\u6210`);
629
+ logger2.success(`[RetryStep] before \u94A9\u5B50\u5B8C\u6210`);
539
630
  } else if (retryMode === "refresh") {
540
- logger.start(`[RetryStep] \u5237\u65B0\u9875\u9762 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);
631
+ logger2.start(`[RetryStep] \u5237\u65B0\u9875\u9762 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);
541
632
  await page.reload({ waitUntil: "domcontentloaded" });
542
- logger.success(`[RetryStep] \u9875\u9762\u5237\u65B0\u5B8C\u6210`);
633
+ logger2.success(`[RetryStep] \u9875\u9762\u5237\u65B0\u5B8C\u6210`);
543
634
  } else {
544
- logger.start(`[RetryStep] \u7B49\u5F85 3 \u79D2 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);
635
+ logger2.start(`[RetryStep] \u7B49\u5F85 3 \u79D2 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);
545
636
  await new Promise((resolve) => setTimeout(resolve, 3e3));
546
- logger.success(`[RetryStep] \u7B49\u5F85\u5B8C\u6210`);
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
- logger.start(`[RetryStep] \u51C6\u5907\u7B2C ${attempt}/${retryTimes} \u6B21\u91CD\u8BD5: ${step}`);
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
- logger.warn(`[RetryStep] \u91CD\u8BD5\u51C6\u5907\u5931\u8D25: ${prepareError.message}`);
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.screenshot({ fullPage: true, type: "jpeg", quality: 60 });
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
- logger.warn(`\u622A\u56FE\u751F\u6210\u5931\u8D25: ${snapErr.message}`);
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
- logger.success("pushSuccess", "Data pushed");
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
- logger.success("pushFailed", "Error data pushed");
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 logger2 = createInternalLogger("InternalUtils");
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
- logger2.success("parseCookies", `parsed ${cookies.length} cookies`);
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 logger3 = createInternalLogger("AntiCheat");
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 logger4 = createInternalLogger("Humanize");
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
- logger4.debug("initializeCursor: cursor already exists, skipping");
904
+ logger5.debug("initializeCursor: cursor already exists, skipping");
810
905
  return;
811
906
  }
812
- logger4.start("initializeCursor", "creating cursor");
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
- logger4.success("initializeCursor", "cursor initialized");
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
- logger4.start("humanMove", `target=${typeof target === "string" ? target : "element/coords"}`);
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
- logger4.warn(`humanMove: \u5143\u7D20\u4E0D\u5B58\u5728 ${target}`);
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
- logger4.warn(`humanMove: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E ${target}`);
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
- logger4.success("humanMove");
946
+ logger5.success("humanMove");
852
947
  return true;
853
948
  } catch (error) {
854
- logger4.fail("humanMove", error);
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
- logger4.start("humanScroll", `target=${targetDesc}`);
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
- logger4.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${target}`);
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
- logger4.warn(`humanScroll | \u8D85\u65F6\u4FDD\u62A4\u89E6\u53D1 (${maxDurationMs}ms)`);
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
- logger4.info("humanScroll | fixed \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
1059
+ logger5.info("humanScroll | fixed \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
965
1060
  } else {
966
- logger4.debug("humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321");
1061
+ logger5.debug("humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321");
967
1062
  }
968
- logger4.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
1063
+ logger5.success("humanScroll", didScroll ? "\u5DF2\u6EDA\u52A8" : "\u65E0\u9700\u6EDA\u52A8");
969
1064
  return { element, didScroll };
970
1065
  }
971
- logger4.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason} ${status.direction ? `(${status.direction})` : ""}`);
1066
+ logger5.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason} ${status.direction ? `(${status.direction})` : ""}`);
972
1067
  if (status.code === "OBSTRUCTED" && status.obstruction) {
973
- logger4.debug(`humanScroll | \u88AB\u4EE5\u4E0B\u5143\u7D20\u906E\u6321 <${status.obstruction.tag} id="${status.obstruction.id}">`);
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
- logger4.warn("humanScroll | fixed \u5BB9\u5668\u5185\u4E14\u65E0\u53EF\u6EDA\u52A8\u7956\u5148\uFF0C\u8DF3\u8FC7\u6EDA\u52A8");
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
- logger4.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);
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
- logger4.fail("humanScroll", error);
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
- logger4.start("humanClick", `target=${targetDesc}`);
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
- logger4.warn(`humanClick: \u6062\u590D\u6EDA\u52A8\u4F4D\u7F6E\u5931\u8D25: ${restoreError.message}`);
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
- logger4.success("humanClick", "Clicked current position");
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
- logger4.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${target}`);
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
- logger4.warn("humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB");
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
- logger4.success("humanClick");
1180
+ logger5.success("humanClick");
1086
1181
  return true;
1087
1182
  } catch (error) {
1088
1183
  await restoreOnce();
1089
- logger4.fail("humanClick", error);
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
- logger4.start("randomSleep", `base=${baseMs}, actual=${ms}ms`);
1195
+ logger5.start("randomSleep", `base=${baseMs}, actual=${ms}ms`);
1101
1196
  await (0, import_delay.default)(ms);
1102
- logger4.success("randomSleep");
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
- logger4.start("simulateGaze", `duration=${durationMs}ms`);
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
- logger4.success("simulateGaze");
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
- logger4.start("humanType", `selector=${selector}, textLen=${text.length}`);
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
- logger4.debug(`\u505C\u987F ${pauseTime}ms...`);
1253
+ logger5.debug(`\u505C\u987F ${pauseTime}ms...`);
1159
1254
  await (0, import_delay.default)(pauseTime);
1160
1255
  }
1161
1256
  }
1162
- logger4.success("humanType");
1257
+ logger5.success("humanType");
1163
1258
  } catch (error) {
1164
- logger4.fail("humanType", error);
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
- logger4.start("humanClear", `selector=${selector}`);
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
- logger4.success("humanClear", "already empty");
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
- logger4.success("humanClear");
1282
+ logger5.success("humanClear");
1188
1283
  } catch (error) {
1189
- logger4.fail("humanClear", error);
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
- logger4.start("warmUpBrowsing", `duration=${durationMs}ms`);
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
- logger4.success("warmUpBrowsing");
1315
+ logger5.success("warmUpBrowsing");
1221
1316
  } catch (error) {
1222
- logger4.fail("warmUpBrowsing", error);
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
- logger4.start("naturalScroll", `dir=${direction}, dist=${actualDistance}, steps=${steps}`);
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
- logger4.success("naturalScroll");
1343
+ logger5.success("naturalScroll");
1249
1344
  } catch (error) {
1250
- logger4.fail("naturalScroll", error);
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 logger5 = createInternalLogger("TrafficMeter");
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
- logger5.warn(`CDP \u76D1\u542C\u6CE8\u518C\u5931\u8D25: ${error?.message || error}`);
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 logger6 = createInternalLogger("Launch");
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
- logger6.info(
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
- logger6.info(
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
- logger6.info(
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
- logger6.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}`);
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 logger7 = createInternalLogger("LiveView");
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
- logger7.fail("Live View Server", error);
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
- logger7.success("startLiveViewServer", `\u76D1\u542C\u7AEF\u53E3 ${port}`);
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.screenshot({ type: "png" });
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
- logger7.info(`(\u622A\u56FE): ${logMessage}`);
1755
+ logger8.info(`(\u622A\u56FE): ${logMessage}`);
1661
1756
  }
1662
1757
  } catch (e) {
1663
- logger7.warn(`\u65E0\u6CD5\u6355\u83B7 Live View \u5C4F\u5E55\u622A\u56FE: ${e.message}`);
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 logger8 = createInternalLogger("Captcha");
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
- logger8.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528: ${domSelector}`);
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
- logger8.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528: ${urlPattern}`);
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
- logger8.info("useCaptchaMonitor", "\u6B63\u5728\u505C\u6B62\u76D1\u63A7...");
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 logger9 = createInternalLogger("Sse");
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
- logger9.debug("parseSseStream", `JSON \u89E3\u6790\u5931\u8D25: ${e.message}, line: ${line.substring(0, 100)}...`);
1914
+ logger10.debug("parseSseStream", `JSON \u89E3\u6790\u5931\u8D25: ${e.message}, line: ${line.substring(0, 100)}...`);
1820
1915
  }
1821
1916
  }
1822
1917
  }
1823
- logger9.success("parseSseStream", `\u89E3\u6790\u5B8C\u6210, events \u6570\u91CF: ${events.length}`);
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
- logger9.info("[MITM] autoUnroute: \u53D6\u6D88\u540E\u7EED\u62E6\u622A");
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
- logger9.info(`[MITM] firstMatchOnly: \u653E\u884C\u540E\u7EED\u8BF7\u6C42: ${route.request().url()}`);
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
- logger9.info("[MITM] firstMatchOnly: \u547D\u4E2D\u9996\u4E2A\u8BF7\u6C42\uFF0C\u53D6\u6D88\u540E\u7EED\u62E6\u622A");
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
- logger9.info(`[MITM] \u5DF2\u62E6\u622A\u8BF7\u6C42: ${request.url()}`);
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
- logger9.debug("[Intercept] \u5DF2\u63A5\u6536\u521D\u59CB\u6570\u636E");
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
- logger9.fail(`onData \u9519\u8BEF`, e);
2034
+ logger10.fail(`onData \u9519\u8BEF`, e);
1940
2035
  }
1941
2036
  }
1942
2037
  });
1943
2038
  res.on("end", () => {
1944
- logger9.info("[MITM] \u4E0A\u6E38\u54CD\u5E94\u7ED3\u675F");
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
- logger9.fail(`onEnd \u9519\u8BEF`, e);
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 logger10 = createInternalLogger("Mutation");
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
- logger10.start("waitForStable", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);
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
- logger10.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
2164
+ logger11.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);
2070
2165
  } catch (e) {
2071
- logger10.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);
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
- logger10.info("waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03");
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
- logger10.warning("waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
2297
+ logger11.warning("waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
2203
2298
  }
2204
- logger10.success("waitForStable", `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
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
- logger10.start("useMonitor", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode}`);
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
- logger10.success("useMonitor", "\u76D1\u63A7\u5668\u5DF2\u542F\u52A8");
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
- logger10.success("useMonitor.stop", `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);
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: (logger12) => setDefaultLogger(logger12),
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: (logger12) => {
3258
- if (logger12) return createTemplateLogger(createBaseLogger("", logger12));
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 logger11 = createInternalLogger("Share");
3266
- var DEFAULT_TIMEOUT_MS = 50 * 1e3;
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
- logger11.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode}`);
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
- logger11.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);
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
- logger11.success("captureLink.domHit", `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);
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
- logger11.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);
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 ?? DEFAULT_TIMEOUT_MS) || 0);
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
- logger11.start("captureLink", `mode=${share.mode}, timeoutMs=${timeoutMs}, prefix=${share.prefix}`);
3465
- logger11.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);
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
- logger11.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);
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
- logger11.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
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
- logger11.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);
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
- logger11.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);
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
- logger11.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);
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
- logger11.success("captureLink.responseHit", `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);
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
- logger11.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);
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
- logger11.info("\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C");
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
- logger11.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);
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
- logger11.start("captureLink.performActions", `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${actionTimeout}ms`);
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
- logger11.fail("captureLink.performActions", actionError);
3691
+ logger12.fail("captureLink.performActions", actionError);
3597
3692
  throw actionError;
3598
3693
  }
3599
3694
  if (actionResult === "__ACTION_TIMEOUT__") {
3600
3695
  stats.actionTimedOut = true;
3601
- logger11.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);
3696
+ logger12.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);
3602
3697
  } else {
3603
- logger11.success("captureLink.performActions", "\u6267\u884C\u52A8\u4F5C\u5B8C\u6210");
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
- logger11.success("captureLink", `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);
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
- logger11.info(
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
- logger11.warning(
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
- logger11.warning(
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
- logger11.info("response \u76D1\u542C\u5DF2\u5378\u8F7D");
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.screenshot({
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 {