@skrillex1224/playwright-toolkit 2.1.54 → 2.1.56
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/browser.js +19 -99
- package/dist/browser.js.map +4 -4
- package/dist/index.cjs +124 -107
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +124 -107
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -45,18 +45,18 @@ var fallbackLog = {
|
|
|
45
45
|
error: (...args) => console.error(...args),
|
|
46
46
|
debug: (...args) => console.debug ? console.debug(...args) : console.log(...args)
|
|
47
47
|
};
|
|
48
|
-
var resolveLogMethod = (
|
|
49
|
-
if (
|
|
50
|
-
return
|
|
48
|
+
var resolveLogMethod = (logger11, name) => {
|
|
49
|
+
if (logger11 && typeof logger11[name] === "function") {
|
|
50
|
+
return logger11[name].bind(logger11);
|
|
51
51
|
}
|
|
52
|
-
if (name === "warning" &&
|
|
53
|
-
return
|
|
52
|
+
if (name === "warning" && logger11 && typeof logger11.warn === "function") {
|
|
53
|
+
return logger11.warn.bind(logger11);
|
|
54
54
|
}
|
|
55
55
|
return fallbackLog[name];
|
|
56
56
|
};
|
|
57
57
|
var defaultLogger = null;
|
|
58
|
-
var setDefaultLogger = (
|
|
59
|
-
defaultLogger =
|
|
58
|
+
var setDefaultLogger = (logger11) => {
|
|
59
|
+
defaultLogger = logger11;
|
|
60
60
|
};
|
|
61
61
|
var resolveLogger = (explicitLogger) => {
|
|
62
62
|
if (explicitLogger && typeof explicitLogger.info === "function") {
|
|
@@ -83,8 +83,8 @@ var colorize = (text, color) => {
|
|
|
83
83
|
var createBaseLogger = (prefix = "", explicitLogger) => {
|
|
84
84
|
const name = prefix ? String(prefix) : "";
|
|
85
85
|
const dispatch = (methodName, icon, message, color) => {
|
|
86
|
-
const
|
|
87
|
-
const logFn = resolveLogMethod(
|
|
86
|
+
const logger11 = resolveLogger(explicitLogger);
|
|
87
|
+
const logFn = resolveLogMethod(logger11, methodName);
|
|
88
88
|
logFn(colorize(formatLine(name, icon, message), color));
|
|
89
89
|
};
|
|
90
90
|
return {
|
|
@@ -334,9 +334,32 @@ var ApifyKit = {
|
|
|
334
334
|
useApifyKit
|
|
335
335
|
};
|
|
336
336
|
|
|
337
|
+
// src/internals/utils.js
|
|
338
|
+
var logger2 = createInternalLogger("InternalUtils");
|
|
339
|
+
var parseCookies = (cookieString, domain) => {
|
|
340
|
+
const cookies = [];
|
|
341
|
+
const pairs = cookieString.split(";").map((c) => c.trim());
|
|
342
|
+
for (const pair of pairs) {
|
|
343
|
+
const [name, ...valueParts] = pair.split("=");
|
|
344
|
+
if (name && valueParts.length > 0) {
|
|
345
|
+
const cookie = {
|
|
346
|
+
name: name.trim(),
|
|
347
|
+
value: valueParts.join("=").trim(),
|
|
348
|
+
path: "/"
|
|
349
|
+
};
|
|
350
|
+
if (domain) {
|
|
351
|
+
cookie.domain = domain;
|
|
352
|
+
}
|
|
353
|
+
cookies.push(cookie);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
logger2.success("parseCookies", `parsed ${cookies.length} cookies`);
|
|
357
|
+
return cookies;
|
|
358
|
+
};
|
|
359
|
+
|
|
337
360
|
// src/utils.js
|
|
338
361
|
import delay from "delay";
|
|
339
|
-
var
|
|
362
|
+
var logger3 = createInternalLogger("Utils");
|
|
340
363
|
var Utils = {
|
|
341
364
|
/**
|
|
342
365
|
* 解析 Cookie 字符串为 Playwright 格式的 Cookie 数组
|
|
@@ -345,24 +368,7 @@ var Utils = {
|
|
|
345
368
|
* @returns {Array} Cookie 数组
|
|
346
369
|
*/
|
|
347
370
|
parseCookies(cookieString, domain) {
|
|
348
|
-
|
|
349
|
-
const pairs = cookieString.split(";").map((c) => c.trim());
|
|
350
|
-
for (const pair of pairs) {
|
|
351
|
-
const [name, ...valueParts] = pair.split("=");
|
|
352
|
-
if (name && valueParts.length > 0) {
|
|
353
|
-
const cookie = {
|
|
354
|
-
name: name.trim(),
|
|
355
|
-
value: valueParts.join("=").trim(),
|
|
356
|
-
path: "/"
|
|
357
|
-
};
|
|
358
|
-
if (domain) {
|
|
359
|
-
cookie.domain = domain;
|
|
360
|
-
}
|
|
361
|
-
cookies.push(cookie);
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
logger2.success("parseCookies", `parsed ${cookies.length} cookies`);
|
|
365
|
-
return cookies;
|
|
371
|
+
return parseCookies(cookieString, domain);
|
|
366
372
|
},
|
|
367
373
|
/**
|
|
368
374
|
* 全页面滚动截图
|
|
@@ -376,7 +382,7 @@ var Utils = {
|
|
|
376
382
|
* @returns {Promise<string>} - base64 编码的 PNG 图片
|
|
377
383
|
*/
|
|
378
384
|
async fullPageScreenshot(page, options = {}) {
|
|
379
|
-
|
|
385
|
+
logger3.start("fullPageScreenshot", "detecting scrollable elements");
|
|
380
386
|
const originalViewport = page.viewportSize();
|
|
381
387
|
const defaultBuffer = Math.round((originalViewport?.height || 1080) / 2);
|
|
382
388
|
const buffer = options.buffer ?? defaultBuffer;
|
|
@@ -413,7 +419,7 @@ var Utils = {
|
|
|
413
419
|
fullPage: true,
|
|
414
420
|
type: "png"
|
|
415
421
|
});
|
|
416
|
-
|
|
422
|
+
logger3.success("fullPageScreenshot", `captured ${Math.round(buffer_.length / 1024)} KB`);
|
|
417
423
|
return buffer_.toString("base64");
|
|
418
424
|
} finally {
|
|
419
425
|
if (restore) {
|
|
@@ -437,7 +443,7 @@ var Utils = {
|
|
|
437
443
|
};
|
|
438
444
|
|
|
439
445
|
// src/anti-cheat.js
|
|
440
|
-
var
|
|
446
|
+
var logger4 = createInternalLogger("AntiCheat");
|
|
441
447
|
var BASE_CONFIG = Object.freeze({
|
|
442
448
|
locale: "zh-CN",
|
|
443
449
|
acceptLanguage: "zh-CN,zh;q=0.9",
|
|
@@ -499,7 +505,7 @@ var AntiCheat = {
|
|
|
499
505
|
// src/humanize.js
|
|
500
506
|
import delay2 from "delay";
|
|
501
507
|
import { createCursor } from "ghost-cursor-playwright";
|
|
502
|
-
var
|
|
508
|
+
var logger5 = createInternalLogger("Humanize");
|
|
503
509
|
var $CursorWeakMap = /* @__PURE__ */ new WeakMap();
|
|
504
510
|
function $GetCursor(page) {
|
|
505
511
|
const cursor = $CursorWeakMap.get(page);
|
|
@@ -527,13 +533,13 @@ var Humanize = {
|
|
|
527
533
|
*/
|
|
528
534
|
async initializeCursor(page) {
|
|
529
535
|
if ($CursorWeakMap.has(page)) {
|
|
530
|
-
|
|
536
|
+
logger5.debug("initializeCursor: cursor already exists, skipping");
|
|
531
537
|
return;
|
|
532
538
|
}
|
|
533
|
-
|
|
539
|
+
logger5.start("initializeCursor", "creating cursor");
|
|
534
540
|
const cursor = await createCursor(page);
|
|
535
541
|
$CursorWeakMap.set(page, cursor);
|
|
536
|
-
|
|
542
|
+
logger5.success("initializeCursor", "cursor initialized");
|
|
537
543
|
},
|
|
538
544
|
/**
|
|
539
545
|
* 人类化鼠标移动 - 使用 ghost-cursor 移动到指定位置或元素
|
|
@@ -543,17 +549,17 @@ var Humanize = {
|
|
|
543
549
|
*/
|
|
544
550
|
async humanMove(page, target) {
|
|
545
551
|
const cursor = $GetCursor(page);
|
|
546
|
-
|
|
552
|
+
logger5.start("humanMove", `target=${typeof target === "string" ? target : "element/coords"}`);
|
|
547
553
|
try {
|
|
548
554
|
if (typeof target === "string") {
|
|
549
555
|
const element = await page.$(target);
|
|
550
556
|
if (!element) {
|
|
551
|
-
|
|
557
|
+
logger5.warn(`humanMove: \u5143\u7D20\u4E0D\u5B58\u5728 ${target}`);
|
|
552
558
|
return false;
|
|
553
559
|
}
|
|
554
560
|
const box = await element.boundingBox();
|
|
555
561
|
if (!box) {
|
|
556
|
-
|
|
562
|
+
logger5.warn(`humanMove: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E ${target}`);
|
|
557
563
|
return false;
|
|
558
564
|
}
|
|
559
565
|
const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.2;
|
|
@@ -569,10 +575,10 @@ var Humanize = {
|
|
|
569
575
|
await cursor.actions.move({ x, y });
|
|
570
576
|
}
|
|
571
577
|
}
|
|
572
|
-
|
|
578
|
+
logger5.success("humanMove");
|
|
573
579
|
return true;
|
|
574
580
|
} catch (error) {
|
|
575
|
-
|
|
581
|
+
logger5.fail("humanMove", error);
|
|
576
582
|
throw error;
|
|
577
583
|
}
|
|
578
584
|
},
|
|
@@ -590,12 +596,12 @@ var Humanize = {
|
|
|
590
596
|
async humanScroll(page, target, options = {}) {
|
|
591
597
|
const { maxSteps = 30, minStep = 150, maxStep = 400 } = options;
|
|
592
598
|
const targetDesc = typeof target === "string" ? target : "ElementHandle";
|
|
593
|
-
|
|
599
|
+
logger5.debug(`humanScroll | \u76EE\u6807=${targetDesc}`);
|
|
594
600
|
let element;
|
|
595
601
|
if (typeof target === "string") {
|
|
596
602
|
element = await page.$(target);
|
|
597
603
|
if (!element) {
|
|
598
|
-
|
|
604
|
+
logger5.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${target}`);
|
|
599
605
|
return { element: null, didScroll: false };
|
|
600
606
|
}
|
|
601
607
|
} else {
|
|
@@ -639,12 +645,12 @@ var Humanize = {
|
|
|
639
645
|
for (let i = 0; i < maxSteps; i++) {
|
|
640
646
|
const status = await checkVisibility();
|
|
641
647
|
if (status.code === "VISIBLE") {
|
|
642
|
-
|
|
648
|
+
logger5.debug("humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321");
|
|
643
649
|
return { element, didScroll };
|
|
644
650
|
}
|
|
645
|
-
|
|
651
|
+
logger5.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason} ${status.direction ? `(${status.direction})` : ""}`);
|
|
646
652
|
if (status.code === "OBSTRUCTED" && status.obstruction) {
|
|
647
|
-
|
|
653
|
+
logger5.debug(`humanScroll | \u88AB\u4EE5\u4E0B\u5143\u7D20\u906E\u6321 <${status.obstruction.tag} id="${status.obstruction.id}">`);
|
|
648
654
|
}
|
|
649
655
|
let deltaY = 0;
|
|
650
656
|
if (status.code === "OUT_OF_VIEWPORT") {
|
|
@@ -672,10 +678,10 @@ var Humanize = {
|
|
|
672
678
|
didScroll = true;
|
|
673
679
|
await delay2(this.jitterMs(100 + Math.random() * 150, 0.2));
|
|
674
680
|
}
|
|
675
|
-
|
|
681
|
+
logger5.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);
|
|
676
682
|
return { element, didScroll };
|
|
677
683
|
} catch (error) {
|
|
678
|
-
|
|
684
|
+
logger5.fail("humanScroll", error);
|
|
679
685
|
throw error;
|
|
680
686
|
}
|
|
681
687
|
},
|
|
@@ -693,7 +699,7 @@ var Humanize = {
|
|
|
693
699
|
const cursor = $GetCursor(page);
|
|
694
700
|
const { reactionDelay = 250, throwOnMissing = true, scrollIfNeeded = true, restore = false } = options;
|
|
695
701
|
const targetDesc = target == null ? "Current Position" : typeof target === "string" ? target : "ElementHandle";
|
|
696
|
-
|
|
702
|
+
logger5.start("humanClick", `target=${targetDesc}`);
|
|
697
703
|
const restoreOnce = async () => {
|
|
698
704
|
if (restoreOnce.restored) return;
|
|
699
705
|
restoreOnce.restored = true;
|
|
@@ -702,14 +708,14 @@ var Humanize = {
|
|
|
702
708
|
await delay2(this.jitterMs(1e3));
|
|
703
709
|
await restoreOnce.do();
|
|
704
710
|
} catch (restoreError) {
|
|
705
|
-
|
|
711
|
+
logger5.warn(`humanClick: \u6062\u590D\u6EDA\u52A8\u4F4D\u7F6E\u5931\u8D25: ${restoreError.message}`);
|
|
706
712
|
}
|
|
707
713
|
};
|
|
708
714
|
try {
|
|
709
715
|
if (target == null) {
|
|
710
716
|
await delay2(this.jitterMs(reactionDelay, 0.4));
|
|
711
717
|
await cursor.actions.click();
|
|
712
|
-
|
|
718
|
+
logger5.success("humanClick", "Clicked current position");
|
|
713
719
|
return true;
|
|
714
720
|
}
|
|
715
721
|
let element;
|
|
@@ -719,7 +725,7 @@ var Humanize = {
|
|
|
719
725
|
if (throwOnMissing) {
|
|
720
726
|
throw new Error(`\u627E\u4E0D\u5230\u5143\u7D20 ${target}`);
|
|
721
727
|
}
|
|
722
|
-
|
|
728
|
+
logger5.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${target}`);
|
|
723
729
|
return false;
|
|
724
730
|
}
|
|
725
731
|
} else {
|
|
@@ -735,7 +741,7 @@ var Humanize = {
|
|
|
735
741
|
if (throwOnMissing) {
|
|
736
742
|
throw new Error("\u65E0\u6CD5\u83B7\u53D6\u5143\u7D20\u4F4D\u7F6E");
|
|
737
743
|
}
|
|
738
|
-
|
|
744
|
+
logger5.warn("humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB");
|
|
739
745
|
return false;
|
|
740
746
|
}
|
|
741
747
|
const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.3;
|
|
@@ -744,11 +750,11 @@ var Humanize = {
|
|
|
744
750
|
await delay2(this.jitterMs(reactionDelay, 0.4));
|
|
745
751
|
await cursor.actions.click();
|
|
746
752
|
await restoreOnce();
|
|
747
|
-
|
|
753
|
+
logger5.success("humanClick");
|
|
748
754
|
return true;
|
|
749
755
|
} catch (error) {
|
|
750
756
|
await restoreOnce();
|
|
751
|
-
|
|
757
|
+
logger5.fail("humanClick", error);
|
|
752
758
|
throw error;
|
|
753
759
|
}
|
|
754
760
|
},
|
|
@@ -759,9 +765,9 @@ var Humanize = {
|
|
|
759
765
|
*/
|
|
760
766
|
async randomSleep(baseMs, jitterPercent = 0.3) {
|
|
761
767
|
const ms = this.jitterMs(baseMs, jitterPercent);
|
|
762
|
-
|
|
768
|
+
logger5.start("randomSleep", `base=${baseMs}, actual=${ms}ms`);
|
|
763
769
|
await delay2(ms);
|
|
764
|
-
|
|
770
|
+
logger5.success("randomSleep");
|
|
765
771
|
},
|
|
766
772
|
/**
|
|
767
773
|
* 模拟人类"注视"或"阅读"行为:鼠标在页面上随机微动
|
|
@@ -771,7 +777,7 @@ var Humanize = {
|
|
|
771
777
|
async simulateGaze(page, baseDurationMs = 2500) {
|
|
772
778
|
const cursor = $GetCursor(page);
|
|
773
779
|
const durationMs = this.jitterMs(baseDurationMs, 0.4);
|
|
774
|
-
|
|
780
|
+
logger5.start("simulateGaze", `duration=${durationMs}ms`);
|
|
775
781
|
const startTime = Date.now();
|
|
776
782
|
const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };
|
|
777
783
|
while (Date.now() - startTime < durationMs) {
|
|
@@ -780,7 +786,7 @@ var Humanize = {
|
|
|
780
786
|
await cursor.actions.move({ x, y });
|
|
781
787
|
await delay2(this.jitterMs(600, 0.5));
|
|
782
788
|
}
|
|
783
|
-
|
|
789
|
+
logger5.success("simulateGaze");
|
|
784
790
|
},
|
|
785
791
|
/**
|
|
786
792
|
* 人类化输入 - 带节奏变化(快-慢-停顿-偶尔加速)
|
|
@@ -793,7 +799,7 @@ var Humanize = {
|
|
|
793
799
|
* @param {number} [options.pauseBase=800] - 停顿时长基础值 (ms),实际 ±50% 抖动
|
|
794
800
|
*/
|
|
795
801
|
async humanType(page, selector, text, options = {}) {
|
|
796
|
-
|
|
802
|
+
logger5.start("humanType", `selector=${selector}, textLen=${text.length}`);
|
|
797
803
|
const {
|
|
798
804
|
baseDelay = 180,
|
|
799
805
|
pauseProbability = 0.08,
|
|
@@ -817,13 +823,13 @@ var Humanize = {
|
|
|
817
823
|
await delay2(charDelay);
|
|
818
824
|
if (Math.random() < pauseProbability && i < text.length - 1) {
|
|
819
825
|
const pauseTime = this.jitterMs(pauseBase, 0.5);
|
|
820
|
-
|
|
826
|
+
logger5.debug(`\u505C\u987F ${pauseTime}ms...`);
|
|
821
827
|
await delay2(pauseTime);
|
|
822
828
|
}
|
|
823
829
|
}
|
|
824
|
-
|
|
830
|
+
logger5.success("humanType");
|
|
825
831
|
} catch (error) {
|
|
826
|
-
|
|
832
|
+
logger5.fail("humanType", error);
|
|
827
833
|
throw error;
|
|
828
834
|
}
|
|
829
835
|
},
|
|
@@ -833,22 +839,22 @@ var Humanize = {
|
|
|
833
839
|
* @param {string} selector - 输入框选择器
|
|
834
840
|
*/
|
|
835
841
|
async humanClear(page, selector) {
|
|
836
|
-
|
|
842
|
+
logger5.start("humanClear", `selector=${selector}`);
|
|
837
843
|
try {
|
|
838
844
|
const locator = page.locator(selector);
|
|
839
845
|
await locator.click();
|
|
840
846
|
await delay2(this.jitterMs(200, 0.4));
|
|
841
847
|
const currentValue = await locator.inputValue();
|
|
842
848
|
if (!currentValue || currentValue.length === 0) {
|
|
843
|
-
|
|
849
|
+
logger5.success("humanClear", "already empty");
|
|
844
850
|
return;
|
|
845
851
|
}
|
|
846
852
|
await page.keyboard.press("Meta+A");
|
|
847
853
|
await delay2(this.jitterMs(100, 0.4));
|
|
848
854
|
await page.keyboard.press("Backspace");
|
|
849
|
-
|
|
855
|
+
logger5.success("humanClear");
|
|
850
856
|
} catch (error) {
|
|
851
|
-
|
|
857
|
+
logger5.fail("humanClear", error);
|
|
852
858
|
throw error;
|
|
853
859
|
}
|
|
854
860
|
},
|
|
@@ -860,7 +866,7 @@ var Humanize = {
|
|
|
860
866
|
async warmUpBrowsing(page, baseDuration = 3500) {
|
|
861
867
|
const cursor = $GetCursor(page);
|
|
862
868
|
const durationMs = this.jitterMs(baseDuration, 0.4);
|
|
863
|
-
|
|
869
|
+
logger5.start("warmUpBrowsing", `duration=${durationMs}ms`);
|
|
864
870
|
const startTime = Date.now();
|
|
865
871
|
const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };
|
|
866
872
|
try {
|
|
@@ -879,9 +885,9 @@ var Humanize = {
|
|
|
879
885
|
await delay2(this.jitterMs(800, 0.5));
|
|
880
886
|
}
|
|
881
887
|
}
|
|
882
|
-
|
|
888
|
+
logger5.success("warmUpBrowsing");
|
|
883
889
|
} catch (error) {
|
|
884
|
-
|
|
890
|
+
logger5.fail("warmUpBrowsing", error);
|
|
885
891
|
throw error;
|
|
886
892
|
}
|
|
887
893
|
},
|
|
@@ -895,7 +901,7 @@ var Humanize = {
|
|
|
895
901
|
async naturalScroll(page, direction = "down", distance = 300, baseSteps = 5) {
|
|
896
902
|
const steps = Math.max(3, baseSteps + Math.floor(Math.random() * 3) - 1);
|
|
897
903
|
const actualDistance = this.jitterMs(distance, 0.15);
|
|
898
|
-
|
|
904
|
+
logger5.start("naturalScroll", `dir=${direction}, dist=${actualDistance}, steps=${steps}`);
|
|
899
905
|
const sign = direction === "down" ? 1 : -1;
|
|
900
906
|
const stepDistance = actualDistance / steps;
|
|
901
907
|
try {
|
|
@@ -907,9 +913,9 @@ var Humanize = {
|
|
|
907
913
|
const baseDelay = 60 + i * 25;
|
|
908
914
|
await delay2(this.jitterMs(baseDelay, 0.3));
|
|
909
915
|
}
|
|
910
|
-
|
|
916
|
+
logger5.success("naturalScroll");
|
|
911
917
|
} catch (error) {
|
|
912
|
-
|
|
918
|
+
logger5.fail("naturalScroll", error);
|
|
913
919
|
throw error;
|
|
914
920
|
}
|
|
915
921
|
}
|
|
@@ -938,7 +944,7 @@ var Launch = {
|
|
|
938
944
|
// src/live-view.js
|
|
939
945
|
import express from "express";
|
|
940
946
|
import { Actor } from "apify";
|
|
941
|
-
var
|
|
947
|
+
var logger6 = createInternalLogger("LiveView");
|
|
942
948
|
async function startLiveViewServer(liveViewKey) {
|
|
943
949
|
const app = express();
|
|
944
950
|
app.get("/", async (req, res) => {
|
|
@@ -963,13 +969,13 @@ async function startLiveViewServer(liveViewKey) {
|
|
|
963
969
|
</html>
|
|
964
970
|
`);
|
|
965
971
|
} catch (error) {
|
|
966
|
-
|
|
972
|
+
logger6.fail("Live View Server", error);
|
|
967
973
|
res.status(500).send(`\u65E0\u6CD5\u52A0\u8F7D\u5C4F\u5E55\u622A\u56FE: ${error.message}`);
|
|
968
974
|
}
|
|
969
975
|
});
|
|
970
976
|
const port = process.env.APIFY_CONTAINER_PORT || 4321;
|
|
971
977
|
app.listen(port, () => {
|
|
972
|
-
|
|
978
|
+
logger6.success("startLiveViewServer", `\u76D1\u542C\u7AEF\u53E3 ${port}`);
|
|
973
979
|
});
|
|
974
980
|
}
|
|
975
981
|
async function takeLiveScreenshot(liveViewKey, page, logMessage) {
|
|
@@ -977,10 +983,10 @@ async function takeLiveScreenshot(liveViewKey, page, logMessage) {
|
|
|
977
983
|
const buffer = await page.screenshot({ type: "png" });
|
|
978
984
|
await Actor.setValue(liveViewKey, buffer, { contentType: "image/png" });
|
|
979
985
|
if (logMessage) {
|
|
980
|
-
|
|
986
|
+
logger6.info(`(\u622A\u56FE): ${logMessage}`);
|
|
981
987
|
}
|
|
982
988
|
} catch (e) {
|
|
983
|
-
|
|
989
|
+
logger6.warn(`\u65E0\u6CD5\u6355\u83B7 Live View \u5C4F\u5E55\u622A\u56FE: ${e.message}`);
|
|
984
990
|
}
|
|
985
991
|
}
|
|
986
992
|
var useLiveView = (liveViewKey = PresetOfLiveViewKey) => {
|
|
@@ -999,7 +1005,7 @@ var LiveView = {
|
|
|
999
1005
|
|
|
1000
1006
|
// src/captcha-monitor.js
|
|
1001
1007
|
import { v4 as uuidv4 } from "uuid";
|
|
1002
|
-
var
|
|
1008
|
+
var logger7 = createInternalLogger("Captcha");
|
|
1003
1009
|
function useCaptchaMonitor(page, options) {
|
|
1004
1010
|
const { domSelector, urlPattern, onDetected } = options;
|
|
1005
1011
|
if (!domSelector && !urlPattern) {
|
|
@@ -1071,7 +1077,7 @@ function useCaptchaMonitor(page, options) {
|
|
|
1071
1077
|
};
|
|
1072
1078
|
})();
|
|
1073
1079
|
}, { selector: domSelector, callbackName: exposedFunctionName, cleanerName });
|
|
1074
|
-
|
|
1080
|
+
logger7.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528: ${domSelector}`);
|
|
1075
1081
|
cleanupFns.push(async () => {
|
|
1076
1082
|
try {
|
|
1077
1083
|
await page.evaluate((name) => {
|
|
@@ -1094,14 +1100,14 @@ function useCaptchaMonitor(page, options) {
|
|
|
1094
1100
|
}
|
|
1095
1101
|
};
|
|
1096
1102
|
page.on("framenavigated", frameHandler);
|
|
1097
|
-
|
|
1103
|
+
logger7.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528: ${urlPattern}`);
|
|
1098
1104
|
cleanupFns.push(async () => {
|
|
1099
1105
|
page.off("framenavigated", frameHandler);
|
|
1100
1106
|
});
|
|
1101
1107
|
}
|
|
1102
1108
|
return {
|
|
1103
1109
|
stop: async () => {
|
|
1104
|
-
|
|
1110
|
+
logger7.info("useCaptchaMonitor", "\u6B63\u5728\u505C\u6B62\u76D1\u63A7...");
|
|
1105
1111
|
for (const fn of cleanupFns) {
|
|
1106
1112
|
await fn();
|
|
1107
1113
|
}
|
|
@@ -1116,7 +1122,7 @@ var Captcha = {
|
|
|
1116
1122
|
// src/sse.js
|
|
1117
1123
|
import https from "https";
|
|
1118
1124
|
import { URL as URL2 } from "url";
|
|
1119
|
-
var
|
|
1125
|
+
var logger8 = createInternalLogger("Sse");
|
|
1120
1126
|
var Sse = {
|
|
1121
1127
|
/**
|
|
1122
1128
|
* 解析 SSE 流文本
|
|
@@ -1135,11 +1141,11 @@ var Sse = {
|
|
|
1135
1141
|
events.push(JSON.parse(jsonContent));
|
|
1136
1142
|
}
|
|
1137
1143
|
} catch (e) {
|
|
1138
|
-
|
|
1144
|
+
logger8.debug("parseSseStream", `JSON \u89E3\u6790\u5931\u8D25: ${e.message}, line: ${line.substring(0, 100)}...`);
|
|
1139
1145
|
}
|
|
1140
1146
|
}
|
|
1141
1147
|
}
|
|
1142
|
-
|
|
1148
|
+
logger8.success("parseSseStream", `\u89E3\u6790\u5B8C\u6210, events \u6570\u91CF: ${events.length}`);
|
|
1143
1149
|
return events;
|
|
1144
1150
|
},
|
|
1145
1151
|
/**
|
|
@@ -1174,7 +1180,7 @@ var Sse = {
|
|
|
1174
1180
|
const workPromise = new Promise((resolve, reject) => {
|
|
1175
1181
|
page.route(urlPattern, async (route) => {
|
|
1176
1182
|
const request = route.request();
|
|
1177
|
-
|
|
1183
|
+
logger8.info(`[MITM] \u5DF2\u62E6\u622A\u8BF7\u6C42: ${request.url()}`);
|
|
1178
1184
|
try {
|
|
1179
1185
|
const headers = await request.allHeaders();
|
|
1180
1186
|
const postData = request.postData();
|
|
@@ -1199,7 +1205,7 @@ var Sse = {
|
|
|
1199
1205
|
clearTimeout(initialTimer);
|
|
1200
1206
|
initialTimer = null;
|
|
1201
1207
|
}
|
|
1202
|
-
|
|
1208
|
+
logger8.debug("[Intercept] \u5DF2\u63A5\u6536\u521D\u59CB\u6570\u636E");
|
|
1203
1209
|
}
|
|
1204
1210
|
chunks.push(chunk);
|
|
1205
1211
|
const textChunk = chunk.toString("utf-8");
|
|
@@ -1208,18 +1214,18 @@ var Sse = {
|
|
|
1208
1214
|
try {
|
|
1209
1215
|
onData(textChunk, resolve, accumulatedText);
|
|
1210
1216
|
} catch (e) {
|
|
1211
|
-
|
|
1217
|
+
logger8.fail(`onData \u9519\u8BEF`, e);
|
|
1212
1218
|
}
|
|
1213
1219
|
}
|
|
1214
1220
|
});
|
|
1215
1221
|
res.on("end", () => {
|
|
1216
|
-
|
|
1222
|
+
logger8.info("[MITM] \u4E0A\u6E38\u54CD\u5E94\u7ED3\u675F");
|
|
1217
1223
|
clearAllTimers();
|
|
1218
1224
|
if (onEnd) {
|
|
1219
1225
|
try {
|
|
1220
1226
|
onEnd(accumulatedText, resolve);
|
|
1221
1227
|
} catch (e) {
|
|
1222
|
-
|
|
1228
|
+
logger8.fail(`onEnd \u9519\u8BEF`, e);
|
|
1223
1229
|
}
|
|
1224
1230
|
} else if (!onData) {
|
|
1225
1231
|
resolve(accumulatedText);
|
|
@@ -1301,9 +1307,20 @@ var Sse = {
|
|
|
1301
1307
|
import { gotScraping } from "got-scraping";
|
|
1302
1308
|
import { Agent as HttpAgent } from "http";
|
|
1303
1309
|
import { Agent as HttpsAgent } from "https";
|
|
1304
|
-
var
|
|
1305
|
-
var SHARED_HTTP_AGENT = new HttpAgent({
|
|
1306
|
-
|
|
1310
|
+
var logger9 = createInternalLogger("Interception");
|
|
1311
|
+
var SHARED_HTTP_AGENT = new HttpAgent({
|
|
1312
|
+
keepAlive: true,
|
|
1313
|
+
keepAliveMsecs: 15e3,
|
|
1314
|
+
maxSockets: 30,
|
|
1315
|
+
maxFreeSockets: 10
|
|
1316
|
+
});
|
|
1317
|
+
var SHARED_HTTPS_AGENT = new HttpsAgent({
|
|
1318
|
+
keepAlive: true,
|
|
1319
|
+
keepAliveMsecs: 15e3,
|
|
1320
|
+
maxSockets: 30,
|
|
1321
|
+
maxFreeSockets: 10,
|
|
1322
|
+
rejectUnauthorized: false
|
|
1323
|
+
});
|
|
1307
1324
|
var DirectConfig = {
|
|
1308
1325
|
/** 直连请求超时时间(秒) */
|
|
1309
1326
|
directTimeout: 12,
|
|
@@ -1432,7 +1449,7 @@ var Interception = {
|
|
|
1432
1449
|
if (mergedBlockingConfig.blockFont) enabledCategories.push("\u5B57\u4F53");
|
|
1433
1450
|
if (mergedBlockingConfig.blockCss) enabledCategories.push("CSS");
|
|
1434
1451
|
if (mergedBlockingConfig.blockOther) enabledCategories.push("\u5176\u4ED6");
|
|
1435
|
-
|
|
1452
|
+
logger9.start("setup", hasDirectDomains ? `\u76F4\u8FDE\u57DF\u540D: [${directDomains.length} \u4E2A] | \u5C4F\u853D: [${enabledCategories.join(", ")}]` : `\u4EC5\u8D44\u6E90\u5C4F\u853D\u6A21\u5F0F | \u5C4F\u853D: [${enabledCategories.join(", ")}]`);
|
|
1436
1453
|
await page.route("**/*", async (route) => {
|
|
1437
1454
|
let handled = false;
|
|
1438
1455
|
try {
|
|
@@ -1495,7 +1512,7 @@ var Interception = {
|
|
|
1495
1512
|
delete resHeaders["transfer-encoding"];
|
|
1496
1513
|
delete resHeaders["connection"];
|
|
1497
1514
|
delete resHeaders["keep-alive"];
|
|
1498
|
-
isSilent ?
|
|
1515
|
+
isSilent ? logger9.debug(`\u76F4\u8FDE\u6210\u529F: ${urlPath}`) : logger9.info(`\u76F4\u8FDE\u6210\u529F: ${urlPath}`);
|
|
1499
1516
|
await safeFulfill(route, {
|
|
1500
1517
|
status: response.statusCode,
|
|
1501
1518
|
headers: resHeaders,
|
|
@@ -1507,7 +1524,7 @@ var Interception = {
|
|
|
1507
1524
|
const isTimeout = e.code === "ETIMEDOUT" || e.message.toLowerCase().includes("timeout");
|
|
1508
1525
|
const action = fallbackToProxy ? "\u56DE\u9000\u4EE3\u7406" : "\u5DF2\u653E\u5F03";
|
|
1509
1526
|
const reason = isTimeout ? `\u8D85\u65F6(${DirectConfig.directTimeout}s)` : `\u5F02\u5E38: ${e.message}`;
|
|
1510
|
-
|
|
1527
|
+
logger9.warn(`\u76F4\u8FDE${reason}\uFF0C${action}: ${urlPath}`);
|
|
1511
1528
|
if (fallbackToProxy) {
|
|
1512
1529
|
await safeContinue(route);
|
|
1513
1530
|
} else {
|
|
@@ -1520,7 +1537,7 @@ var Interception = {
|
|
|
1520
1537
|
await safeContinue(route);
|
|
1521
1538
|
handled = true;
|
|
1522
1539
|
} catch (err) {
|
|
1523
|
-
|
|
1540
|
+
logger9.warn(`\u8DEF\u7531\u5904\u7406\u5F02\u5E38: ${err.message}`);
|
|
1524
1541
|
if (!handled) {
|
|
1525
1542
|
try {
|
|
1526
1543
|
await route.continue();
|
|
@@ -2257,7 +2274,7 @@ var createTemplateLogger = (baseLogger = createBaseLogger()) => {
|
|
|
2257
2274
|
};
|
|
2258
2275
|
var getDefaultBaseLogger = () => createBaseLogger("");
|
|
2259
2276
|
var Logger = {
|
|
2260
|
-
setLogger: (
|
|
2277
|
+
setLogger: (logger11) => setDefaultLogger(logger11),
|
|
2261
2278
|
info: (message) => getDefaultBaseLogger().info(message),
|
|
2262
2279
|
success: (message) => getDefaultBaseLogger().success(message),
|
|
2263
2280
|
warning: (message) => getDefaultBaseLogger().warning(message),
|
|
@@ -2265,14 +2282,14 @@ var Logger = {
|
|
|
2265
2282
|
error: (message) => getDefaultBaseLogger().error(message),
|
|
2266
2283
|
debug: (message) => getDefaultBaseLogger().debug(message),
|
|
2267
2284
|
start: (message) => getDefaultBaseLogger().start(message),
|
|
2268
|
-
useTemplate: (
|
|
2269
|
-
if (
|
|
2285
|
+
useTemplate: (logger11) => {
|
|
2286
|
+
if (logger11) return createTemplateLogger(createBaseLogger("", logger11));
|
|
2270
2287
|
return createTemplateLogger();
|
|
2271
2288
|
}
|
|
2272
2289
|
};
|
|
2273
2290
|
|
|
2274
2291
|
// src/mutation.js
|
|
2275
|
-
var
|
|
2292
|
+
var logger10 = createInternalLogger("Mutation");
|
|
2276
2293
|
function generateKey(prefix) {
|
|
2277
2294
|
return `__${prefix}_${uuidv42().replace(/-/g, "_")}`;
|
|
2278
2295
|
}
|
|
@@ -2297,7 +2314,7 @@ var Mutation = {
|
|
|
2297
2314
|
const stableTime = options.stableTime ?? 5e3;
|
|
2298
2315
|
const timeout = options.timeout ?? 6e4;
|
|
2299
2316
|
const onMutation = options.onMutation;
|
|
2300
|
-
|
|
2317
|
+
logger10.start("waitForStable", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);
|
|
2301
2318
|
const callbackName = generateKey("pk_mut_cb");
|
|
2302
2319
|
if (onMutation) {
|
|
2303
2320
|
try {
|
|
@@ -2310,7 +2327,7 @@ var Mutation = {
|
|
|
2310
2327
|
return "__CONTINUE__";
|
|
2311
2328
|
}
|
|
2312
2329
|
});
|
|
2313
|
-
|
|
2330
|
+
logger10.info("waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03");
|
|
2314
2331
|
} catch (e) {
|
|
2315
2332
|
}
|
|
2316
2333
|
}
|
|
@@ -2416,9 +2433,9 @@ var Mutation = {
|
|
|
2416
2433
|
{ selectorList, stableTime, timeout, callbackName, hasCallback: !!onMutation }
|
|
2417
2434
|
);
|
|
2418
2435
|
if (result.mutationCount === 0 && result.stableTime === 0) {
|
|
2419
|
-
|
|
2436
|
+
logger10.warning("waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20");
|
|
2420
2437
|
}
|
|
2421
|
-
|
|
2438
|
+
logger10.success("waitForStable", `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ", \u66FE\u6682\u505C\u8BA1\u65F6" : ""}`);
|
|
2422
2439
|
return result;
|
|
2423
2440
|
},
|
|
2424
2441
|
/**
|
|
@@ -2433,7 +2450,7 @@ var Mutation = {
|
|
|
2433
2450
|
async useMonitor(page, selectors, options = {}) {
|
|
2434
2451
|
const selectorList = Array.isArray(selectors) ? selectors : [selectors];
|
|
2435
2452
|
const onMutation = options.onMutation;
|
|
2436
|
-
|
|
2453
|
+
logger10.start("useMonitor", `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668`);
|
|
2437
2454
|
const monitorKey = generateKey("pk_mon");
|
|
2438
2455
|
const callbackName = generateKey("pk_mon_cb");
|
|
2439
2456
|
const cleanerName = generateKey("pk_mon_clean");
|
|
@@ -2483,7 +2500,7 @@ var Mutation = {
|
|
|
2483
2500
|
return total;
|
|
2484
2501
|
};
|
|
2485
2502
|
}, { selectorList, monitorKey, callbackName, cleanerName, hasCallback: !!onMutation });
|
|
2486
|
-
|
|
2503
|
+
logger10.success("useMonitor", "\u76D1\u63A7\u5668\u5DF2\u542F\u52A8");
|
|
2487
2504
|
return {
|
|
2488
2505
|
stop: async () => {
|
|
2489
2506
|
let totalMutations = 0;
|
|
@@ -2496,7 +2513,7 @@ var Mutation = {
|
|
|
2496
2513
|
}, cleanerName);
|
|
2497
2514
|
} catch (e) {
|
|
2498
2515
|
}
|
|
2499
|
-
|
|
2516
|
+
logger10.success("useMonitor.stop", `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);
|
|
2500
2517
|
return { totalMutations };
|
|
2501
2518
|
}
|
|
2502
2519
|
};
|