@skrillex1224/playwright-toolkit 2.0.38 → 2.0.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -6
- package/dist/index.cjs +59 -56
- package/dist/index.cjs.map +2 -2
- package/dist/index.js +60 -57
- package/dist/index.js.map +2 -2
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -100,12 +100,13 @@ await Actor.exit();
|
|
|
100
100
|
| `Stealth` | `setupBlockingResources(page, types?)` | 资源拦截 |
|
|
101
101
|
| `Stealth` | `setChinaTimezone(context)` | 设置中国时区 (UTC+8) |
|
|
102
102
|
| `Humanize` | `initializeCursor(page)` | 初始化 Cursor (必须先调用) |
|
|
103
|
-
| `Humanize` | `
|
|
104
|
-
| `Humanize` | `
|
|
105
|
-
| `Humanize` | `
|
|
106
|
-
| `Humanize` | `
|
|
107
|
-
| `Humanize` | `
|
|
108
|
-
| `Humanize` | `
|
|
103
|
+
| `Humanize` | `jitterMs(base, jitterPercent?)` | 生成带抖动的毫秒数 (同步,返回 number) |
|
|
104
|
+
| `Humanize` | `humanType(page, selector, text, options?)` | 人类化输入 (baseDelay=180ms ±40%) |
|
|
105
|
+
| `Humanize` | `humanClick(page, selector, options?)` | 人类化点击 (reactionDelay=250ms ±40%) |
|
|
106
|
+
| `Humanize` | `warmUpBrowsing(page, baseDuration?)` | 页面预热 (3500ms ±40%) |
|
|
107
|
+
| `Humanize` | `naturalScroll(page, direction?, distance?, steps?)` | 自然滚动 (带惯性+抖动) |
|
|
108
|
+
| `Humanize` | `simulateGaze(page, baseDurationMs?)` | 模拟注视 (2500ms ±40%) |
|
|
109
|
+
| `Humanize` | `randomSleep(baseMs, jitterPercent?)` | 随机延迟 (±30% 抖动) |
|
|
109
110
|
| `Captcha` | `useCaptchaMonitor(page, options)` | 验证码监控 |
|
|
110
111
|
|
|
111
112
|
---
|
package/dist/index.cjs
CHANGED
|
@@ -411,6 +411,16 @@ function $GetCursor(page) {
|
|
|
411
411
|
return cursor;
|
|
412
412
|
}
|
|
413
413
|
var Humanize = {
|
|
414
|
+
/**
|
|
415
|
+
* 生成带抖动的毫秒数 - 基于基础值添加随机浮动 (±30% 默认)
|
|
416
|
+
* @param {number} base - 基础延迟 (ms)
|
|
417
|
+
* @param {number} [jitterPercent=0.3] - 抖动百分比 (0.3 = ±30%)
|
|
418
|
+
* @returns {number} 抖动后的毫秒数
|
|
419
|
+
*/
|
|
420
|
+
jitterMs(base, jitterPercent = 0.3) {
|
|
421
|
+
const jitter = base * jitterPercent * (Math.random() * 2 - 1);
|
|
422
|
+
return Math.max(10, Math.round(base + jitter));
|
|
423
|
+
},
|
|
414
424
|
/**
|
|
415
425
|
* 初始化页面的 Ghost Cursor(必须在使用其他 cursor 相关方法前调用)
|
|
416
426
|
*
|
|
@@ -474,13 +484,12 @@ var Humanize = {
|
|
|
474
484
|
* @param {import('playwright').Page} page
|
|
475
485
|
* @param {string|import('playwright').ElementHandle} target - CSS 选择器或元素句柄
|
|
476
486
|
* @param {Object} [options]
|
|
477
|
-
* @param {number} [options.
|
|
478
|
-
* @param {number} [options.delayAfter=300] - 点击后延迟 (ms)
|
|
487
|
+
* @param {number} [options.reactionDelay=250] - 反应延迟基础值 (ms),实际 ±30% 抖动
|
|
479
488
|
* @param {boolean} [options.throwOnMissing=true] - 元素不存在时是否抛出错误
|
|
480
489
|
*/
|
|
481
490
|
async humanClick(page, target, options = {}) {
|
|
482
491
|
const cursor = $GetCursor(page);
|
|
483
|
-
const {
|
|
492
|
+
const { reactionDelay = 250, throwOnMissing = true } = options;
|
|
484
493
|
logger4.start("humanClick", `target=${typeof target === "string" ? target : "ElementHandle"}`);
|
|
485
494
|
try {
|
|
486
495
|
let element;
|
|
@@ -507,7 +516,7 @@ var Humanize = {
|
|
|
507
516
|
const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.3;
|
|
508
517
|
const y = box.y + box.height / 2 + (Math.random() - 0.5) * box.height * 0.3;
|
|
509
518
|
await cursor.actions.move({ x, y });
|
|
510
|
-
await (0, import_delay.
|
|
519
|
+
await (0, import_delay.default)(this.jitterMs(reactionDelay, 0.4));
|
|
511
520
|
await cursor.actions.click();
|
|
512
521
|
logger4.success("humanClick");
|
|
513
522
|
return true;
|
|
@@ -517,30 +526,32 @@ var Humanize = {
|
|
|
517
526
|
}
|
|
518
527
|
},
|
|
519
528
|
/**
|
|
520
|
-
*
|
|
521
|
-
* @param {number}
|
|
522
|
-
* @param {number}
|
|
529
|
+
* 随机延迟一段毫秒数(带 ±30% 抖动)
|
|
530
|
+
* @param {number} baseMs - 基础延迟毫秒数
|
|
531
|
+
* @param {number} [jitterPercent=0.3] - 抖动百分比
|
|
523
532
|
*/
|
|
524
|
-
async randomSleep(
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
await ms;
|
|
533
|
+
async randomSleep(baseMs, jitterPercent = 0.3) {
|
|
534
|
+
const ms = this.jitterMs(baseMs, jitterPercent);
|
|
535
|
+
logger4.start("randomSleep", `base=${baseMs}, actual=${ms}ms`);
|
|
536
|
+
await (0, import_delay.default)(ms);
|
|
528
537
|
logger4.success("randomSleep");
|
|
529
538
|
},
|
|
530
539
|
/**
|
|
531
540
|
* 模拟人类"注视"或"阅读"行为:鼠标在页面上随机微动
|
|
532
541
|
* @param {import('playwright').Page} page
|
|
533
|
-
* @param {number}
|
|
542
|
+
* @param {number} [baseDurationMs=2500] - 基础持续时间 (±40% 抖动)
|
|
534
543
|
*/
|
|
535
|
-
async simulateGaze(page,
|
|
544
|
+
async simulateGaze(page, baseDurationMs = 2500) {
|
|
536
545
|
const cursor = $GetCursor(page);
|
|
546
|
+
const durationMs = this.jitterMs(baseDurationMs, 0.4);
|
|
537
547
|
logger4.start("simulateGaze", `duration=${durationMs}ms`);
|
|
538
548
|
const startTime = Date.now();
|
|
549
|
+
const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };
|
|
539
550
|
while (Date.now() - startTime < durationMs) {
|
|
540
|
-
const x = Math.random() *
|
|
541
|
-
const y = Math.random() *
|
|
551
|
+
const x = 100 + Math.random() * (viewportSize.width - 200);
|
|
552
|
+
const y = 100 + Math.random() * (viewportSize.height - 200);
|
|
542
553
|
await cursor.actions.move({ x, y });
|
|
543
|
-
await (0, import_delay.
|
|
554
|
+
await (0, import_delay.default)(this.jitterMs(600, 0.5));
|
|
544
555
|
}
|
|
545
556
|
logger4.success("simulateGaze");
|
|
546
557
|
},
|
|
@@ -550,41 +561,36 @@ var Humanize = {
|
|
|
550
561
|
* @param {string} selector - 输入框选择器
|
|
551
562
|
* @param {string} text - 要输入的文本
|
|
552
563
|
* @param {Object} [options]
|
|
553
|
-
* @param {number} [options.
|
|
554
|
-
* @param {number} [options.
|
|
555
|
-
* @param {number} [options.
|
|
556
|
-
* @param {number} [options.pauseMin=300] - 停顿最小时长 (ms)
|
|
557
|
-
* @param {number} [options.pauseMax=800] - 停顿最大时长 (ms)
|
|
558
|
-
*
|
|
564
|
+
* @param {number} [options.baseDelay=180] - 基础按键延迟 (ms),实际 ±40% 抖动
|
|
565
|
+
* @param {number} [options.pauseProbability=0.08] - 停顿概率 (0-1)
|
|
566
|
+
* @param {number} [options.pauseBase=800] - 停顿时长基础值 (ms),实际 ±50% 抖动
|
|
559
567
|
*/
|
|
560
568
|
async humanType(page, selector, text, options = {}) {
|
|
561
569
|
logger4.start("humanType", `selector=${selector}, textLen=${text.length}`);
|
|
562
570
|
const {
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
pauseMin = 300,
|
|
567
|
-
pauseMax = 800
|
|
571
|
+
baseDelay = 180,
|
|
572
|
+
pauseProbability = 0.08,
|
|
573
|
+
pauseBase = 800
|
|
568
574
|
} = options;
|
|
569
575
|
try {
|
|
570
576
|
const locator = page.locator(selector);
|
|
571
577
|
await locator.click();
|
|
572
|
-
await (0, import_delay.
|
|
578
|
+
await (0, import_delay.default)(this.jitterMs(200, 0.4));
|
|
573
579
|
for (let i = 0; i < text.length; i++) {
|
|
574
580
|
const char = text[i];
|
|
575
581
|
let charDelay;
|
|
576
582
|
if (char === " ") {
|
|
577
|
-
charDelay =
|
|
583
|
+
charDelay = this.jitterMs(baseDelay * 0.6, 0.3);
|
|
578
584
|
} else if (/[,.!?;:,。!?;:]/.test(char)) {
|
|
579
|
-
charDelay =
|
|
585
|
+
charDelay = this.jitterMs(baseDelay * 1.5, 0.4);
|
|
580
586
|
} else {
|
|
581
|
-
charDelay =
|
|
587
|
+
charDelay = this.jitterMs(baseDelay, 0.4);
|
|
582
588
|
}
|
|
583
589
|
await page.keyboard.type(char);
|
|
584
590
|
await (0, import_delay.default)(charDelay);
|
|
585
591
|
if (Math.random() < pauseProbability && i < text.length - 1) {
|
|
586
|
-
const pauseTime =
|
|
587
|
-
logger4.debug(`\u505C\u987F ${
|
|
592
|
+
const pauseTime = this.jitterMs(pauseBase, 0.5);
|
|
593
|
+
logger4.debug(`\u505C\u987F ${pauseTime}ms...`);
|
|
588
594
|
await (0, import_delay.default)(pauseTime);
|
|
589
595
|
}
|
|
590
596
|
}
|
|
@@ -604,14 +610,14 @@ var Humanize = {
|
|
|
604
610
|
try {
|
|
605
611
|
const locator = page.locator(selector);
|
|
606
612
|
await locator.click();
|
|
607
|
-
await (0, import_delay.
|
|
613
|
+
await (0, import_delay.default)(this.jitterMs(200, 0.4));
|
|
608
614
|
const currentValue = await locator.inputValue();
|
|
609
615
|
if (!currentValue || currentValue.length === 0) {
|
|
610
616
|
logger4.success("humanClear", "already empty");
|
|
611
617
|
return;
|
|
612
618
|
}
|
|
613
619
|
await page.keyboard.press("Meta+A");
|
|
614
|
-
await (0, import_delay.
|
|
620
|
+
await (0, import_delay.default)(this.jitterMs(100, 0.4));
|
|
615
621
|
await page.keyboard.press("Backspace");
|
|
616
622
|
logger4.success("humanClear");
|
|
617
623
|
} catch (error) {
|
|
@@ -622,17 +628,11 @@ var Humanize = {
|
|
|
622
628
|
/**
|
|
623
629
|
* 页面预热浏览 - 模拟人类进入页面后的探索行为
|
|
624
630
|
* @param {import('playwright').Page} page
|
|
625
|
-
* @param {number
|
|
631
|
+
* @param {number} [baseDuration=3500] - 预热时长基础值 (±40% 抖动)
|
|
626
632
|
*/
|
|
627
|
-
async warmUpBrowsing(page,
|
|
633
|
+
async warmUpBrowsing(page, baseDuration = 3500) {
|
|
628
634
|
const cursor = $GetCursor(page);
|
|
629
|
-
|
|
630
|
-
if (typeof duration === "object" && duration.min !== void 0 && duration.max !== void 0) {
|
|
631
|
-
durationMs = duration.min + Math.random() * (duration.max - duration.min);
|
|
632
|
-
} else {
|
|
633
|
-
durationMs = duration;
|
|
634
|
-
}
|
|
635
|
-
durationMs = Math.round(durationMs);
|
|
635
|
+
const durationMs = this.jitterMs(baseDuration, 0.4);
|
|
636
636
|
logger4.start("warmUpBrowsing", `duration=${durationMs}ms`);
|
|
637
637
|
const startTime = Date.now();
|
|
638
638
|
const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };
|
|
@@ -643,13 +643,13 @@ var Humanize = {
|
|
|
643
643
|
const x = 100 + Math.random() * (viewportSize.width - 200);
|
|
644
644
|
const y = 100 + Math.random() * (viewportSize.height - 200);
|
|
645
645
|
await cursor.actions.move({ x, y });
|
|
646
|
-
await (0, import_delay.
|
|
646
|
+
await (0, import_delay.default)(this.jitterMs(350, 0.4));
|
|
647
647
|
} else if (action < 0.7) {
|
|
648
648
|
const scrollY = (Math.random() - 0.5) * 200;
|
|
649
649
|
await page.mouse.wheel(0, scrollY);
|
|
650
|
-
await (0, import_delay.
|
|
650
|
+
await (0, import_delay.default)(this.jitterMs(500, 0.4));
|
|
651
651
|
} else {
|
|
652
|
-
await (0, import_delay.
|
|
652
|
+
await (0, import_delay.default)(this.jitterMs(800, 0.5));
|
|
653
653
|
}
|
|
654
654
|
}
|
|
655
655
|
logger4.success("warmUpBrowsing");
|
|
@@ -659,23 +659,26 @@ var Humanize = {
|
|
|
659
659
|
}
|
|
660
660
|
},
|
|
661
661
|
/**
|
|
662
|
-
* 自然滚动 -
|
|
662
|
+
* 自然滚动 - 带惯性、减速效果和随机抖动
|
|
663
663
|
* @param {import('playwright').Page} page
|
|
664
664
|
* @param {'up' | 'down'} [direction='down'] - 滚动方向
|
|
665
|
-
* @param {number} [distance=300] -
|
|
666
|
-
* @param {number} [
|
|
665
|
+
* @param {number} [distance=300] - 总滚动距离基础值 (px),±15% 抖动
|
|
666
|
+
* @param {number} [baseSteps=5] - 分几步完成基础值,±1 随机
|
|
667
667
|
*/
|
|
668
|
-
async naturalScroll(page, direction = "down", distance = 300,
|
|
669
|
-
|
|
668
|
+
async naturalScroll(page, direction = "down", distance = 300, baseSteps = 5) {
|
|
669
|
+
const steps = Math.max(3, baseSteps + Math.floor(Math.random() * 3) - 1);
|
|
670
|
+
const actualDistance = this.jitterMs(distance, 0.15);
|
|
671
|
+
logger4.start("naturalScroll", `dir=${direction}, dist=${actualDistance}, steps=${steps}`);
|
|
670
672
|
const sign = direction === "down" ? 1 : -1;
|
|
671
|
-
const stepDistance =
|
|
673
|
+
const stepDistance = actualDistance / steps;
|
|
672
674
|
try {
|
|
673
675
|
for (let i = 0; i < steps; i++) {
|
|
674
676
|
const factor = 1 - i / steps * 0.5;
|
|
675
|
-
const
|
|
677
|
+
const jitter = 0.9 + Math.random() * 0.2;
|
|
678
|
+
const scrollAmount = stepDistance * factor * sign * jitter;
|
|
676
679
|
await page.mouse.wheel(0, scrollAmount);
|
|
677
|
-
const
|
|
678
|
-
await (0, import_delay.default)(
|
|
680
|
+
const baseDelay = 60 + i * 25;
|
|
681
|
+
await (0, import_delay.default)(this.jitterMs(baseDelay, 0.3));
|
|
679
682
|
}
|
|
680
683
|
logger4.success("naturalScroll");
|
|
681
684
|
} catch (error) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../index.js", "../src/apify-kit.js", "../src/constants.js", "../src/internal/logger.js", "../src/utils.js", "../src/stealth.js", "../src/humanize.js", "../src/launch.js", "../src/live-view.js", "../src/captcha-monitor.js"],
|
|
4
|
-
"sourcesContent": ["import { ApifyKit } from './src/apify-kit';\nimport { Utils } from './src/utils';\nimport { Stealth } from './src/stealth';\nimport { Humanize } from './src/humanize';\nimport { Launch } from './src/launch';\nimport { LiveView } from './src/live-view';\nimport { Captcha } from './src/captcha-monitor';\nimport * as Constants from './src/constants';\n\n// Unified Entry Point\nexport const usePlaywrightToolKit = () => {\n return {\n ApifyKit,\n Stealth,\n Humanize,\n Launch,\n LiveView,\n Constants,\n Utils,\n Captcha\n };\n};\n", "import { log as originalLog } from 'crawlee'; // \u4FDD\u7559\u539F\u59CB log \u7528\u4E8E\u7279\u6B8A\u7528\u9014\u6216\u76F4\u63A5\u8C03\u7528\nimport { Status, FAILED_KEY_SEPARATOR, StatusCode } from './constants';\nimport { createLogger } from './internal/logger';\n\nconst logger = createLogger('ApifyKit');\n\n/**\n * \u521B\u5EFA ApifyKit \u5B9E\u4F8B\n * \u5982\u679C apify \u53EF\u7528\uFF0C\u8FD4\u56DE\u5B8C\u6574\u529F\u80FD\u7684 ApifyKit\n * \u5982\u679C apify \u4E0D\u53EF\u7528\uFF0C\u8FD4\u56DE\u964D\u7EA7\u7248\u672C\uFF08\u975E apify \u76F8\u5173\u529F\u80FD\u4ECD\u53EF\u7528\uFF09\n */\nasync function createApifyKit() {\n let apify = null;\n\n // \u5C1D\u8BD5\u52A0\u8F7D apify\n try {\n apify = await import('apify');\n } catch (error) {\n // apify \u4E0D\u53EF\u7528\uFF0C\u5C06\u4F7F\u7528\u964D\u7EA7\u7248\u672C\n throw new Error('\u26A0\uFE0F apify \u5E93\u672A\u5B89\u88C5\uFF0CApifyKit \u7684 Actor \u76F8\u5173\u529F\u80FD\u4E0D\u53EF\u7528')\n }\n\n const { Actor } = apify;\n\n return {\n /**\n * \u5305\u88C5 Step Name\n */\n wrapStepNameWithFailedKey(key, stepName) {\n return `${key}${FAILED_KEY_SEPARATOR}${stepName}`;\n },\n\n /**\n * \u89E3\u5305 Step Name\n */\n unwrapStepName(stepName) {\n const splitIndex = stepName.indexOf(FAILED_KEY_SEPARATOR);\n if (splitIndex === -1) {\n return ['-', stepName];\n }\n const key = stepName.substring(0, splitIndex);\n const value = stepName.substring(splitIndex + FAILED_KEY_SEPARATOR.length);\n return [key, value];\n },\n\n /**\n * \u6838\u5FC3\u5C01\u88C5\uFF1A\u6267\u884C\u6B65\u9AA4\uFF0C\u5E26\u81EA\u52A8\u65E5\u5FD7\u786E\u8BA4\u548C\u5931\u8D25\u622A\u56FE\u5904\u7406\n */\n async runStep(pendingStepName, page, actionFn, options = {}) {\n const { failActor = true } = options; // \u9ED8\u8BA4\u8C03\u7528 Actor.fail\n const [failedKey, stepName] = this.unwrapStepName(pendingStepName);\n\n // log.info(`\uD83D\uDD04 [\u6B63\u5728\u6267\u884C] ${stepName}...`);\n logger.start(`[Step] ${stepName}`);\n\n try {\n const result = await actionFn();\n // log.info(`\u2705 [\u6267\u884C\u6210\u529F] ${stepName}`);\n logger.success(`[Step] ${stepName}`);\n return result;\n } catch (error) {\n // log.error(`\u274C [\u6267\u884C\u5931\u8D25] ${stepName}: ${error.message}`);\n logger.fail(`[Step] ${stepName}`, error);\n\n let screenshotBase64 = '\u622A\u56FE\u5931\u8D25';\n try {\n if (page) {\n const buffer = await page.screenshot({ fullPage: true, type: 'jpeg', quality: 60 });\n screenshotBase64 = `data:image/jpeg;base64,${buffer.toString('base64')}`;\n }\n } catch (snapErr) {\n logger.warn(`\u622A\u56FE\u751F\u6210\u5931\u8D25: ${snapErr.message}`);\n }\n\n // \u4F7F\u7528 pushFailed \u65B9\u6CD5\u63A8\u9001\u5931\u8D25\u6570\u636E\uFF08\u79C1\u6709\u4F7F\u7528\uFF09\n await this.pushFailed(error, {\n failedStep: stepName,\n failedKey: failedKey,\n errorMessage: error.message,\n errorStack: error.stack,\n screenshotBase64: screenshotBase64\n });\n\n // \u6839\u636E failActor \u51B3\u5B9A\u662F\u5426\u8C03\u7528 Actor.fail\n if (failActor) {\n await Actor.fail(`Run Step ${stepName} \u5931\u8D25: ${error.message}`);\n } else {\n // \u4E0D\u8C03\u7528 Actor.fail\uFF0C\u76F4\u63A5\u629B\u51FA\u9519\u8BEF\n throw error;\n }\n }\n },\n\n /**\n * \u5BBD\u677E\u7248runStep\uFF1A\u5931\u8D25\u65F6\u4E0D\u8C03\u7528Actor.fail\uFF0C\u53EA\u629B\u51FA\u5F02\u5E38\n */\n async runStepLoose(stepName, page, fn) {\n return await this.runStep(stepName, page, fn, { failActor: false });\n },\n\n /**\n * \u63A8\u9001\u6210\u529F\u6570\u636E\u7684\u901A\u7528\u65B9\u6CD5\n * @param {Object} data - \u8981\u63A8\u9001\u7684\u6570\u636E\u5BF9\u8C61\n */\n async pushSuccess(data) {\n await Actor.pushData({\n code: StatusCode.Success,\n status: Status.Success,\n timestamp: new Date().toISOString(),\n ...data\n });\n logger.success('pushSuccess', 'Data pushed');\n },\n\n /**\n * \u63A8\u9001\u5931\u8D25\u6570\u636E\u7684\u901A\u7528\u65B9\u6CD5\uFF08\u79C1\u6709\u65B9\u6CD5\uFF0C\u4EC5\u4F9BrunStep\u5185\u90E8\u4F7F\u7528\uFF09\n * @param {Error|Object} error - \u9519\u8BEF\u5BF9\u8C61\uFF08\u53EF\u5305\u542B\u5176\u4ED6\u7684\u9519\u8BEF/\u6216\u90E8\u5206\u5904\u7406\u6210\u529F\u7684\u989D\u5916\u4FE1\u606F\uFF09\n * @param {Object} [meta] - \u989D\u5916\u7684\u6570\u636E\uFF08\u5982failedStep, screenshotBase64\u7B49\uFF0C\u4EC5runStep\u4F7F\u7528\uFF09\n * @private\n */\n async pushFailed(error, meta = {}) {\n await Actor.pushData({\n code: StatusCode.Failed,\n status: Status.Failed,\n // \u8FD9\u91CC\u53EF\u80FD\u5E26\u5176\u4ED6\u9519\u8BEF\u4FE1\u606F\n error,\n timestamp: new Date().toISOString(),\n ...meta\n });\n logger.success('pushFailed', 'Error data pushed');\n }\n };\n}\n\n// \u61D2\u52A0\u8F7D\u5355\u4F8B\nlet instance = null;\n\n/**\n * \u83B7\u53D6 ApifyKit \u5B9E\u4F8B\uFF08\u61D2\u52A0\u8F7D\uFF09\n * @returns {Promise<Object>} ApifyKit \u5B9E\u4F8B\n */\nasync function useApifyKit() {\n if (!instance) {\n instance = await createApifyKit();\n }\n return instance;\n}\n\n// \u4E5F\u5BFC\u51FA\u521D\u59CB\u5316\u51FD\u6570\uFF0C\u4F9B\u9700\u8981\u7684\u7528\u6237\u4F7F\u7528\nexport const ApifyKit = {\n useApifyKit\n};\n", "export const ErrorKeygen = {\n NotLogin: 30000001,\n Chaptcha: 30000002,\n}\n\nexport const Status = {\n Success: 'SUCCESS',\n Failed: 'FAILED'\n}\n\nexport const StatusCode = {\n Success: 0,\n Failed: -1\n}\n\nexport const FAILED_KEY_SEPARATOR = '::<@>::';\n\nexport const PresetOfLiveViewKey = 'LIVE_VIEW_SCREENSHOT';\n", "import { log } from 'crawlee';\n\n/**\n * \u521B\u5EFA\u6A21\u5757\u7EA7\u65E5\u5FD7\u5668\n * @param {string} moduleName - \u6A21\u5757\u540D\u79F0\uFF0C\u4F8B\u5982 'Humanize', 'Stealth'\n */\nexport function createLogger(moduleName) {\n const prefix = `[${moduleName}]`;\n\n return {\n /**\n * \u65B9\u6CD5\u5F00\u59CB\u65E5\u5FD7\n * @param {string} methodName - \u65B9\u6CD5\u540D\u79F0\n * @param {string} [params] - \u53C2\u6570\u6458\u8981 (\u53EF\u9009)\n */\n start(methodName, params = '') {\n const paramStr = params ? ` (${params})` : '';\n log.info(`${prefix} \uD83D\uDD37 ${methodName} \u5F00\u59CB${paramStr}`);\n },\n\n /**\n * \u65B9\u6CD5\u6210\u529F\u65E5\u5FD7\n * @param {string} methodName - \u65B9\u6CD5\u540D\u79F0\n * @param {string} [result] - \u7ED3\u679C\u6458\u8981 (\u53EF\u9009)\n */\n success(methodName, result = '') {\n const resultStr = result ? ` (${result})` : '';\n log.info(`${prefix} \u2705 ${methodName} \u5B8C\u6210${resultStr}`);\n },\n\n /**\n * \u65B9\u6CD5\u5931\u8D25\u65E5\u5FD7\n * @param {string} methodName - \u65B9\u6CD5\u540D\u79F0\n * @param {Error|string} error - \u9519\u8BEF\u5BF9\u8C61\u6216\u4FE1\u606F\n */\n fail(methodName, error) {\n const message = error instanceof Error ? error.message : error;\n log.error(`${prefix} \u274C ${methodName} \u5931\u8D25: ${message}`);\n },\n\n /**\n * \u8C03\u8BD5\u65E5\u5FD7\n * @param {string} message - \u8BE6\u60C5\n */\n debug(message) {\n log.debug(`${prefix} \uD83D\uDD39 ${message}`);\n },\n\n /**\n * \u8B66\u544A\u65E5\u5FD7\n * @param {string} message - \u8B66\u544A\u4FE1\u606F\n */\n warn(message) {\n log.warning(`${prefix} \u26A0\uFE0F ${message}`);\n },\n\n /**\n * \u666E\u901A\u4FE1\u606F\u65E5\u5FD7\n * @param {string} message - \u4FE1\u606F\n */\n info(message) {\n log.info(`${prefix} \uD83D\uDCD6 ${message}`);\n }\n };\n}\n", "import { createLogger } from './internal/logger';\n\nconst logger = createLogger('Utils');\n\nexport const Utils = {\n /**\n * \u89E3\u6790 SSE \u6D41\u6587\u672C\n */\n parseSseStream(sseStreamText) {\n const events = [];\n const lines = sseStreamText.split('\\n');\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n try {\n const jsonContent = line.substring(6).trim();\n if (jsonContent && jsonContent !== '[DONE]') {\n events.push(JSON.parse(jsonContent));\n }\n } catch (e) {\n // Ignore lines that are not valid JSON\n }\n }\n }\n logger.success('parseSseStream', `parsed events: ${events.length}`);\n return events;\n },\n\n /**\n * \u89E3\u6790 Cookie \u5B57\u7B26\u4E32\u4E3A Playwright \u683C\u5F0F\u7684 Cookie \u6570\u7EC4\n * @param {string} cookieString - Cookie \u5B57\u7B26\u4E32\n * @param {string} [domain] - Cookie \u57DF\u540D (\u53EF\u9009)\n * @returns {Array} Cookie \u6570\u7EC4\n */\n parseCookies(cookieString, domain) {\n const cookies = [];\n const pairs = cookieString.split(';').map(c => c.trim());\n\n for (const pair of pairs) {\n const [name, ...valueParts] = pair.split('=');\n if (name && valueParts.length > 0) {\n const cookie = {\n name: name.trim(),\n value: valueParts.join('=').trim(),\n path: '/',\n };\n if (domain) {\n cookie.domain = domain;\n }\n cookies.push(cookie);\n }\n }\n logger.success('parseCookies', `parsed ${cookies.length} cookies`);\n return cookies;\n }\n}\n", "import { createLogger } from './internal/logger';\n\nconst logger = createLogger('Stealth');\n\nexport const Stealth = {\n /**\n * \u5173\u952E\u4FEE\u590D\uFF1A\u5C06 Page \u89C6\u53E3\u8C03\u6574\u4E3A\u4E0E\u6D4F\u89C8\u5668\u6307\u7EB9 (window.screen) \u4E00\u81F4\u3002\n * \u9632\u6B62 \"Viewport Mismatch\" \u7C7B\u578B\u7684\u53CD\u722C\u68C0\u6D4B\u3002\n * @param {import('playwright').Page} page \n */\n async syncViewportWithScreen(page) {\n try {\n // \u83B7\u53D6\u6307\u7EB9\u4E2D\u7684\u5C4F\u5E55\u5C3A\u5BF8\n const screen = await page.evaluate(() => ({\n width: window.screen.width,\n height: window.screen.height,\n availWidth: window.screen.availWidth,\n availHeight: window.screen.availHeight,\n }));\n\n // \u8C03\u6574\u89C6\u53E3\n await page.setViewportSize({\n width: screen.width,\n height: screen.height\n });\n\n logger.success('syncViewportWithScreen', `size=${screen.width}x${screen.height}`);\n } catch (e) {\n logger.warn(`syncViewportWithScreen Failed: ${e.message}. Fallback to 1920x1080.`);\n await page.setViewportSize({ width: 1920, height: 1080 });\n }\n },\n\n /**\n * \u786E\u4FDD navigator.webdriver \u9690\u85CF (\u901A\u5E38 Playwright Stealth \u63D2\u4EF6\u5DF2\u5904\u7406\uFF0C\u4F46\u53CC\u91CD\u4FDD\u9669)\n */\n async hideWebdriver(page) {\n await page.addInitScript(() => {\n Object.defineProperty(navigator, 'webdriver', {\n get: () => false,\n });\n });\n logger.success('hideWebdriver');\n },\n\n /**\n * \u901A\u7528\u7684 Playwright \u8D44\u6E90\u62E6\u622A\u5668\uFF0C\u7528\u4E8E\u5C4F\u853D\u4E0D\u5FC5\u8981\u7684\u8D44\u6E90\u4EE5\u52A0\u901F\u52A0\u8F7D\n * @param {import('playwright').Page} page\n * @param {string[]} [resourceTypes] - \u8981\u5C4F\u853D\u7684\u8D44\u6E90\u7C7B\u578B\uFF0C\u9ED8\u8BA4\u4E3A ['font', 'image', 'media']\n */\n async setupBlockingResources(page, resourceTypes = ['font', 'image', 'media']) {\n await page.route('**/*', (route) => {\n const request = route.request();\n const type = request.resourceType();\n if (resourceTypes.includes(type)) {\n return route.abort();\n }\n return route.continue();\n });\n logger.success('setupBlockingResources', `types=[${resourceTypes.join(',')}]`);\n },\n\n /**\n * \u83B7\u53D6\u63A8\u8350\u7684 Stealth \u542F\u52A8\u53C2\u6570\n */\n getStealthLaunchArgs() {\n return [\n '--disable-blink-features=AutomationControlled',\n '--no-sandbox',\n '--disable-setuid-sandbox',\n '--disable-infobars',\n '--window-position=0,0',\n '--ignore-certificate-errors',\n '--disable-web-security',\n // \u6CE8\u610F\uFF1A\u4E0D\u5EFA\u8BAE\u8FD9\u91CC\u5F3A\u5236\u6307\u5B9A window-size\uFF0C\u8BA9 syncViewportWithScreen \u53BB\u52A8\u6001\u8C03\u6574\n // '--window-size=1920,1080' \n ];\n },\n\n /**\n * \u83B7\u53D6\u589E\u5F3A\u7248 Stealth \u542F\u52A8\u53C2\u6570 (\u63A8\u8350\u7528\u4E8E\u9AD8\u98CE\u9669\u53CD\u722C\u573A\u666F)\n * \u5305\u542B\u66F4\u591A\u9488\u5BF9\u81EA\u52A8\u5316\u68C0\u6D4B\u7684\u9632\u62A4\n */\n getAdvancedStealthArgs() {\n return [\n ...this.getStealthLaunchArgs(),\n // \u7981\u7528\u5404\u79CD\u53EF\u80FD\u66B4\u9732\u81EA\u52A8\u5316\u7684\u7279\u5F81\n '--disable-dev-shm-usage',\n '--disable-accelerated-2d-canvas',\n '--disable-gpu-sandbox',\n '--disable-background-networking',\n '--disable-default-apps',\n '--disable-extensions',\n '--disable-sync',\n '--disable-translate',\n '--metrics-recording-only',\n '--mute-audio',\n '--no-first-run',\n // \u6A21\u62DF\u771F\u5B9E\u7528\u6237\u914D\u7F6E\n '--lang=zh-CN,zh',\n ];\n },\n\n /**\n * \u8BBE\u7F6E\u4E2D\u56FD\u65F6\u533A (Asia/Shanghai, UTC+8)\n * \n * \u9632\u6B62\u65F6\u533A\u4E0D\u4E00\u81F4\u7684\u68C0\u6D4B\u3002\u5BF9\u4E8E\u4E2D\u56FD\u5883\u5185\u722C\u53D6\u5F3A\u70C8\u63A8\u8350\u4F7F\u7528\u3002\n * \u5E94\u5728 preNavigationHooks \u6216 BrowserContext \u521B\u5EFA\u540E\u8C03\u7528\u3002\n * \n * @param {import('playwright').BrowserContext} context\n */\n async setChinaTimezone(context) {\n // Playwright \u901A\u8FC7 context \u8BBE\u7F6E\u65F6\u533A\n // \u6CE8\u610F\uFF1A\u8FD9\u9700\u8981\u5728 context \u521B\u5EFA\u65F6\u8BBE\u7F6E\uFF0C\u6216\u8005\u4F7F\u7528 CDP\n // \u8FD9\u91CC\u4F7F\u7528 addInitScript \u6CE8\u5165 Intl \u8986\u76D6\n await context.addInitScript(() => {\n // \u8986\u76D6 Intl.DateTimeFormat \u9ED8\u8BA4\u65F6\u533A\n const originalDateTimeFormat = Intl.DateTimeFormat;\n Intl.DateTimeFormat = function (locales, options) {\n options = options || {};\n options.timeZone = options.timeZone || 'Asia/Shanghai';\n return new originalDateTimeFormat(locales, options);\n };\n Intl.DateTimeFormat.prototype = originalDateTimeFormat.prototype;\n\n // \u8986\u76D6 Date.prototype.getTimezoneOffset \u8FD4\u56DE -480 (UTC+8)\n Date.prototype.getTimezoneOffset = function () {\n return -480; // UTC+8 = -480 \u5206\u949F\n };\n });\n logger.success('setChinaTimezone', 'Asia/Shanghai (UTC+8)');\n }\n}\n", "import delay, { rangeDelay } from 'delay';\nimport { createCursor } from 'ghost-cursor-playwright';\nimport { createLogger } from './internal/logger';\n\nconst logger = createLogger('Humanize');\n\n// \u5185\u90E8 cursor \u5B9E\u4F8B\u7F13\u5B58 (\u6BCF\u4E2A page \u4E00\u4E2A) - \u4E0D\u5BF9\u5916\u66B4\u9732\nconst $CursorWeakMap = new WeakMap();\n\n/**\n * \u5185\u90E8\u65B9\u6CD5\uFF1A\u83B7\u53D6\u9875\u9762\u7684 cursor\uFF0C\u5982\u679C\u4E0D\u5B58\u5728\u5219\u629B\u51FA\u9519\u8BEF\n */\nfunction $GetCursor(page) {\n const cursor = $CursorWeakMap.get(page);\n if (!cursor) {\n throw new Error('Cursor \u672A\u521D\u59CB\u5316\uFF0C\u8BF7\u5148\u8C03\u7528 Humanize.initializeCursor(page)');\n }\n return cursor;\n}\n\nexport const Humanize = {\n /**\n * \u521D\u59CB\u5316\u9875\u9762\u7684 Ghost Cursor\uFF08\u5FC5\u987B\u5728\u4F7F\u7528\u5176\u4ED6 cursor \u76F8\u5173\u65B9\u6CD5\u524D\u8C03\u7528\uFF09\n * \n * @param {import('playwright').Page} page\n * @returns {Promise<void>}\n */\n async initializeCursor(page) {\n if ($CursorWeakMap.has(page)) {\n logger.debug('initializeCursor: cursor already exists, skipping');\n return;\n }\n logger.start('initializeCursor', 'creating cursor');\n const cursor = await createCursor(page);\n $CursorWeakMap.set(page, cursor);\n logger.success('initializeCursor', 'cursor initialized');\n },\n\n /**\n * \u4EBA\u7C7B\u5316\u9F20\u6807\u79FB\u52A8 - \u4F7F\u7528 ghost-cursor \u79FB\u52A8\u5230\u6307\u5B9A\u4F4D\u7F6E\u6216\u5143\u7D20\n * \n * @param {import('playwright').Page} page\n * @param {string|{x: number, y: number}|import('playwright').ElementHandle} target - CSS\u9009\u62E9\u5668\u3001\u5750\u6807\u5BF9\u8C61\u6216\u5143\u7D20\u53E5\u67C4\n */\n async humanMove(page, target) {\n const cursor = $GetCursor(page);\n logger.start('humanMove', `target=${typeof target === 'string' ? target : 'element/coords'}`);\n try {\n if (typeof target === 'string') {\n // CSS \u9009\u62E9\u5668\n const element = await page.$(target);\n if (!element) {\n logger.warn(`humanMove: \u5143\u7D20\u4E0D\u5B58\u5728 ${target}`);\n return false;\n }\n const box = await element.boundingBox();\n if (!box) {\n logger.warn(`humanMove: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E ${target}`);\n return false;\n }\n const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.2;\n const y = box.y + box.height / 2 + (Math.random() - 0.5) * box.height * 0.2;\n await cursor.actions.move({ x, y });\n } else if (target && typeof target.x === 'number' && typeof target.y === 'number') {\n // \u5750\u6807\u5BF9\u8C61\n await cursor.actions.move(target);\n } else if (target && typeof target.boundingBox === 'function') {\n // ElementHandle\n const box = await target.boundingBox();\n if (box) {\n const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.2;\n const y = box.y + box.height / 2 + (Math.random() - 0.5) * box.height * 0.2;\n await cursor.actions.move({ x, y });\n }\n }\n logger.success('humanMove');\n return true;\n } catch (error) {\n logger.fail('humanMove', error);\n throw error;\n }\n },\n\n /**\n * \u4EBA\u7C7B\u5316\u70B9\u51FB - \u4F7F\u7528 ghost-cursor \u6A21\u62DF\u4EBA\u7C7B\u9F20\u6807\u79FB\u52A8\u8F68\u8FF9\u5E76\u70B9\u51FB\n * \n * @param {import('playwright').Page} page\n * @param {string|import('playwright').ElementHandle} target - CSS \u9009\u62E9\u5668\u6216\u5143\u7D20\u53E5\u67C4\n * @param {Object} [options]\n * @param {number} [options.delayBefore=100] - \u70B9\u51FB\u524D\u5EF6\u8FDF (ms)\n * @param {number} [options.delayAfter=300] - \u70B9\u51FB\u540E\u5EF6\u8FDF (ms)\n * @param {boolean} [options.throwOnMissing=true] - \u5143\u7D20\u4E0D\u5B58\u5728\u65F6\u662F\u5426\u629B\u51FA\u9519\u8BEF\n */\n async humanClick(page, target, options = {}) {\n const cursor = $GetCursor(page);\n const { delayBefore = 100, delayAfter = 100, throwOnMissing = true } = options;\n logger.start('humanClick', `target=${typeof target === 'string' ? target : 'ElementHandle'}`);\n\n try {\n let element;\n if (typeof target === 'string') {\n element = await page.$(target);\n if (!element) {\n if (throwOnMissing) {\n throw new Error(`\u627E\u4E0D\u5230\u5143\u7D20 ${target}`);\n }\n logger.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${target}`);\n return false;\n }\n } else {\n element = target;\n }\n\n const box = await element.boundingBox();\n if (!box) {\n if (throwOnMissing) {\n throw new Error('\u65E0\u6CD5\u83B7\u53D6\u5143\u7D20\u4F4D\u7F6E');\n }\n logger.warn('humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB');\n return false;\n }\n\n // \u8BA1\u7B97\u5E26\u968F\u673A\u504F\u79FB\u7684\u70B9\u51FB\u4F4D\u7F6E\n const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.3;\n const y = box.y + box.height / 2 + (Math.random() - 0.5) * box.height * 0.3;\n\n await cursor.actions.move({ x, y });\n await rangeDelay(delayBefore, delayAfter);\n await cursor.actions.click();\n\n logger.success('humanClick');\n return true;\n } catch (error) {\n logger.fail('humanClick', error);\n throw error;\n }\n },\n\n /**\n * \u968F\u673A\u5EF6\u8FDF\u4E00\u6BB5\u6BEB\u79D2\u6570\n * @param {number} min - \u6700\u5C0F\u6BEB\u79D2\n * @param {number} max - \u6700\u5927\u6BEB\u79D2\n */\n async randomSleep(min, max) {\n logger.start('randomSleep', `min=${min}, max=${max}`);\n const ms = typeof max === 'number'\n ? rangeDelay(min, max)\n : delay(min);\n await ms;\n logger.success('randomSleep');\n },\n\n /**\n * \u6A21\u62DF\u4EBA\u7C7B\"\u6CE8\u89C6\"\u6216\"\u9605\u8BFB\"\u884C\u4E3A\uFF1A\u9F20\u6807\u5728\u9875\u9762\u4E0A\u968F\u673A\u5FAE\u52A8\n * @param {import('playwright').Page} page\n * @param {number} durationMs - \u6301\u7EED\u65F6\u95F4\n */\n async simulateGaze(page, durationMs = 2000) {\n const cursor = $GetCursor(page);\n logger.start('simulateGaze', `duration=${durationMs}ms`);\n const startTime = Date.now();\n while (Date.now() - startTime < durationMs) {\n const x = Math.random() * 800;\n const y = Math.random() * 600;\n await cursor.actions.move({ x, y });\n await rangeDelay(200, 800);\n }\n logger.success('simulateGaze');\n },\n\n /**\n * \u4EBA\u7C7B\u5316\u8F93\u5165 - \u5E26\u8282\u594F\u53D8\u5316\uFF08\u5FEB-\u6162-\u505C\u987F-\u5076\u5C14\u52A0\u901F\uFF09\n * @param {import('playwright').Page} page\n * @param {string} selector - \u8F93\u5165\u6846\u9009\u62E9\u5668\n * @param {string} text - \u8981\u8F93\u5165\u7684\u6587\u672C\n * @param {Object} [options] \n * @param {number} [options.minDelay=50] - \u6700\u5C0F\u6309\u952E\u5EF6\u8FDF (ms)\n * @param {number} [options.maxDelay=200] - \u6700\u5927\u6309\u952E\u5EF6\u8FDF (ms)\n * @param {number} [options.pauseProbability=0.1] - \u505C\u987F\u6982\u7387 (0-1)\n * @param {number} [options.pauseMin=300] - \u505C\u987F\u6700\u5C0F\u65F6\u957F (ms)\n * @param {number} [options.pauseMax=800] - \u505C\u987F\u6700\u5927\u65F6\u957F (ms)\n * \n */\n async humanType(page, selector, text, options = {}) {\n logger.start('humanType', `selector=${selector}, textLen=${text.length}`);\n const {\n minDelay = 100,\n maxDelay = 300,\n pauseProbability = 0.1,\n pauseMin = 300,\n pauseMax = 800\n } = options;\n\n try {\n const locator = page.locator(selector);\n await locator.click();\n await rangeDelay(100, 300);\n\n for (let i = 0; i < text.length; i++) {\n const char = text[i];\n let charDelay;\n if (char === ' ') {\n charDelay = minDelay + Math.random() * 50;\n } else if (/[,.!?;:\uFF0C\u3002\uFF01\uFF1F\uFF1B\uFF1A]/.test(char)) {\n charDelay = maxDelay + Math.random() * 100;\n } else {\n charDelay = minDelay + Math.random() * (maxDelay - minDelay);\n }\n\n await page.keyboard.type(char);\n await delay(charDelay);\n\n if (Math.random() < pauseProbability && i < text.length - 1) {\n const pauseTime = pauseMin + Math.random() * (pauseMax - pauseMin);\n logger.debug(`\u505C\u987F ${Math.round(pauseTime)}ms...`);\n await delay(pauseTime);\n }\n }\n logger.success('humanType');\n } catch (error) {\n logger.fail('humanType', error);\n throw error;\n }\n },\n\n /**\n * \u4EBA\u7C7B\u5316\u6E05\u7A7A\u8F93\u5165\u6846 - \u6A21\u62DF\u4EBA\u7C7B\u5220\u9664\u6587\u672C\u7684\u884C\u4E3A\n * @param {import('playwright').Page} page\n * @param {string} selector - \u8F93\u5165\u6846\u9009\u62E9\u5668\n */\n async humanClear(page, selector) {\n logger.start('humanClear', `selector=${selector}`);\n try {\n const locator = page.locator(selector);\n await locator.click();\n await rangeDelay(100, 300);\n\n const currentValue = await locator.inputValue();\n if (!currentValue || currentValue.length === 0) {\n logger.success('humanClear', 'already empty');\n return;\n }\n\n // \u5168\u9009 + \u5220\u9664\n await page.keyboard.press('Meta+A');\n await rangeDelay(50, 150);\n await page.keyboard.press('Backspace');\n\n logger.success('humanClear');\n } catch (error) {\n logger.fail('humanClear', error);\n throw error;\n }\n },\n\n /**\n * \u9875\u9762\u9884\u70ED\u6D4F\u89C8 - \u6A21\u62DF\u4EBA\u7C7B\u8FDB\u5165\u9875\u9762\u540E\u7684\u63A2\u7D22\u884C\u4E3A\n * @param {import('playwright').Page} page\n * @param {number|{min: number, max: number}} [duration=3000] - \u9884\u70ED\u65F6\u957F\n */\n async warmUpBrowsing(page, duration = 3000) {\n const cursor = $GetCursor(page);\n let durationMs;\n if (typeof duration === 'object' && duration.min !== undefined && duration.max !== undefined) {\n durationMs = duration.min + Math.random() * (duration.max - duration.min);\n } else {\n durationMs = duration;\n }\n durationMs = Math.round(durationMs);\n\n logger.start('warmUpBrowsing', `duration=${durationMs}ms`);\n const startTime = Date.now();\n const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };\n\n try {\n while (Date.now() - startTime < durationMs) {\n const action = Math.random();\n\n if (action < 0.4) {\n const x = 100 + Math.random() * (viewportSize.width - 200);\n const y = 100 + Math.random() * (viewportSize.height - 200);\n await cursor.actions.move({ x, y });\n await rangeDelay(200, 500);\n } else if (action < 0.7) {\n const scrollY = (Math.random() - 0.5) * 200;\n await page.mouse.wheel(0, scrollY);\n await rangeDelay(300, 700);\n } else {\n await rangeDelay(500, 1000);\n }\n }\n logger.success('warmUpBrowsing');\n } catch (error) {\n logger.fail('warmUpBrowsing', error);\n throw error;\n }\n },\n\n /**\n * \u81EA\u7136\u6EDA\u52A8 - \u5E26\u60EF\u6027\u548C\u51CF\u901F\u6548\u679C\n * @param {import('playwright').Page} page\n * @param {'up' | 'down'} [direction='down'] - \u6EDA\u52A8\u65B9\u5411\n * @param {number} [distance=300] - \u603B\u6EDA\u52A8\u8DDD\u79BB (px)\n * @param {number} [steps=5] - \u5206\u51E0\u6B65\u5B8C\u6210\n */\n async naturalScroll(page, direction = 'down', distance = 300, steps = 5) {\n logger.start('naturalScroll', `dir=${direction}, dist=${distance}, steps=${steps}`);\n const sign = direction === 'down' ? 1 : -1;\n const stepDistance = distance / steps;\n\n try {\n for (let i = 0; i < steps; i++) {\n const factor = 1 - (i / steps) * 0.5;\n const scrollAmount = stepDistance * factor * sign;\n await page.mouse.wheel(0, scrollAmount);\n const delayTime = 50 + i * 30;\n await delay(delayTime);\n }\n logger.success('naturalScroll');\n } catch (error) {\n logger.fail('naturalScroll', error);\n throw error;\n }\n }\n}\n", "// \u96C6\u4E2D\u7BA1\u7406\u542F\u52A8\u914D\u7F6E\uFF0C\u6682\u65F6\u4E3B\u8981\u7531 Stealth \u6A21\u5757\u63D0\u4F9B Args\uFF0C\u8FD9\u91CC\u4F5C\u4E3A\u6269\u5C55\u70B9\nimport { Stealth } from './stealth';\nimport { createLogger } from './internal/logger';\n\nconst logger = createLogger('Launch');\n\nexport const Launch = {\n getLaunchOptions(customArgs = []) {\n return {\n args: [\n ...Stealth.getStealthLaunchArgs(),\n ...customArgs\n ],\n ignoreDefaultArgs: ['--enable-automation'],\n };\n },\n\n /**\n * \u83B7\u53D6\u589E\u5F3A\u7248\u542F\u52A8\u9009\u9879\uFF08\u7528\u4E8E\u9AD8\u98CE\u9669\u53CD\u722C\u573A\u666F\uFF09\n */\n getAdvancedLaunchOptions(customArgs = []) {\n return {\n args: [\n ...Stealth.getAdvancedStealthArgs(),\n ...customArgs\n ],\n ignoreDefaultArgs: ['--enable-automation'],\n };\n },\n\n /**\n * \u63A8\u8350\u7684 Fingerprint Generator \u9009\u9879\n * \u786E\u4FDD\u751F\u6210\u7684\u662F\u684C\u9762\u7AEF\u3001\u8F83\u65B0\u7684 Chrome\uFF0C\u4EE5\u5339\u914D\u6211\u4EEC\u7684\u811A\u672C\u903B\u8F91\n */\n getFingerprintGeneratorOptions() {\n return {\n browsers: [{ name: 'chrome', minVersion: 110 }],\n devices: ['desktop'],\n operatingSystems: ['windows', 'linux'], // \u5305\u542B Linux \u517C\u5BB9\u5BB9\u5668\n };\n },\n\n /**\n * \u521B\u5EFA\u5DF2\u6CE8\u518C Stealth \u63D2\u4EF6\u7684 Chromium \u5B9E\u4F8B\n * \n * \u5C01\u88C5\u4E86 `chromium.use(stealthPlugin())` \u7684\u5E38\u7528\u6A21\u5F0F\n * \n * @example\n * ```javascript\n * import { chromium } from 'playwright-extra';\n * import stealthPlugin from 'puppeteer-extra-plugin-stealth';\n * \n * const stealthChromium = Launch.createStealthChromium(chromium, stealthPlugin);\n * // \u73B0\u5728 stealthChromium \u5DF2\u6CE8\u518C stealth \u63D2\u4EF6\uFF0C\u53EF\u7528\u4E8E launchContext.launcher\n * ```\n * \n * @param {import('playwright-extra').ChromiumExtra} chromium - playwright-extra \u7684 chromium\n * @param {Function} stealthPlugin - puppeteer-extra-plugin-stealth \u7684\u9ED8\u8BA4\u5BFC\u51FA\n * @returns {import('playwright-extra').ChromiumExtra} \u5DF2\u6CE8\u518C stealth \u7684 chromium\n */\n createStealthChromium(chromium, stealthPlugin) {\n chromium.use(stealthPlugin());\n logger.success('createStealthChromium', 'Stealth plugin registered');\n return chromium;\n }\n}\n\n", "import express from 'express';\nimport { Actor } from 'apify';\nimport { PresetOfLiveViewKey } from './constants';\nimport { createLogger } from './internal/logger';\n\nconst logger = createLogger('LiveView');\n\n/**\n * \u542F\u52A8\u4E00\u4E2A Web \u670D\u52A1\u5668\u4EE5\u5728 Live View \u9009\u9879\u5361\u4E2D\u663E\u793A\u6700\u65B0\u7684\u5C4F\u5E55\u622A\u56FE\u3002\n */\nasync function startLiveViewServer(liveViewKey) {\n const app = express();\n\n app.get('/', async (req, res) => {\n try {\n // \u4ECE\u9ED8\u8BA4\u7684 Key-Value Store \u4E2D\u8BFB\u53D6\u6700\u65B0\u7684\u5C4F\u5E55\u622A\u56FE\n const screenshotBuffer = await Actor.getValue(liveViewKey);\n\n if (!screenshotBuffer) {\n // \u5982\u679C\u8FD8\u6CA1\u6709\u622A\u56FE\uFF0C\u53D1\u9001\u4E00\u4E2A\u81EA\u52A8\u5237\u65B0\u7684\u5360\u4F4D\u9875\u9762\n res.send('<html><head><meta http-equiv=\"refresh\" content=\"2\"></head><body>\u7B49\u5F85\u7B2C\u4E00\u4E2A\u5C4F\u5E55\u622A\u56FE...</body></html>');\n return;\n }\n\n // \u5C06 Buffer \u8F6C\u6362\u4E3A Base64 \u5B57\u7B26\u4E32\n const screenshotBase64 = screenshotBuffer.toString('base64');\n\n // \u53D1\u9001\u4E00\u4E2A HTML \u9875\u9762\uFF0C\u8BE5\u9875\u9762\u6BCF 1 \u79D2\u81EA\u52A8\u5237\u65B0\u4E00\u6B21\uFF0C\u5E76\u663E\u793A\u622A\u56FE\n res.send(`\n <html>\n <head>\n <title>Live View (\u622A\u56FE)</title>\n <meta http-equiv=\"refresh\" content=\"1\">\n </head>\n <body style=\"margin:0; padding:0;\">\n <img src=\"data:image/png;base64,${screenshotBase64}\" \n alt=\"Live View Screenshot\" \n style=\"width: 100%; height: auto;\" />\n </body>\n </html>\n `);\n } catch (error) {\n logger.fail('Live View Server', error);\n res.status(500).send(`\u65E0\u6CD5\u52A0\u8F7D\u5C4F\u5E55\u622A\u56FE: ${error.message}`);\n }\n });\n\n // \u76D1\u542C Apify \u5BB9\u5668\u7AEF\u53E3 \n const port = process.env.APIFY_CONTAINER_PORT || 4321;\n app.listen(port, () => { logger.success('startLiveViewServer', `\u76D1\u542C\u7AEF\u53E3 ${port}`); });\n}\n\n/**\n * \u62CD\u6444\u5F53\u524D\u9875\u9762\u7684\u5C4F\u5E55\u622A\u56FE\u5E76\u5C06\u5176\u4FDD\u5B58\u5230 Key-Value Store\u3002\n * @param {import('playwright').Page} page\n * @param {string} [logMessage] - \u53EF\u9009\u7684\u65E5\u5FD7\u6D88\u606F\u3002\n */\nasync function takeLiveScreenshot(liveViewKey, page, logMessage) {\n try {\n const buffer = await page.screenshot({ type: 'png' });\n await Actor.setValue(liveViewKey, buffer, { contentType: 'image/png' });\n if (logMessage) {\n logger.info(`(\u622A\u56FE): ${logMessage}`);\n }\n } catch (e) {\n logger.warn(`\u65E0\u6CD5\u6355\u83B7 Live View \u5C4F\u5E55\u622A\u56FE: ${e.message}`);\n }\n}\n\nconst useLiveView = (liveViewKey = PresetOfLiveViewKey) => {\n return {\n takeLiveScreenshot: async (page, logMessage) => {\n return await takeLiveScreenshot(liveViewKey, page, logMessage)\n },\n startLiveViewServer: async () => {\n return await startLiveViewServer(liveViewKey);\n }\n }\n}\n\nexport const LiveView = {\n useLiveView,\n};\n", "import { createLogger } from './internal/logger';\n\nconst logger = createLogger('Captcha');\n\n/**\n * \u521B\u5EFA\u9A8C\u8BC1\u7801\u76D1\u63A7\u5668 - \u652F\u6301 DOM \u9009\u62E9\u5668 \u548C URL \u6A21\u5F0F \u4E24\u79CD\u68C0\u6D4B\u65B9\u5F0F\n * \n * \u6CE8\u610F\uFF1A\u76D1\u63A7\u5668\u968F\u9875\u9762\u751F\u547D\u5468\u671F\u81EA\u52A8\u6E05\u7406\uFF0C\u65E0\u9700\u624B\u52A8 cleanup\n * \n * @param {import('playwright').Page} page\n * @param {Object} options\n * @param {string} [options.domSelector] - DOM \u5143\u7D20\u9009\u62E9\u5668 (\u5982 '#captcha_container')\n * @param {string} [options.urlPattern] - URL \u5339\u914D\u6A21\u5F0F (\u5982 '/captcha')\n * @param {Function} options.onDetected - \u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\u65F6\u7684\u56DE\u8C03 (async function)\n */\nexport function useCaptchaMonitor(page, options) {\n const { domSelector, urlPattern, onDetected } = options;\n\n if (!domSelector && !urlPattern) {\n throw new Error('[CaptchaMonitor] \u5FC5\u987B\u63D0\u4F9B domSelector \u6216 urlPattern \u81F3\u5C11\u4E00\u4E2A');\n }\n\n if (!onDetected || typeof onDetected !== 'function') {\n throw new Error('[CaptchaMonitor] onDetected \u5FC5\u987B\u662F\u4E00\u4E2A\u51FD\u6570');\n }\n\n let isHandled = false;\n let frameHandler = null;\n let exposedFunctionName = null;\n\n const triggerDetected = async () => {\n if (isHandled) return;\n isHandled = true;\n logger.fail('Captcha Detected', '\uD83D\uDED1 \u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\uFF01');\n await onDetected();\n };\n\n // ============================================================\n // \u6A21\u5F0F1: DOM \u76D1\u63A7 (\u4F7F\u7528 MutationObserver)\n // ============================================================\n if (domSelector) {\n // \u751F\u6210\u552F\u4E00\u7684\u51FD\u6570\u540D\u907F\u514D\u51B2\u7A81\n exposedFunctionName = `__c_d_${Date.now()}`;\n\n // \u66B4\u9732\u56DE\u8C03\u51FD\u6570\u7ED9\u9875\u9762\n page.exposeFunction(exposedFunctionName, triggerDetected).catch(() => {\n // \u5FFD\u7565\u91CD\u590D\u66B4\u9732\u9519\u8BEF\n });\n\n // \u6CE8\u5165 MutationObserver \u76D1\u542C\u811A\u672C\n page.addInitScript(({ selector, callbackName }) => {\n (() => {\n let observer = null;\n\n const checkAndReport = () => {\n const element = document.querySelector(selector);\n if (element) {\n if (observer) {\n observer.disconnect();\n observer = null;\n }\n if (window[callbackName]) {\n window[callbackName]();\n }\n return true;\n }\n return false;\n };\n\n // 1. \u7ACB\u5373\u68C0\u67E5\u4E00\u6B21\n if (checkAndReport()) return;\n\n // 2. \u542F\u52A8 MutationObserver\n observer = new MutationObserver((mutations) => {\n let shouldCheck = false;\n for (const mutation of mutations) {\n if (mutation.addedNodes.length > 0) {\n shouldCheck = true;\n break;\n }\n }\n if (shouldCheck && observer) {\n checkAndReport();\n }\n });\n\n // 3. \u6302\u8F7D\u76D1\u542C\uFF08\u786E\u4FDD DOM \u51C6\u5907\u5C31\u7EEA\uFF09\n const mountObserver = () => {\n const target = document.documentElement;\n if (target && observer) {\n observer.observe(target, { childList: true, subtree: true });\n }\n };\n\n if (document.readyState === 'loading') {\n window.addEventListener('DOMContentLoaded', mountObserver);\n } else {\n mountObserver();\n }\n })();\n }, { selector: domSelector, callbackName: exposedFunctionName });\n\n logger.success('useCaptchaMonitor', `DOM \u76D1\u63A7\u5DF2\u542F\u7528: ${domSelector}`);\n }\n\n // ============================================================\n // \u6A21\u5F0F2: URL \u76D1\u63A7 (\u76D1\u542C framenavigated)\n // ============================================================\n if (urlPattern) {\n frameHandler = async (frame) => {\n if (frame === page.mainFrame()) {\n const currentUrl = page.url();\n if (currentUrl.includes(urlPattern)) {\n await triggerDetected();\n }\n }\n };\n\n page.on('framenavigated', frameHandler);\n logger.success('useCaptchaMonitor', `URL \u76D1\u63A7\u5DF2\u542F\u7528: ${urlPattern}`);\n }\n\n // \u6CE8\u610F\uFF1A\u4E0D\u63D0\u4F9B cleanup \u51FD\u6570\n // - DOM \u6A21\u5F0F\uFF1AaddInitScript \u6CE8\u5165\u7684\u4EE3\u7801\u65E0\u6CD5\u4ECE Node \u7AEF\u6E05\u7406\n // - URL \u6A21\u5F0F\uFF1Aframenavigated \u76D1\u542C\u901A\u5E38\u8DDF\u968F\u9875\u9762\u751F\u547D\u5468\u671F\uFF0C\u65E0\u9700\u624B\u52A8\u6E05\u7406\n // \u5982\u679C\u9700\u8981\u63D0\u524D\u7EC8\u6B62\u76D1\u63A7\uFF0C\u8BBE\u8BA1\u4E0A\u5E94\u8BE5\u8BA9 onDetected \u5904\u7406\u540E\u7EED\u903B\u8F91\uFF08\u5982 Actor.fail\uFF09\n}\n\n// \u6309\u7167 toolkit \u7EDF\u4E00\u7684\u5BFC\u51FA\u6A21\u5F0F\nexport const Captcha = {\n useCaptchaMonitor\n};\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { ApifyKit } from './src/apify-kit';\nimport { Utils } from './src/utils';\nimport { Stealth } from './src/stealth';\nimport { Humanize } from './src/humanize';\nimport { Launch } from './src/launch';\nimport { LiveView } from './src/live-view';\nimport { Captcha } from './src/captcha-monitor';\nimport * as Constants from './src/constants';\n\n// Unified Entry Point\nexport const usePlaywrightToolKit = () => {\n return {\n ApifyKit,\n Stealth,\n Humanize,\n Launch,\n LiveView,\n Constants,\n Utils,\n Captcha\n };\n};\n", "import { log as originalLog } from 'crawlee'; // \u4FDD\u7559\u539F\u59CB log \u7528\u4E8E\u7279\u6B8A\u7528\u9014\u6216\u76F4\u63A5\u8C03\u7528\nimport { Status, FAILED_KEY_SEPARATOR, StatusCode } from './constants';\nimport { createLogger } from './internal/logger';\n\nconst logger = createLogger('ApifyKit');\n\n/**\n * \u521B\u5EFA ApifyKit \u5B9E\u4F8B\n * \u5982\u679C apify \u53EF\u7528\uFF0C\u8FD4\u56DE\u5B8C\u6574\u529F\u80FD\u7684 ApifyKit\n * \u5982\u679C apify \u4E0D\u53EF\u7528\uFF0C\u8FD4\u56DE\u964D\u7EA7\u7248\u672C\uFF08\u975E apify \u76F8\u5173\u529F\u80FD\u4ECD\u53EF\u7528\uFF09\n */\nasync function createApifyKit() {\n let apify = null;\n\n // \u5C1D\u8BD5\u52A0\u8F7D apify\n try {\n apify = await import('apify');\n } catch (error) {\n // apify \u4E0D\u53EF\u7528\uFF0C\u5C06\u4F7F\u7528\u964D\u7EA7\u7248\u672C\n throw new Error('\u26A0\uFE0F apify \u5E93\u672A\u5B89\u88C5\uFF0CApifyKit \u7684 Actor \u76F8\u5173\u529F\u80FD\u4E0D\u53EF\u7528')\n }\n\n const { Actor } = apify;\n\n return {\n /**\n * \u5305\u88C5 Step Name\n */\n wrapStepNameWithFailedKey(key, stepName) {\n return `${key}${FAILED_KEY_SEPARATOR}${stepName}`;\n },\n\n /**\n * \u89E3\u5305 Step Name\n */\n unwrapStepName(stepName) {\n const splitIndex = stepName.indexOf(FAILED_KEY_SEPARATOR);\n if (splitIndex === -1) {\n return ['-', stepName];\n }\n const key = stepName.substring(0, splitIndex);\n const value = stepName.substring(splitIndex + FAILED_KEY_SEPARATOR.length);\n return [key, value];\n },\n\n /**\n * \u6838\u5FC3\u5C01\u88C5\uFF1A\u6267\u884C\u6B65\u9AA4\uFF0C\u5E26\u81EA\u52A8\u65E5\u5FD7\u786E\u8BA4\u548C\u5931\u8D25\u622A\u56FE\u5904\u7406\n */\n async runStep(pendingStepName, page, actionFn, options = {}) {\n const { failActor = true } = options; // \u9ED8\u8BA4\u8C03\u7528 Actor.fail\n const [failedKey, stepName] = this.unwrapStepName(pendingStepName);\n\n // log.info(`\uD83D\uDD04 [\u6B63\u5728\u6267\u884C] ${stepName}...`);\n logger.start(`[Step] ${stepName}`);\n\n try {\n const result = await actionFn();\n // log.info(`\u2705 [\u6267\u884C\u6210\u529F] ${stepName}`);\n logger.success(`[Step] ${stepName}`);\n return result;\n } catch (error) {\n // log.error(`\u274C [\u6267\u884C\u5931\u8D25] ${stepName}: ${error.message}`);\n logger.fail(`[Step] ${stepName}`, error);\n\n let screenshotBase64 = '\u622A\u56FE\u5931\u8D25';\n try {\n if (page) {\n const buffer = await page.screenshot({ fullPage: true, type: 'jpeg', quality: 60 });\n screenshotBase64 = `data:image/jpeg;base64,${buffer.toString('base64')}`;\n }\n } catch (snapErr) {\n logger.warn(`\u622A\u56FE\u751F\u6210\u5931\u8D25: ${snapErr.message}`);\n }\n\n // \u4F7F\u7528 pushFailed \u65B9\u6CD5\u63A8\u9001\u5931\u8D25\u6570\u636E\uFF08\u79C1\u6709\u4F7F\u7528\uFF09\n await this.pushFailed(error, {\n failedStep: stepName,\n failedKey: failedKey,\n errorMessage: error.message,\n errorStack: error.stack,\n screenshotBase64: screenshotBase64\n });\n\n // \u6839\u636E failActor \u51B3\u5B9A\u662F\u5426\u8C03\u7528 Actor.fail\n if (failActor) {\n await Actor.fail(`Run Step ${stepName} \u5931\u8D25: ${error.message}`);\n } else {\n // \u4E0D\u8C03\u7528 Actor.fail\uFF0C\u76F4\u63A5\u629B\u51FA\u9519\u8BEF\n throw error;\n }\n }\n },\n\n /**\n * \u5BBD\u677E\u7248runStep\uFF1A\u5931\u8D25\u65F6\u4E0D\u8C03\u7528Actor.fail\uFF0C\u53EA\u629B\u51FA\u5F02\u5E38\n */\n async runStepLoose(stepName, page, fn) {\n return await this.runStep(stepName, page, fn, { failActor: false });\n },\n\n /**\n * \u63A8\u9001\u6210\u529F\u6570\u636E\u7684\u901A\u7528\u65B9\u6CD5\n * @param {Object} data - \u8981\u63A8\u9001\u7684\u6570\u636E\u5BF9\u8C61\n */\n async pushSuccess(data) {\n await Actor.pushData({\n code: StatusCode.Success,\n status: Status.Success,\n timestamp: new Date().toISOString(),\n ...data\n });\n logger.success('pushSuccess', 'Data pushed');\n },\n\n /**\n * \u63A8\u9001\u5931\u8D25\u6570\u636E\u7684\u901A\u7528\u65B9\u6CD5\uFF08\u79C1\u6709\u65B9\u6CD5\uFF0C\u4EC5\u4F9BrunStep\u5185\u90E8\u4F7F\u7528\uFF09\n * @param {Error|Object} error - \u9519\u8BEF\u5BF9\u8C61\uFF08\u53EF\u5305\u542B\u5176\u4ED6\u7684\u9519\u8BEF/\u6216\u90E8\u5206\u5904\u7406\u6210\u529F\u7684\u989D\u5916\u4FE1\u606F\uFF09\n * @param {Object} [meta] - \u989D\u5916\u7684\u6570\u636E\uFF08\u5982failedStep, screenshotBase64\u7B49\uFF0C\u4EC5runStep\u4F7F\u7528\uFF09\n * @private\n */\n async pushFailed(error, meta = {}) {\n await Actor.pushData({\n code: StatusCode.Failed,\n status: Status.Failed,\n // \u8FD9\u91CC\u53EF\u80FD\u5E26\u5176\u4ED6\u9519\u8BEF\u4FE1\u606F\n error,\n timestamp: new Date().toISOString(),\n ...meta\n });\n logger.success('pushFailed', 'Error data pushed');\n }\n };\n}\n\n// \u61D2\u52A0\u8F7D\u5355\u4F8B\nlet instance = null;\n\n/**\n * \u83B7\u53D6 ApifyKit \u5B9E\u4F8B\uFF08\u61D2\u52A0\u8F7D\uFF09\n * @returns {Promise<Object>} ApifyKit \u5B9E\u4F8B\n */\nasync function useApifyKit() {\n if (!instance) {\n instance = await createApifyKit();\n }\n return instance;\n}\n\n// \u4E5F\u5BFC\u51FA\u521D\u59CB\u5316\u51FD\u6570\uFF0C\u4F9B\u9700\u8981\u7684\u7528\u6237\u4F7F\u7528\nexport const ApifyKit = {\n useApifyKit\n};\n", "export const ErrorKeygen = {\n NotLogin: 30000001,\n Chaptcha: 30000002,\n}\n\nexport const Status = {\n Success: 'SUCCESS',\n Failed: 'FAILED'\n}\n\nexport const StatusCode = {\n Success: 0,\n Failed: -1\n}\n\nexport const FAILED_KEY_SEPARATOR = '::<@>::';\n\nexport const PresetOfLiveViewKey = 'LIVE_VIEW_SCREENSHOT';\n", "import { log } from 'crawlee';\n\n/**\n * \u521B\u5EFA\u6A21\u5757\u7EA7\u65E5\u5FD7\u5668\n * @param {string} moduleName - \u6A21\u5757\u540D\u79F0\uFF0C\u4F8B\u5982 'Humanize', 'Stealth'\n */\nexport function createLogger(moduleName) {\n const prefix = `[${moduleName}]`;\n\n return {\n /**\n * \u65B9\u6CD5\u5F00\u59CB\u65E5\u5FD7\n * @param {string} methodName - \u65B9\u6CD5\u540D\u79F0\n * @param {string} [params] - \u53C2\u6570\u6458\u8981 (\u53EF\u9009)\n */\n start(methodName, params = '') {\n const paramStr = params ? ` (${params})` : '';\n log.info(`${prefix} \uD83D\uDD37 ${methodName} \u5F00\u59CB${paramStr}`);\n },\n\n /**\n * \u65B9\u6CD5\u6210\u529F\u65E5\u5FD7\n * @param {string} methodName - \u65B9\u6CD5\u540D\u79F0\n * @param {string} [result] - \u7ED3\u679C\u6458\u8981 (\u53EF\u9009)\n */\n success(methodName, result = '') {\n const resultStr = result ? ` (${result})` : '';\n log.info(`${prefix} \u2705 ${methodName} \u5B8C\u6210${resultStr}`);\n },\n\n /**\n * \u65B9\u6CD5\u5931\u8D25\u65E5\u5FD7\n * @param {string} methodName - \u65B9\u6CD5\u540D\u79F0\n * @param {Error|string} error - \u9519\u8BEF\u5BF9\u8C61\u6216\u4FE1\u606F\n */\n fail(methodName, error) {\n const message = error instanceof Error ? error.message : error;\n log.error(`${prefix} \u274C ${methodName} \u5931\u8D25: ${message}`);\n },\n\n /**\n * \u8C03\u8BD5\u65E5\u5FD7\n * @param {string} message - \u8BE6\u60C5\n */\n debug(message) {\n log.debug(`${prefix} \uD83D\uDD39 ${message}`);\n },\n\n /**\n * \u8B66\u544A\u65E5\u5FD7\n * @param {string} message - \u8B66\u544A\u4FE1\u606F\n */\n warn(message) {\n log.warning(`${prefix} \u26A0\uFE0F ${message}`);\n },\n\n /**\n * \u666E\u901A\u4FE1\u606F\u65E5\u5FD7\n * @param {string} message - \u4FE1\u606F\n */\n info(message) {\n log.info(`${prefix} \uD83D\uDCD6 ${message}`);\n }\n };\n}\n", "import { createLogger } from './internal/logger';\n\nconst logger = createLogger('Utils');\n\nexport const Utils = {\n /**\n * \u89E3\u6790 SSE \u6D41\u6587\u672C\n */\n parseSseStream(sseStreamText) {\n const events = [];\n const lines = sseStreamText.split('\\n');\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n try {\n const jsonContent = line.substring(6).trim();\n if (jsonContent && jsonContent !== '[DONE]') {\n events.push(JSON.parse(jsonContent));\n }\n } catch (e) {\n // Ignore lines that are not valid JSON\n }\n }\n }\n logger.success('parseSseStream', `parsed events: ${events.length}`);\n return events;\n },\n\n /**\n * \u89E3\u6790 Cookie \u5B57\u7B26\u4E32\u4E3A Playwright \u683C\u5F0F\u7684 Cookie \u6570\u7EC4\n * @param {string} cookieString - Cookie \u5B57\u7B26\u4E32\n * @param {string} [domain] - Cookie \u57DF\u540D (\u53EF\u9009)\n * @returns {Array} Cookie \u6570\u7EC4\n */\n parseCookies(cookieString, domain) {\n const cookies = [];\n const pairs = cookieString.split(';').map(c => c.trim());\n\n for (const pair of pairs) {\n const [name, ...valueParts] = pair.split('=');\n if (name && valueParts.length > 0) {\n const cookie = {\n name: name.trim(),\n value: valueParts.join('=').trim(),\n path: '/',\n };\n if (domain) {\n cookie.domain = domain;\n }\n cookies.push(cookie);\n }\n }\n logger.success('parseCookies', `parsed ${cookies.length} cookies`);\n return cookies;\n }\n}\n", "import { createLogger } from './internal/logger';\n\nconst logger = createLogger('Stealth');\n\nexport const Stealth = {\n /**\n * \u5173\u952E\u4FEE\u590D\uFF1A\u5C06 Page \u89C6\u53E3\u8C03\u6574\u4E3A\u4E0E\u6D4F\u89C8\u5668\u6307\u7EB9 (window.screen) \u4E00\u81F4\u3002\n * \u9632\u6B62 \"Viewport Mismatch\" \u7C7B\u578B\u7684\u53CD\u722C\u68C0\u6D4B\u3002\n * @param {import('playwright').Page} page \n */\n async syncViewportWithScreen(page) {\n try {\n // \u83B7\u53D6\u6307\u7EB9\u4E2D\u7684\u5C4F\u5E55\u5C3A\u5BF8\n const screen = await page.evaluate(() => ({\n width: window.screen.width,\n height: window.screen.height,\n availWidth: window.screen.availWidth,\n availHeight: window.screen.availHeight,\n }));\n\n // \u8C03\u6574\u89C6\u53E3\n await page.setViewportSize({\n width: screen.width,\n height: screen.height\n });\n\n logger.success('syncViewportWithScreen', `size=${screen.width}x${screen.height}`);\n } catch (e) {\n logger.warn(`syncViewportWithScreen Failed: ${e.message}. Fallback to 1920x1080.`);\n await page.setViewportSize({ width: 1920, height: 1080 });\n }\n },\n\n /**\n * \u786E\u4FDD navigator.webdriver \u9690\u85CF (\u901A\u5E38 Playwright Stealth \u63D2\u4EF6\u5DF2\u5904\u7406\uFF0C\u4F46\u53CC\u91CD\u4FDD\u9669)\n */\n async hideWebdriver(page) {\n await page.addInitScript(() => {\n Object.defineProperty(navigator, 'webdriver', {\n get: () => false,\n });\n });\n logger.success('hideWebdriver');\n },\n\n /**\n * \u901A\u7528\u7684 Playwright \u8D44\u6E90\u62E6\u622A\u5668\uFF0C\u7528\u4E8E\u5C4F\u853D\u4E0D\u5FC5\u8981\u7684\u8D44\u6E90\u4EE5\u52A0\u901F\u52A0\u8F7D\n * @param {import('playwright').Page} page\n * @param {string[]} [resourceTypes] - \u8981\u5C4F\u853D\u7684\u8D44\u6E90\u7C7B\u578B\uFF0C\u9ED8\u8BA4\u4E3A ['font', 'image', 'media']\n */\n async setupBlockingResources(page, resourceTypes = ['font', 'image', 'media']) {\n await page.route('**/*', (route) => {\n const request = route.request();\n const type = request.resourceType();\n if (resourceTypes.includes(type)) {\n return route.abort();\n }\n return route.continue();\n });\n logger.success('setupBlockingResources', `types=[${resourceTypes.join(',')}]`);\n },\n\n /**\n * \u83B7\u53D6\u63A8\u8350\u7684 Stealth \u542F\u52A8\u53C2\u6570\n */\n getStealthLaunchArgs() {\n return [\n '--disable-blink-features=AutomationControlled',\n '--no-sandbox',\n '--disable-setuid-sandbox',\n '--disable-infobars',\n '--window-position=0,0',\n '--ignore-certificate-errors',\n '--disable-web-security',\n // \u6CE8\u610F\uFF1A\u4E0D\u5EFA\u8BAE\u8FD9\u91CC\u5F3A\u5236\u6307\u5B9A window-size\uFF0C\u8BA9 syncViewportWithScreen \u53BB\u52A8\u6001\u8C03\u6574\n // '--window-size=1920,1080' \n ];\n },\n\n /**\n * \u83B7\u53D6\u589E\u5F3A\u7248 Stealth \u542F\u52A8\u53C2\u6570 (\u63A8\u8350\u7528\u4E8E\u9AD8\u98CE\u9669\u53CD\u722C\u573A\u666F)\n * \u5305\u542B\u66F4\u591A\u9488\u5BF9\u81EA\u52A8\u5316\u68C0\u6D4B\u7684\u9632\u62A4\n */\n getAdvancedStealthArgs() {\n return [\n ...this.getStealthLaunchArgs(),\n // \u7981\u7528\u5404\u79CD\u53EF\u80FD\u66B4\u9732\u81EA\u52A8\u5316\u7684\u7279\u5F81\n '--disable-dev-shm-usage',\n '--disable-accelerated-2d-canvas',\n '--disable-gpu-sandbox',\n '--disable-background-networking',\n '--disable-default-apps',\n '--disable-extensions',\n '--disable-sync',\n '--disable-translate',\n '--metrics-recording-only',\n '--mute-audio',\n '--no-first-run',\n // \u6A21\u62DF\u771F\u5B9E\u7528\u6237\u914D\u7F6E\n '--lang=zh-CN,zh',\n ];\n },\n\n /**\n * \u8BBE\u7F6E\u4E2D\u56FD\u65F6\u533A (Asia/Shanghai, UTC+8)\n * \n * \u9632\u6B62\u65F6\u533A\u4E0D\u4E00\u81F4\u7684\u68C0\u6D4B\u3002\u5BF9\u4E8E\u4E2D\u56FD\u5883\u5185\u722C\u53D6\u5F3A\u70C8\u63A8\u8350\u4F7F\u7528\u3002\n * \u5E94\u5728 preNavigationHooks \u6216 BrowserContext \u521B\u5EFA\u540E\u8C03\u7528\u3002\n * \n * @param {import('playwright').BrowserContext} context\n */\n async setChinaTimezone(context) {\n // Playwright \u901A\u8FC7 context \u8BBE\u7F6E\u65F6\u533A\n // \u6CE8\u610F\uFF1A\u8FD9\u9700\u8981\u5728 context \u521B\u5EFA\u65F6\u8BBE\u7F6E\uFF0C\u6216\u8005\u4F7F\u7528 CDP\n // \u8FD9\u91CC\u4F7F\u7528 addInitScript \u6CE8\u5165 Intl \u8986\u76D6\n await context.addInitScript(() => {\n // \u8986\u76D6 Intl.DateTimeFormat \u9ED8\u8BA4\u65F6\u533A\n const originalDateTimeFormat = Intl.DateTimeFormat;\n Intl.DateTimeFormat = function (locales, options) {\n options = options || {};\n options.timeZone = options.timeZone || 'Asia/Shanghai';\n return new originalDateTimeFormat(locales, options);\n };\n Intl.DateTimeFormat.prototype = originalDateTimeFormat.prototype;\n\n // \u8986\u76D6 Date.prototype.getTimezoneOffset \u8FD4\u56DE -480 (UTC+8)\n Date.prototype.getTimezoneOffset = function () {\n return -480; // UTC+8 = -480 \u5206\u949F\n };\n });\n logger.success('setChinaTimezone', 'Asia/Shanghai (UTC+8)');\n }\n}\n", "import delay from 'delay';\nimport { createCursor } from 'ghost-cursor-playwright';\nimport { createLogger } from './internal/logger';\n\nconst logger = createLogger('Humanize');\n\n// \u5185\u90E8 cursor \u5B9E\u4F8B\u7F13\u5B58 (\u6BCF\u4E2A page \u4E00\u4E2A) - \u4E0D\u5BF9\u5916\u66B4\u9732\nconst $CursorWeakMap = new WeakMap();\n\n/**\n * \u5185\u90E8\u65B9\u6CD5\uFF1A\u83B7\u53D6\u9875\u9762\u7684 cursor\uFF0C\u5982\u679C\u4E0D\u5B58\u5728\u5219\u629B\u51FA\u9519\u8BEF\n */\nfunction $GetCursor(page) {\n const cursor = $CursorWeakMap.get(page);\n if (!cursor) {\n throw new Error('Cursor \u672A\u521D\u59CB\u5316\uFF0C\u8BF7\u5148\u8C03\u7528 Humanize.initializeCursor(page)');\n }\n return cursor;\n}\n\nexport const Humanize = {\n /**\n * \u751F\u6210\u5E26\u6296\u52A8\u7684\u6BEB\u79D2\u6570 - \u57FA\u4E8E\u57FA\u7840\u503C\u6DFB\u52A0\u968F\u673A\u6D6E\u52A8 (\u00B130% \u9ED8\u8BA4)\n * @param {number} base - \u57FA\u7840\u5EF6\u8FDF (ms)\n * @param {number} [jitterPercent=0.3] - \u6296\u52A8\u767E\u5206\u6BD4 (0.3 = \u00B130%)\n * @returns {number} \u6296\u52A8\u540E\u7684\u6BEB\u79D2\u6570\n */\n jitterMs(base, jitterPercent = 0.3) {\n const jitter = base * jitterPercent * (Math.random() * 2 - 1);\n return Math.max(10, Math.round(base + jitter));\n },\n\n /**\n * \u521D\u59CB\u5316\u9875\u9762\u7684 Ghost Cursor\uFF08\u5FC5\u987B\u5728\u4F7F\u7528\u5176\u4ED6 cursor \u76F8\u5173\u65B9\u6CD5\u524D\u8C03\u7528\uFF09\n * \n * @param {import('playwright').Page} page\n * @returns {Promise<void>}\n */\n async initializeCursor(page) {\n if ($CursorWeakMap.has(page)) {\n logger.debug('initializeCursor: cursor already exists, skipping');\n return;\n }\n logger.start('initializeCursor', 'creating cursor');\n const cursor = await createCursor(page);\n $CursorWeakMap.set(page, cursor);\n logger.success('initializeCursor', 'cursor initialized');\n },\n\n /**\n * \u4EBA\u7C7B\u5316\u9F20\u6807\u79FB\u52A8 - \u4F7F\u7528 ghost-cursor \u79FB\u52A8\u5230\u6307\u5B9A\u4F4D\u7F6E\u6216\u5143\u7D20\n * \n * @param {import('playwright').Page} page\n * @param {string|{x: number, y: number}|import('playwright').ElementHandle} target - CSS\u9009\u62E9\u5668\u3001\u5750\u6807\u5BF9\u8C61\u6216\u5143\u7D20\u53E5\u67C4\n */\n async humanMove(page, target) {\n const cursor = $GetCursor(page);\n logger.start('humanMove', `target=${typeof target === 'string' ? target : 'element/coords'}`);\n try {\n if (typeof target === 'string') {\n // CSS \u9009\u62E9\u5668\n const element = await page.$(target);\n if (!element) {\n logger.warn(`humanMove: \u5143\u7D20\u4E0D\u5B58\u5728 ${target}`);\n return false;\n }\n const box = await element.boundingBox();\n if (!box) {\n logger.warn(`humanMove: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E ${target}`);\n return false;\n }\n const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.2;\n const y = box.y + box.height / 2 + (Math.random() - 0.5) * box.height * 0.2;\n await cursor.actions.move({ x, y });\n } else if (target && typeof target.x === 'number' && typeof target.y === 'number') {\n // \u5750\u6807\u5BF9\u8C61\n await cursor.actions.move(target);\n } else if (target && typeof target.boundingBox === 'function') {\n // ElementHandle\n const box = await target.boundingBox();\n if (box) {\n const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.2;\n const y = box.y + box.height / 2 + (Math.random() - 0.5) * box.height * 0.2;\n await cursor.actions.move({ x, y });\n }\n }\n logger.success('humanMove');\n return true;\n } catch (error) {\n logger.fail('humanMove', error);\n throw error;\n }\n },\n\n /**\n * \u4EBA\u7C7B\u5316\u70B9\u51FB - \u4F7F\u7528 ghost-cursor \u6A21\u62DF\u4EBA\u7C7B\u9F20\u6807\u79FB\u52A8\u8F68\u8FF9\u5E76\u70B9\u51FB\n * \n * @param {import('playwright').Page} page\n * @param {string|import('playwright').ElementHandle} target - CSS \u9009\u62E9\u5668\u6216\u5143\u7D20\u53E5\u67C4\n * @param {Object} [options]\n * @param {number} [options.reactionDelay=250] - \u53CD\u5E94\u5EF6\u8FDF\u57FA\u7840\u503C (ms)\uFF0C\u5B9E\u9645 \u00B130% \u6296\u52A8\n * @param {boolean} [options.throwOnMissing=true] - \u5143\u7D20\u4E0D\u5B58\u5728\u65F6\u662F\u5426\u629B\u51FA\u9519\u8BEF\n */\n async humanClick(page, target, options = {}) {\n const cursor = $GetCursor(page);\n const { reactionDelay = 250, throwOnMissing = true } = options;\n logger.start('humanClick', `target=${typeof target === 'string' ? target : 'ElementHandle'}`);\n\n try {\n let element;\n if (typeof target === 'string') {\n element = await page.$(target);\n if (!element) {\n if (throwOnMissing) {\n throw new Error(`\u627E\u4E0D\u5230\u5143\u7D20 ${target}`);\n }\n logger.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${target}`);\n return false;\n }\n } else {\n element = target;\n }\n\n const box = await element.boundingBox();\n if (!box) {\n if (throwOnMissing) {\n throw new Error('\u65E0\u6CD5\u83B7\u53D6\u5143\u7D20\u4F4D\u7F6E');\n }\n logger.warn('humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB');\n return false;\n }\n\n // \u8BA1\u7B97\u5E26\u968F\u673A\u504F\u79FB\u7684\u70B9\u51FB\u4F4D\u7F6E\n const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.3;\n const y = box.y + box.height / 2 + (Math.random() - 0.5) * box.height * 0.3;\n\n await cursor.actions.move({ x, y });\n // \u4EBA\u7C7B\u53CD\u5E94\u5EF6\u8FDF (150-400ms \u8303\u56F4)\n await delay(this.jitterMs(reactionDelay, 0.4));\n await cursor.actions.click();\n\n logger.success('humanClick');\n return true;\n } catch (error) {\n logger.fail('humanClick', error);\n throw error;\n }\n },\n\n /**\n * \u968F\u673A\u5EF6\u8FDF\u4E00\u6BB5\u6BEB\u79D2\u6570\uFF08\u5E26 \u00B130% \u6296\u52A8\uFF09\n * @param {number} baseMs - \u57FA\u7840\u5EF6\u8FDF\u6BEB\u79D2\u6570\n * @param {number} [jitterPercent=0.3] - \u6296\u52A8\u767E\u5206\u6BD4\n */\n async randomSleep(baseMs, jitterPercent = 0.3) {\n const ms = this.jitterMs(baseMs, jitterPercent);\n logger.start('randomSleep', `base=${baseMs}, actual=${ms}ms`);\n await delay(ms);\n logger.success('randomSleep');\n },\n\n /**\n * \u6A21\u62DF\u4EBA\u7C7B\"\u6CE8\u89C6\"\u6216\"\u9605\u8BFB\"\u884C\u4E3A\uFF1A\u9F20\u6807\u5728\u9875\u9762\u4E0A\u968F\u673A\u5FAE\u52A8\n * @param {import('playwright').Page} page\n * @param {number} [baseDurationMs=2500] - \u57FA\u7840\u6301\u7EED\u65F6\u95F4 (\u00B140% \u6296\u52A8)\n */\n async simulateGaze(page, baseDurationMs = 2500) {\n const cursor = $GetCursor(page);\n const durationMs = this.jitterMs(baseDurationMs, 0.4);\n logger.start('simulateGaze', `duration=${durationMs}ms`);\n const startTime = Date.now();\n const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };\n\n while (Date.now() - startTime < durationMs) {\n // \u5728\u89C6\u53E3\u8303\u56F4\u5185\u968F\u673A\u79FB\u52A8\n const x = 100 + Math.random() * (viewportSize.width - 200);\n const y = 100 + Math.random() * (viewportSize.height - 200);\n await cursor.actions.move({ x, y });\n // \u6CE8\u89C6\u505C\u7559 300-1200ms\n await delay(this.jitterMs(600, 0.5));\n }\n logger.success('simulateGaze');\n },\n\n /**\n * \u4EBA\u7C7B\u5316\u8F93\u5165 - \u5E26\u8282\u594F\u53D8\u5316\uFF08\u5FEB-\u6162-\u505C\u987F-\u5076\u5C14\u52A0\u901F\uFF09\n * @param {import('playwright').Page} page\n * @param {string} selector - \u8F93\u5165\u6846\u9009\u62E9\u5668\n * @param {string} text - \u8981\u8F93\u5165\u7684\u6587\u672C\n * @param {Object} [options] \n * @param {number} [options.baseDelay=180] - \u57FA\u7840\u6309\u952E\u5EF6\u8FDF (ms)\uFF0C\u5B9E\u9645 \u00B140% \u6296\u52A8\n * @param {number} [options.pauseProbability=0.08] - \u505C\u987F\u6982\u7387 (0-1)\n * @param {number} [options.pauseBase=800] - \u505C\u987F\u65F6\u957F\u57FA\u7840\u503C (ms)\uFF0C\u5B9E\u9645 \u00B150% \u6296\u52A8\n */\n async humanType(page, selector, text, options = {}) {\n logger.start('humanType', `selector=${selector}, textLen=${text.length}`);\n const {\n baseDelay = 180,\n pauseProbability = 0.08,\n pauseBase = 800\n } = options;\n\n try {\n const locator = page.locator(selector);\n await locator.click();\n // \u70B9\u51FB\u540E\u601D\u8003\u5EF6\u8FDF\n await delay(this.jitterMs(200, 0.4));\n\n for (let i = 0; i < text.length; i++) {\n const char = text[i];\n let charDelay;\n\n if (char === ' ') {\n // \u7A7A\u683C\u952E\u7A0D\u5FEB\n charDelay = this.jitterMs(baseDelay * 0.6, 0.3);\n } else if (/[,.!?;:\uFF0C\u3002\uFF01\uFF1F\uFF1B\uFF1A]/.test(char)) {\n // \u6807\u70B9\u7B26\u53F7\u540E\u7A0D\u6162\uFF08\u6A21\u62DF\u601D\u8003\uFF09\n charDelay = this.jitterMs(baseDelay * 1.5, 0.4);\n } else {\n // \u666E\u901A\u5B57\u7B26\n charDelay = this.jitterMs(baseDelay, 0.4);\n }\n\n await page.keyboard.type(char);\n await delay(charDelay);\n\n // \u968F\u673A\u505C\u987F\uFF08\u6A21\u62DF\u601D\u8003/\u56DE\u987E\uFF09\n if (Math.random() < pauseProbability && i < text.length - 1) {\n const pauseTime = this.jitterMs(pauseBase, 0.5);\n logger.debug(`\u505C\u987F ${pauseTime}ms...`);\n await delay(pauseTime);\n }\n }\n logger.success('humanType');\n } catch (error) {\n logger.fail('humanType', error);\n throw error;\n }\n },\n\n /**\n * \u4EBA\u7C7B\u5316\u6E05\u7A7A\u8F93\u5165\u6846 - \u6A21\u62DF\u4EBA\u7C7B\u5220\u9664\u6587\u672C\u7684\u884C\u4E3A\n * @param {import('playwright').Page} page\n * @param {string} selector - \u8F93\u5165\u6846\u9009\u62E9\u5668\n */\n async humanClear(page, selector) {\n logger.start('humanClear', `selector=${selector}`);\n try {\n const locator = page.locator(selector);\n await locator.click();\n await delay(this.jitterMs(200, 0.4));\n\n const currentValue = await locator.inputValue();\n if (!currentValue || currentValue.length === 0) {\n logger.success('humanClear', 'already empty');\n return;\n }\n\n // \u5168\u9009 + \u5220\u9664\n await page.keyboard.press('Meta+A');\n await delay(this.jitterMs(100, 0.4));\n await page.keyboard.press('Backspace');\n\n logger.success('humanClear');\n } catch (error) {\n logger.fail('humanClear', error);\n throw error;\n }\n },\n\n /**\n * \u9875\u9762\u9884\u70ED\u6D4F\u89C8 - \u6A21\u62DF\u4EBA\u7C7B\u8FDB\u5165\u9875\u9762\u540E\u7684\u63A2\u7D22\u884C\u4E3A\n * @param {import('playwright').Page} page\n * @param {number} [baseDuration=3500] - \u9884\u70ED\u65F6\u957F\u57FA\u7840\u503C (\u00B140% \u6296\u52A8)\n */\n async warmUpBrowsing(page, baseDuration = 3500) {\n const cursor = $GetCursor(page);\n const durationMs = this.jitterMs(baseDuration, 0.4);\n\n logger.start('warmUpBrowsing', `duration=${durationMs}ms`);\n const startTime = Date.now();\n const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };\n\n try {\n while (Date.now() - startTime < durationMs) {\n const action = Math.random();\n\n if (action < 0.4) {\n // \u9F20\u6807\u79FB\u52A8\n const x = 100 + Math.random() * (viewportSize.width - 200);\n const y = 100 + Math.random() * (viewportSize.height - 200);\n await cursor.actions.move({ x, y });\n await delay(this.jitterMs(350, 0.4));\n } else if (action < 0.7) {\n // \u6EDA\u52A8\n const scrollY = (Math.random() - 0.5) * 200;\n await page.mouse.wheel(0, scrollY);\n await delay(this.jitterMs(500, 0.4));\n } else {\n // \u505C\u987F/\u6CE8\u89C6\n await delay(this.jitterMs(800, 0.5));\n }\n }\n logger.success('warmUpBrowsing');\n } catch (error) {\n logger.fail('warmUpBrowsing', error);\n throw error;\n }\n },\n\n /**\n * \u81EA\u7136\u6EDA\u52A8 - \u5E26\u60EF\u6027\u3001\u51CF\u901F\u6548\u679C\u548C\u968F\u673A\u6296\u52A8\n * @param {import('playwright').Page} page\n * @param {'up' | 'down'} [direction='down'] - \u6EDA\u52A8\u65B9\u5411\n * @param {number} [distance=300] - \u603B\u6EDA\u52A8\u8DDD\u79BB\u57FA\u7840\u503C (px)\uFF0C\u00B115% \u6296\u52A8\n * @param {number} [baseSteps=5] - \u5206\u51E0\u6B65\u5B8C\u6210\u57FA\u7840\u503C\uFF0C\u00B11 \u968F\u673A\n */\n async naturalScroll(page, direction = 'down', distance = 300, baseSteps = 5) {\n // steps \u52A0\u968F\u673A\u6D6E\u52A8 \u00B11\n const steps = Math.max(3, baseSteps + Math.floor(Math.random() * 3) - 1);\n // distance \u52A0\u6296\u52A8\n const actualDistance = this.jitterMs(distance, 0.15);\n\n logger.start('naturalScroll', `dir=${direction}, dist=${actualDistance}, steps=${steps}`);\n const sign = direction === 'down' ? 1 : -1;\n const stepDistance = actualDistance / steps;\n\n try {\n for (let i = 0; i < steps; i++) {\n // \u60EF\u6027\u51CF\u901F\u56E0\u5B50\n const factor = 1 - (i / steps) * 0.5;\n // \u6BCF\u6B65\u52A0 \u00B110% \u6296\u52A8\n const jitter = 0.9 + Math.random() * 0.2;\n const scrollAmount = stepDistance * factor * sign * jitter;\n\n await page.mouse.wheel(0, scrollAmount);\n\n // \u5EF6\u8FDF\u4E5F\u5E26\u6296\u52A8\n const baseDelay = 60 + i * 25;\n await delay(this.jitterMs(baseDelay, 0.3));\n }\n logger.success('naturalScroll');\n } catch (error) {\n logger.fail('naturalScroll', error);\n throw error;\n }\n }\n}\n", "// \u96C6\u4E2D\u7BA1\u7406\u542F\u52A8\u914D\u7F6E\uFF0C\u6682\u65F6\u4E3B\u8981\u7531 Stealth \u6A21\u5757\u63D0\u4F9B Args\uFF0C\u8FD9\u91CC\u4F5C\u4E3A\u6269\u5C55\u70B9\nimport { Stealth } from './stealth';\nimport { createLogger } from './internal/logger';\n\nconst logger = createLogger('Launch');\n\nexport const Launch = {\n getLaunchOptions(customArgs = []) {\n return {\n args: [\n ...Stealth.getStealthLaunchArgs(),\n ...customArgs\n ],\n ignoreDefaultArgs: ['--enable-automation'],\n };\n },\n\n /**\n * \u83B7\u53D6\u589E\u5F3A\u7248\u542F\u52A8\u9009\u9879\uFF08\u7528\u4E8E\u9AD8\u98CE\u9669\u53CD\u722C\u573A\u666F\uFF09\n */\n getAdvancedLaunchOptions(customArgs = []) {\n return {\n args: [\n ...Stealth.getAdvancedStealthArgs(),\n ...customArgs\n ],\n ignoreDefaultArgs: ['--enable-automation'],\n };\n },\n\n /**\n * \u63A8\u8350\u7684 Fingerprint Generator \u9009\u9879\n * \u786E\u4FDD\u751F\u6210\u7684\u662F\u684C\u9762\u7AEF\u3001\u8F83\u65B0\u7684 Chrome\uFF0C\u4EE5\u5339\u914D\u6211\u4EEC\u7684\u811A\u672C\u903B\u8F91\n */\n getFingerprintGeneratorOptions() {\n return {\n browsers: [{ name: 'chrome', minVersion: 110 }],\n devices: ['desktop'],\n operatingSystems: ['windows', 'linux'], // \u5305\u542B Linux \u517C\u5BB9\u5BB9\u5668\n };\n },\n\n /**\n * \u521B\u5EFA\u5DF2\u6CE8\u518C Stealth \u63D2\u4EF6\u7684 Chromium \u5B9E\u4F8B\n * \n * \u5C01\u88C5\u4E86 `chromium.use(stealthPlugin())` \u7684\u5E38\u7528\u6A21\u5F0F\n * \n * @example\n * ```javascript\n * import { chromium } from 'playwright-extra';\n * import stealthPlugin from 'puppeteer-extra-plugin-stealth';\n * \n * const stealthChromium = Launch.createStealthChromium(chromium, stealthPlugin);\n * // \u73B0\u5728 stealthChromium \u5DF2\u6CE8\u518C stealth \u63D2\u4EF6\uFF0C\u53EF\u7528\u4E8E launchContext.launcher\n * ```\n * \n * @param {import('playwright-extra').ChromiumExtra} chromium - playwright-extra \u7684 chromium\n * @param {Function} stealthPlugin - puppeteer-extra-plugin-stealth \u7684\u9ED8\u8BA4\u5BFC\u51FA\n * @returns {import('playwright-extra').ChromiumExtra} \u5DF2\u6CE8\u518C stealth \u7684 chromium\n */\n createStealthChromium(chromium, stealthPlugin) {\n chromium.use(stealthPlugin());\n logger.success('createStealthChromium', 'Stealth plugin registered');\n return chromium;\n }\n}\n\n", "import express from 'express';\nimport { Actor } from 'apify';\nimport { PresetOfLiveViewKey } from './constants';\nimport { createLogger } from './internal/logger';\n\nconst logger = createLogger('LiveView');\n\n/**\n * \u542F\u52A8\u4E00\u4E2A Web \u670D\u52A1\u5668\u4EE5\u5728 Live View \u9009\u9879\u5361\u4E2D\u663E\u793A\u6700\u65B0\u7684\u5C4F\u5E55\u622A\u56FE\u3002\n */\nasync function startLiveViewServer(liveViewKey) {\n const app = express();\n\n app.get('/', async (req, res) => {\n try {\n // \u4ECE\u9ED8\u8BA4\u7684 Key-Value Store \u4E2D\u8BFB\u53D6\u6700\u65B0\u7684\u5C4F\u5E55\u622A\u56FE\n const screenshotBuffer = await Actor.getValue(liveViewKey);\n\n if (!screenshotBuffer) {\n // \u5982\u679C\u8FD8\u6CA1\u6709\u622A\u56FE\uFF0C\u53D1\u9001\u4E00\u4E2A\u81EA\u52A8\u5237\u65B0\u7684\u5360\u4F4D\u9875\u9762\n res.send('<html><head><meta http-equiv=\"refresh\" content=\"2\"></head><body>\u7B49\u5F85\u7B2C\u4E00\u4E2A\u5C4F\u5E55\u622A\u56FE...</body></html>');\n return;\n }\n\n // \u5C06 Buffer \u8F6C\u6362\u4E3A Base64 \u5B57\u7B26\u4E32\n const screenshotBase64 = screenshotBuffer.toString('base64');\n\n // \u53D1\u9001\u4E00\u4E2A HTML \u9875\u9762\uFF0C\u8BE5\u9875\u9762\u6BCF 1 \u79D2\u81EA\u52A8\u5237\u65B0\u4E00\u6B21\uFF0C\u5E76\u663E\u793A\u622A\u56FE\n res.send(`\n <html>\n <head>\n <title>Live View (\u622A\u56FE)</title>\n <meta http-equiv=\"refresh\" content=\"1\">\n </head>\n <body style=\"margin:0; padding:0;\">\n <img src=\"data:image/png;base64,${screenshotBase64}\" \n alt=\"Live View Screenshot\" \n style=\"width: 100%; height: auto;\" />\n </body>\n </html>\n `);\n } catch (error) {\n logger.fail('Live View Server', error);\n res.status(500).send(`\u65E0\u6CD5\u52A0\u8F7D\u5C4F\u5E55\u622A\u56FE: ${error.message}`);\n }\n });\n\n // \u76D1\u542C Apify \u5BB9\u5668\u7AEF\u53E3 \n const port = process.env.APIFY_CONTAINER_PORT || 4321;\n app.listen(port, () => { logger.success('startLiveViewServer', `\u76D1\u542C\u7AEF\u53E3 ${port}`); });\n}\n\n/**\n * \u62CD\u6444\u5F53\u524D\u9875\u9762\u7684\u5C4F\u5E55\u622A\u56FE\u5E76\u5C06\u5176\u4FDD\u5B58\u5230 Key-Value Store\u3002\n * @param {import('playwright').Page} page\n * @param {string} [logMessage] - \u53EF\u9009\u7684\u65E5\u5FD7\u6D88\u606F\u3002\n */\nasync function takeLiveScreenshot(liveViewKey, page, logMessage) {\n try {\n const buffer = await page.screenshot({ type: 'png' });\n await Actor.setValue(liveViewKey, buffer, { contentType: 'image/png' });\n if (logMessage) {\n logger.info(`(\u622A\u56FE): ${logMessage}`);\n }\n } catch (e) {\n logger.warn(`\u65E0\u6CD5\u6355\u83B7 Live View \u5C4F\u5E55\u622A\u56FE: ${e.message}`);\n }\n}\n\nconst useLiveView = (liveViewKey = PresetOfLiveViewKey) => {\n return {\n takeLiveScreenshot: async (page, logMessage) => {\n return await takeLiveScreenshot(liveViewKey, page, logMessage)\n },\n startLiveViewServer: async () => {\n return await startLiveViewServer(liveViewKey);\n }\n }\n}\n\nexport const LiveView = {\n useLiveView,\n};\n", "import { createLogger } from './internal/logger';\n\nconst logger = createLogger('Captcha');\n\n/**\n * \u521B\u5EFA\u9A8C\u8BC1\u7801\u76D1\u63A7\u5668 - \u652F\u6301 DOM \u9009\u62E9\u5668 \u548C URL \u6A21\u5F0F \u4E24\u79CD\u68C0\u6D4B\u65B9\u5F0F\n * \n * \u6CE8\u610F\uFF1A\u76D1\u63A7\u5668\u968F\u9875\u9762\u751F\u547D\u5468\u671F\u81EA\u52A8\u6E05\u7406\uFF0C\u65E0\u9700\u624B\u52A8 cleanup\n * \n * @param {import('playwright').Page} page\n * @param {Object} options\n * @param {string} [options.domSelector] - DOM \u5143\u7D20\u9009\u62E9\u5668 (\u5982 '#captcha_container')\n * @param {string} [options.urlPattern] - URL \u5339\u914D\u6A21\u5F0F (\u5982 '/captcha')\n * @param {Function} options.onDetected - \u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\u65F6\u7684\u56DE\u8C03 (async function)\n */\nexport function useCaptchaMonitor(page, options) {\n const { domSelector, urlPattern, onDetected } = options;\n\n if (!domSelector && !urlPattern) {\n throw new Error('[CaptchaMonitor] \u5FC5\u987B\u63D0\u4F9B domSelector \u6216 urlPattern \u81F3\u5C11\u4E00\u4E2A');\n }\n\n if (!onDetected || typeof onDetected !== 'function') {\n throw new Error('[CaptchaMonitor] onDetected \u5FC5\u987B\u662F\u4E00\u4E2A\u51FD\u6570');\n }\n\n let isHandled = false;\n let frameHandler = null;\n let exposedFunctionName = null;\n\n const triggerDetected = async () => {\n if (isHandled) return;\n isHandled = true;\n logger.fail('Captcha Detected', '\uD83D\uDED1 \u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\uFF01');\n await onDetected();\n };\n\n // ============================================================\n // \u6A21\u5F0F1: DOM \u76D1\u63A7 (\u4F7F\u7528 MutationObserver)\n // ============================================================\n if (domSelector) {\n // \u751F\u6210\u552F\u4E00\u7684\u51FD\u6570\u540D\u907F\u514D\u51B2\u7A81\n exposedFunctionName = `__c_d_${Date.now()}`;\n\n // \u66B4\u9732\u56DE\u8C03\u51FD\u6570\u7ED9\u9875\u9762\n page.exposeFunction(exposedFunctionName, triggerDetected).catch(() => {\n // \u5FFD\u7565\u91CD\u590D\u66B4\u9732\u9519\u8BEF\n });\n\n // \u6CE8\u5165 MutationObserver \u76D1\u542C\u811A\u672C\n page.addInitScript(({ selector, callbackName }) => {\n (() => {\n let observer = null;\n\n const checkAndReport = () => {\n const element = document.querySelector(selector);\n if (element) {\n if (observer) {\n observer.disconnect();\n observer = null;\n }\n if (window[callbackName]) {\n window[callbackName]();\n }\n return true;\n }\n return false;\n };\n\n // 1. \u7ACB\u5373\u68C0\u67E5\u4E00\u6B21\n if (checkAndReport()) return;\n\n // 2. \u542F\u52A8 MutationObserver\n observer = new MutationObserver((mutations) => {\n let shouldCheck = false;\n for (const mutation of mutations) {\n if (mutation.addedNodes.length > 0) {\n shouldCheck = true;\n break;\n }\n }\n if (shouldCheck && observer) {\n checkAndReport();\n }\n });\n\n // 3. \u6302\u8F7D\u76D1\u542C\uFF08\u786E\u4FDD DOM \u51C6\u5907\u5C31\u7EEA\uFF09\n const mountObserver = () => {\n const target = document.documentElement;\n if (target && observer) {\n observer.observe(target, { childList: true, subtree: true });\n }\n };\n\n if (document.readyState === 'loading') {\n window.addEventListener('DOMContentLoaded', mountObserver);\n } else {\n mountObserver();\n }\n })();\n }, { selector: domSelector, callbackName: exposedFunctionName });\n\n logger.success('useCaptchaMonitor', `DOM \u76D1\u63A7\u5DF2\u542F\u7528: ${domSelector}`);\n }\n\n // ============================================================\n // \u6A21\u5F0F2: URL \u76D1\u63A7 (\u76D1\u542C framenavigated)\n // ============================================================\n if (urlPattern) {\n frameHandler = async (frame) => {\n if (frame === page.mainFrame()) {\n const currentUrl = page.url();\n if (currentUrl.includes(urlPattern)) {\n await triggerDetected();\n }\n }\n };\n\n page.on('framenavigated', frameHandler);\n logger.success('useCaptchaMonitor', `URL \u76D1\u63A7\u5DF2\u542F\u7528: ${urlPattern}`);\n }\n\n // \u6CE8\u610F\uFF1A\u4E0D\u63D0\u4F9B cleanup \u51FD\u6570\n // - DOM \u6A21\u5F0F\uFF1AaddInitScript \u6CE8\u5165\u7684\u4EE3\u7801\u65E0\u6CD5\u4ECE Node \u7AEF\u6E05\u7406\n // - URL \u6A21\u5F0F\uFF1Aframenavigated \u76D1\u542C\u901A\u5E38\u8DDF\u968F\u9875\u9762\u751F\u547D\u5468\u671F\uFF0C\u65E0\u9700\u624B\u52A8\u6E05\u7406\n // \u5982\u679C\u9700\u8981\u63D0\u524D\u7EC8\u6B62\u76D1\u63A7\uFF0C\u8BBE\u8BA1\u4E0A\u5E94\u8BE5\u8BA9 onDetected \u5904\u7406\u540E\u7EED\u903B\u8F91\uFF08\u5982 Actor.fail\uFF09\n}\n\n// \u6309\u7167 toolkit \u7EDF\u4E00\u7684\u5BFC\u51FA\u6A21\u5F0F\nexport const Captcha = {\n useCaptchaMonitor\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["import_crawlee", "Actor", "logger", "logger", "logger", "delay", "logger", "logger", "express", "logger"]
|
|
7
7
|
}
|
package/dist/index.js
CHANGED
|
@@ -370,7 +370,7 @@ var Stealth = {
|
|
|
370
370
|
};
|
|
371
371
|
|
|
372
372
|
// src/humanize.js
|
|
373
|
-
import delay
|
|
373
|
+
import delay from "delay";
|
|
374
374
|
import { createCursor } from "ghost-cursor-playwright";
|
|
375
375
|
var logger4 = createLogger("Humanize");
|
|
376
376
|
var $CursorWeakMap = /* @__PURE__ */ new WeakMap();
|
|
@@ -382,6 +382,16 @@ function $GetCursor(page) {
|
|
|
382
382
|
return cursor;
|
|
383
383
|
}
|
|
384
384
|
var Humanize = {
|
|
385
|
+
/**
|
|
386
|
+
* 生成带抖动的毫秒数 - 基于基础值添加随机浮动 (±30% 默认)
|
|
387
|
+
* @param {number} base - 基础延迟 (ms)
|
|
388
|
+
* @param {number} [jitterPercent=0.3] - 抖动百分比 (0.3 = ±30%)
|
|
389
|
+
* @returns {number} 抖动后的毫秒数
|
|
390
|
+
*/
|
|
391
|
+
jitterMs(base, jitterPercent = 0.3) {
|
|
392
|
+
const jitter = base * jitterPercent * (Math.random() * 2 - 1);
|
|
393
|
+
return Math.max(10, Math.round(base + jitter));
|
|
394
|
+
},
|
|
385
395
|
/**
|
|
386
396
|
* 初始化页面的 Ghost Cursor(必须在使用其他 cursor 相关方法前调用)
|
|
387
397
|
*
|
|
@@ -445,13 +455,12 @@ var Humanize = {
|
|
|
445
455
|
* @param {import('playwright').Page} page
|
|
446
456
|
* @param {string|import('playwright').ElementHandle} target - CSS 选择器或元素句柄
|
|
447
457
|
* @param {Object} [options]
|
|
448
|
-
* @param {number} [options.
|
|
449
|
-
* @param {number} [options.delayAfter=300] - 点击后延迟 (ms)
|
|
458
|
+
* @param {number} [options.reactionDelay=250] - 反应延迟基础值 (ms),实际 ±30% 抖动
|
|
450
459
|
* @param {boolean} [options.throwOnMissing=true] - 元素不存在时是否抛出错误
|
|
451
460
|
*/
|
|
452
461
|
async humanClick(page, target, options = {}) {
|
|
453
462
|
const cursor = $GetCursor(page);
|
|
454
|
-
const {
|
|
463
|
+
const { reactionDelay = 250, throwOnMissing = true } = options;
|
|
455
464
|
logger4.start("humanClick", `target=${typeof target === "string" ? target : "ElementHandle"}`);
|
|
456
465
|
try {
|
|
457
466
|
let element;
|
|
@@ -478,7 +487,7 @@ var Humanize = {
|
|
|
478
487
|
const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.3;
|
|
479
488
|
const y = box.y + box.height / 2 + (Math.random() - 0.5) * box.height * 0.3;
|
|
480
489
|
await cursor.actions.move({ x, y });
|
|
481
|
-
await
|
|
490
|
+
await delay(this.jitterMs(reactionDelay, 0.4));
|
|
482
491
|
await cursor.actions.click();
|
|
483
492
|
logger4.success("humanClick");
|
|
484
493
|
return true;
|
|
@@ -488,30 +497,32 @@ var Humanize = {
|
|
|
488
497
|
}
|
|
489
498
|
},
|
|
490
499
|
/**
|
|
491
|
-
*
|
|
492
|
-
* @param {number}
|
|
493
|
-
* @param {number}
|
|
500
|
+
* 随机延迟一段毫秒数(带 ±30% 抖动)
|
|
501
|
+
* @param {number} baseMs - 基础延迟毫秒数
|
|
502
|
+
* @param {number} [jitterPercent=0.3] - 抖动百分比
|
|
494
503
|
*/
|
|
495
|
-
async randomSleep(
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
await ms;
|
|
504
|
+
async randomSleep(baseMs, jitterPercent = 0.3) {
|
|
505
|
+
const ms = this.jitterMs(baseMs, jitterPercent);
|
|
506
|
+
logger4.start("randomSleep", `base=${baseMs}, actual=${ms}ms`);
|
|
507
|
+
await delay(ms);
|
|
499
508
|
logger4.success("randomSleep");
|
|
500
509
|
},
|
|
501
510
|
/**
|
|
502
511
|
* 模拟人类"注视"或"阅读"行为:鼠标在页面上随机微动
|
|
503
512
|
* @param {import('playwright').Page} page
|
|
504
|
-
* @param {number}
|
|
513
|
+
* @param {number} [baseDurationMs=2500] - 基础持续时间 (±40% 抖动)
|
|
505
514
|
*/
|
|
506
|
-
async simulateGaze(page,
|
|
515
|
+
async simulateGaze(page, baseDurationMs = 2500) {
|
|
507
516
|
const cursor = $GetCursor(page);
|
|
517
|
+
const durationMs = this.jitterMs(baseDurationMs, 0.4);
|
|
508
518
|
logger4.start("simulateGaze", `duration=${durationMs}ms`);
|
|
509
519
|
const startTime = Date.now();
|
|
520
|
+
const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };
|
|
510
521
|
while (Date.now() - startTime < durationMs) {
|
|
511
|
-
const x = Math.random() *
|
|
512
|
-
const y = Math.random() *
|
|
522
|
+
const x = 100 + Math.random() * (viewportSize.width - 200);
|
|
523
|
+
const y = 100 + Math.random() * (viewportSize.height - 200);
|
|
513
524
|
await cursor.actions.move({ x, y });
|
|
514
|
-
await
|
|
525
|
+
await delay(this.jitterMs(600, 0.5));
|
|
515
526
|
}
|
|
516
527
|
logger4.success("simulateGaze");
|
|
517
528
|
},
|
|
@@ -521,41 +532,36 @@ var Humanize = {
|
|
|
521
532
|
* @param {string} selector - 输入框选择器
|
|
522
533
|
* @param {string} text - 要输入的文本
|
|
523
534
|
* @param {Object} [options]
|
|
524
|
-
* @param {number} [options.
|
|
525
|
-
* @param {number} [options.
|
|
526
|
-
* @param {number} [options.
|
|
527
|
-
* @param {number} [options.pauseMin=300] - 停顿最小时长 (ms)
|
|
528
|
-
* @param {number} [options.pauseMax=800] - 停顿最大时长 (ms)
|
|
529
|
-
*
|
|
535
|
+
* @param {number} [options.baseDelay=180] - 基础按键延迟 (ms),实际 ±40% 抖动
|
|
536
|
+
* @param {number} [options.pauseProbability=0.08] - 停顿概率 (0-1)
|
|
537
|
+
* @param {number} [options.pauseBase=800] - 停顿时长基础值 (ms),实际 ±50% 抖动
|
|
530
538
|
*/
|
|
531
539
|
async humanType(page, selector, text, options = {}) {
|
|
532
540
|
logger4.start("humanType", `selector=${selector}, textLen=${text.length}`);
|
|
533
541
|
const {
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
pauseMin = 300,
|
|
538
|
-
pauseMax = 800
|
|
542
|
+
baseDelay = 180,
|
|
543
|
+
pauseProbability = 0.08,
|
|
544
|
+
pauseBase = 800
|
|
539
545
|
} = options;
|
|
540
546
|
try {
|
|
541
547
|
const locator = page.locator(selector);
|
|
542
548
|
await locator.click();
|
|
543
|
-
await
|
|
549
|
+
await delay(this.jitterMs(200, 0.4));
|
|
544
550
|
for (let i = 0; i < text.length; i++) {
|
|
545
551
|
const char = text[i];
|
|
546
552
|
let charDelay;
|
|
547
553
|
if (char === " ") {
|
|
548
|
-
charDelay =
|
|
554
|
+
charDelay = this.jitterMs(baseDelay * 0.6, 0.3);
|
|
549
555
|
} else if (/[,.!?;:,。!?;:]/.test(char)) {
|
|
550
|
-
charDelay =
|
|
556
|
+
charDelay = this.jitterMs(baseDelay * 1.5, 0.4);
|
|
551
557
|
} else {
|
|
552
|
-
charDelay =
|
|
558
|
+
charDelay = this.jitterMs(baseDelay, 0.4);
|
|
553
559
|
}
|
|
554
560
|
await page.keyboard.type(char);
|
|
555
561
|
await delay(charDelay);
|
|
556
562
|
if (Math.random() < pauseProbability && i < text.length - 1) {
|
|
557
|
-
const pauseTime =
|
|
558
|
-
logger4.debug(`\u505C\u987F ${
|
|
563
|
+
const pauseTime = this.jitterMs(pauseBase, 0.5);
|
|
564
|
+
logger4.debug(`\u505C\u987F ${pauseTime}ms...`);
|
|
559
565
|
await delay(pauseTime);
|
|
560
566
|
}
|
|
561
567
|
}
|
|
@@ -575,14 +581,14 @@ var Humanize = {
|
|
|
575
581
|
try {
|
|
576
582
|
const locator = page.locator(selector);
|
|
577
583
|
await locator.click();
|
|
578
|
-
await
|
|
584
|
+
await delay(this.jitterMs(200, 0.4));
|
|
579
585
|
const currentValue = await locator.inputValue();
|
|
580
586
|
if (!currentValue || currentValue.length === 0) {
|
|
581
587
|
logger4.success("humanClear", "already empty");
|
|
582
588
|
return;
|
|
583
589
|
}
|
|
584
590
|
await page.keyboard.press("Meta+A");
|
|
585
|
-
await
|
|
591
|
+
await delay(this.jitterMs(100, 0.4));
|
|
586
592
|
await page.keyboard.press("Backspace");
|
|
587
593
|
logger4.success("humanClear");
|
|
588
594
|
} catch (error) {
|
|
@@ -593,17 +599,11 @@ var Humanize = {
|
|
|
593
599
|
/**
|
|
594
600
|
* 页面预热浏览 - 模拟人类进入页面后的探索行为
|
|
595
601
|
* @param {import('playwright').Page} page
|
|
596
|
-
* @param {number
|
|
602
|
+
* @param {number} [baseDuration=3500] - 预热时长基础值 (±40% 抖动)
|
|
597
603
|
*/
|
|
598
|
-
async warmUpBrowsing(page,
|
|
604
|
+
async warmUpBrowsing(page, baseDuration = 3500) {
|
|
599
605
|
const cursor = $GetCursor(page);
|
|
600
|
-
|
|
601
|
-
if (typeof duration === "object" && duration.min !== void 0 && duration.max !== void 0) {
|
|
602
|
-
durationMs = duration.min + Math.random() * (duration.max - duration.min);
|
|
603
|
-
} else {
|
|
604
|
-
durationMs = duration;
|
|
605
|
-
}
|
|
606
|
-
durationMs = Math.round(durationMs);
|
|
606
|
+
const durationMs = this.jitterMs(baseDuration, 0.4);
|
|
607
607
|
logger4.start("warmUpBrowsing", `duration=${durationMs}ms`);
|
|
608
608
|
const startTime = Date.now();
|
|
609
609
|
const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };
|
|
@@ -614,13 +614,13 @@ var Humanize = {
|
|
|
614
614
|
const x = 100 + Math.random() * (viewportSize.width - 200);
|
|
615
615
|
const y = 100 + Math.random() * (viewportSize.height - 200);
|
|
616
616
|
await cursor.actions.move({ x, y });
|
|
617
|
-
await
|
|
617
|
+
await delay(this.jitterMs(350, 0.4));
|
|
618
618
|
} else if (action < 0.7) {
|
|
619
619
|
const scrollY = (Math.random() - 0.5) * 200;
|
|
620
620
|
await page.mouse.wheel(0, scrollY);
|
|
621
|
-
await
|
|
621
|
+
await delay(this.jitterMs(500, 0.4));
|
|
622
622
|
} else {
|
|
623
|
-
await
|
|
623
|
+
await delay(this.jitterMs(800, 0.5));
|
|
624
624
|
}
|
|
625
625
|
}
|
|
626
626
|
logger4.success("warmUpBrowsing");
|
|
@@ -630,23 +630,26 @@ var Humanize = {
|
|
|
630
630
|
}
|
|
631
631
|
},
|
|
632
632
|
/**
|
|
633
|
-
* 自然滚动 -
|
|
633
|
+
* 自然滚动 - 带惯性、减速效果和随机抖动
|
|
634
634
|
* @param {import('playwright').Page} page
|
|
635
635
|
* @param {'up' | 'down'} [direction='down'] - 滚动方向
|
|
636
|
-
* @param {number} [distance=300] -
|
|
637
|
-
* @param {number} [
|
|
636
|
+
* @param {number} [distance=300] - 总滚动距离基础值 (px),±15% 抖动
|
|
637
|
+
* @param {number} [baseSteps=5] - 分几步完成基础值,±1 随机
|
|
638
638
|
*/
|
|
639
|
-
async naturalScroll(page, direction = "down", distance = 300,
|
|
640
|
-
|
|
639
|
+
async naturalScroll(page, direction = "down", distance = 300, baseSteps = 5) {
|
|
640
|
+
const steps = Math.max(3, baseSteps + Math.floor(Math.random() * 3) - 1);
|
|
641
|
+
const actualDistance = this.jitterMs(distance, 0.15);
|
|
642
|
+
logger4.start("naturalScroll", `dir=${direction}, dist=${actualDistance}, steps=${steps}`);
|
|
641
643
|
const sign = direction === "down" ? 1 : -1;
|
|
642
|
-
const stepDistance =
|
|
644
|
+
const stepDistance = actualDistance / steps;
|
|
643
645
|
try {
|
|
644
646
|
for (let i = 0; i < steps; i++) {
|
|
645
647
|
const factor = 1 - i / steps * 0.5;
|
|
646
|
-
const
|
|
648
|
+
const jitter = 0.9 + Math.random() * 0.2;
|
|
649
|
+
const scrollAmount = stepDistance * factor * sign * jitter;
|
|
647
650
|
await page.mouse.wheel(0, scrollAmount);
|
|
648
|
-
const
|
|
649
|
-
await delay(
|
|
651
|
+
const baseDelay = 60 + i * 25;
|
|
652
|
+
await delay(this.jitterMs(baseDelay, 0.3));
|
|
650
653
|
}
|
|
651
654
|
logger4.success("naturalScroll");
|
|
652
655
|
} catch (error) {
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/apify-kit.js", "../src/constants.js", "../src/internal/logger.js", "../src/utils.js", "../src/stealth.js", "../src/humanize.js", "../src/launch.js", "../src/live-view.js", "../src/captcha-monitor.js", "../index.js"],
|
|
4
|
-
"sourcesContent": ["import { log as originalLog } from 'crawlee'; // \u4FDD\u7559\u539F\u59CB log \u7528\u4E8E\u7279\u6B8A\u7528\u9014\u6216\u76F4\u63A5\u8C03\u7528\nimport { Status, FAILED_KEY_SEPARATOR, StatusCode } from './constants';\nimport { createLogger } from './internal/logger';\n\nconst logger = createLogger('ApifyKit');\n\n/**\n * \u521B\u5EFA ApifyKit \u5B9E\u4F8B\n * \u5982\u679C apify \u53EF\u7528\uFF0C\u8FD4\u56DE\u5B8C\u6574\u529F\u80FD\u7684 ApifyKit\n * \u5982\u679C apify \u4E0D\u53EF\u7528\uFF0C\u8FD4\u56DE\u964D\u7EA7\u7248\u672C\uFF08\u975E apify \u76F8\u5173\u529F\u80FD\u4ECD\u53EF\u7528\uFF09\n */\nasync function createApifyKit() {\n let apify = null;\n\n // \u5C1D\u8BD5\u52A0\u8F7D apify\n try {\n apify = await import('apify');\n } catch (error) {\n // apify \u4E0D\u53EF\u7528\uFF0C\u5C06\u4F7F\u7528\u964D\u7EA7\u7248\u672C\n throw new Error('\u26A0\uFE0F apify \u5E93\u672A\u5B89\u88C5\uFF0CApifyKit \u7684 Actor \u76F8\u5173\u529F\u80FD\u4E0D\u53EF\u7528')\n }\n\n const { Actor } = apify;\n\n return {\n /**\n * \u5305\u88C5 Step Name\n */\n wrapStepNameWithFailedKey(key, stepName) {\n return `${key}${FAILED_KEY_SEPARATOR}${stepName}`;\n },\n\n /**\n * \u89E3\u5305 Step Name\n */\n unwrapStepName(stepName) {\n const splitIndex = stepName.indexOf(FAILED_KEY_SEPARATOR);\n if (splitIndex === -1) {\n return ['-', stepName];\n }\n const key = stepName.substring(0, splitIndex);\n const value = stepName.substring(splitIndex + FAILED_KEY_SEPARATOR.length);\n return [key, value];\n },\n\n /**\n * \u6838\u5FC3\u5C01\u88C5\uFF1A\u6267\u884C\u6B65\u9AA4\uFF0C\u5E26\u81EA\u52A8\u65E5\u5FD7\u786E\u8BA4\u548C\u5931\u8D25\u622A\u56FE\u5904\u7406\n */\n async runStep(pendingStepName, page, actionFn, options = {}) {\n const { failActor = true } = options; // \u9ED8\u8BA4\u8C03\u7528 Actor.fail\n const [failedKey, stepName] = this.unwrapStepName(pendingStepName);\n\n // log.info(`\uD83D\uDD04 [\u6B63\u5728\u6267\u884C] ${stepName}...`);\n logger.start(`[Step] ${stepName}`);\n\n try {\n const result = await actionFn();\n // log.info(`\u2705 [\u6267\u884C\u6210\u529F] ${stepName}`);\n logger.success(`[Step] ${stepName}`);\n return result;\n } catch (error) {\n // log.error(`\u274C [\u6267\u884C\u5931\u8D25] ${stepName}: ${error.message}`);\n logger.fail(`[Step] ${stepName}`, error);\n\n let screenshotBase64 = '\u622A\u56FE\u5931\u8D25';\n try {\n if (page) {\n const buffer = await page.screenshot({ fullPage: true, type: 'jpeg', quality: 60 });\n screenshotBase64 = `data:image/jpeg;base64,${buffer.toString('base64')}`;\n }\n } catch (snapErr) {\n logger.warn(`\u622A\u56FE\u751F\u6210\u5931\u8D25: ${snapErr.message}`);\n }\n\n // \u4F7F\u7528 pushFailed \u65B9\u6CD5\u63A8\u9001\u5931\u8D25\u6570\u636E\uFF08\u79C1\u6709\u4F7F\u7528\uFF09\n await this.pushFailed(error, {\n failedStep: stepName,\n failedKey: failedKey,\n errorMessage: error.message,\n errorStack: error.stack,\n screenshotBase64: screenshotBase64\n });\n\n // \u6839\u636E failActor \u51B3\u5B9A\u662F\u5426\u8C03\u7528 Actor.fail\n if (failActor) {\n await Actor.fail(`Run Step ${stepName} \u5931\u8D25: ${error.message}`);\n } else {\n // \u4E0D\u8C03\u7528 Actor.fail\uFF0C\u76F4\u63A5\u629B\u51FA\u9519\u8BEF\n throw error;\n }\n }\n },\n\n /**\n * \u5BBD\u677E\u7248runStep\uFF1A\u5931\u8D25\u65F6\u4E0D\u8C03\u7528Actor.fail\uFF0C\u53EA\u629B\u51FA\u5F02\u5E38\n */\n async runStepLoose(stepName, page, fn) {\n return await this.runStep(stepName, page, fn, { failActor: false });\n },\n\n /**\n * \u63A8\u9001\u6210\u529F\u6570\u636E\u7684\u901A\u7528\u65B9\u6CD5\n * @param {Object} data - \u8981\u63A8\u9001\u7684\u6570\u636E\u5BF9\u8C61\n */\n async pushSuccess(data) {\n await Actor.pushData({\n code: StatusCode.Success,\n status: Status.Success,\n timestamp: new Date().toISOString(),\n ...data\n });\n logger.success('pushSuccess', 'Data pushed');\n },\n\n /**\n * \u63A8\u9001\u5931\u8D25\u6570\u636E\u7684\u901A\u7528\u65B9\u6CD5\uFF08\u79C1\u6709\u65B9\u6CD5\uFF0C\u4EC5\u4F9BrunStep\u5185\u90E8\u4F7F\u7528\uFF09\n * @param {Error|Object} error - \u9519\u8BEF\u5BF9\u8C61\uFF08\u53EF\u5305\u542B\u5176\u4ED6\u7684\u9519\u8BEF/\u6216\u90E8\u5206\u5904\u7406\u6210\u529F\u7684\u989D\u5916\u4FE1\u606F\uFF09\n * @param {Object} [meta] - \u989D\u5916\u7684\u6570\u636E\uFF08\u5982failedStep, screenshotBase64\u7B49\uFF0C\u4EC5runStep\u4F7F\u7528\uFF09\n * @private\n */\n async pushFailed(error, meta = {}) {\n await Actor.pushData({\n code: StatusCode.Failed,\n status: Status.Failed,\n // \u8FD9\u91CC\u53EF\u80FD\u5E26\u5176\u4ED6\u9519\u8BEF\u4FE1\u606F\n error,\n timestamp: new Date().toISOString(),\n ...meta\n });\n logger.success('pushFailed', 'Error data pushed');\n }\n };\n}\n\n// \u61D2\u52A0\u8F7D\u5355\u4F8B\nlet instance = null;\n\n/**\n * \u83B7\u53D6 ApifyKit \u5B9E\u4F8B\uFF08\u61D2\u52A0\u8F7D\uFF09\n * @returns {Promise<Object>} ApifyKit \u5B9E\u4F8B\n */\nasync function useApifyKit() {\n if (!instance) {\n instance = await createApifyKit();\n }\n return instance;\n}\n\n// \u4E5F\u5BFC\u51FA\u521D\u59CB\u5316\u51FD\u6570\uFF0C\u4F9B\u9700\u8981\u7684\u7528\u6237\u4F7F\u7528\nexport const ApifyKit = {\n useApifyKit\n};\n", "export const ErrorKeygen = {\n NotLogin: 30000001,\n Chaptcha: 30000002,\n}\n\nexport const Status = {\n Success: 'SUCCESS',\n Failed: 'FAILED'\n}\n\nexport const StatusCode = {\n Success: 0,\n Failed: -1\n}\n\nexport const FAILED_KEY_SEPARATOR = '::<@>::';\n\nexport const PresetOfLiveViewKey = 'LIVE_VIEW_SCREENSHOT';\n", "import { log } from 'crawlee';\n\n/**\n * \u521B\u5EFA\u6A21\u5757\u7EA7\u65E5\u5FD7\u5668\n * @param {string} moduleName - \u6A21\u5757\u540D\u79F0\uFF0C\u4F8B\u5982 'Humanize', 'Stealth'\n */\nexport function createLogger(moduleName) {\n const prefix = `[${moduleName}]`;\n\n return {\n /**\n * \u65B9\u6CD5\u5F00\u59CB\u65E5\u5FD7\n * @param {string} methodName - \u65B9\u6CD5\u540D\u79F0\n * @param {string} [params] - \u53C2\u6570\u6458\u8981 (\u53EF\u9009)\n */\n start(methodName, params = '') {\n const paramStr = params ? ` (${params})` : '';\n log.info(`${prefix} \uD83D\uDD37 ${methodName} \u5F00\u59CB${paramStr}`);\n },\n\n /**\n * \u65B9\u6CD5\u6210\u529F\u65E5\u5FD7\n * @param {string} methodName - \u65B9\u6CD5\u540D\u79F0\n * @param {string} [result] - \u7ED3\u679C\u6458\u8981 (\u53EF\u9009)\n */\n success(methodName, result = '') {\n const resultStr = result ? ` (${result})` : '';\n log.info(`${prefix} \u2705 ${methodName} \u5B8C\u6210${resultStr}`);\n },\n\n /**\n * \u65B9\u6CD5\u5931\u8D25\u65E5\u5FD7\n * @param {string} methodName - \u65B9\u6CD5\u540D\u79F0\n * @param {Error|string} error - \u9519\u8BEF\u5BF9\u8C61\u6216\u4FE1\u606F\n */\n fail(methodName, error) {\n const message = error instanceof Error ? error.message : error;\n log.error(`${prefix} \u274C ${methodName} \u5931\u8D25: ${message}`);\n },\n\n /**\n * \u8C03\u8BD5\u65E5\u5FD7\n * @param {string} message - \u8BE6\u60C5\n */\n debug(message) {\n log.debug(`${prefix} \uD83D\uDD39 ${message}`);\n },\n\n /**\n * \u8B66\u544A\u65E5\u5FD7\n * @param {string} message - \u8B66\u544A\u4FE1\u606F\n */\n warn(message) {\n log.warning(`${prefix} \u26A0\uFE0F ${message}`);\n },\n\n /**\n * \u666E\u901A\u4FE1\u606F\u65E5\u5FD7\n * @param {string} message - \u4FE1\u606F\n */\n info(message) {\n log.info(`${prefix} \uD83D\uDCD6 ${message}`);\n }\n };\n}\n", "import { createLogger } from './internal/logger';\n\nconst logger = createLogger('Utils');\n\nexport const Utils = {\n /**\n * \u89E3\u6790 SSE \u6D41\u6587\u672C\n */\n parseSseStream(sseStreamText) {\n const events = [];\n const lines = sseStreamText.split('\\n');\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n try {\n const jsonContent = line.substring(6).trim();\n if (jsonContent && jsonContent !== '[DONE]') {\n events.push(JSON.parse(jsonContent));\n }\n } catch (e) {\n // Ignore lines that are not valid JSON\n }\n }\n }\n logger.success('parseSseStream', `parsed events: ${events.length}`);\n return events;\n },\n\n /**\n * \u89E3\u6790 Cookie \u5B57\u7B26\u4E32\u4E3A Playwright \u683C\u5F0F\u7684 Cookie \u6570\u7EC4\n * @param {string} cookieString - Cookie \u5B57\u7B26\u4E32\n * @param {string} [domain] - Cookie \u57DF\u540D (\u53EF\u9009)\n * @returns {Array} Cookie \u6570\u7EC4\n */\n parseCookies(cookieString, domain) {\n const cookies = [];\n const pairs = cookieString.split(';').map(c => c.trim());\n\n for (const pair of pairs) {\n const [name, ...valueParts] = pair.split('=');\n if (name && valueParts.length > 0) {\n const cookie = {\n name: name.trim(),\n value: valueParts.join('=').trim(),\n path: '/',\n };\n if (domain) {\n cookie.domain = domain;\n }\n cookies.push(cookie);\n }\n }\n logger.success('parseCookies', `parsed ${cookies.length} cookies`);\n return cookies;\n }\n}\n", "import { createLogger } from './internal/logger';\n\nconst logger = createLogger('Stealth');\n\nexport const Stealth = {\n /**\n * \u5173\u952E\u4FEE\u590D\uFF1A\u5C06 Page \u89C6\u53E3\u8C03\u6574\u4E3A\u4E0E\u6D4F\u89C8\u5668\u6307\u7EB9 (window.screen) \u4E00\u81F4\u3002\n * \u9632\u6B62 \"Viewport Mismatch\" \u7C7B\u578B\u7684\u53CD\u722C\u68C0\u6D4B\u3002\n * @param {import('playwright').Page} page \n */\n async syncViewportWithScreen(page) {\n try {\n // \u83B7\u53D6\u6307\u7EB9\u4E2D\u7684\u5C4F\u5E55\u5C3A\u5BF8\n const screen = await page.evaluate(() => ({\n width: window.screen.width,\n height: window.screen.height,\n availWidth: window.screen.availWidth,\n availHeight: window.screen.availHeight,\n }));\n\n // \u8C03\u6574\u89C6\u53E3\n await page.setViewportSize({\n width: screen.width,\n height: screen.height\n });\n\n logger.success('syncViewportWithScreen', `size=${screen.width}x${screen.height}`);\n } catch (e) {\n logger.warn(`syncViewportWithScreen Failed: ${e.message}. Fallback to 1920x1080.`);\n await page.setViewportSize({ width: 1920, height: 1080 });\n }\n },\n\n /**\n * \u786E\u4FDD navigator.webdriver \u9690\u85CF (\u901A\u5E38 Playwright Stealth \u63D2\u4EF6\u5DF2\u5904\u7406\uFF0C\u4F46\u53CC\u91CD\u4FDD\u9669)\n */\n async hideWebdriver(page) {\n await page.addInitScript(() => {\n Object.defineProperty(navigator, 'webdriver', {\n get: () => false,\n });\n });\n logger.success('hideWebdriver');\n },\n\n /**\n * \u901A\u7528\u7684 Playwright \u8D44\u6E90\u62E6\u622A\u5668\uFF0C\u7528\u4E8E\u5C4F\u853D\u4E0D\u5FC5\u8981\u7684\u8D44\u6E90\u4EE5\u52A0\u901F\u52A0\u8F7D\n * @param {import('playwright').Page} page\n * @param {string[]} [resourceTypes] - \u8981\u5C4F\u853D\u7684\u8D44\u6E90\u7C7B\u578B\uFF0C\u9ED8\u8BA4\u4E3A ['font', 'image', 'media']\n */\n async setupBlockingResources(page, resourceTypes = ['font', 'image', 'media']) {\n await page.route('**/*', (route) => {\n const request = route.request();\n const type = request.resourceType();\n if (resourceTypes.includes(type)) {\n return route.abort();\n }\n return route.continue();\n });\n logger.success('setupBlockingResources', `types=[${resourceTypes.join(',')}]`);\n },\n\n /**\n * \u83B7\u53D6\u63A8\u8350\u7684 Stealth \u542F\u52A8\u53C2\u6570\n */\n getStealthLaunchArgs() {\n return [\n '--disable-blink-features=AutomationControlled',\n '--no-sandbox',\n '--disable-setuid-sandbox',\n '--disable-infobars',\n '--window-position=0,0',\n '--ignore-certificate-errors',\n '--disable-web-security',\n // \u6CE8\u610F\uFF1A\u4E0D\u5EFA\u8BAE\u8FD9\u91CC\u5F3A\u5236\u6307\u5B9A window-size\uFF0C\u8BA9 syncViewportWithScreen \u53BB\u52A8\u6001\u8C03\u6574\n // '--window-size=1920,1080' \n ];\n },\n\n /**\n * \u83B7\u53D6\u589E\u5F3A\u7248 Stealth \u542F\u52A8\u53C2\u6570 (\u63A8\u8350\u7528\u4E8E\u9AD8\u98CE\u9669\u53CD\u722C\u573A\u666F)\n * \u5305\u542B\u66F4\u591A\u9488\u5BF9\u81EA\u52A8\u5316\u68C0\u6D4B\u7684\u9632\u62A4\n */\n getAdvancedStealthArgs() {\n return [\n ...this.getStealthLaunchArgs(),\n // \u7981\u7528\u5404\u79CD\u53EF\u80FD\u66B4\u9732\u81EA\u52A8\u5316\u7684\u7279\u5F81\n '--disable-dev-shm-usage',\n '--disable-accelerated-2d-canvas',\n '--disable-gpu-sandbox',\n '--disable-background-networking',\n '--disable-default-apps',\n '--disable-extensions',\n '--disable-sync',\n '--disable-translate',\n '--metrics-recording-only',\n '--mute-audio',\n '--no-first-run',\n // \u6A21\u62DF\u771F\u5B9E\u7528\u6237\u914D\u7F6E\n '--lang=zh-CN,zh',\n ];\n },\n\n /**\n * \u8BBE\u7F6E\u4E2D\u56FD\u65F6\u533A (Asia/Shanghai, UTC+8)\n * \n * \u9632\u6B62\u65F6\u533A\u4E0D\u4E00\u81F4\u7684\u68C0\u6D4B\u3002\u5BF9\u4E8E\u4E2D\u56FD\u5883\u5185\u722C\u53D6\u5F3A\u70C8\u63A8\u8350\u4F7F\u7528\u3002\n * \u5E94\u5728 preNavigationHooks \u6216 BrowserContext \u521B\u5EFA\u540E\u8C03\u7528\u3002\n * \n * @param {import('playwright').BrowserContext} context\n */\n async setChinaTimezone(context) {\n // Playwright \u901A\u8FC7 context \u8BBE\u7F6E\u65F6\u533A\n // \u6CE8\u610F\uFF1A\u8FD9\u9700\u8981\u5728 context \u521B\u5EFA\u65F6\u8BBE\u7F6E\uFF0C\u6216\u8005\u4F7F\u7528 CDP\n // \u8FD9\u91CC\u4F7F\u7528 addInitScript \u6CE8\u5165 Intl \u8986\u76D6\n await context.addInitScript(() => {\n // \u8986\u76D6 Intl.DateTimeFormat \u9ED8\u8BA4\u65F6\u533A\n const originalDateTimeFormat = Intl.DateTimeFormat;\n Intl.DateTimeFormat = function (locales, options) {\n options = options || {};\n options.timeZone = options.timeZone || 'Asia/Shanghai';\n return new originalDateTimeFormat(locales, options);\n };\n Intl.DateTimeFormat.prototype = originalDateTimeFormat.prototype;\n\n // \u8986\u76D6 Date.prototype.getTimezoneOffset \u8FD4\u56DE -480 (UTC+8)\n Date.prototype.getTimezoneOffset = function () {\n return -480; // UTC+8 = -480 \u5206\u949F\n };\n });\n logger.success('setChinaTimezone', 'Asia/Shanghai (UTC+8)');\n }\n}\n", "import delay, { rangeDelay } from 'delay';\nimport { createCursor } from 'ghost-cursor-playwright';\nimport { createLogger } from './internal/logger';\n\nconst logger = createLogger('Humanize');\n\n// \u5185\u90E8 cursor \u5B9E\u4F8B\u7F13\u5B58 (\u6BCF\u4E2A page \u4E00\u4E2A) - \u4E0D\u5BF9\u5916\u66B4\u9732\nconst $CursorWeakMap = new WeakMap();\n\n/**\n * \u5185\u90E8\u65B9\u6CD5\uFF1A\u83B7\u53D6\u9875\u9762\u7684 cursor\uFF0C\u5982\u679C\u4E0D\u5B58\u5728\u5219\u629B\u51FA\u9519\u8BEF\n */\nfunction $GetCursor(page) {\n const cursor = $CursorWeakMap.get(page);\n if (!cursor) {\n throw new Error('Cursor \u672A\u521D\u59CB\u5316\uFF0C\u8BF7\u5148\u8C03\u7528 Humanize.initializeCursor(page)');\n }\n return cursor;\n}\n\nexport const Humanize = {\n /**\n * \u521D\u59CB\u5316\u9875\u9762\u7684 Ghost Cursor\uFF08\u5FC5\u987B\u5728\u4F7F\u7528\u5176\u4ED6 cursor \u76F8\u5173\u65B9\u6CD5\u524D\u8C03\u7528\uFF09\n * \n * @param {import('playwright').Page} page\n * @returns {Promise<void>}\n */\n async initializeCursor(page) {\n if ($CursorWeakMap.has(page)) {\n logger.debug('initializeCursor: cursor already exists, skipping');\n return;\n }\n logger.start('initializeCursor', 'creating cursor');\n const cursor = await createCursor(page);\n $CursorWeakMap.set(page, cursor);\n logger.success('initializeCursor', 'cursor initialized');\n },\n\n /**\n * \u4EBA\u7C7B\u5316\u9F20\u6807\u79FB\u52A8 - \u4F7F\u7528 ghost-cursor \u79FB\u52A8\u5230\u6307\u5B9A\u4F4D\u7F6E\u6216\u5143\u7D20\n * \n * @param {import('playwright').Page} page\n * @param {string|{x: number, y: number}|import('playwright').ElementHandle} target - CSS\u9009\u62E9\u5668\u3001\u5750\u6807\u5BF9\u8C61\u6216\u5143\u7D20\u53E5\u67C4\n */\n async humanMove(page, target) {\n const cursor = $GetCursor(page);\n logger.start('humanMove', `target=${typeof target === 'string' ? target : 'element/coords'}`);\n try {\n if (typeof target === 'string') {\n // CSS \u9009\u62E9\u5668\n const element = await page.$(target);\n if (!element) {\n logger.warn(`humanMove: \u5143\u7D20\u4E0D\u5B58\u5728 ${target}`);\n return false;\n }\n const box = await element.boundingBox();\n if (!box) {\n logger.warn(`humanMove: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E ${target}`);\n return false;\n }\n const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.2;\n const y = box.y + box.height / 2 + (Math.random() - 0.5) * box.height * 0.2;\n await cursor.actions.move({ x, y });\n } else if (target && typeof target.x === 'number' && typeof target.y === 'number') {\n // \u5750\u6807\u5BF9\u8C61\n await cursor.actions.move(target);\n } else if (target && typeof target.boundingBox === 'function') {\n // ElementHandle\n const box = await target.boundingBox();\n if (box) {\n const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.2;\n const y = box.y + box.height / 2 + (Math.random() - 0.5) * box.height * 0.2;\n await cursor.actions.move({ x, y });\n }\n }\n logger.success('humanMove');\n return true;\n } catch (error) {\n logger.fail('humanMove', error);\n throw error;\n }\n },\n\n /**\n * \u4EBA\u7C7B\u5316\u70B9\u51FB - \u4F7F\u7528 ghost-cursor \u6A21\u62DF\u4EBA\u7C7B\u9F20\u6807\u79FB\u52A8\u8F68\u8FF9\u5E76\u70B9\u51FB\n * \n * @param {import('playwright').Page} page\n * @param {string|import('playwright').ElementHandle} target - CSS \u9009\u62E9\u5668\u6216\u5143\u7D20\u53E5\u67C4\n * @param {Object} [options]\n * @param {number} [options.delayBefore=100] - \u70B9\u51FB\u524D\u5EF6\u8FDF (ms)\n * @param {number} [options.delayAfter=300] - \u70B9\u51FB\u540E\u5EF6\u8FDF (ms)\n * @param {boolean} [options.throwOnMissing=true] - \u5143\u7D20\u4E0D\u5B58\u5728\u65F6\u662F\u5426\u629B\u51FA\u9519\u8BEF\n */\n async humanClick(page, target, options = {}) {\n const cursor = $GetCursor(page);\n const { delayBefore = 100, delayAfter = 100, throwOnMissing = true } = options;\n logger.start('humanClick', `target=${typeof target === 'string' ? target : 'ElementHandle'}`);\n\n try {\n let element;\n if (typeof target === 'string') {\n element = await page.$(target);\n if (!element) {\n if (throwOnMissing) {\n throw new Error(`\u627E\u4E0D\u5230\u5143\u7D20 ${target}`);\n }\n logger.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${target}`);\n return false;\n }\n } else {\n element = target;\n }\n\n const box = await element.boundingBox();\n if (!box) {\n if (throwOnMissing) {\n throw new Error('\u65E0\u6CD5\u83B7\u53D6\u5143\u7D20\u4F4D\u7F6E');\n }\n logger.warn('humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB');\n return false;\n }\n\n // \u8BA1\u7B97\u5E26\u968F\u673A\u504F\u79FB\u7684\u70B9\u51FB\u4F4D\u7F6E\n const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.3;\n const y = box.y + box.height / 2 + (Math.random() - 0.5) * box.height * 0.3;\n\n await cursor.actions.move({ x, y });\n await rangeDelay(delayBefore, delayAfter);\n await cursor.actions.click();\n\n logger.success('humanClick');\n return true;\n } catch (error) {\n logger.fail('humanClick', error);\n throw error;\n }\n },\n\n /**\n * \u968F\u673A\u5EF6\u8FDF\u4E00\u6BB5\u6BEB\u79D2\u6570\n * @param {number} min - \u6700\u5C0F\u6BEB\u79D2\n * @param {number} max - \u6700\u5927\u6BEB\u79D2\n */\n async randomSleep(min, max) {\n logger.start('randomSleep', `min=${min}, max=${max}`);\n const ms = typeof max === 'number'\n ? rangeDelay(min, max)\n : delay(min);\n await ms;\n logger.success('randomSleep');\n },\n\n /**\n * \u6A21\u62DF\u4EBA\u7C7B\"\u6CE8\u89C6\"\u6216\"\u9605\u8BFB\"\u884C\u4E3A\uFF1A\u9F20\u6807\u5728\u9875\u9762\u4E0A\u968F\u673A\u5FAE\u52A8\n * @param {import('playwright').Page} page\n * @param {number} durationMs - \u6301\u7EED\u65F6\u95F4\n */\n async simulateGaze(page, durationMs = 2000) {\n const cursor = $GetCursor(page);\n logger.start('simulateGaze', `duration=${durationMs}ms`);\n const startTime = Date.now();\n while (Date.now() - startTime < durationMs) {\n const x = Math.random() * 800;\n const y = Math.random() * 600;\n await cursor.actions.move({ x, y });\n await rangeDelay(200, 800);\n }\n logger.success('simulateGaze');\n },\n\n /**\n * \u4EBA\u7C7B\u5316\u8F93\u5165 - \u5E26\u8282\u594F\u53D8\u5316\uFF08\u5FEB-\u6162-\u505C\u987F-\u5076\u5C14\u52A0\u901F\uFF09\n * @param {import('playwright').Page} page\n * @param {string} selector - \u8F93\u5165\u6846\u9009\u62E9\u5668\n * @param {string} text - \u8981\u8F93\u5165\u7684\u6587\u672C\n * @param {Object} [options] \n * @param {number} [options.minDelay=50] - \u6700\u5C0F\u6309\u952E\u5EF6\u8FDF (ms)\n * @param {number} [options.maxDelay=200] - \u6700\u5927\u6309\u952E\u5EF6\u8FDF (ms)\n * @param {number} [options.pauseProbability=0.1] - \u505C\u987F\u6982\u7387 (0-1)\n * @param {number} [options.pauseMin=300] - \u505C\u987F\u6700\u5C0F\u65F6\u957F (ms)\n * @param {number} [options.pauseMax=800] - \u505C\u987F\u6700\u5927\u65F6\u957F (ms)\n * \n */\n async humanType(page, selector, text, options = {}) {\n logger.start('humanType', `selector=${selector}, textLen=${text.length}`);\n const {\n minDelay = 100,\n maxDelay = 300,\n pauseProbability = 0.1,\n pauseMin = 300,\n pauseMax = 800\n } = options;\n\n try {\n const locator = page.locator(selector);\n await locator.click();\n await rangeDelay(100, 300);\n\n for (let i = 0; i < text.length; i++) {\n const char = text[i];\n let charDelay;\n if (char === ' ') {\n charDelay = minDelay + Math.random() * 50;\n } else if (/[,.!?;:\uFF0C\u3002\uFF01\uFF1F\uFF1B\uFF1A]/.test(char)) {\n charDelay = maxDelay + Math.random() * 100;\n } else {\n charDelay = minDelay + Math.random() * (maxDelay - minDelay);\n }\n\n await page.keyboard.type(char);\n await delay(charDelay);\n\n if (Math.random() < pauseProbability && i < text.length - 1) {\n const pauseTime = pauseMin + Math.random() * (pauseMax - pauseMin);\n logger.debug(`\u505C\u987F ${Math.round(pauseTime)}ms...`);\n await delay(pauseTime);\n }\n }\n logger.success('humanType');\n } catch (error) {\n logger.fail('humanType', error);\n throw error;\n }\n },\n\n /**\n * \u4EBA\u7C7B\u5316\u6E05\u7A7A\u8F93\u5165\u6846 - \u6A21\u62DF\u4EBA\u7C7B\u5220\u9664\u6587\u672C\u7684\u884C\u4E3A\n * @param {import('playwright').Page} page\n * @param {string} selector - \u8F93\u5165\u6846\u9009\u62E9\u5668\n */\n async humanClear(page, selector) {\n logger.start('humanClear', `selector=${selector}`);\n try {\n const locator = page.locator(selector);\n await locator.click();\n await rangeDelay(100, 300);\n\n const currentValue = await locator.inputValue();\n if (!currentValue || currentValue.length === 0) {\n logger.success('humanClear', 'already empty');\n return;\n }\n\n // \u5168\u9009 + \u5220\u9664\n await page.keyboard.press('Meta+A');\n await rangeDelay(50, 150);\n await page.keyboard.press('Backspace');\n\n logger.success('humanClear');\n } catch (error) {\n logger.fail('humanClear', error);\n throw error;\n }\n },\n\n /**\n * \u9875\u9762\u9884\u70ED\u6D4F\u89C8 - \u6A21\u62DF\u4EBA\u7C7B\u8FDB\u5165\u9875\u9762\u540E\u7684\u63A2\u7D22\u884C\u4E3A\n * @param {import('playwright').Page} page\n * @param {number|{min: number, max: number}} [duration=3000] - \u9884\u70ED\u65F6\u957F\n */\n async warmUpBrowsing(page, duration = 3000) {\n const cursor = $GetCursor(page);\n let durationMs;\n if (typeof duration === 'object' && duration.min !== undefined && duration.max !== undefined) {\n durationMs = duration.min + Math.random() * (duration.max - duration.min);\n } else {\n durationMs = duration;\n }\n durationMs = Math.round(durationMs);\n\n logger.start('warmUpBrowsing', `duration=${durationMs}ms`);\n const startTime = Date.now();\n const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };\n\n try {\n while (Date.now() - startTime < durationMs) {\n const action = Math.random();\n\n if (action < 0.4) {\n const x = 100 + Math.random() * (viewportSize.width - 200);\n const y = 100 + Math.random() * (viewportSize.height - 200);\n await cursor.actions.move({ x, y });\n await rangeDelay(200, 500);\n } else if (action < 0.7) {\n const scrollY = (Math.random() - 0.5) * 200;\n await page.mouse.wheel(0, scrollY);\n await rangeDelay(300, 700);\n } else {\n await rangeDelay(500, 1000);\n }\n }\n logger.success('warmUpBrowsing');\n } catch (error) {\n logger.fail('warmUpBrowsing', error);\n throw error;\n }\n },\n\n /**\n * \u81EA\u7136\u6EDA\u52A8 - \u5E26\u60EF\u6027\u548C\u51CF\u901F\u6548\u679C\n * @param {import('playwright').Page} page\n * @param {'up' | 'down'} [direction='down'] - \u6EDA\u52A8\u65B9\u5411\n * @param {number} [distance=300] - \u603B\u6EDA\u52A8\u8DDD\u79BB (px)\n * @param {number} [steps=5] - \u5206\u51E0\u6B65\u5B8C\u6210\n */\n async naturalScroll(page, direction = 'down', distance = 300, steps = 5) {\n logger.start('naturalScroll', `dir=${direction}, dist=${distance}, steps=${steps}`);\n const sign = direction === 'down' ? 1 : -1;\n const stepDistance = distance / steps;\n\n try {\n for (let i = 0; i < steps; i++) {\n const factor = 1 - (i / steps) * 0.5;\n const scrollAmount = stepDistance * factor * sign;\n await page.mouse.wheel(0, scrollAmount);\n const delayTime = 50 + i * 30;\n await delay(delayTime);\n }\n logger.success('naturalScroll');\n } catch (error) {\n logger.fail('naturalScroll', error);\n throw error;\n }\n }\n}\n", "// \u96C6\u4E2D\u7BA1\u7406\u542F\u52A8\u914D\u7F6E\uFF0C\u6682\u65F6\u4E3B\u8981\u7531 Stealth \u6A21\u5757\u63D0\u4F9B Args\uFF0C\u8FD9\u91CC\u4F5C\u4E3A\u6269\u5C55\u70B9\nimport { Stealth } from './stealth';\nimport { createLogger } from './internal/logger';\n\nconst logger = createLogger('Launch');\n\nexport const Launch = {\n getLaunchOptions(customArgs = []) {\n return {\n args: [\n ...Stealth.getStealthLaunchArgs(),\n ...customArgs\n ],\n ignoreDefaultArgs: ['--enable-automation'],\n };\n },\n\n /**\n * \u83B7\u53D6\u589E\u5F3A\u7248\u542F\u52A8\u9009\u9879\uFF08\u7528\u4E8E\u9AD8\u98CE\u9669\u53CD\u722C\u573A\u666F\uFF09\n */\n getAdvancedLaunchOptions(customArgs = []) {\n return {\n args: [\n ...Stealth.getAdvancedStealthArgs(),\n ...customArgs\n ],\n ignoreDefaultArgs: ['--enable-automation'],\n };\n },\n\n /**\n * \u63A8\u8350\u7684 Fingerprint Generator \u9009\u9879\n * \u786E\u4FDD\u751F\u6210\u7684\u662F\u684C\u9762\u7AEF\u3001\u8F83\u65B0\u7684 Chrome\uFF0C\u4EE5\u5339\u914D\u6211\u4EEC\u7684\u811A\u672C\u903B\u8F91\n */\n getFingerprintGeneratorOptions() {\n return {\n browsers: [{ name: 'chrome', minVersion: 110 }],\n devices: ['desktop'],\n operatingSystems: ['windows', 'linux'], // \u5305\u542B Linux \u517C\u5BB9\u5BB9\u5668\n };\n },\n\n /**\n * \u521B\u5EFA\u5DF2\u6CE8\u518C Stealth \u63D2\u4EF6\u7684 Chromium \u5B9E\u4F8B\n * \n * \u5C01\u88C5\u4E86 `chromium.use(stealthPlugin())` \u7684\u5E38\u7528\u6A21\u5F0F\n * \n * @example\n * ```javascript\n * import { chromium } from 'playwright-extra';\n * import stealthPlugin from 'puppeteer-extra-plugin-stealth';\n * \n * const stealthChromium = Launch.createStealthChromium(chromium, stealthPlugin);\n * // \u73B0\u5728 stealthChromium \u5DF2\u6CE8\u518C stealth \u63D2\u4EF6\uFF0C\u53EF\u7528\u4E8E launchContext.launcher\n * ```\n * \n * @param {import('playwright-extra').ChromiumExtra} chromium - playwright-extra \u7684 chromium\n * @param {Function} stealthPlugin - puppeteer-extra-plugin-stealth \u7684\u9ED8\u8BA4\u5BFC\u51FA\n * @returns {import('playwright-extra').ChromiumExtra} \u5DF2\u6CE8\u518C stealth \u7684 chromium\n */\n createStealthChromium(chromium, stealthPlugin) {\n chromium.use(stealthPlugin());\n logger.success('createStealthChromium', 'Stealth plugin registered');\n return chromium;\n }\n}\n\n", "import express from 'express';\nimport { Actor } from 'apify';\nimport { PresetOfLiveViewKey } from './constants';\nimport { createLogger } from './internal/logger';\n\nconst logger = createLogger('LiveView');\n\n/**\n * \u542F\u52A8\u4E00\u4E2A Web \u670D\u52A1\u5668\u4EE5\u5728 Live View \u9009\u9879\u5361\u4E2D\u663E\u793A\u6700\u65B0\u7684\u5C4F\u5E55\u622A\u56FE\u3002\n */\nasync function startLiveViewServer(liveViewKey) {\n const app = express();\n\n app.get('/', async (req, res) => {\n try {\n // \u4ECE\u9ED8\u8BA4\u7684 Key-Value Store \u4E2D\u8BFB\u53D6\u6700\u65B0\u7684\u5C4F\u5E55\u622A\u56FE\n const screenshotBuffer = await Actor.getValue(liveViewKey);\n\n if (!screenshotBuffer) {\n // \u5982\u679C\u8FD8\u6CA1\u6709\u622A\u56FE\uFF0C\u53D1\u9001\u4E00\u4E2A\u81EA\u52A8\u5237\u65B0\u7684\u5360\u4F4D\u9875\u9762\n res.send('<html><head><meta http-equiv=\"refresh\" content=\"2\"></head><body>\u7B49\u5F85\u7B2C\u4E00\u4E2A\u5C4F\u5E55\u622A\u56FE...</body></html>');\n return;\n }\n\n // \u5C06 Buffer \u8F6C\u6362\u4E3A Base64 \u5B57\u7B26\u4E32\n const screenshotBase64 = screenshotBuffer.toString('base64');\n\n // \u53D1\u9001\u4E00\u4E2A HTML \u9875\u9762\uFF0C\u8BE5\u9875\u9762\u6BCF 1 \u79D2\u81EA\u52A8\u5237\u65B0\u4E00\u6B21\uFF0C\u5E76\u663E\u793A\u622A\u56FE\n res.send(`\n <html>\n <head>\n <title>Live View (\u622A\u56FE)</title>\n <meta http-equiv=\"refresh\" content=\"1\">\n </head>\n <body style=\"margin:0; padding:0;\">\n <img src=\"data:image/png;base64,${screenshotBase64}\" \n alt=\"Live View Screenshot\" \n style=\"width: 100%; height: auto;\" />\n </body>\n </html>\n `);\n } catch (error) {\n logger.fail('Live View Server', error);\n res.status(500).send(`\u65E0\u6CD5\u52A0\u8F7D\u5C4F\u5E55\u622A\u56FE: ${error.message}`);\n }\n });\n\n // \u76D1\u542C Apify \u5BB9\u5668\u7AEF\u53E3 \n const port = process.env.APIFY_CONTAINER_PORT || 4321;\n app.listen(port, () => { logger.success('startLiveViewServer', `\u76D1\u542C\u7AEF\u53E3 ${port}`); });\n}\n\n/**\n * \u62CD\u6444\u5F53\u524D\u9875\u9762\u7684\u5C4F\u5E55\u622A\u56FE\u5E76\u5C06\u5176\u4FDD\u5B58\u5230 Key-Value Store\u3002\n * @param {import('playwright').Page} page\n * @param {string} [logMessage] - \u53EF\u9009\u7684\u65E5\u5FD7\u6D88\u606F\u3002\n */\nasync function takeLiveScreenshot(liveViewKey, page, logMessage) {\n try {\n const buffer = await page.screenshot({ type: 'png' });\n await Actor.setValue(liveViewKey, buffer, { contentType: 'image/png' });\n if (logMessage) {\n logger.info(`(\u622A\u56FE): ${logMessage}`);\n }\n } catch (e) {\n logger.warn(`\u65E0\u6CD5\u6355\u83B7 Live View \u5C4F\u5E55\u622A\u56FE: ${e.message}`);\n }\n}\n\nconst useLiveView = (liveViewKey = PresetOfLiveViewKey) => {\n return {\n takeLiveScreenshot: async (page, logMessage) => {\n return await takeLiveScreenshot(liveViewKey, page, logMessage)\n },\n startLiveViewServer: async () => {\n return await startLiveViewServer(liveViewKey);\n }\n }\n}\n\nexport const LiveView = {\n useLiveView,\n};\n", "import { createLogger } from './internal/logger';\n\nconst logger = createLogger('Captcha');\n\n/**\n * \u521B\u5EFA\u9A8C\u8BC1\u7801\u76D1\u63A7\u5668 - \u652F\u6301 DOM \u9009\u62E9\u5668 \u548C URL \u6A21\u5F0F \u4E24\u79CD\u68C0\u6D4B\u65B9\u5F0F\n * \n * \u6CE8\u610F\uFF1A\u76D1\u63A7\u5668\u968F\u9875\u9762\u751F\u547D\u5468\u671F\u81EA\u52A8\u6E05\u7406\uFF0C\u65E0\u9700\u624B\u52A8 cleanup\n * \n * @param {import('playwright').Page} page\n * @param {Object} options\n * @param {string} [options.domSelector] - DOM \u5143\u7D20\u9009\u62E9\u5668 (\u5982 '#captcha_container')\n * @param {string} [options.urlPattern] - URL \u5339\u914D\u6A21\u5F0F (\u5982 '/captcha')\n * @param {Function} options.onDetected - \u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\u65F6\u7684\u56DE\u8C03 (async function)\n */\nexport function useCaptchaMonitor(page, options) {\n const { domSelector, urlPattern, onDetected } = options;\n\n if (!domSelector && !urlPattern) {\n throw new Error('[CaptchaMonitor] \u5FC5\u987B\u63D0\u4F9B domSelector \u6216 urlPattern \u81F3\u5C11\u4E00\u4E2A');\n }\n\n if (!onDetected || typeof onDetected !== 'function') {\n throw new Error('[CaptchaMonitor] onDetected \u5FC5\u987B\u662F\u4E00\u4E2A\u51FD\u6570');\n }\n\n let isHandled = false;\n let frameHandler = null;\n let exposedFunctionName = null;\n\n const triggerDetected = async () => {\n if (isHandled) return;\n isHandled = true;\n logger.fail('Captcha Detected', '\uD83D\uDED1 \u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\uFF01');\n await onDetected();\n };\n\n // ============================================================\n // \u6A21\u5F0F1: DOM \u76D1\u63A7 (\u4F7F\u7528 MutationObserver)\n // ============================================================\n if (domSelector) {\n // \u751F\u6210\u552F\u4E00\u7684\u51FD\u6570\u540D\u907F\u514D\u51B2\u7A81\n exposedFunctionName = `__c_d_${Date.now()}`;\n\n // \u66B4\u9732\u56DE\u8C03\u51FD\u6570\u7ED9\u9875\u9762\n page.exposeFunction(exposedFunctionName, triggerDetected).catch(() => {\n // \u5FFD\u7565\u91CD\u590D\u66B4\u9732\u9519\u8BEF\n });\n\n // \u6CE8\u5165 MutationObserver \u76D1\u542C\u811A\u672C\n page.addInitScript(({ selector, callbackName }) => {\n (() => {\n let observer = null;\n\n const checkAndReport = () => {\n const element = document.querySelector(selector);\n if (element) {\n if (observer) {\n observer.disconnect();\n observer = null;\n }\n if (window[callbackName]) {\n window[callbackName]();\n }\n return true;\n }\n return false;\n };\n\n // 1. \u7ACB\u5373\u68C0\u67E5\u4E00\u6B21\n if (checkAndReport()) return;\n\n // 2. \u542F\u52A8 MutationObserver\n observer = new MutationObserver((mutations) => {\n let shouldCheck = false;\n for (const mutation of mutations) {\n if (mutation.addedNodes.length > 0) {\n shouldCheck = true;\n break;\n }\n }\n if (shouldCheck && observer) {\n checkAndReport();\n }\n });\n\n // 3. \u6302\u8F7D\u76D1\u542C\uFF08\u786E\u4FDD DOM \u51C6\u5907\u5C31\u7EEA\uFF09\n const mountObserver = () => {\n const target = document.documentElement;\n if (target && observer) {\n observer.observe(target, { childList: true, subtree: true });\n }\n };\n\n if (document.readyState === 'loading') {\n window.addEventListener('DOMContentLoaded', mountObserver);\n } else {\n mountObserver();\n }\n })();\n }, { selector: domSelector, callbackName: exposedFunctionName });\n\n logger.success('useCaptchaMonitor', `DOM \u76D1\u63A7\u5DF2\u542F\u7528: ${domSelector}`);\n }\n\n // ============================================================\n // \u6A21\u5F0F2: URL \u76D1\u63A7 (\u76D1\u542C framenavigated)\n // ============================================================\n if (urlPattern) {\n frameHandler = async (frame) => {\n if (frame === page.mainFrame()) {\n const currentUrl = page.url();\n if (currentUrl.includes(urlPattern)) {\n await triggerDetected();\n }\n }\n };\n\n page.on('framenavigated', frameHandler);\n logger.success('useCaptchaMonitor', `URL \u76D1\u63A7\u5DF2\u542F\u7528: ${urlPattern}`);\n }\n\n // \u6CE8\u610F\uFF1A\u4E0D\u63D0\u4F9B cleanup \u51FD\u6570\n // - DOM \u6A21\u5F0F\uFF1AaddInitScript \u6CE8\u5165\u7684\u4EE3\u7801\u65E0\u6CD5\u4ECE Node \u7AEF\u6E05\u7406\n // - URL \u6A21\u5F0F\uFF1Aframenavigated \u76D1\u542C\u901A\u5E38\u8DDF\u968F\u9875\u9762\u751F\u547D\u5468\u671F\uFF0C\u65E0\u9700\u624B\u52A8\u6E05\u7406\n // \u5982\u679C\u9700\u8981\u63D0\u524D\u7EC8\u6B62\u76D1\u63A7\uFF0C\u8BBE\u8BA1\u4E0A\u5E94\u8BE5\u8BA9 onDetected \u5904\u7406\u540E\u7EED\u903B\u8F91\uFF08\u5982 Actor.fail\uFF09\n}\n\n// \u6309\u7167 toolkit \u7EDF\u4E00\u7684\u5BFC\u51FA\u6A21\u5F0F\nexport const Captcha = {\n useCaptchaMonitor\n};\n", "import { ApifyKit } from './src/apify-kit';\nimport { Utils } from './src/utils';\nimport { Stealth } from './src/stealth';\nimport { Humanize } from './src/humanize';\nimport { Launch } from './src/launch';\nimport { LiveView } from './src/live-view';\nimport { Captcha } from './src/captcha-monitor';\nimport * as Constants from './src/constants';\n\n// Unified Entry Point\nexport const usePlaywrightToolKit = () => {\n return {\n ApifyKit,\n Stealth,\n Humanize,\n Launch,\n LiveView,\n Constants,\n Utils,\n Captcha\n };\n};\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { log as originalLog } from 'crawlee'; // \u4FDD\u7559\u539F\u59CB log \u7528\u4E8E\u7279\u6B8A\u7528\u9014\u6216\u76F4\u63A5\u8C03\u7528\nimport { Status, FAILED_KEY_SEPARATOR, StatusCode } from './constants';\nimport { createLogger } from './internal/logger';\n\nconst logger = createLogger('ApifyKit');\n\n/**\n * \u521B\u5EFA ApifyKit \u5B9E\u4F8B\n * \u5982\u679C apify \u53EF\u7528\uFF0C\u8FD4\u56DE\u5B8C\u6574\u529F\u80FD\u7684 ApifyKit\n * \u5982\u679C apify \u4E0D\u53EF\u7528\uFF0C\u8FD4\u56DE\u964D\u7EA7\u7248\u672C\uFF08\u975E apify \u76F8\u5173\u529F\u80FD\u4ECD\u53EF\u7528\uFF09\n */\nasync function createApifyKit() {\n let apify = null;\n\n // \u5C1D\u8BD5\u52A0\u8F7D apify\n try {\n apify = await import('apify');\n } catch (error) {\n // apify \u4E0D\u53EF\u7528\uFF0C\u5C06\u4F7F\u7528\u964D\u7EA7\u7248\u672C\n throw new Error('\u26A0\uFE0F apify \u5E93\u672A\u5B89\u88C5\uFF0CApifyKit \u7684 Actor \u76F8\u5173\u529F\u80FD\u4E0D\u53EF\u7528')\n }\n\n const { Actor } = apify;\n\n return {\n /**\n * \u5305\u88C5 Step Name\n */\n wrapStepNameWithFailedKey(key, stepName) {\n return `${key}${FAILED_KEY_SEPARATOR}${stepName}`;\n },\n\n /**\n * \u89E3\u5305 Step Name\n */\n unwrapStepName(stepName) {\n const splitIndex = stepName.indexOf(FAILED_KEY_SEPARATOR);\n if (splitIndex === -1) {\n return ['-', stepName];\n }\n const key = stepName.substring(0, splitIndex);\n const value = stepName.substring(splitIndex + FAILED_KEY_SEPARATOR.length);\n return [key, value];\n },\n\n /**\n * \u6838\u5FC3\u5C01\u88C5\uFF1A\u6267\u884C\u6B65\u9AA4\uFF0C\u5E26\u81EA\u52A8\u65E5\u5FD7\u786E\u8BA4\u548C\u5931\u8D25\u622A\u56FE\u5904\u7406\n */\n async runStep(pendingStepName, page, actionFn, options = {}) {\n const { failActor = true } = options; // \u9ED8\u8BA4\u8C03\u7528 Actor.fail\n const [failedKey, stepName] = this.unwrapStepName(pendingStepName);\n\n // log.info(`\uD83D\uDD04 [\u6B63\u5728\u6267\u884C] ${stepName}...`);\n logger.start(`[Step] ${stepName}`);\n\n try {\n const result = await actionFn();\n // log.info(`\u2705 [\u6267\u884C\u6210\u529F] ${stepName}`);\n logger.success(`[Step] ${stepName}`);\n return result;\n } catch (error) {\n // log.error(`\u274C [\u6267\u884C\u5931\u8D25] ${stepName}: ${error.message}`);\n logger.fail(`[Step] ${stepName}`, error);\n\n let screenshotBase64 = '\u622A\u56FE\u5931\u8D25';\n try {\n if (page) {\n const buffer = await page.screenshot({ fullPage: true, type: 'jpeg', quality: 60 });\n screenshotBase64 = `data:image/jpeg;base64,${buffer.toString('base64')}`;\n }\n } catch (snapErr) {\n logger.warn(`\u622A\u56FE\u751F\u6210\u5931\u8D25: ${snapErr.message}`);\n }\n\n // \u4F7F\u7528 pushFailed \u65B9\u6CD5\u63A8\u9001\u5931\u8D25\u6570\u636E\uFF08\u79C1\u6709\u4F7F\u7528\uFF09\n await this.pushFailed(error, {\n failedStep: stepName,\n failedKey: failedKey,\n errorMessage: error.message,\n errorStack: error.stack,\n screenshotBase64: screenshotBase64\n });\n\n // \u6839\u636E failActor \u51B3\u5B9A\u662F\u5426\u8C03\u7528 Actor.fail\n if (failActor) {\n await Actor.fail(`Run Step ${stepName} \u5931\u8D25: ${error.message}`);\n } else {\n // \u4E0D\u8C03\u7528 Actor.fail\uFF0C\u76F4\u63A5\u629B\u51FA\u9519\u8BEF\n throw error;\n }\n }\n },\n\n /**\n * \u5BBD\u677E\u7248runStep\uFF1A\u5931\u8D25\u65F6\u4E0D\u8C03\u7528Actor.fail\uFF0C\u53EA\u629B\u51FA\u5F02\u5E38\n */\n async runStepLoose(stepName, page, fn) {\n return await this.runStep(stepName, page, fn, { failActor: false });\n },\n\n /**\n * \u63A8\u9001\u6210\u529F\u6570\u636E\u7684\u901A\u7528\u65B9\u6CD5\n * @param {Object} data - \u8981\u63A8\u9001\u7684\u6570\u636E\u5BF9\u8C61\n */\n async pushSuccess(data) {\n await Actor.pushData({\n code: StatusCode.Success,\n status: Status.Success,\n timestamp: new Date().toISOString(),\n ...data\n });\n logger.success('pushSuccess', 'Data pushed');\n },\n\n /**\n * \u63A8\u9001\u5931\u8D25\u6570\u636E\u7684\u901A\u7528\u65B9\u6CD5\uFF08\u79C1\u6709\u65B9\u6CD5\uFF0C\u4EC5\u4F9BrunStep\u5185\u90E8\u4F7F\u7528\uFF09\n * @param {Error|Object} error - \u9519\u8BEF\u5BF9\u8C61\uFF08\u53EF\u5305\u542B\u5176\u4ED6\u7684\u9519\u8BEF/\u6216\u90E8\u5206\u5904\u7406\u6210\u529F\u7684\u989D\u5916\u4FE1\u606F\uFF09\n * @param {Object} [meta] - \u989D\u5916\u7684\u6570\u636E\uFF08\u5982failedStep, screenshotBase64\u7B49\uFF0C\u4EC5runStep\u4F7F\u7528\uFF09\n * @private\n */\n async pushFailed(error, meta = {}) {\n await Actor.pushData({\n code: StatusCode.Failed,\n status: Status.Failed,\n // \u8FD9\u91CC\u53EF\u80FD\u5E26\u5176\u4ED6\u9519\u8BEF\u4FE1\u606F\n error,\n timestamp: new Date().toISOString(),\n ...meta\n });\n logger.success('pushFailed', 'Error data pushed');\n }\n };\n}\n\n// \u61D2\u52A0\u8F7D\u5355\u4F8B\nlet instance = null;\n\n/**\n * \u83B7\u53D6 ApifyKit \u5B9E\u4F8B\uFF08\u61D2\u52A0\u8F7D\uFF09\n * @returns {Promise<Object>} ApifyKit \u5B9E\u4F8B\n */\nasync function useApifyKit() {\n if (!instance) {\n instance = await createApifyKit();\n }\n return instance;\n}\n\n// \u4E5F\u5BFC\u51FA\u521D\u59CB\u5316\u51FD\u6570\uFF0C\u4F9B\u9700\u8981\u7684\u7528\u6237\u4F7F\u7528\nexport const ApifyKit = {\n useApifyKit\n};\n", "export const ErrorKeygen = {\n NotLogin: 30000001,\n Chaptcha: 30000002,\n}\n\nexport const Status = {\n Success: 'SUCCESS',\n Failed: 'FAILED'\n}\n\nexport const StatusCode = {\n Success: 0,\n Failed: -1\n}\n\nexport const FAILED_KEY_SEPARATOR = '::<@>::';\n\nexport const PresetOfLiveViewKey = 'LIVE_VIEW_SCREENSHOT';\n", "import { log } from 'crawlee';\n\n/**\n * \u521B\u5EFA\u6A21\u5757\u7EA7\u65E5\u5FD7\u5668\n * @param {string} moduleName - \u6A21\u5757\u540D\u79F0\uFF0C\u4F8B\u5982 'Humanize', 'Stealth'\n */\nexport function createLogger(moduleName) {\n const prefix = `[${moduleName}]`;\n\n return {\n /**\n * \u65B9\u6CD5\u5F00\u59CB\u65E5\u5FD7\n * @param {string} methodName - \u65B9\u6CD5\u540D\u79F0\n * @param {string} [params] - \u53C2\u6570\u6458\u8981 (\u53EF\u9009)\n */\n start(methodName, params = '') {\n const paramStr = params ? ` (${params})` : '';\n log.info(`${prefix} \uD83D\uDD37 ${methodName} \u5F00\u59CB${paramStr}`);\n },\n\n /**\n * \u65B9\u6CD5\u6210\u529F\u65E5\u5FD7\n * @param {string} methodName - \u65B9\u6CD5\u540D\u79F0\n * @param {string} [result] - \u7ED3\u679C\u6458\u8981 (\u53EF\u9009)\n */\n success(methodName, result = '') {\n const resultStr = result ? ` (${result})` : '';\n log.info(`${prefix} \u2705 ${methodName} \u5B8C\u6210${resultStr}`);\n },\n\n /**\n * \u65B9\u6CD5\u5931\u8D25\u65E5\u5FD7\n * @param {string} methodName - \u65B9\u6CD5\u540D\u79F0\n * @param {Error|string} error - \u9519\u8BEF\u5BF9\u8C61\u6216\u4FE1\u606F\n */\n fail(methodName, error) {\n const message = error instanceof Error ? error.message : error;\n log.error(`${prefix} \u274C ${methodName} \u5931\u8D25: ${message}`);\n },\n\n /**\n * \u8C03\u8BD5\u65E5\u5FD7\n * @param {string} message - \u8BE6\u60C5\n */\n debug(message) {\n log.debug(`${prefix} \uD83D\uDD39 ${message}`);\n },\n\n /**\n * \u8B66\u544A\u65E5\u5FD7\n * @param {string} message - \u8B66\u544A\u4FE1\u606F\n */\n warn(message) {\n log.warning(`${prefix} \u26A0\uFE0F ${message}`);\n },\n\n /**\n * \u666E\u901A\u4FE1\u606F\u65E5\u5FD7\n * @param {string} message - \u4FE1\u606F\n */\n info(message) {\n log.info(`${prefix} \uD83D\uDCD6 ${message}`);\n }\n };\n}\n", "import { createLogger } from './internal/logger';\n\nconst logger = createLogger('Utils');\n\nexport const Utils = {\n /**\n * \u89E3\u6790 SSE \u6D41\u6587\u672C\n */\n parseSseStream(sseStreamText) {\n const events = [];\n const lines = sseStreamText.split('\\n');\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n try {\n const jsonContent = line.substring(6).trim();\n if (jsonContent && jsonContent !== '[DONE]') {\n events.push(JSON.parse(jsonContent));\n }\n } catch (e) {\n // Ignore lines that are not valid JSON\n }\n }\n }\n logger.success('parseSseStream', `parsed events: ${events.length}`);\n return events;\n },\n\n /**\n * \u89E3\u6790 Cookie \u5B57\u7B26\u4E32\u4E3A Playwright \u683C\u5F0F\u7684 Cookie \u6570\u7EC4\n * @param {string} cookieString - Cookie \u5B57\u7B26\u4E32\n * @param {string} [domain] - Cookie \u57DF\u540D (\u53EF\u9009)\n * @returns {Array} Cookie \u6570\u7EC4\n */\n parseCookies(cookieString, domain) {\n const cookies = [];\n const pairs = cookieString.split(';').map(c => c.trim());\n\n for (const pair of pairs) {\n const [name, ...valueParts] = pair.split('=');\n if (name && valueParts.length > 0) {\n const cookie = {\n name: name.trim(),\n value: valueParts.join('=').trim(),\n path: '/',\n };\n if (domain) {\n cookie.domain = domain;\n }\n cookies.push(cookie);\n }\n }\n logger.success('parseCookies', `parsed ${cookies.length} cookies`);\n return cookies;\n }\n}\n", "import { createLogger } from './internal/logger';\n\nconst logger = createLogger('Stealth');\n\nexport const Stealth = {\n /**\n * \u5173\u952E\u4FEE\u590D\uFF1A\u5C06 Page \u89C6\u53E3\u8C03\u6574\u4E3A\u4E0E\u6D4F\u89C8\u5668\u6307\u7EB9 (window.screen) \u4E00\u81F4\u3002\n * \u9632\u6B62 \"Viewport Mismatch\" \u7C7B\u578B\u7684\u53CD\u722C\u68C0\u6D4B\u3002\n * @param {import('playwright').Page} page \n */\n async syncViewportWithScreen(page) {\n try {\n // \u83B7\u53D6\u6307\u7EB9\u4E2D\u7684\u5C4F\u5E55\u5C3A\u5BF8\n const screen = await page.evaluate(() => ({\n width: window.screen.width,\n height: window.screen.height,\n availWidth: window.screen.availWidth,\n availHeight: window.screen.availHeight,\n }));\n\n // \u8C03\u6574\u89C6\u53E3\n await page.setViewportSize({\n width: screen.width,\n height: screen.height\n });\n\n logger.success('syncViewportWithScreen', `size=${screen.width}x${screen.height}`);\n } catch (e) {\n logger.warn(`syncViewportWithScreen Failed: ${e.message}. Fallback to 1920x1080.`);\n await page.setViewportSize({ width: 1920, height: 1080 });\n }\n },\n\n /**\n * \u786E\u4FDD navigator.webdriver \u9690\u85CF (\u901A\u5E38 Playwright Stealth \u63D2\u4EF6\u5DF2\u5904\u7406\uFF0C\u4F46\u53CC\u91CD\u4FDD\u9669)\n */\n async hideWebdriver(page) {\n await page.addInitScript(() => {\n Object.defineProperty(navigator, 'webdriver', {\n get: () => false,\n });\n });\n logger.success('hideWebdriver');\n },\n\n /**\n * \u901A\u7528\u7684 Playwright \u8D44\u6E90\u62E6\u622A\u5668\uFF0C\u7528\u4E8E\u5C4F\u853D\u4E0D\u5FC5\u8981\u7684\u8D44\u6E90\u4EE5\u52A0\u901F\u52A0\u8F7D\n * @param {import('playwright').Page} page\n * @param {string[]} [resourceTypes] - \u8981\u5C4F\u853D\u7684\u8D44\u6E90\u7C7B\u578B\uFF0C\u9ED8\u8BA4\u4E3A ['font', 'image', 'media']\n */\n async setupBlockingResources(page, resourceTypes = ['font', 'image', 'media']) {\n await page.route('**/*', (route) => {\n const request = route.request();\n const type = request.resourceType();\n if (resourceTypes.includes(type)) {\n return route.abort();\n }\n return route.continue();\n });\n logger.success('setupBlockingResources', `types=[${resourceTypes.join(',')}]`);\n },\n\n /**\n * \u83B7\u53D6\u63A8\u8350\u7684 Stealth \u542F\u52A8\u53C2\u6570\n */\n getStealthLaunchArgs() {\n return [\n '--disable-blink-features=AutomationControlled',\n '--no-sandbox',\n '--disable-setuid-sandbox',\n '--disable-infobars',\n '--window-position=0,0',\n '--ignore-certificate-errors',\n '--disable-web-security',\n // \u6CE8\u610F\uFF1A\u4E0D\u5EFA\u8BAE\u8FD9\u91CC\u5F3A\u5236\u6307\u5B9A window-size\uFF0C\u8BA9 syncViewportWithScreen \u53BB\u52A8\u6001\u8C03\u6574\n // '--window-size=1920,1080' \n ];\n },\n\n /**\n * \u83B7\u53D6\u589E\u5F3A\u7248 Stealth \u542F\u52A8\u53C2\u6570 (\u63A8\u8350\u7528\u4E8E\u9AD8\u98CE\u9669\u53CD\u722C\u573A\u666F)\n * \u5305\u542B\u66F4\u591A\u9488\u5BF9\u81EA\u52A8\u5316\u68C0\u6D4B\u7684\u9632\u62A4\n */\n getAdvancedStealthArgs() {\n return [\n ...this.getStealthLaunchArgs(),\n // \u7981\u7528\u5404\u79CD\u53EF\u80FD\u66B4\u9732\u81EA\u52A8\u5316\u7684\u7279\u5F81\n '--disable-dev-shm-usage',\n '--disable-accelerated-2d-canvas',\n '--disable-gpu-sandbox',\n '--disable-background-networking',\n '--disable-default-apps',\n '--disable-extensions',\n '--disable-sync',\n '--disable-translate',\n '--metrics-recording-only',\n '--mute-audio',\n '--no-first-run',\n // \u6A21\u62DF\u771F\u5B9E\u7528\u6237\u914D\u7F6E\n '--lang=zh-CN,zh',\n ];\n },\n\n /**\n * \u8BBE\u7F6E\u4E2D\u56FD\u65F6\u533A (Asia/Shanghai, UTC+8)\n * \n * \u9632\u6B62\u65F6\u533A\u4E0D\u4E00\u81F4\u7684\u68C0\u6D4B\u3002\u5BF9\u4E8E\u4E2D\u56FD\u5883\u5185\u722C\u53D6\u5F3A\u70C8\u63A8\u8350\u4F7F\u7528\u3002\n * \u5E94\u5728 preNavigationHooks \u6216 BrowserContext \u521B\u5EFA\u540E\u8C03\u7528\u3002\n * \n * @param {import('playwright').BrowserContext} context\n */\n async setChinaTimezone(context) {\n // Playwright \u901A\u8FC7 context \u8BBE\u7F6E\u65F6\u533A\n // \u6CE8\u610F\uFF1A\u8FD9\u9700\u8981\u5728 context \u521B\u5EFA\u65F6\u8BBE\u7F6E\uFF0C\u6216\u8005\u4F7F\u7528 CDP\n // \u8FD9\u91CC\u4F7F\u7528 addInitScript \u6CE8\u5165 Intl \u8986\u76D6\n await context.addInitScript(() => {\n // \u8986\u76D6 Intl.DateTimeFormat \u9ED8\u8BA4\u65F6\u533A\n const originalDateTimeFormat = Intl.DateTimeFormat;\n Intl.DateTimeFormat = function (locales, options) {\n options = options || {};\n options.timeZone = options.timeZone || 'Asia/Shanghai';\n return new originalDateTimeFormat(locales, options);\n };\n Intl.DateTimeFormat.prototype = originalDateTimeFormat.prototype;\n\n // \u8986\u76D6 Date.prototype.getTimezoneOffset \u8FD4\u56DE -480 (UTC+8)\n Date.prototype.getTimezoneOffset = function () {\n return -480; // UTC+8 = -480 \u5206\u949F\n };\n });\n logger.success('setChinaTimezone', 'Asia/Shanghai (UTC+8)');\n }\n}\n", "import delay from 'delay';\nimport { createCursor } from 'ghost-cursor-playwright';\nimport { createLogger } from './internal/logger';\n\nconst logger = createLogger('Humanize');\n\n// \u5185\u90E8 cursor \u5B9E\u4F8B\u7F13\u5B58 (\u6BCF\u4E2A page \u4E00\u4E2A) - \u4E0D\u5BF9\u5916\u66B4\u9732\nconst $CursorWeakMap = new WeakMap();\n\n/**\n * \u5185\u90E8\u65B9\u6CD5\uFF1A\u83B7\u53D6\u9875\u9762\u7684 cursor\uFF0C\u5982\u679C\u4E0D\u5B58\u5728\u5219\u629B\u51FA\u9519\u8BEF\n */\nfunction $GetCursor(page) {\n const cursor = $CursorWeakMap.get(page);\n if (!cursor) {\n throw new Error('Cursor \u672A\u521D\u59CB\u5316\uFF0C\u8BF7\u5148\u8C03\u7528 Humanize.initializeCursor(page)');\n }\n return cursor;\n}\n\nexport const Humanize = {\n /**\n * \u751F\u6210\u5E26\u6296\u52A8\u7684\u6BEB\u79D2\u6570 - \u57FA\u4E8E\u57FA\u7840\u503C\u6DFB\u52A0\u968F\u673A\u6D6E\u52A8 (\u00B130% \u9ED8\u8BA4)\n * @param {number} base - \u57FA\u7840\u5EF6\u8FDF (ms)\n * @param {number} [jitterPercent=0.3] - \u6296\u52A8\u767E\u5206\u6BD4 (0.3 = \u00B130%)\n * @returns {number} \u6296\u52A8\u540E\u7684\u6BEB\u79D2\u6570\n */\n jitterMs(base, jitterPercent = 0.3) {\n const jitter = base * jitterPercent * (Math.random() * 2 - 1);\n return Math.max(10, Math.round(base + jitter));\n },\n\n /**\n * \u521D\u59CB\u5316\u9875\u9762\u7684 Ghost Cursor\uFF08\u5FC5\u987B\u5728\u4F7F\u7528\u5176\u4ED6 cursor \u76F8\u5173\u65B9\u6CD5\u524D\u8C03\u7528\uFF09\n * \n * @param {import('playwright').Page} page\n * @returns {Promise<void>}\n */\n async initializeCursor(page) {\n if ($CursorWeakMap.has(page)) {\n logger.debug('initializeCursor: cursor already exists, skipping');\n return;\n }\n logger.start('initializeCursor', 'creating cursor');\n const cursor = await createCursor(page);\n $CursorWeakMap.set(page, cursor);\n logger.success('initializeCursor', 'cursor initialized');\n },\n\n /**\n * \u4EBA\u7C7B\u5316\u9F20\u6807\u79FB\u52A8 - \u4F7F\u7528 ghost-cursor \u79FB\u52A8\u5230\u6307\u5B9A\u4F4D\u7F6E\u6216\u5143\u7D20\n * \n * @param {import('playwright').Page} page\n * @param {string|{x: number, y: number}|import('playwright').ElementHandle} target - CSS\u9009\u62E9\u5668\u3001\u5750\u6807\u5BF9\u8C61\u6216\u5143\u7D20\u53E5\u67C4\n */\n async humanMove(page, target) {\n const cursor = $GetCursor(page);\n logger.start('humanMove', `target=${typeof target === 'string' ? target : 'element/coords'}`);\n try {\n if (typeof target === 'string') {\n // CSS \u9009\u62E9\u5668\n const element = await page.$(target);\n if (!element) {\n logger.warn(`humanMove: \u5143\u7D20\u4E0D\u5B58\u5728 ${target}`);\n return false;\n }\n const box = await element.boundingBox();\n if (!box) {\n logger.warn(`humanMove: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E ${target}`);\n return false;\n }\n const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.2;\n const y = box.y + box.height / 2 + (Math.random() - 0.5) * box.height * 0.2;\n await cursor.actions.move({ x, y });\n } else if (target && typeof target.x === 'number' && typeof target.y === 'number') {\n // \u5750\u6807\u5BF9\u8C61\n await cursor.actions.move(target);\n } else if (target && typeof target.boundingBox === 'function') {\n // ElementHandle\n const box = await target.boundingBox();\n if (box) {\n const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.2;\n const y = box.y + box.height / 2 + (Math.random() - 0.5) * box.height * 0.2;\n await cursor.actions.move({ x, y });\n }\n }\n logger.success('humanMove');\n return true;\n } catch (error) {\n logger.fail('humanMove', error);\n throw error;\n }\n },\n\n /**\n * \u4EBA\u7C7B\u5316\u70B9\u51FB - \u4F7F\u7528 ghost-cursor \u6A21\u62DF\u4EBA\u7C7B\u9F20\u6807\u79FB\u52A8\u8F68\u8FF9\u5E76\u70B9\u51FB\n * \n * @param {import('playwright').Page} page\n * @param {string|import('playwright').ElementHandle} target - CSS \u9009\u62E9\u5668\u6216\u5143\u7D20\u53E5\u67C4\n * @param {Object} [options]\n * @param {number} [options.reactionDelay=250] - \u53CD\u5E94\u5EF6\u8FDF\u57FA\u7840\u503C (ms)\uFF0C\u5B9E\u9645 \u00B130% \u6296\u52A8\n * @param {boolean} [options.throwOnMissing=true] - \u5143\u7D20\u4E0D\u5B58\u5728\u65F6\u662F\u5426\u629B\u51FA\u9519\u8BEF\n */\n async humanClick(page, target, options = {}) {\n const cursor = $GetCursor(page);\n const { reactionDelay = 250, throwOnMissing = true } = options;\n logger.start('humanClick', `target=${typeof target === 'string' ? target : 'ElementHandle'}`);\n\n try {\n let element;\n if (typeof target === 'string') {\n element = await page.$(target);\n if (!element) {\n if (throwOnMissing) {\n throw new Error(`\u627E\u4E0D\u5230\u5143\u7D20 ${target}`);\n }\n logger.warn(`humanClick: \u5143\u7D20\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u70B9\u51FB ${target}`);\n return false;\n }\n } else {\n element = target;\n }\n\n const box = await element.boundingBox();\n if (!box) {\n if (throwOnMissing) {\n throw new Error('\u65E0\u6CD5\u83B7\u53D6\u5143\u7D20\u4F4D\u7F6E');\n }\n logger.warn('humanClick: \u65E0\u6CD5\u83B7\u53D6\u4F4D\u7F6E\uFF0C\u8DF3\u8FC7\u70B9\u51FB');\n return false;\n }\n\n // \u8BA1\u7B97\u5E26\u968F\u673A\u504F\u79FB\u7684\u70B9\u51FB\u4F4D\u7F6E\n const x = box.x + box.width / 2 + (Math.random() - 0.5) * box.width * 0.3;\n const y = box.y + box.height / 2 + (Math.random() - 0.5) * box.height * 0.3;\n\n await cursor.actions.move({ x, y });\n // \u4EBA\u7C7B\u53CD\u5E94\u5EF6\u8FDF (150-400ms \u8303\u56F4)\n await delay(this.jitterMs(reactionDelay, 0.4));\n await cursor.actions.click();\n\n logger.success('humanClick');\n return true;\n } catch (error) {\n logger.fail('humanClick', error);\n throw error;\n }\n },\n\n /**\n * \u968F\u673A\u5EF6\u8FDF\u4E00\u6BB5\u6BEB\u79D2\u6570\uFF08\u5E26 \u00B130% \u6296\u52A8\uFF09\n * @param {number} baseMs - \u57FA\u7840\u5EF6\u8FDF\u6BEB\u79D2\u6570\n * @param {number} [jitterPercent=0.3] - \u6296\u52A8\u767E\u5206\u6BD4\n */\n async randomSleep(baseMs, jitterPercent = 0.3) {\n const ms = this.jitterMs(baseMs, jitterPercent);\n logger.start('randomSleep', `base=${baseMs}, actual=${ms}ms`);\n await delay(ms);\n logger.success('randomSleep');\n },\n\n /**\n * \u6A21\u62DF\u4EBA\u7C7B\"\u6CE8\u89C6\"\u6216\"\u9605\u8BFB\"\u884C\u4E3A\uFF1A\u9F20\u6807\u5728\u9875\u9762\u4E0A\u968F\u673A\u5FAE\u52A8\n * @param {import('playwright').Page} page\n * @param {number} [baseDurationMs=2500] - \u57FA\u7840\u6301\u7EED\u65F6\u95F4 (\u00B140% \u6296\u52A8)\n */\n async simulateGaze(page, baseDurationMs = 2500) {\n const cursor = $GetCursor(page);\n const durationMs = this.jitterMs(baseDurationMs, 0.4);\n logger.start('simulateGaze', `duration=${durationMs}ms`);\n const startTime = Date.now();\n const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };\n\n while (Date.now() - startTime < durationMs) {\n // \u5728\u89C6\u53E3\u8303\u56F4\u5185\u968F\u673A\u79FB\u52A8\n const x = 100 + Math.random() * (viewportSize.width - 200);\n const y = 100 + Math.random() * (viewportSize.height - 200);\n await cursor.actions.move({ x, y });\n // \u6CE8\u89C6\u505C\u7559 300-1200ms\n await delay(this.jitterMs(600, 0.5));\n }\n logger.success('simulateGaze');\n },\n\n /**\n * \u4EBA\u7C7B\u5316\u8F93\u5165 - \u5E26\u8282\u594F\u53D8\u5316\uFF08\u5FEB-\u6162-\u505C\u987F-\u5076\u5C14\u52A0\u901F\uFF09\n * @param {import('playwright').Page} page\n * @param {string} selector - \u8F93\u5165\u6846\u9009\u62E9\u5668\n * @param {string} text - \u8981\u8F93\u5165\u7684\u6587\u672C\n * @param {Object} [options] \n * @param {number} [options.baseDelay=180] - \u57FA\u7840\u6309\u952E\u5EF6\u8FDF (ms)\uFF0C\u5B9E\u9645 \u00B140% \u6296\u52A8\n * @param {number} [options.pauseProbability=0.08] - \u505C\u987F\u6982\u7387 (0-1)\n * @param {number} [options.pauseBase=800] - \u505C\u987F\u65F6\u957F\u57FA\u7840\u503C (ms)\uFF0C\u5B9E\u9645 \u00B150% \u6296\u52A8\n */\n async humanType(page, selector, text, options = {}) {\n logger.start('humanType', `selector=${selector}, textLen=${text.length}`);\n const {\n baseDelay = 180,\n pauseProbability = 0.08,\n pauseBase = 800\n } = options;\n\n try {\n const locator = page.locator(selector);\n await locator.click();\n // \u70B9\u51FB\u540E\u601D\u8003\u5EF6\u8FDF\n await delay(this.jitterMs(200, 0.4));\n\n for (let i = 0; i < text.length; i++) {\n const char = text[i];\n let charDelay;\n\n if (char === ' ') {\n // \u7A7A\u683C\u952E\u7A0D\u5FEB\n charDelay = this.jitterMs(baseDelay * 0.6, 0.3);\n } else if (/[,.!?;:\uFF0C\u3002\uFF01\uFF1F\uFF1B\uFF1A]/.test(char)) {\n // \u6807\u70B9\u7B26\u53F7\u540E\u7A0D\u6162\uFF08\u6A21\u62DF\u601D\u8003\uFF09\n charDelay = this.jitterMs(baseDelay * 1.5, 0.4);\n } else {\n // \u666E\u901A\u5B57\u7B26\n charDelay = this.jitterMs(baseDelay, 0.4);\n }\n\n await page.keyboard.type(char);\n await delay(charDelay);\n\n // \u968F\u673A\u505C\u987F\uFF08\u6A21\u62DF\u601D\u8003/\u56DE\u987E\uFF09\n if (Math.random() < pauseProbability && i < text.length - 1) {\n const pauseTime = this.jitterMs(pauseBase, 0.5);\n logger.debug(`\u505C\u987F ${pauseTime}ms...`);\n await delay(pauseTime);\n }\n }\n logger.success('humanType');\n } catch (error) {\n logger.fail('humanType', error);\n throw error;\n }\n },\n\n /**\n * \u4EBA\u7C7B\u5316\u6E05\u7A7A\u8F93\u5165\u6846 - \u6A21\u62DF\u4EBA\u7C7B\u5220\u9664\u6587\u672C\u7684\u884C\u4E3A\n * @param {import('playwright').Page} page\n * @param {string} selector - \u8F93\u5165\u6846\u9009\u62E9\u5668\n */\n async humanClear(page, selector) {\n logger.start('humanClear', `selector=${selector}`);\n try {\n const locator = page.locator(selector);\n await locator.click();\n await delay(this.jitterMs(200, 0.4));\n\n const currentValue = await locator.inputValue();\n if (!currentValue || currentValue.length === 0) {\n logger.success('humanClear', 'already empty');\n return;\n }\n\n // \u5168\u9009 + \u5220\u9664\n await page.keyboard.press('Meta+A');\n await delay(this.jitterMs(100, 0.4));\n await page.keyboard.press('Backspace');\n\n logger.success('humanClear');\n } catch (error) {\n logger.fail('humanClear', error);\n throw error;\n }\n },\n\n /**\n * \u9875\u9762\u9884\u70ED\u6D4F\u89C8 - \u6A21\u62DF\u4EBA\u7C7B\u8FDB\u5165\u9875\u9762\u540E\u7684\u63A2\u7D22\u884C\u4E3A\n * @param {import('playwright').Page} page\n * @param {number} [baseDuration=3500] - \u9884\u70ED\u65F6\u957F\u57FA\u7840\u503C (\u00B140% \u6296\u52A8)\n */\n async warmUpBrowsing(page, baseDuration = 3500) {\n const cursor = $GetCursor(page);\n const durationMs = this.jitterMs(baseDuration, 0.4);\n\n logger.start('warmUpBrowsing', `duration=${durationMs}ms`);\n const startTime = Date.now();\n const viewportSize = page.viewportSize() || { width: 1920, height: 1080 };\n\n try {\n while (Date.now() - startTime < durationMs) {\n const action = Math.random();\n\n if (action < 0.4) {\n // \u9F20\u6807\u79FB\u52A8\n const x = 100 + Math.random() * (viewportSize.width - 200);\n const y = 100 + Math.random() * (viewportSize.height - 200);\n await cursor.actions.move({ x, y });\n await delay(this.jitterMs(350, 0.4));\n } else if (action < 0.7) {\n // \u6EDA\u52A8\n const scrollY = (Math.random() - 0.5) * 200;\n await page.mouse.wheel(0, scrollY);\n await delay(this.jitterMs(500, 0.4));\n } else {\n // \u505C\u987F/\u6CE8\u89C6\n await delay(this.jitterMs(800, 0.5));\n }\n }\n logger.success('warmUpBrowsing');\n } catch (error) {\n logger.fail('warmUpBrowsing', error);\n throw error;\n }\n },\n\n /**\n * \u81EA\u7136\u6EDA\u52A8 - \u5E26\u60EF\u6027\u3001\u51CF\u901F\u6548\u679C\u548C\u968F\u673A\u6296\u52A8\n * @param {import('playwright').Page} page\n * @param {'up' | 'down'} [direction='down'] - \u6EDA\u52A8\u65B9\u5411\n * @param {number} [distance=300] - \u603B\u6EDA\u52A8\u8DDD\u79BB\u57FA\u7840\u503C (px)\uFF0C\u00B115% \u6296\u52A8\n * @param {number} [baseSteps=5] - \u5206\u51E0\u6B65\u5B8C\u6210\u57FA\u7840\u503C\uFF0C\u00B11 \u968F\u673A\n */\n async naturalScroll(page, direction = 'down', distance = 300, baseSteps = 5) {\n // steps \u52A0\u968F\u673A\u6D6E\u52A8 \u00B11\n const steps = Math.max(3, baseSteps + Math.floor(Math.random() * 3) - 1);\n // distance \u52A0\u6296\u52A8\n const actualDistance = this.jitterMs(distance, 0.15);\n\n logger.start('naturalScroll', `dir=${direction}, dist=${actualDistance}, steps=${steps}`);\n const sign = direction === 'down' ? 1 : -1;\n const stepDistance = actualDistance / steps;\n\n try {\n for (let i = 0; i < steps; i++) {\n // \u60EF\u6027\u51CF\u901F\u56E0\u5B50\n const factor = 1 - (i / steps) * 0.5;\n // \u6BCF\u6B65\u52A0 \u00B110% \u6296\u52A8\n const jitter = 0.9 + Math.random() * 0.2;\n const scrollAmount = stepDistance * factor * sign * jitter;\n\n await page.mouse.wheel(0, scrollAmount);\n\n // \u5EF6\u8FDF\u4E5F\u5E26\u6296\u52A8\n const baseDelay = 60 + i * 25;\n await delay(this.jitterMs(baseDelay, 0.3));\n }\n logger.success('naturalScroll');\n } catch (error) {\n logger.fail('naturalScroll', error);\n throw error;\n }\n }\n}\n", "// \u96C6\u4E2D\u7BA1\u7406\u542F\u52A8\u914D\u7F6E\uFF0C\u6682\u65F6\u4E3B\u8981\u7531 Stealth \u6A21\u5757\u63D0\u4F9B Args\uFF0C\u8FD9\u91CC\u4F5C\u4E3A\u6269\u5C55\u70B9\nimport { Stealth } from './stealth';\nimport { createLogger } from './internal/logger';\n\nconst logger = createLogger('Launch');\n\nexport const Launch = {\n getLaunchOptions(customArgs = []) {\n return {\n args: [\n ...Stealth.getStealthLaunchArgs(),\n ...customArgs\n ],\n ignoreDefaultArgs: ['--enable-automation'],\n };\n },\n\n /**\n * \u83B7\u53D6\u589E\u5F3A\u7248\u542F\u52A8\u9009\u9879\uFF08\u7528\u4E8E\u9AD8\u98CE\u9669\u53CD\u722C\u573A\u666F\uFF09\n */\n getAdvancedLaunchOptions(customArgs = []) {\n return {\n args: [\n ...Stealth.getAdvancedStealthArgs(),\n ...customArgs\n ],\n ignoreDefaultArgs: ['--enable-automation'],\n };\n },\n\n /**\n * \u63A8\u8350\u7684 Fingerprint Generator \u9009\u9879\n * \u786E\u4FDD\u751F\u6210\u7684\u662F\u684C\u9762\u7AEF\u3001\u8F83\u65B0\u7684 Chrome\uFF0C\u4EE5\u5339\u914D\u6211\u4EEC\u7684\u811A\u672C\u903B\u8F91\n */\n getFingerprintGeneratorOptions() {\n return {\n browsers: [{ name: 'chrome', minVersion: 110 }],\n devices: ['desktop'],\n operatingSystems: ['windows', 'linux'], // \u5305\u542B Linux \u517C\u5BB9\u5BB9\u5668\n };\n },\n\n /**\n * \u521B\u5EFA\u5DF2\u6CE8\u518C Stealth \u63D2\u4EF6\u7684 Chromium \u5B9E\u4F8B\n * \n * \u5C01\u88C5\u4E86 `chromium.use(stealthPlugin())` \u7684\u5E38\u7528\u6A21\u5F0F\n * \n * @example\n * ```javascript\n * import { chromium } from 'playwright-extra';\n * import stealthPlugin from 'puppeteer-extra-plugin-stealth';\n * \n * const stealthChromium = Launch.createStealthChromium(chromium, stealthPlugin);\n * // \u73B0\u5728 stealthChromium \u5DF2\u6CE8\u518C stealth \u63D2\u4EF6\uFF0C\u53EF\u7528\u4E8E launchContext.launcher\n * ```\n * \n * @param {import('playwright-extra').ChromiumExtra} chromium - playwright-extra \u7684 chromium\n * @param {Function} stealthPlugin - puppeteer-extra-plugin-stealth \u7684\u9ED8\u8BA4\u5BFC\u51FA\n * @returns {import('playwright-extra').ChromiumExtra} \u5DF2\u6CE8\u518C stealth \u7684 chromium\n */\n createStealthChromium(chromium, stealthPlugin) {\n chromium.use(stealthPlugin());\n logger.success('createStealthChromium', 'Stealth plugin registered');\n return chromium;\n }\n}\n\n", "import express from 'express';\nimport { Actor } from 'apify';\nimport { PresetOfLiveViewKey } from './constants';\nimport { createLogger } from './internal/logger';\n\nconst logger = createLogger('LiveView');\n\n/**\n * \u542F\u52A8\u4E00\u4E2A Web \u670D\u52A1\u5668\u4EE5\u5728 Live View \u9009\u9879\u5361\u4E2D\u663E\u793A\u6700\u65B0\u7684\u5C4F\u5E55\u622A\u56FE\u3002\n */\nasync function startLiveViewServer(liveViewKey) {\n const app = express();\n\n app.get('/', async (req, res) => {\n try {\n // \u4ECE\u9ED8\u8BA4\u7684 Key-Value Store \u4E2D\u8BFB\u53D6\u6700\u65B0\u7684\u5C4F\u5E55\u622A\u56FE\n const screenshotBuffer = await Actor.getValue(liveViewKey);\n\n if (!screenshotBuffer) {\n // \u5982\u679C\u8FD8\u6CA1\u6709\u622A\u56FE\uFF0C\u53D1\u9001\u4E00\u4E2A\u81EA\u52A8\u5237\u65B0\u7684\u5360\u4F4D\u9875\u9762\n res.send('<html><head><meta http-equiv=\"refresh\" content=\"2\"></head><body>\u7B49\u5F85\u7B2C\u4E00\u4E2A\u5C4F\u5E55\u622A\u56FE...</body></html>');\n return;\n }\n\n // \u5C06 Buffer \u8F6C\u6362\u4E3A Base64 \u5B57\u7B26\u4E32\n const screenshotBase64 = screenshotBuffer.toString('base64');\n\n // \u53D1\u9001\u4E00\u4E2A HTML \u9875\u9762\uFF0C\u8BE5\u9875\u9762\u6BCF 1 \u79D2\u81EA\u52A8\u5237\u65B0\u4E00\u6B21\uFF0C\u5E76\u663E\u793A\u622A\u56FE\n res.send(`\n <html>\n <head>\n <title>Live View (\u622A\u56FE)</title>\n <meta http-equiv=\"refresh\" content=\"1\">\n </head>\n <body style=\"margin:0; padding:0;\">\n <img src=\"data:image/png;base64,${screenshotBase64}\" \n alt=\"Live View Screenshot\" \n style=\"width: 100%; height: auto;\" />\n </body>\n </html>\n `);\n } catch (error) {\n logger.fail('Live View Server', error);\n res.status(500).send(`\u65E0\u6CD5\u52A0\u8F7D\u5C4F\u5E55\u622A\u56FE: ${error.message}`);\n }\n });\n\n // \u76D1\u542C Apify \u5BB9\u5668\u7AEF\u53E3 \n const port = process.env.APIFY_CONTAINER_PORT || 4321;\n app.listen(port, () => { logger.success('startLiveViewServer', `\u76D1\u542C\u7AEF\u53E3 ${port}`); });\n}\n\n/**\n * \u62CD\u6444\u5F53\u524D\u9875\u9762\u7684\u5C4F\u5E55\u622A\u56FE\u5E76\u5C06\u5176\u4FDD\u5B58\u5230 Key-Value Store\u3002\n * @param {import('playwright').Page} page\n * @param {string} [logMessage] - \u53EF\u9009\u7684\u65E5\u5FD7\u6D88\u606F\u3002\n */\nasync function takeLiveScreenshot(liveViewKey, page, logMessage) {\n try {\n const buffer = await page.screenshot({ type: 'png' });\n await Actor.setValue(liveViewKey, buffer, { contentType: 'image/png' });\n if (logMessage) {\n logger.info(`(\u622A\u56FE): ${logMessage}`);\n }\n } catch (e) {\n logger.warn(`\u65E0\u6CD5\u6355\u83B7 Live View \u5C4F\u5E55\u622A\u56FE: ${e.message}`);\n }\n}\n\nconst useLiveView = (liveViewKey = PresetOfLiveViewKey) => {\n return {\n takeLiveScreenshot: async (page, logMessage) => {\n return await takeLiveScreenshot(liveViewKey, page, logMessage)\n },\n startLiveViewServer: async () => {\n return await startLiveViewServer(liveViewKey);\n }\n }\n}\n\nexport const LiveView = {\n useLiveView,\n};\n", "import { createLogger } from './internal/logger';\n\nconst logger = createLogger('Captcha');\n\n/**\n * \u521B\u5EFA\u9A8C\u8BC1\u7801\u76D1\u63A7\u5668 - \u652F\u6301 DOM \u9009\u62E9\u5668 \u548C URL \u6A21\u5F0F \u4E24\u79CD\u68C0\u6D4B\u65B9\u5F0F\n * \n * \u6CE8\u610F\uFF1A\u76D1\u63A7\u5668\u968F\u9875\u9762\u751F\u547D\u5468\u671F\u81EA\u52A8\u6E05\u7406\uFF0C\u65E0\u9700\u624B\u52A8 cleanup\n * \n * @param {import('playwright').Page} page\n * @param {Object} options\n * @param {string} [options.domSelector] - DOM \u5143\u7D20\u9009\u62E9\u5668 (\u5982 '#captcha_container')\n * @param {string} [options.urlPattern] - URL \u5339\u914D\u6A21\u5F0F (\u5982 '/captcha')\n * @param {Function} options.onDetected - \u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\u65F6\u7684\u56DE\u8C03 (async function)\n */\nexport function useCaptchaMonitor(page, options) {\n const { domSelector, urlPattern, onDetected } = options;\n\n if (!domSelector && !urlPattern) {\n throw new Error('[CaptchaMonitor] \u5FC5\u987B\u63D0\u4F9B domSelector \u6216 urlPattern \u81F3\u5C11\u4E00\u4E2A');\n }\n\n if (!onDetected || typeof onDetected !== 'function') {\n throw new Error('[CaptchaMonitor] onDetected \u5FC5\u987B\u662F\u4E00\u4E2A\u51FD\u6570');\n }\n\n let isHandled = false;\n let frameHandler = null;\n let exposedFunctionName = null;\n\n const triggerDetected = async () => {\n if (isHandled) return;\n isHandled = true;\n logger.fail('Captcha Detected', '\uD83D\uDED1 \u68C0\u6D4B\u5230\u9A8C\u8BC1\u7801\uFF01');\n await onDetected();\n };\n\n // ============================================================\n // \u6A21\u5F0F1: DOM \u76D1\u63A7 (\u4F7F\u7528 MutationObserver)\n // ============================================================\n if (domSelector) {\n // \u751F\u6210\u552F\u4E00\u7684\u51FD\u6570\u540D\u907F\u514D\u51B2\u7A81\n exposedFunctionName = `__c_d_${Date.now()}`;\n\n // \u66B4\u9732\u56DE\u8C03\u51FD\u6570\u7ED9\u9875\u9762\n page.exposeFunction(exposedFunctionName, triggerDetected).catch(() => {\n // \u5FFD\u7565\u91CD\u590D\u66B4\u9732\u9519\u8BEF\n });\n\n // \u6CE8\u5165 MutationObserver \u76D1\u542C\u811A\u672C\n page.addInitScript(({ selector, callbackName }) => {\n (() => {\n let observer = null;\n\n const checkAndReport = () => {\n const element = document.querySelector(selector);\n if (element) {\n if (observer) {\n observer.disconnect();\n observer = null;\n }\n if (window[callbackName]) {\n window[callbackName]();\n }\n return true;\n }\n return false;\n };\n\n // 1. \u7ACB\u5373\u68C0\u67E5\u4E00\u6B21\n if (checkAndReport()) return;\n\n // 2. \u542F\u52A8 MutationObserver\n observer = new MutationObserver((mutations) => {\n let shouldCheck = false;\n for (const mutation of mutations) {\n if (mutation.addedNodes.length > 0) {\n shouldCheck = true;\n break;\n }\n }\n if (shouldCheck && observer) {\n checkAndReport();\n }\n });\n\n // 3. \u6302\u8F7D\u76D1\u542C\uFF08\u786E\u4FDD DOM \u51C6\u5907\u5C31\u7EEA\uFF09\n const mountObserver = () => {\n const target = document.documentElement;\n if (target && observer) {\n observer.observe(target, { childList: true, subtree: true });\n }\n };\n\n if (document.readyState === 'loading') {\n window.addEventListener('DOMContentLoaded', mountObserver);\n } else {\n mountObserver();\n }\n })();\n }, { selector: domSelector, callbackName: exposedFunctionName });\n\n logger.success('useCaptchaMonitor', `DOM \u76D1\u63A7\u5DF2\u542F\u7528: ${domSelector}`);\n }\n\n // ============================================================\n // \u6A21\u5F0F2: URL \u76D1\u63A7 (\u76D1\u542C framenavigated)\n // ============================================================\n if (urlPattern) {\n frameHandler = async (frame) => {\n if (frame === page.mainFrame()) {\n const currentUrl = page.url();\n if (currentUrl.includes(urlPattern)) {\n await triggerDetected();\n }\n }\n };\n\n page.on('framenavigated', frameHandler);\n logger.success('useCaptchaMonitor', `URL \u76D1\u63A7\u5DF2\u542F\u7528: ${urlPattern}`);\n }\n\n // \u6CE8\u610F\uFF1A\u4E0D\u63D0\u4F9B cleanup \u51FD\u6570\n // - DOM \u6A21\u5F0F\uFF1AaddInitScript \u6CE8\u5165\u7684\u4EE3\u7801\u65E0\u6CD5\u4ECE Node \u7AEF\u6E05\u7406\n // - URL \u6A21\u5F0F\uFF1Aframenavigated \u76D1\u542C\u901A\u5E38\u8DDF\u968F\u9875\u9762\u751F\u547D\u5468\u671F\uFF0C\u65E0\u9700\u624B\u52A8\u6E05\u7406\n // \u5982\u679C\u9700\u8981\u63D0\u524D\u7EC8\u6B62\u76D1\u63A7\uFF0C\u8BBE\u8BA1\u4E0A\u5E94\u8BE5\u8BA9 onDetected \u5904\u7406\u540E\u7EED\u903B\u8F91\uFF08\u5982 Actor.fail\uFF09\n}\n\n// \u6309\u7167 toolkit \u7EDF\u4E00\u7684\u5BFC\u51FA\u6A21\u5F0F\nexport const Captcha = {\n useCaptchaMonitor\n};\n", "import { ApifyKit } from './src/apify-kit';\nimport { Utils } from './src/utils';\nimport { Stealth } from './src/stealth';\nimport { Humanize } from './src/humanize';\nimport { Launch } from './src/launch';\nimport { LiveView } from './src/live-view';\nimport { Captcha } from './src/captcha-monitor';\nimport * as Constants from './src/constants';\n\n// Unified Entry Point\nexport const usePlaywrightToolKit = () => {\n return {\n ApifyKit,\n Stealth,\n Humanize,\n Launch,\n LiveView,\n Constants,\n Utils,\n Captcha\n };\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["Actor", "logger", "logger", "logger", "logger", "logger", "logger"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skrillex1224/playwright-toolkit",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.41",
|
|
4
4
|
"description": "一个在 Apify/Crawlee Actor 中启用实时截图视图的实用工具库。",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -40,7 +40,8 @@
|
|
|
40
40
|
"playwright": "*",
|
|
41
41
|
"playwright-extra": "*",
|
|
42
42
|
"puppeteer-extra-plugin-stealth": "*",
|
|
43
|
-
"ghost-cursor-playwright": "*"
|
|
43
|
+
"ghost-cursor-playwright": "*",
|
|
44
|
+
"delay": "*"
|
|
44
45
|
},
|
|
45
46
|
"devDependencies": {
|
|
46
47
|
"esbuild": "^0.24.2"
|