@skrillex1224/playwright-toolkit 2.1.125 → 2.1.126

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../entrys/node.js", "../src/constants.js", "../src/internals/logger.js", "../src/errors.js", "../src/apify-kit.js", "../src/internals/utils.js", "../src/utils.js", "../src/anti-cheat.js", "../src/humanize.js", "../src/launch.js", "../src/live-view.js", "../src/captcha-monitor.js", "../src/sse.js", "../src/interception.js", "../src/mutation.js", "../src/display.js", "../src/logger.js", "../src/share.js"],
4
- "sourcesContent": ["import { log as crawleeLog } from 'crawlee';\nimport { ApifyKit } from '../src/apify-kit';\nimport { Utils } from '../src/utils';\nimport { AntiCheat } from '../src/anti-cheat';\nimport { Humanize } from '../src/humanize';\nimport { Launch } from '../src/launch';\nimport { LiveView } from '../src/live-view';\nimport { Captcha } from '../src/captcha-monitor';\nimport { Sse } from '../src/sse';\nimport { Interception } from '../src/interception';\nimport { Mutation } from '../src/mutation';\nimport { Display } from '../src/display.js';\nimport * as Constants from '../src/constants';\nimport * as Errors from '../src/errors';\nimport { Logger, LOG_TEMPLATES, stripAnsi } from '../src/logger';\nimport { Share } from '../src/share';\n\n// \u4FEE\u6539\u9ED8\u8BA4logger \u4ECEconsole.log \u5230 crawleeLog\nLogger.setLogger(crawleeLog);\n\n// Unified Entry Point\nexport const usePlaywrightToolKit = () => {\n return {\n ApifyKit,\n AntiCheat,\n Humanize,\n Launch,\n LiveView,\n Constants,\n Utils,\n Captcha,\n Sse,\n Errors,\n Interception,\n Mutation,\n Display,\n Logger,\n Share,\n $Internals: { LOG_TEMPLATES, stripAnsi }\n };\n};\n", "export const Code = {\n Success: 0,\n UnknownError: -1,\n NotLogin: 30000001,\n Chaptcha: 30000002,\n Timeout: 30000003,\n InitialTimeout: 30000004,\n OverallTimeout: 30000005,\n}\n\nexport const Status = {\n Success: 'SUCCESS',\n Failed: 'FAILED'\n}\n\nexport const PresetOfLiveViewKey = 'LIVE_VIEW_SCREENSHOT';\n\n\nconst createActorInfo = (info) => {\n const normalizeDomain = (value) => {\n if (!value) return '';\n return String(value).trim().replace(/^https?:\\/\\//, '').replace(/\\/.*$/, '');\n };\n\n const normalizePath = (value) => {\n if (!value) return '/';\n const raw = String(value).trim();\n if (!raw) return '/';\n return raw.startsWith('/') ? raw : `/${raw}`;\n };\n\n const normalizeShare = (value) => {\n const raw = value && typeof value === 'object' ? value : {};\n\n const modeRaw = String(raw.mode || 'dom').trim().toLowerCase();\n const mode = modeRaw === 'response' ? 'response' : 'dom';\n\n const prefix = String(raw.prefix || '').trim();\n\n const rawXurl = Array.isArray(raw.xurl)\n ? raw.xurl\n : [];\n\n const normalizeMatcherList = (input) => {\n if (Array.isArray(input)) {\n return input\n .map((item) => String(item || '').trim().replace(/\\.+$/, ''))\n .filter(Boolean);\n }\n\n const single = String(input || '').trim().replace(/\\.+$/, '');\n return single ? [single] : [];\n };\n\n const normalizeSegments = (input) => {\n if (Array.isArray(input)) {\n return input\n .map((item) => String(item || '').trim().replace(/\\.+$/, ''))\n .filter(Boolean);\n }\n\n const rawPath = String(input || '').trim();\n if (!rawPath) return [];\n\n return rawPath\n .split('.')\n .map((segment) => String(segment || '').trim().replace(/\\.+$/, ''))\n .filter(Boolean);\n };\n\n const xurl = [];\n\n const matcherList = normalizeMatcherList(rawXurl[0]);\n if (matcherList.length > 0) {\n xurl.push(matcherList);\n }\n\n const flatPath = [];\n const extraPaths = [];\n\n rawXurl.slice(1).forEach((item) => {\n if (Array.isArray(item)) {\n const segments = normalizeSegments(item);\n if (segments.length > 0) {\n extraPaths.push(segments);\n }\n return;\n }\n\n const segments = normalizeSegments(item);\n if (segments.length > 0) {\n flatPath.push(...segments);\n }\n });\n\n if (flatPath.length > 0) {\n xurl.push(flatPath);\n }\n\n if (extraPaths.length > 0) {\n xurl.push(...extraPaths);\n }\n\n return {\n mode,\n prefix,\n xurl,\n };\n };\n\n const buildLandingUrl = ({ protocol, domain, path }) => {\n const safeProtocol = String(protocol).trim();\n const safeDomain = normalizeDomain(domain);\n const safePath = normalizePath(path);\n return `${safeProtocol}://${safeDomain}${safePath}`;\n };\n\n const buildIcon = ({ key }) => {\n return `https://heartbitai.com/general/actors/${key}.png`;\n }\n\n\n const protocol = info.protocol || 'https';\n const domain = normalizeDomain(info.domain);\n const path = normalizePath(info.path);\n const share = normalizeShare(info.share);\n\n return {\n ...info,\n protocol,\n domain,\n path,\n share,\n get icon() {\n if (info.icon) return info.icon;\n return buildIcon(this);\n },\n get landingUrl() {\n return buildLandingUrl(this);\n },\n };\n};\n\nexport const ActorInfo = {\n doubao: createActorInfo({\n key: 'doubao',\n name: '\u8C46\u5305',\n domain: 'www.doubao.com',\n path: '/',\n share: {\n mode: 'response',\n prefix: 'https://www.doubao.com/thread/',\n xurl: [\n '/samantha/thread/share/save',\n 'data', 'share_id',\n ],\n },\n }),\n deepseek: createActorInfo({\n key: 'deepseek',\n name: 'DeepSeek',\n domain: 'chat.deepseek.com',\n path: '/',\n share: {\n mode: 'response',\n prefix: 'https://chat.deepseek.com/share/',\n xurl: [\n '/api/v0/share/create',\n 'data', 'biz_data', 'share_id',\n ],\n },\n }),\n erine: createActorInfo({\n key: 'erine',\n name: '\u6587\u5FC3\u4E00\u8A00',\n domain: 'yiyan.baidu.com',\n path: '/',\n share: {\n mode: 'response',\n prefix: 'https://yiyan.baidu.com/share/',\n xurl: [\n '/eb/share/key/gen',\n 'data', 'key',\n ],\n },\n }),\n erinechat: createActorInfo({\n key: 'erinechat',\n name: '\u6587\u5FC3\u4E00\u8A00Chat',\n domain: 'chat.baidu.com',\n path: '/',\n share: {\n mode: 'response',\n prefix: '',\n xurl: [\n '/aichat/api/shortURL',\n 'data', 'short_url',\n ],\n },\n }),\n yuanbao: createActorInfo({\n key: 'yuanbao',\n name: '\u5143\u5B9D',\n domain: 'yuanbao.tencent.com',\n path: '/chat/',\n share: {\n mode: 'response',\n prefix: 'https://yb.tencent.com/s/',\n xurl: [\n '/api/conversations/v2/share', 'shareId',\n ],\n },\n }),\n kimi: createActorInfo({\n key: 'kimi',\n name: 'Kimi',\n domain: 'www.kimi.com',\n path: '/',\n share: {\n mode: 'response',\n prefix: 'https://www.kimi.com/share/',\n xurl: [\n '/kimi.gateway.chat.v1.ChatService/CreateChatShare', 'share', 'id'\n ],\n },\n }),\n qwen: createActorInfo({\n key: 'qwen',\n name: '\u901A\u4E49\u5343\u95EE',\n domain: 'www.qianwen.com',\n path: '/chat',\n share: {\n mode: 'response',\n prefix: 'https://www.qianwen.com/share/',\n xurl: [\n '/api/v1/share/create', 'data', 'share_id'\n ],\n },\n }),\n}\n", "\n// =============================================================================\n// Core Helpers & State\n// =============================================================================\n\nconst pad = (value, size = 2) => String(value).padStart(size, '0');\n\nconst FORCED_TIMEZONE_OFFSET_MINUTES = -8 * 60;\n\nconst formatTimestamp = (date = new Date()) => {\n const source = date instanceof Date ? date : new Date(date);\n const forcedDate = new Date(source.getTime() - (FORCED_TIMEZONE_OFFSET_MINUTES * 60 * 1000));\n\n const year = forcedDate.getUTCFullYear();\n const month = pad(forcedDate.getUTCMonth() + 1);\n const day = pad(forcedDate.getUTCDate());\n const hours = pad(forcedDate.getUTCHours());\n const minutes = pad(forcedDate.getUTCMinutes());\n const seconds = pad(forcedDate.getUTCSeconds());\n const millis = pad(forcedDate.getUTCMilliseconds(), 3);\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${millis}`;\n};\n\nconst formatLine = (prefix, icon, message) => {\n const parts = [];\n if (prefix) parts.push(`[${prefix}]`);\n if (icon) parts.push(icon);\n if (message) parts.push(message);\n return parts.join(' ').trim();\n};\n\nconst fallbackLog = {\n info: (...args) => console.log(...args),\n warning: (...args) => (console.warn ? console.warn(...args) : console.log(...args)),\n error: (...args) => console.error(...args),\n debug: (...args) => (console.debug ? console.debug(...args) : console.log(...args)),\n};\n\nconst resolveLogMethod = (logger, name) => {\n if (logger && typeof logger[name] === 'function') {\n return logger[name].bind(logger);\n }\n if (name === 'warning' && logger && typeof logger.warn === 'function') {\n return logger.warn.bind(logger);\n }\n return fallbackLog[name];\n};\n\nlet defaultLogger = null;\n\nexport const setDefaultLogger = (logger) => {\n defaultLogger = logger;\n};\n\n// Lazy resolver: always checks current state\nconst resolveLogger = (explicitLogger) => {\n if (explicitLogger && typeof explicitLogger.info === 'function') {\n return explicitLogger;\n }\n if (defaultLogger && typeof defaultLogger.info === 'function') {\n return defaultLogger;\n }\n return fallbackLog;\n};\n\nconst ANSI = {\n reset: '\\x1b[0m',\n gray: '\\x1b[90m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n cyan: '\\x1b[36m',\n};\n\nconst colorize = (text, color) => {\n if (!text || !color) return text;\n return `${color}${text}${ANSI.reset}`;\n};\n\nexport const createBaseLogger = (prefix = '', explicitLogger) => {\n const name = prefix ? String(prefix) : '';\n\n const dispatch = (methodName, icon, message, color) => {\n const logger = resolveLogger(explicitLogger);\n const logFn = resolveLogMethod(logger, methodName);\n const timestamp = colorize(`[${formatTimestamp()}]`, ANSI.gray);\n const line = formatLine(name, icon, message);\n const coloredLine = colorize(line, color);\n logFn(`${timestamp} ${coloredLine}`.trim());\n };\n\n return {\n info: (message) => dispatch('info', '\uD83D\uDCD6', message, ANSI.cyan),\n success: (message) => dispatch('info', '\u2705', message, ANSI.green),\n warning: (message) => dispatch('warning', '\u26A0\uFE0F', message, ANSI.yellow),\n warn: (message) => dispatch('warning', '\u26A0\uFE0F', message, ANSI.yellow),\n error: (message) => dispatch('error', '\u274C', message, ANSI.red),\n debug: (message) => dispatch('debug', '\uD83D\uDD39', message, ANSI.gray),\n start: (message) => dispatch('info', '\uD83D\uDD37', message, ANSI.blue),\n };\n};\n\n/**\n * \u521B\u5EFA\u6A21\u5757\u7EA7\u65E5\u5FD7\u5668\n * @param {string} moduleName - \u6A21\u5757\u540D\u79F0\n * @param {object} [logger] - \u53EF\u9009\u7684\u663E\u5F0F\u65E5\u5FD7\u5668\uFF0C\u901A\u5E38\u4E0D\u9700\u8981\u4F20\uFF0C\u4F1A\u81EA\u52A8\u4F7F\u7528 setDefaultLogger \u8BBE\u7F6E\u7684\u5168\u5C40\u65E5\u5FD7\u5668\n */\nexport function createInternalLogger(moduleName, explicitLogger) {\n const baseLogger = createBaseLogger(moduleName, explicitLogger);\n\n return {\n start(methodName, params = '') {\n const paramStr = params ? ` (${params})` : '';\n baseLogger.start(`${methodName} \u5F00\u59CB${paramStr}`);\n },\n success(methodName, result = '') {\n const resultStr = result ? ` (${result})` : '';\n baseLogger.success(`${methodName} \u5B8C\u6210${resultStr}`);\n },\n fail(methodName, error) {\n const message = error instanceof Error ? error.message : error;\n baseLogger.error(`${methodName} \u5931\u8D25: ${message}`);\n },\n debug(message) {\n baseLogger.debug(message);\n },\n warn(message) {\n baseLogger.warning(message);\n },\n warning(message) {\n baseLogger.warning(message);\n },\n info(message) {\n baseLogger.info(message);\n }\n };\n}\n", "/**\n * \u722C\u866B\u81EA\u5B9A\u4E49\u9519\u8BEF\u7C7B\n * \u7528\u4E8E\u643A\u5E26\u4E0A\u4E0B\u6587\u4FE1\u606F\uFF0C\u5728 pushFailed \u65F6\u81EA\u52A8\u89E3\u6790\n */\n\nimport { serializeError } from \"serialize-error\";\nimport { Code } from \"./constants\";\n\n/**\n * CrawlerError - \u81EA\u5B9A\u4E49\u722C\u866B\u9519\u8BEF\u7C7B\n * \n * @example\n * // \u7B80\u5355\u7528\u6CD5 (\u53EA\u6709 message)\n * throw new CrawlerError('\u672A\u6355\u83B7 Feed \u63A5\u53E3\u54CD\u5E94');\n * \n * @example\n * // \u5B8C\u6574\u7528\u6CD5 (\u5E26 code \u548C context)\n * throw new CrawlerError({\n * message: '\u767B\u5F55\u5931\u8D25',\n * code: ErrorKeygen.NotLogin,\n * context: { url: currentUrl, userId: '123' }\n * });\n */\nexport class CrawlerError extends Error {\n /**\n * @param {string|Object} info - \u9519\u8BEF\u4FE1\u606F\u5B57\u7B26\u4E32\u6216\u914D\u7F6E\u5BF9\u8C61\n * @param {string} info.message - \u9519\u8BEF\u4FE1\u606F\n * @param {number} [info.code] - ErrorKeygen \u679A\u4E3E\u503C\uFF08\u7528\u4E8E\u9519\u8BEF\u5206\u7C7B\uFF09\n * @param {Object} [info.context] - \u4E0A\u4E0B\u6587\u4FE1\u606F\u5BF9\u8C61\n */\n constructor(info) {\n // \u517C\u5BB9 string\n if (typeof info === 'string') {\n info = { message: info };\n }\n\n // \u26A0\uFE0F super() \u5FC5\u987B\u5728\u8BBF\u95EE this \u4E4B\u524D\u8C03\u7528\n super(info.message);\n\n this.name = 'CrawlerError';\n this.code = info.code ?? Code.UnknownError;\n this.context = info.context ?? {};\n this.timestamp = new Date().toISOString();\n\n // \u7EF4\u62A4\u6B63\u786E\u7684\u5806\u6808\u8DDF\u8E2A\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, CrawlerError);\n }\n }\n\n /**\n * \u8F6C\u6362\u4E3A\u53EF\u63A8\u9001\u7684\u6570\u636E\u5BF9\u8C61\n * @returns {Object}\n */\n toJSON() {\n return serializeError(this)\n }\n\n /**\n * \u68C0\u67E5\u4E00\u4E2A error \u662F\u5426\u662F CrawlerError\n * @param {Error} error\n * @returns {boolean}\n */\n static isCrawlerError(error) {\n return error instanceof CrawlerError || error?.name === 'CrawlerError';\n }\n\n /**\n * \u4ECE\u666E\u901A Error \u521B\u5EFA CrawlerError\n * @param {Error} error - \u539F\u59CB\u9519\u8BEF\n * @param {Object} [options={}] - \u9009\u9879\u5BF9\u8C61 (\u5305\u542B code \u548C context)\n * @returns {CrawlerError}\n */\n static from(error, options = {}) {\n const crawlerError = new CrawlerError({\n message: error.message,\n ...options\n });\n crawlerError.stack = error.stack;\n return crawlerError;\n }\n}\n\n\n", "import { Status, Code } from './constants';\nimport { createInternalLogger } from './internals/logger';\nimport { CrawlerError } from './errors';\nimport { serializeError } from 'serialize-error';\n\nconst logger = createInternalLogger('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 * \u6838\u5FC3\u5C01\u88C5\uFF1A\u6267\u884C\u6B65\u9AA4\uFF0C\u5E26\u81EA\u52A8\u65E5\u5FD7\u786E\u8BA4\u3001\u5931\u8D25\u622A\u56FE\u5904\u7406\u548C\u91CD\u8BD5\u673A\u5236\n * \n * @param {string} step - \u6B65\u9AA4\u540D\u79F0\n * @param {import('playwright').Page} page - Playwright page \u5BF9\u8C61\n * @param {Function} actionFn - \u6267\u884C\u7684\u5F02\u6B65\u64CD\u4F5C\n * @param {Object} [options] - \u914D\u7F6E\u9009\u9879\n * @param {boolean} [options.failActor=true] - \u5931\u8D25\u65F6\u662F\u5426\u8C03\u7528 Actor.fail\n * @param {Object} [options.retry] - \u91CD\u8BD5\u914D\u7F6E\n * @param {number} [options.retry.times=0] - \u91CD\u8BD5\u6B21\u6570\n * @param {'direct'|'refresh'} [options.retry.mode='direct'] - \u91CD\u8BD5\u6A21\u5F0F\n * @param {Function} [options.retry.before] - \u91CD\u8BD5\u524D\u94A9\u5B50\uFF0C\u53EF\u8986\u76D6\u9ED8\u8BA4\u7B49\u5F85\u884C\u4E3A\n */\n async runStep(step, page, actionFn, options = {}) {\n const { failActor = true, retry = {} } = options;\n const { times: retryTimes = 0, mode: retryMode = 'direct', before: beforeRetry } = retry;\n\n // \u5185\u90E8\u6267\u884C\u51FD\u6570\n const executeAction = async (attemptNumber) => {\n const attemptLabel = attemptNumber > 0 ? ` (\u91CD\u8BD5 #${attemptNumber})` : '';\n logger.start(`[Step] ${step}${attemptLabel}`);\n\n try {\n const result = await actionFn();\n logger.success(`[Step] ${step}${attemptLabel}`);\n return { success: true, result };\n } catch (error) {\n logger.fail(`[Step] ${step}${attemptLabel}`, error);\n return { success: false, error };\n }\n };\n\n // \u91CD\u8BD5\u524D\u7684\u51C6\u5907\u64CD\u4F5C\n const prepareForRetry = async (attemptNumber) => {\n if (typeof beforeRetry === 'function') {\n // \u4F7F\u7528\u81EA\u5B9A\u4E49\u94A9\u5B50\n logger.start(`[RetryStep] \u6267\u884C\u81EA\u5B9A\u4E49 before \u94A9\u5B50 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);\n await beforeRetry(page, attemptNumber);\n logger.success(`[RetryStep] before \u94A9\u5B50\u5B8C\u6210`);\n } else if (retryMode === 'refresh') {\n // \u5237\u65B0\u6A21\u5F0F\uFF1A\u5237\u65B0\u9875\u9762\u5E76\u7B49\u5F85 DOMContentLoaded\n logger.start(`[RetryStep] \u5237\u65B0\u9875\u9762 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);\n await page.reload({ waitUntil: 'domcontentloaded' });\n logger.success(`[RetryStep] \u9875\u9762\u5237\u65B0\u5B8C\u6210`);\n } else {\n // direct \u6A21\u5F0F\uFF1A\u9ED8\u8BA4\u7B49\u5F85 3 \u79D2\n logger.start(`[RetryStep] \u7B49\u5F85 3 \u79D2 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);\n await new Promise(resolve => setTimeout(resolve, 3000));\n logger.success(`[RetryStep] \u7B49\u5F85\u5B8C\u6210`);\n }\n };\n\n // \u9996\u6B21\u6267\u884C\n let lastResult = await executeAction(0);\n\n // \u5982\u679C\u9996\u6B21\u6210\u529F\uFF0C\u76F4\u63A5\u8FD4\u56DE\n if (lastResult.success) {\n return lastResult.result;\n }\n\n // \u91CD\u8BD5\u903B\u8F91\n for (let attempt = 1; attempt <= retryTimes; attempt++) {\n logger.start(`[RetryStep] \u51C6\u5907\u7B2C ${attempt}/${retryTimes} \u6B21\u91CD\u8BD5: ${step}`);\n\n try {\n await prepareForRetry(attempt);\n } catch (prepareError) {\n logger.warn(`[RetryStep] \u91CD\u8BD5\u51C6\u5907\u5931\u8D25: ${prepareError.message}`);\n // \u51C6\u5907\u5931\u8D25\uFF0C\u7EE7\u7EED\u5C1D\u8BD5\u4E0B\u4E00\u6B21\u91CD\u8BD5\n continue;\n }\n\n lastResult = await executeAction(attempt);\n if (lastResult.success) {\n return lastResult.result;\n }\n }\n\n // \u6240\u6709\u91CD\u8BD5\u90FD\u5931\u8D25\uFF0C\u5904\u7406\u6700\u7EC8\u9519\u8BEF\n const finalError = lastResult.error;\n if (failActor) {\n let base64 = '\u622A\u56FE\u5931\u8D25';\n try {\n if (page) {\n const buffer = await page.screenshot({ fullPage: true, type: 'jpeg', quality: 60 });\n base64 = `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 await this.pushFailed(finalError, {\n step,\n page,\n options,\n base64,\n retryAttempts: retryTimes\n });\n await Actor.fail(`Run Step ${step} \u5931\u8D25 (\u5DF2\u91CD\u8BD5 ${retryTimes} \u6B21): ${finalError.message}`);\n } else {\n throw finalError;\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(step, page, fn) {\n return await this.runStep(step, 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 // \u56FA\u5B9A\u4E3A0\n code: Code.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 * \u81EA\u52A8\u89E3\u6790 CrawlerError \u7684 code \u548C context\n * @param {Error|CrawlerError} error - \u9519\u8BEF\u5BF9\u8C61\n * @param {Object} [meta] - \u989D\u5916\u7684\u6570\u636E\uFF08\u5982failedStep, screenshotBase64\u7B49\uFF09\n * @private\n */\n async pushFailed(error, meta = {}) {\n // \u5982\u679C\u662F CrawlerError\uFF0C\u63D0\u53D6\u5176 key \u548C context\n const isCrawlerError = CrawlerError.isCrawlerError(error);\n const code = isCrawlerError ? error.code : Code.UnknownError;\n const context = isCrawlerError ? error.context : {};\n\n await Actor.pushData({\n // \u5982\u679C\u662F CrawlerError\uFF0C\u4F7F\u7528\u5176 code\uFF0C\u5426\u5219\u4F7F\u7528\u9ED8\u8BA4 Failed code\n code,\n status: Status.Failed,\n error: serializeError(error),\n meta,\n context,\n timestamp: new Date().toISOString(),\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", "import { createInternalLogger } from './logger.js';\n\nconst logger = createInternalLogger('InternalUtils');\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 */\nexport const 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", "import { createInternalLogger } from './internals/logger.js';\nimport { parseCookies as internalParseCookies } from './internals/utils.js';\nimport delay from 'delay';\n\nconst logger = createInternalLogger('Utils');\n\nexport const Utils = {\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 return internalParseCookies(cookieString, domain);\n },\n\n /**\n * \u4ECE\u5B57\u7B26\u4E32\u4E2D\u63D0\u53D6 URL \u94FE\u63A5\n * @param {string} text\n * @param {Object} [options]\n * @param {string} [options.prefix] - \u4EC5\u8FD4\u56DE\u6B64\u524D\u7F00\u5F00\u5934\uFF0C\u4E14\u524D\u7F00\u540E\u81F3\u5C11 1 \u4F4D\u5B57\u7B26\u7684\u94FE\u63A5\n * @returns {string[]}\n */\n parseLinks(text, options = {}) {\n const raw = String(text || '');\n if (!raw) return [];\n\n const opts = options && typeof options === 'object' ? options : {};\n const prefix = String(opts.prefix || '').trim();\n\n const matched = raw.match(/https?:\\/\\/[\\w\\-._~:/?#[\\]@!$&'()*+,;=%]+/g) || [];\n const unique = new Set();\n\n for (const item of matched) {\n const link = String(item || '').trim().replace(/[\"'\u201C\u201D\u2018\u2019>\\].,\uFF0C\u3002\uFF1B;!\uFF01?\uFF1F]+$/, '');\n if (!link || !/^https?:\\/\\//i.test(link)) continue;\n\n if (prefix) {\n if (!link.startsWith(prefix)) continue;\n if (link.length <= prefix.length) continue;\n }\n\n unique.add(link);\n }\n\n return Array.from(unique);\n },\n\n /**\n * \u5168\u9875\u9762\u6EDA\u52A8\u622A\u56FE\n * \u81EA\u52A8\u68C0\u6D4B\u9875\u9762\u6240\u6709\u53EF\u6EDA\u52A8\u5143\u7D20\uFF0C\u53D6\u6700\u5927\u9AD8\u5EA6\uFF0C\u5F3A\u5236\u5C55\u5F00\u540E\u622A\u56FE\n * \n * @param {import('playwright').Page} page - Playwright page \u5BF9\u8C61\n * @param {Object} [options] - \u914D\u7F6E\u9009\u9879\n * @param {number} [options.buffer] - \u989D\u5916\u7F13\u51B2\u9AD8\u5EA6 (\u9ED8\u8BA4: \u89C6\u53E3\u9AD8\u5EA6\u7684\u4E00\u534A)\n * @param {boolean} [options.restore] - \u622A\u56FE\u540E\u662F\u5426\u6062\u590D\u9875\u9762\u9AD8\u5EA6\u548C\u6837\u5F0F (\u9ED8\u8BA4: false)\n * @param {number} [options.maxHeight] - \u6700\u5927\u622A\u56FE\u9AD8\u5EA6 (\u9ED8\u8BA4: 8000px)\n * @returns {Promise<string>} - base64 \u7F16\u7801\u7684 PNG \u56FE\u7247\n */\n async fullPageScreenshot(page, options = {}) {\n logger.start('fullPageScreenshot', 'detecting scrollable elements');\n const originalViewport = page.viewportSize();\n const defaultBuffer = Math.round((originalViewport?.height || 1080) / 2);\n const buffer = options.buffer ?? defaultBuffer;\n const restore = options.restore ?? false;\n const maxHeight = options.maxHeight ?? 8000;\n\n try {\n // 1. \u81EA\u52A8\u627E\u51FA\u6240\u6709\u53EF\u6EDA\u52A8\u5143\u7D20\u5E76\u5C55\u5F00\uFF0C\u8FD4\u56DE\u6700\u5927\u9AD8\u5EA6\n const maxScrollHeight = await page.evaluate(() => {\n let maxHeight = document.body.scrollHeight;\n\n document.querySelectorAll('*').forEach(el => {\n const style = window.getComputedStyle(el);\n const overflowY = style.overflowY;\n\n if ((overflowY === 'auto' || overflowY === 'scroll') &&\n el.scrollHeight > el.clientHeight) {\n if (el.scrollHeight > maxHeight) {\n maxHeight = el.scrollHeight;\n }\n\n // Save original styles\n el.dataset.pkOrigOverflow = el.style.overflow;\n el.dataset.pkOrigHeight = el.style.height;\n el.dataset.pkOrigMaxHeight = el.style.maxHeight;\n el.classList.add('__pk_expanded__');\n\n el.style.overflow = 'visible';\n el.style.height = 'auto';\n el.style.maxHeight = 'none';\n }\n });\n\n return maxHeight;\n });\n\n // 2. \u8BA1\u7B97\u6700\u7EC8\u9AD8\u5EA6 (\u5E94\u7528 maxHeight \u9650\u5236)\n const targetHeight = Math.min(maxScrollHeight + buffer, maxHeight);\n\n // 3. \u8C03\u6574\u89C6\u53E3\u9AD8\u5EA6\n await page.setViewportSize({\n width: originalViewport?.width || 1280,\n height: targetHeight\n });\n\n // \u7B49\u5F85\u6E32\u67D3\n await delay(1000);\n\n // 4. \u622A\u56FE\n const buffer_ = await page.screenshot({\n fullPage: true,\n type: 'png'\n });\n\n logger.success('fullPageScreenshot', `captured ${Math.round(buffer_.length / 1024)} KB`);\n return buffer_.toString('base64');\n } finally {\n // \u4EC5\u5728 restore=true \u65F6\u6062\u590D\u6837\u5F0F\u548C\u89C6\u53E3\n if (restore) {\n await page.evaluate(() => {\n document.querySelectorAll('.__pk_expanded__').forEach(el => {\n el.style.overflow = el.dataset.pkOrigOverflow || '';\n el.style.height = el.dataset.pkOrigHeight || '';\n el.style.maxHeight = el.dataset.pkOrigMaxHeight || '';\n\n delete el.dataset.pkOrigOverflow;\n delete el.dataset.pkOrigHeight;\n delete el.dataset.pkOrigMaxHeight;\n el.classList.remove('__pk_expanded__');\n });\n });\n\n if (originalViewport) {\n await page.setViewportSize(originalViewport);\n }\n }\n }\n }\n}\n", "import { createInternalLogger } from './internals/logger';\n\nconst logger = createInternalLogger('AntiCheat');\n\nconst BASE_CONFIG = Object.freeze({\n locale: 'zh-CN',\n acceptLanguage: 'zh-CN,zh;q=0.9',\n timezoneId: 'Asia/Shanghai',\n timezoneOffset: -480,\n geolocation: null,\n});\n\n// \u6700\u5C0F\u5316\u542F\u52A8\u53C2\u6570\uFF0C\u4F9D\u8D56 Crawlee/Playwright \u9ED8\u8BA4\u884C\u4E3A\nconst DEFAULT_LAUNCH_ARGS = [\n // '--disable-blink-features=AutomationControlled', // Crawlee \u53EF\u80FD\u4F1A\u81EA\u52A8\u5904\u7406\uFF0C\u8FC7\u591A\u5E72\u9884\u53CD\u800C\u4F1A\u88AB\u8BC6\u522B\n '--no-sandbox',\n '--disable-setuid-sandbox',\n '--window-position=0,0',\n `--lang=${BASE_CONFIG.locale}`,\n];\n\nfunction buildFingerprintOptions(locale) {\n return {\n browsers: [{ name: 'chrome', minVersion: 110 }],\n devices: ['desktop'],\n operatingSystems: ['windows', 'macos', 'linux'],\n locales: [locale],\n };\n}\n\nexport const AntiCheat = {\n /**\n * \u83B7\u53D6\u7EDF\u4E00\u7684\u57FA\u7840\u914D\u7F6E\n */\n getBaseConfig() {\n return { ...BASE_CONFIG };\n },\n\n /**\n * \u7528\u4E8E Crawlee fingerprint generator \u7684\u7EDF\u4E00\u914D\u7F6E\uFF08\u684C\u9762\u7AEF\uFF09\u3002\n */\n getFingerprintGeneratorOptions() {\n return buildFingerprintOptions(BASE_CONFIG.locale);\n },\n\n /**\n * \u83B7\u53D6\u57FA\u7840\u542F\u52A8\u53C2\u6570\u3002\n */\n getLaunchArgs() {\n return [...DEFAULT_LAUNCH_ARGS];\n },\n\n /**\n * \u4E3A got-scraping \u751F\u6210\u4E0E\u6D4F\u89C8\u5668\u4E00\u81F4\u7684 TLS \u6307\u7EB9\u914D\u7F6E\uFF08\u684C\u9762\u7AEF\uFF09\u3002\n */\n getTlsFingerprintOptions(userAgent = '', acceptLanguage = '') {\n // \u7B80\u5316\u903B\u8F91\uFF0C\u4E0D\u518D\u89E3\u6790 acceptLanguage\uFF0C\u4EC5\u63D0\u4F9B\u57FA\u7840\u6307\u7EB9\u914D\u7F6E\n return buildFingerprintOptions(BASE_CONFIG.locale);\n },\n\n /**\n * \u89C4\u8303\u5316\u8BF7\u6C42\u5934\n */\n applyLocaleHeaders(headers, acceptLanguage = '') {\n if (!headers['accept-language']) {\n headers['accept-language'] = acceptLanguage || BASE_CONFIG.acceptLanguage;\n }\n return headers;\n },\n};\n", "import delay from 'delay';\nimport { createCursor } from 'ghost-cursor-playwright';\nimport { createInternalLogger } from './internals/logger.js';\n\nconst logger = createInternalLogger('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 * \u6E10\u8FDB\u5F0F\u6EDA\u52A8\u5230\u5143\u7D20\u53EF\u89C1\uFF08\u4EC5\u5904\u7406 Y \u8F74\u6EDA\u52A8\uFF09\n * \u8FD4\u56DE restore \u65B9\u6CD5\uFF0C\u7528\u4E8E\u5C06\u6EDA\u52A8\u5BB9\u5668\u6062\u590D\u5230\u539F\u4F4D\u7F6E\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.maxSteps=14] - \u6700\u5927\u6EDA\u52A8\u6B65\u6570\n * @param {number} [options.minStep=260] - \u5355\u6B21\u6EDA\u52A8\u6700\u5C0F\u6B65\u957F\n * @param {number} [options.maxStep=800] - \u5355\u6B21\u6EDA\u52A8\u6700\u5927\u6B65\u957F\n * @param {number} [options.maxDurationMs] - \u6700\u957F\u8017\u65F6\u4E0A\u9650 (\u9ED8\u8BA4\u968F maxSteps \u4F30\u7B97)\n */\n async humanScroll(page, target, options = {}) {\n const {\n maxSteps = 14,\n minStep = 260,\n maxStep = 800,\n maxDurationMs = maxSteps * 220 + 800\n } = options;\n const targetDesc = typeof target === 'string' ? target : 'ElementHandle';\n\n logger.start('humanScroll', `target=${targetDesc}`);\n\n let element;\n if (typeof target === 'string') {\n element = await page.$(target);\n if (!element) {\n logger.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${target}`);\n return { element: null, didScroll: false };\n }\n } else {\n element = target;\n }\n\n const cursor = $GetCursor(page);\n let didScroll = false;\n\n // \u8F85\u52A9\u51FD\u6570\uFF1A\u68C0\u67E5\u53EF\u89C1\u6027\u548C\u906E\u6321\n const checkVisibility = async () => {\n return await element.evaluate((el) => {\n const rect = el.getBoundingClientRect();\n if (!rect || rect.width === 0 || rect.height === 0) {\n return { code: 'ZERO_DIMENSIONS', reason: '\u5C3A\u5BF8\u4E3A\u96F6' };\n }\n\n const cx = rect.left + rect.width / 2;\n const cy = rect.top + rect.height / 2;\n const viewH = window.innerHeight;\n const viewW = window.innerWidth;\n let isFixed = false;\n\n for (let node = el; node && node !== document.body; node = node.parentElement) {\n const style = window.getComputedStyle(node);\n if (style && style.position === 'fixed') {\n isFixed = true;\n break;\n }\n }\n\n // 1. \u68C0\u67E5\u662F\u5426\u5728\u51E0\u4F55\u89C6\u53E3\u5185\n if (cy < 0 || cy > viewH || cx < 0 || cx > viewW) {\n // \u8BA1\u7B97\u6240\u9700\u65B9\u5411\n const direction = cy < 0 ? 'up' : (cy > viewH ? 'down' : 'unknown');\n return { code: 'OUT_OF_VIEWPORT', reason: '\u4E0D\u5728\u89C6\u53E3\u5185', direction, cy, viewH, isFixed };\n }\n\n // 2. \u68C0\u67E5\u906E\u6321\n const pointElement = document.elementFromPoint(cx, cy);\n if (pointElement && !el.contains(pointElement) && !pointElement.contains(el)) {\n return {\n code: 'OBSTRUCTED',\n reason: '\u88AB\u906E\u6321',\n obstruction: {\n tag: pointElement.tagName,\n id: pointElement.id,\n className: pointElement.className\n },\n cy, // Return Center Y for smart direction calculation\n viewH,\n isFixed\n };\n }\n\n return { code: 'VISIBLE', isFixed };\n });\n };\n\n const getScrollableRect = async () => {\n return await element.evaluate((el) => {\n const isScrollable = (node) => {\n const style = window.getComputedStyle(node);\n if (!style) return false;\n const overflowY = style.overflowY;\n if (!['auto', 'scroll', 'overlay'].includes(overflowY)) return false;\n return node.scrollHeight > node.clientHeight + 1;\n };\n\n let current = el;\n while (current && current !== document.body) {\n if (isScrollable(current)) {\n const rect = current.getBoundingClientRect();\n if (rect && rect.width > 0 && rect.height > 0) {\n return { x: rect.x, y: rect.y, width: rect.width, height: rect.height };\n }\n }\n current = current.parentElement;\n }\n\n return null;\n });\n };\n\n const startTime = Date.now();\n\n try {\n for (let i = 0; i < maxSteps; i++) {\n if (Date.now() - startTime > maxDurationMs) {\n logger.warn(`humanScroll | \u8D85\u65F6\u4FDD\u62A4\u89E6\u53D1 (${maxDurationMs}ms)`);\n return { element, didScroll };\n }\n\n const status = await checkVisibility();\n\n if (status.code === 'VISIBLE') {\n if (status.isFixed) {\n logger.info('humanScroll | fixed \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8');\n } else {\n logger.debug('humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321');\n }\n logger.success('humanScroll', didScroll ? '\u5DF2\u6EDA\u52A8' : '\u65E0\u9700\u6EDA\u52A8');\n return { element, didScroll };\n }\n\n logger.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason} ${status.direction ? `(${status.direction})` : ''}`);\n\n if (status.code === 'OBSTRUCTED' && status.obstruction) {\n logger.debug(`humanScroll | \u88AB\u4EE5\u4E0B\u5143\u7D20\u906E\u6321 <${status.obstruction.tag} id=\"${status.obstruction.id}\">`);\n }\n\n const scrollRect = await getScrollableRect();\n if (!scrollRect && status.isFixed) {\n logger.warn('humanScroll | fixed \u5BB9\u5668\u5185\u4E14\u65E0\u53EF\u6EDA\u52A8\u7956\u5148\uFF0C\u8DF3\u8FC7\u6EDA\u52A8');\n return { element, didScroll };\n }\n\n const stepMin = scrollRect ? Math.min(minStep, Math.max(60, scrollRect.height * 0.4)) : minStep;\n const stepMax = scrollRect ? Math.min(maxStep, Math.max(stepMin + 40, scrollRect.height * 0.8)) : maxStep;\n\n // \u786E\u5B9A\u6EDA\u52A8\u65B9\u5411\u548C\u8DDD\u79BB\n let deltaY = 0;\n if (status.code === 'OUT_OF_VIEWPORT') {\n if (status.direction === 'down') {\n deltaY = stepMin + Math.random() * (stepMax - stepMin);\n } else if (status.direction === 'up') {\n deltaY = -(stepMin + Math.random() * (stepMax - stepMin));\n } else {\n // \u6C34\u5E73\u95EE\u9898\u6216\u5947\u602A\u72B6\u6001\uFF0C\u5C1D\u8BD5\u5411\u4E0B\u6EDA\u52A8\u4E00\u70B9\n deltaY = 100;\n }\n } else if (status.code === 'OBSTRUCTED') {\n // \u667A\u80FD\u907F\u8BA9\u906E\u6321\n // \u5982\u679C\u5143\u7D20\u5728\u89C6\u53E3\u4E0B\u534A\u90E8\u5206\u88AB\u906E\u6321\uFF0C\u901A\u5E38\u662F\u88AB\u5E95\u90E8\u56FA\u5B9A\u5143\u7D20\uFF08\u5982 Footer\uFF09\u906E\u6321 -> \u9700\u8981\u5411\u4E0B\u6EDA\u52A8\u66F4\u591A\uFF08\u5185\u5BB9\u4E0A\u79FB\uFF09\n // \u5982\u679C\u5143\u7D20\u5728\u89C6\u53E3\u4E0A\u534A\u90E8\u5206\u88AB\u906E\u6321\uFF0C\u901A\u5E38\u662F\u88AB\u9876\u90E8\u56FA\u5B9A\u5143\u7D20\uFF08\u5982 Header\uFF09\u906E\u6321 -> \u9700\u8981\u5411\u4E0A\u6EDA\u52A8\u66F4\u591A\uFF08\u5185\u5BB9\u4E0B\u79FB\uFF09\n const halfY = scrollRect ? (scrollRect.y + scrollRect.height / 2) : (status.viewH / 2);\n const isBottomHalf = status.cy > halfY;\n const direction = isBottomHalf ? 1 : -1;\n\n // \u57FA\u7840\u6EDA\u52A8\u91CF + \u968F\u673A\u6CE2\u52A8\n deltaY = direction * (stepMin + Math.random() * 50);\n }\n\n // \u5C06\u9F20\u6807\u79FB\u52A8\u5230\u53EF\u6EDA\u52A8\u5BB9\u5668\uFF08\u4F18\u5148\uFF09\uFF0C\u5426\u5219\u79FB\u52A8\u5230\u89C6\u53E3\u4E2D\u5FC3\n if (i === 0) {\n const viewSize = page.viewportSize();\n if (scrollRect) {\n const safeX = scrollRect.x + scrollRect.width * 0.5 + (Math.random() - 0.5) * Math.min(80, scrollRect.width * 0.4);\n const safeY = scrollRect.y + scrollRect.height * 0.5 + (Math.random() - 0.5) * Math.min(80, scrollRect.height * 0.4);\n await cursor.actions.move({ x: safeX, y: safeY });\n } else if (viewSize) {\n const safeX = viewSize.width * 0.5 + (Math.random() - 0.5) * 80;\n const safeY = viewSize.height * 0.5 + (Math.random() - 0.5) * 80;\n await cursor.actions.move({ x: safeX, y: safeY });\n }\n }\n\n // \u6267\u884C\u6EDA\u52A8\n await page.mouse.wheel(0, deltaY);\n didScroll = true;\n\n // \u7B49\u5F85\u6EDA\u52A8\u7A33\u5B9A - \u7D27\u51D1\u8282\u594F (20ms - 60ms)\n await delay(this.jitterMs(20 + Math.random() * 40, 0.2));\n }\n\n logger.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);\n return { element, didScroll };\n\n } catch (error) {\n logger.fail('humanScroll', 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\u3002\u5982\u679C\u4E3A\u7A7A\uFF0C\u5219\u70B9\u51FB\u5F53\u524D\u9F20\u6807\u4F4D\u7F6E\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 * @param {boolean} [options.scrollIfNeeded=true] - \u5143\u7D20\u4E0D\u5728\u89C6\u53E3\u65F6\u662F\u5426\u81EA\u52A8\u6EDA\u52A8\n */\n async humanClick(page, target, options = {}) {\n const cursor = $GetCursor(page);\n\n // \u589E\u52A0 restore \u9009\u9879\uFF0C\u9ED8\u8BA4 false (\u4E0D\u8FD8\u539F\u6EDA\u52A8\u4F4D\u7F6E)\n const { reactionDelay = 250, throwOnMissing = true, scrollIfNeeded = true, restore = false } = options;\n\n const targetDesc = target == null ? 'Current Position' : (typeof target === 'string' ? target : 'ElementHandle');\n logger.start('humanClick', `target=${targetDesc}`);\n\n\n const restoreOnce = async () => {\n if (restoreOnce.restored) return;\n restoreOnce.restored = true;\n\n if (typeof restoreOnce.do !== 'function') return;\n try {\n await delay(this.jitterMs(1000));\n await restoreOnce.do();\n } catch (restoreError) {\n logger.warn(`humanClick: \u6062\u590D\u6EDA\u52A8\u4F4D\u7F6E\u5931\u8D25: ${restoreError.message}`);\n }\n };\n\n\n try {\n // Case 1: \u70B9\u51FB\u5F53\u524D\u4F4D\u7F6E (target \u4E3A null/undefined)\n if (target == null) {\n // \u4EC5\u6267\u884C\u53CD\u5E94\u5EF6\u8FDF + \u70B9\u51FB\n await delay(this.jitterMs(reactionDelay, 0.4));\n await cursor.actions.click();\n logger.success('humanClick', 'Clicked current position');\n return true;\n }\n\n // Case 2: \u70B9\u51FB\u6307\u5B9A\u76EE\u6807\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 if (scrollIfNeeded) {\n const { restore: restoreFn, didScroll } = await this.humanScroll(page, element);\n // \u4EC5\u5728 didScroll \u4E3A true \u4E14 options.restore \u4E3A true \u65F6\u624D\u8FD8\u539F\n restoreOnce.do = (didScroll && restore) ? restoreFn : null;\n }\n\n const box = await element.boundingBox();\n if (!box) {\n await restoreOnce();\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 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 delay(this.jitterMs(reactionDelay, 0.4));\n await cursor.actions.click();\n\n await restoreOnce();\n\n logger.success('humanClick');\n return true;\n } catch (error) {\n await restoreOnce();\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 Humanize.humanClick(page, locator);\n\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\u53CD\u722C\u53C2\u6570\u4E0E\u6307\u7EB9\u914D\u7F6E\u7EDF\u4E00\u7531 AntiCheat \u63D0\u4F9B\nimport { AntiCheat } from './anti-cheat';\n\nexport const Launch = {\n getLaunchOptions(customArgs = []) {\n return {\n args: [\n ...AntiCheat.getLaunchArgs(),\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 AntiCheat.getFingerprintGeneratorOptions();\n },\n};\n", "import express from 'express';\nimport { Actor } from 'apify';\nimport { PresetOfLiveViewKey } from './constants';\nimport { createInternalLogger } from './internals/logger';\n\nconst logger = createInternalLogger('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 { v4 as uuidv4 } from 'uuid';\nimport { createInternalLogger } from './internals/logger';\n\nconst logger = createInternalLogger('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 await onDetected();\n };\n\n const cleanupFns = [];\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_${uuidv4().replace(/-/g, '_')}`;\n // \u751F\u6210\u552F\u4E00\u7684\u6E05\u7406\u51FD\u6570\u540D (\u6302\u8F7D\u5728 window \u4E0A)\n const cleanerName = `__c_cleaner_${uuidv4().replace(/-/g, '_')}`;\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, cleanerName }) => {\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 // 4. \u6CE8\u518C\u6E05\u7406\u51FD\u6570\n window[cleanerName] = () => {\n if (observer) {\n observer.disconnect();\n observer = null;\n }\n };\n })();\n }, { selector: domSelector, callbackName: exposedFunctionName, cleanerName });\n\n logger.success('useCaptchaMonitor', `DOM \u76D1\u63A7\u5DF2\u542F\u7528: ${domSelector}`);\n\n // \u6DFB\u52A0\u6E05\u7406\u903B\u8F91\n cleanupFns.push(async () => {\n try {\n // \u8C03\u7528\u9875\u9762\u5185\u7684\u6E05\u7406\u51FD\u6570\n await page.evaluate((name) => {\n if (window[name]) {\n window[name]();\n delete window[name];\n }\n }, cleanerName);\n } catch (e) {\n // \u9875\u9762\u53EF\u80FD\u5DF2\u5173\u95ED\u6216\u8DF3\u8F6C\uFF0C\u5FFD\u7565\u9519\u8BEF\n }\n });\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 // \u6DFB\u52A0\u6E05\u7406\u903B\u8F91\n cleanupFns.push(async () => {\n page.off('framenavigated', frameHandler);\n });\n }\n\n // \u8FD4\u56DE\u63A7\u5236\u53E5\u67C4\n return {\n stop: async () => {\n logger.info('useCaptchaMonitor', '\u6B63\u5728\u505C\u6B62\u76D1\u63A7...');\n for (const fn of cleanupFns) {\n await fn();\n }\n isHandled = true; // \u9632\u6B62\u540E\u7EED\u89E6\u53D1\n }\n };\n}\n\n// \u6309\u7167 toolkit \u7EDF\u4E00\u7684\u5BFC\u51FA\u6A21\u5F0F\nexport const Captcha = {\n useCaptchaMonitor\n};\n", "import https from 'https';\nimport { URL } from 'url';\nimport { createInternalLogger } from './internals/logger';\nimport { CrawlerError } from './errors';\nimport { Code } from './constants';\n\nconst logger = createInternalLogger('Sse');\n\nexport const Sse = {\n /**\n * \u89E3\u6790 SSE \u6D41\u6587\u672C\n * \u652F\u6301 `data: {...}` \u548C `data:{...}` \u4E24\u79CD\u683C\u5F0F\n * @param {string} sseStreamText\n * @returns {Array<Object>} events\n */\n parseSseStream(sseStreamText) {\n const events = [];\n const lines = sseStreamText.split('\\n');\n for (const line of lines) {\n // \u517C\u5BB9\u4E24\u79CD\u683C\u5F0F: \"data: {...}\" \u548C \"data:{...}\"\n if (line.startsWith('data:')) {\n try {\n // \u79FB\u9664 \"data:\" \u524D\u7F00\u5E76 trim\uFF0C\u7EDF\u4E00\u5904\u7406\u6709\u65E0\u7A7A\u683C\u7684\u60C5\u51B5\n const jsonContent = line.substring(5).trim();\n if (jsonContent) {\n events.push(JSON.parse(jsonContent));\n }\n } catch (e) {\n // \u5FFD\u7565\u975E\u6709\u6548 JSON \u7684\u884C\n logger.debug('parseSseStream', `JSON \u89E3\u6790\u5931\u8D25: ${e.message}, line: ${line.substring(0, 100)}...`);\n }\n }\n }\n logger.success('parseSseStream', `\u89E3\u6790\u5B8C\u6210, events \u6570\u91CF: ${events.length}`);\n return events;\n },\n\n /**\n * \u62E6\u622A\u7F51\u7EDC\u8BF7\u6C42\u5E76\u4F7F\u7528 Node.js \u539F\u751F https \u6A21\u5757\u8F6C\u53D1\uFF0C\u4EE5\u89E3\u51B3\u6D41\u5F0F\u6570\u636E\u6355\u83B7\u95EE\u9898\u3002\n * @param {import('playwright').Page} page\n * @param {string|RegExp} urlPattern - \u62E6\u622A\u7684 URL \u6A21\u5F0F\n * @param {object} options\n * @param {function(string, function, string): void} [options.onData] - (textChunk, resolve, accumulatedText) => void\n * @param {function(string, function): void} [options.onEnd] - (fullText, resolve) => void\n * @param {function(Error, function): void} [options.onTimeout] - (error, reject) => void\n * @param {number} [options.initialTimeout=90000] - \u521D\u59CB\u6570\u636E\u63A5\u6536\u8D85\u65F6 (ms)\uFF0C\u9ED8\u8BA4 90s\n * @param {number} [options.overallTimeout=180000] - \u6574\u4F53\u8BF7\u6C42\u8D85\u65F6\u65F6\u95F4 (ms)\uFF0C\u9ED8\u8BA4 180s\n * @param {boolean} [options.autoUnroute=true] - resolve/reject \u540E\u662F\u5426\u81EA\u52A8\u53D6\u6D88\u62E6\u622A\n * @param {boolean} [options.firstMatchOnly=true] - \u53EA\u62E6\u622A\u7B2C\u4E00\u4E2A\u547D\u4E2D\u7684\u8BF7\u6C42\uFF0C\u540E\u7EED\u8BF7\u6C42\u5168\u90E8\u653E\u884C\n * @returns {Promise<any>} - \u8FD4\u56DE Promise\uFF0C\u5F53\u6D41\u6EE1\u8DB3\u6761\u4EF6\u65F6 resolve\n */\n async intercept(page, urlPattern, options = {}) {\n const {\n onData,\n onEnd,\n onTimeout,\n initialTimeout = 90000,\n overallTimeout = 180000,\n autoUnroute = true,\n firstMatchOnly = true\n } = options;\n\n let initialTimer = null;\n let overallTimer = null;\n let hasReceivedInitialData = false;\n\n const clearAllTimers = () => {\n if (initialTimer) clearTimeout(initialTimer);\n if (overallTimer) clearTimeout(overallTimer);\n initialTimer = null;\n overallTimer = null;\n };\n\n // \u5148\u58F0\u660E\uFF0C\u907F\u514D\u8D85\u65F6\u903B\u8F91\u8BBF\u95EE\u4E0D\u5230\n let safeResolve = () => { };\n let safeReject = () => { };\n let safeUnroute = () => { };\n\n // 1. \u6838\u5FC3\u62E6\u622A\u903B\u8F91\n const workPromise = new Promise((resolve, reject) => {\n let finished = false;\n let unrouteRequested = false;\n let hasMatchedOnce = false;\n\n safeUnroute = () => {\n if (!autoUnroute) return;\n if (unrouteRequested) return;\n unrouteRequested = true;\n logger.info('[MITM] autoUnroute: \u53D6\u6D88\u540E\u7EED\u62E6\u622A');\n page.unroute(urlPattern, routeHandler).catch(() => { });\n };\n\n safeResolve = (value) => {\n if (finished) return;\n finished = true;\n clearAllTimers();\n safeUnroute();\n resolve(value);\n };\n\n safeReject = (error) => {\n if (finished) return;\n finished = true;\n clearAllTimers();\n safeUnroute();\n reject(error);\n };\n\n const routeHandler = async (route) => {\n if (firstMatchOnly && hasMatchedOnce) {\n logger.info(`[MITM] firstMatchOnly: \u653E\u884C\u540E\u7EED\u8BF7\u6C42: ${route.request().url()}`);\n route.continue().catch(() => { });\n return;\n }\n\n if (firstMatchOnly && !hasMatchedOnce) {\n hasMatchedOnce = true;\n logger.info('[MITM] firstMatchOnly: \u547D\u4E2D\u9996\u4E2A\u8BF7\u6C42\uFF0C\u53D6\u6D88\u540E\u7EED\u62E6\u622A');\n page.unroute(urlPattern, routeHandler).catch(() => { });\n }\n\n const request = route.request();\n logger.info(`[MITM] \u5DF2\u62E6\u622A\u8BF7\u6C42: ${request.url()}`);\n\n try {\n const headers = await request.allHeaders();\n const postData = request.postData();\n const urlObj = new URL(request.url());\n\n delete headers['accept-encoding'];\n delete headers['content-length'];\n\n const reqOptions = {\n hostname: urlObj.hostname,\n port: 443,\n path: urlObj.pathname + urlObj.search,\n method: request.method(),\n headers: headers,\n timeout: overallTimeout\n };\n\n const req = https.request(reqOptions, (res) => {\n const chunks = [];\n let accumulatedText = \"\";\n\n res.on('data', (chunk) => {\n if (!hasReceivedInitialData) {\n hasReceivedInitialData = true;\n if (initialTimer) {\n clearTimeout(initialTimer);\n initialTimer = null;\n }\n logger.debug('[Intercept] \u5DF2\u63A5\u6536\u521D\u59CB\u6570\u636E');\n }\n\n chunks.push(chunk);\n const textChunk = chunk.toString('utf-8');\n accumulatedText += textChunk;\n\n if (onData) {\n try {\n onData(textChunk, safeResolve, accumulatedText);\n } catch (e) {\n logger.fail(`onData \u9519\u8BEF`, e);\n }\n }\n });\n\n res.on('end', () => {\n logger.info('[MITM] \u4E0A\u6E38\u54CD\u5E94\u7ED3\u675F');\n clearAllTimers();\n if (onEnd) {\n try {\n onEnd(accumulatedText, safeResolve);\n } catch (e) {\n logger.fail(`onEnd \u9519\u8BEF`, e);\n }\n } else if (!onData) {\n safeResolve(accumulatedText);\n }\n route.fulfill({\n status: res.statusCode,\n headers: res.headers,\n body: Buffer.concat(chunks)\n }).catch(() => { });\n });\n });\n\n req.on('error', (e) => {\n clearAllTimers();\n route.abort().catch(() => { });\n safeReject(e);\n });\n\n if (postData) req.write(postData);\n req.end();\n } catch (e) {\n clearAllTimers();\n route.continue().catch(() => { });\n safeReject(e);\n }\n };\n\n page.route(urlPattern, routeHandler).catch(safeReject); // \u6355\u83B7 page.route \u521D\u59CB\u5316\u9519\u8BEF\n });\n\n // 2. \u8D85\u65F6\u8BA1\u901F\u903B\u8F91\n const timeoutPromise = new Promise((_, reject) => {\n initialTimer = setTimeout(() => {\n if (!hasReceivedInitialData) {\n const error = new CrawlerError({\n message: `\u521D\u59CB\u6570\u636E\u63A5\u6536\u8D85\u65F6 (${initialTimeout}ms)`,\n code: Code.InitialTimeout,\n context: { timeout: initialTimeout }\n });\n clearAllTimers();\n if (onTimeout) {\n try {\n onTimeout(error, (err) => safeReject(err));\n } catch (e) {\n safeReject(e);\n }\n } else {\n safeReject(error);\n }\n }\n }, initialTimeout);\n\n overallTimer = setTimeout(() => {\n const error = new CrawlerError({\n message: `\u6574\u4F53\u8BF7\u6C42\u8D85\u65F6 (${overallTimeout}ms)`,\n code: Code.OverallTimeout,\n context: { timeout: overallTimeout }\n });\n clearAllTimers();\n if (onTimeout) {\n try {\n onTimeout(error, (err) => safeReject(err));\n } catch (e) {\n safeReject(e);\n }\n } else {\n safeReject(error);\n }\n }, overallTimeout);\n });\n\n // 3. \u7ADE\u901F\u8FD4\u56DE\n // \u5173\u952E\uFF1A\u9632\u6B62 race \u7ED3\u679C\u672A\u88AB\u7ACB\u5373 await \u65F6\u7684\u5D29\u6E83\uFF0C\u4EE5\u53CA\u9632\u6B62\u975E\u83B7\u80DC Promise \u540E\u7EED reject \u5BFC\u81F4\u7684\u5D29\u6E83\n workPromise.catch(() => { });\n timeoutPromise.catch(() => { });\n\n const racePromise = Promise.race([workPromise, timeoutPromise]);\n racePromise.catch(() => { }); // \u5173\u952E\uFF1A\u9632\u6B62 race \u7ED3\u679C\u672A\u88AB\u7ACB\u5373 await \u65F6\u7684\u5D29\u6E83\n\n return racePromise;\n }\n};\n", "import { createInternalLogger } from './internals/logger';\nimport { gotScraping } from 'got-scraping';\nimport { Agent as HttpAgent } from 'http';\nimport { Agent as HttpsAgent } from 'https';\n\nconst logger = createInternalLogger('Interception');\n\n// ============================================================================\n// \u907F\u514D\u6BCF\u6B21\u8BF7\u6C42\u90FD\u521B\u5EFA\u65B0\u5B9E\u4F8B\uFF0C\u51CF\u5C11 GC \u538B\u529B\n// ============================================================================\nconst SHARED_HTTP_AGENT = new HttpAgent({\n keepAlive: true,\n keepAliveMsecs: 15000,\n maxSockets: 30,\n maxFreeSockets: 10,\n});\nconst SHARED_HTTPS_AGENT = new HttpsAgent({\n keepAlive: true,\n keepAliveMsecs: 15000,\n maxSockets: 30,\n maxFreeSockets: 10,\n rejectUnauthorized: false,\n});\n\n/** \u76F4\u8FDE\u914D\u7F6E */\nconst DirectConfig = {\n /** \u76F4\u8FDE\u8BF7\u6C42\u8D85\u65F6\u65F6\u95F4\uFF08\u79D2\uFF09 */\n directTimeout: 12,\n /** \u9759\u9ED8\u6269\u5C55\u540D\uFF1A\u8FD9\u4E9B\u6269\u5C55\u540D\u7684\u76F4\u8FDE\u6210\u529F\u65E5\u5FD7\u7528 debug \u7EA7\u522B */\n silentExtensions: ['.js'],\n};\n\n// ============================================================================\n// \u8D44\u6E90\u5C4F\u853D\u6269\u5C55\u540D\u5E38\u91CF\n// ============================================================================\n\n/** \u538B\u7F29\u5305\u7C7B\u6269\u5C55\u540D */\nconst ARCHIVE_EXTENSIONS = ['.7z', '.zip', '.rar', '.gz', '.bz2', '.tar', '.zst'];\n\n/** \u53EF\u6267\u884C/\u5B89\u88C5\u5305\u7C7B\u6269\u5C55\u540D */\nconst EXECUTABLE_EXTENSIONS = ['.exe', '.apk', '.bin', '.dmg', '.jar', '.class'];\n\n/** \u529E\u516C\u6587\u6863\u7C7B\u6269\u5C55\u540D */\nconst DOCUMENT_EXTENSIONS = ['.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.pdf', '.csv'];\n\n/** \u56FE\u7247\u7C7B\u6269\u5C55\u540D */\nconst IMAGE_EXTENSIONS = [\n '.jpg', '.jpeg', '.png', '.gif', '.bmp', '.ico',\n '.svg', '.svgz', '.webp', '.avif', '.pis', '.pict',\n '.tif', '.tiff', '.eps', '.ejs', '.eot'\n];\n\n/** \u97F3\u89C6\u9891\u7C7B\u6269\u5C55\u540D */\nconst MEDIA_EXTENSIONS = ['.mp3', '.mp4', '.avi', '.mkv', '.webm', '.midi', '.mid', '.ogg', '.flac', '.swf'];\n\n/** \u5B57\u4F53\u7C7B\u6269\u5C55\u540D */\nconst FONT_EXTENSIONS = ['.woff', '.woff2', '.ttf', '.otf'];\n\n/** CSS \u6837\u5F0F\u7C7B\u6269\u5C55\u540D */\nconst CSS_EXTENSIONS = ['.css'];\n\n/** \u5176\u4ED6\u8D44\u6E90\u7C7B\u6269\u5C55\u540D */\nconst OTHER_EXTENSIONS = ['.ps', '.iso'];\n\n// ============================================================================\n// \u9ED8\u8BA4\u914D\u7F6E\n// ============================================================================\n\n/** \u9ED8\u8BA4\u5C4F\u853D\u914D\u7F6E */\nconst DEFAULT_BLOCKING_CONFIG = {\n /** \u5C4F\u853D\u538B\u7F29\u5305 */\n blockArchive: true,\n /** \u5C4F\u853D\u53EF\u6267\u884C\u6587\u4EF6 */\n blockExecutable: true,\n /** \u5C4F\u853D\u529E\u516C\u6587\u6863 */\n blockDocument: true,\n /** \u5C4F\u853D\u56FE\u7247 */\n blockImage: true,\n /** \u5C4F\u853D\u97F3\u89C6\u9891 */\n blockMedia: true,\n /** \u5C4F\u853D\u5B57\u4F53 */\n blockFont: true,\n /** \u5C4F\u853D CSS (\u6CE8\u610F\uFF1A\u53EF\u80FD\u5F71\u54CD\u9875\u9762\u89C6\u89C9\u6548\u679C) */\n blockCss: false,\n /** \u5C4F\u853D\u5176\u4ED6\u8D44\u6E90 */\n blockOther: true,\n /** \u989D\u5916\u81EA\u5B9A\u4E49\u6269\u5C55\u540D\u5217\u8868 */\n customExtensions: [],\n};\n\n// ============================================================================\n// \u5171\u4EAB\u7684\u8BF7\u6C42\u914D\u7F6E\uFF08\u51CF\u5C11\u5783\u573E\u56DE\u6536\u538B\u529B\uFF09\n// ============================================================================\nconst SHARED_GOT_OPTIONS = {\n http2: false, // \u7981\u7528 HTTP2 \u907F\u514D\u5728\u62E6\u622A\u573A\u666F\u4E0B\u7684\u63E1\u624B\u517C\u5BB9\u6027\u95EE\u9898\n retry: { limit: 0 }, // \u8BA9 Playwright \u6216\u5916\u5C42\u903B\u8F91\u5904\u7406\u91CD\u8BD5\n throwHttpErrors: false, // 404/500 \u7B49\u9519\u8BEF\u4E0D\u629B\u51FA\u5F02\u5E38\uFF0C\u76F4\u63A5\u900F\u4F20\u7ED9\u6D4F\u89C8\u5668\n};\n\nexport const Interception = {\n /**\n * \u6839\u636E\u914D\u7F6E\u751F\u6210\u9700\u8981\u5C4F\u853D\u7684\u6269\u5C55\u540D\u5217\u8868\n * \n * @param {Object} [config] - \u5C4F\u853D\u914D\u7F6E\n * @returns {string[]} \u9700\u8981\u5C4F\u853D\u7684\u6269\u5C55\u540D\u5217\u8868\n */\n getBlockedExtensions(config = {}) {\n const mergedConfig = { ...DEFAULT_BLOCKING_CONFIG, ...config };\n const extensions = [];\n\n if (mergedConfig.blockArchive) extensions.push(...ARCHIVE_EXTENSIONS);\n if (mergedConfig.blockExecutable) extensions.push(...EXECUTABLE_EXTENSIONS);\n if (mergedConfig.blockDocument) extensions.push(...DOCUMENT_EXTENSIONS);\n if (mergedConfig.blockImage) extensions.push(...IMAGE_EXTENSIONS);\n if (mergedConfig.blockMedia) extensions.push(...MEDIA_EXTENSIONS);\n if (mergedConfig.blockFont) extensions.push(...FONT_EXTENSIONS);\n if (mergedConfig.blockCss) extensions.push(...CSS_EXTENSIONS);\n if (mergedConfig.blockOther) extensions.push(...OTHER_EXTENSIONS);\n\n if (mergedConfig.customExtensions?.length > 0) {\n extensions.push(...mergedConfig.customExtensions);\n }\n\n return [...new Set(extensions)];\n },\n\n /**\n * \u83B7\u53D6\u6240\u6709\u53EF\u7528\u7684\u6269\u5C55\u540D\u5206\u7C7B\u4FE1\u606F\n * \n * @returns {Object} \u5206\u7C7B\u4FE1\u606F\n */\n getExtensionCategories() {\n return {\n archive: { name: '\u538B\u7F29\u5305', extensions: ARCHIVE_EXTENSIONS },\n executable: { name: '\u53EF\u6267\u884C\u6587\u4EF6', extensions: EXECUTABLE_EXTENSIONS },\n document: { name: '\u529E\u516C\u6587\u6863', extensions: DOCUMENT_EXTENSIONS },\n image: { name: '\u56FE\u7247', extensions: IMAGE_EXTENSIONS },\n media: { name: '\u97F3\u89C6\u9891', extensions: MEDIA_EXTENSIONS },\n font: { name: '\u5B57\u4F53', extensions: FONT_EXTENSIONS },\n css: { name: 'CSS \u6837\u5F0F', extensions: CSS_EXTENSIONS },\n other: { name: '\u5176\u4ED6\u8D44\u6E90', extensions: OTHER_EXTENSIONS },\n };\n },\n\n /**\n * \u8BBE\u7F6E\u7F51\u7EDC\u62E6\u622A\u89C4\u5219\uFF08\u8D44\u6E90\u5C4F\u853D + CDN \u76F4\u8FDE\uFF09\n * \n * @param {import('playwright').Page} page - Playwright Page \u5BF9\u8C61\n * @param {Object} [options] - \u914D\u7F6E\u9009\u9879\n * @param {string[]} [options.directDomains] - \u9700\u8981\u76F4\u8FDE\u7684\u57DF\u540D\u5217\u8868\n * @param {Object} [options.blockingConfig] - \u8D44\u6E90\u5C4F\u853D\u914D\u7F6E\n * @param {boolean} [options.fallbackToProxy] - \u76F4\u8FDE\u5931\u8D25\u65F6\u662F\u5426\u56DE\u9000\u5230\u4EE3\u7406\uFF08\u9ED8\u8BA4 true\uFF09\n * @returns {Promise<void>}\n */\n async setup(page, options = {}) {\n const {\n directDomains = [],\n blockingConfig = {},\n fallbackToProxy = true,\n } = options;\n\n const mergedBlockingConfig = { ...DEFAULT_BLOCKING_CONFIG, ...blockingConfig };\n const blockedExtensions = this.getBlockedExtensions(mergedBlockingConfig);\n const hasDirectDomains = directDomains.length > 0;\n\n // \u6784\u5EFA\u65E5\u5FD7\u4FE1\u606F\n const enabledCategories = [];\n if (mergedBlockingConfig.blockArchive) enabledCategories.push('\u538B\u7F29\u5305');\n if (mergedBlockingConfig.blockExecutable) enabledCategories.push('\u53EF\u6267\u884C\u6587\u4EF6');\n if (mergedBlockingConfig.blockDocument) enabledCategories.push('\u529E\u516C\u6587\u6863');\n if (mergedBlockingConfig.blockImage) enabledCategories.push('\u56FE\u7247');\n if (mergedBlockingConfig.blockMedia) enabledCategories.push('\u97F3\u89C6\u9891');\n if (mergedBlockingConfig.blockFont) enabledCategories.push('\u5B57\u4F53');\n if (mergedBlockingConfig.blockCss) enabledCategories.push('CSS');\n if (mergedBlockingConfig.blockOther) enabledCategories.push('\u5176\u4ED6');\n\n logger.start('setup', hasDirectDomains\n ? `\u76F4\u8FDE\u57DF\u540D: [${directDomains.length} \u4E2A] | \u5C4F\u853D: [${enabledCategories.join(', ')}]`\n : `\u4EC5\u8D44\u6E90\u5C4F\u853D\u6A21\u5F0F | \u5C4F\u853D: [${enabledCategories.join(', ')}]`);\n\n await page.route('**/*', async (route) => {\n // \u4F7F\u7528 handled flag \u8DDF\u8E2A route \u662F\u5426\u5DF2\u5904\u7406\uFF0C\u907F\u514D\u91CD\u590D\u64CD\u4F5C\n let handled = false;\n\n try {\n const request = route.request();\n const url = request.url();\n const urlLower = url.toLowerCase();\n const urlPath = urlLower.split('?')[0];\n\n // \u5224\u65AD\u662F\u5426\u4E3A\u9759\u9ED8\u8D44\u6E90\uFF08\u7528\u4E8E\u964D\u4F4E\u65E5\u5FD7\u9891\u7387\uFF09\n const isSilent = DirectConfig.silentExtensions.some(ext => urlPath.endsWith(ext));\n\n // ----------------------------------------------------------------\n // Step 1: \u68C0\u67E5\u662F\u5426\u5728\u5C4F\u853D\u5217\u8868\u4E2D\n // ----------------------------------------------------------------\n const shouldBlock = blockedExtensions.some(ext => urlPath.endsWith(ext));\n if (shouldBlock) {\n await route.abort();\n handled = true;\n return;\n }\n\n // ----------------------------------------------------------------\n // Step 2: \u68C0\u67E5\u662F\u5426\u5339\u914D\u76F4\u8FDE\u57DF\u540D\n // ----------------------------------------------------------------\n let isDirect = false;\n if (hasDirectDomains) {\n try {\n const hostname = new URL(url).hostname;\n isDirect = directDomains.some(domain => hostname.startsWith(domain));\n } catch (e) {\n // ignore invalid url\n }\n }\n\n if (isDirect) {\n try {\n const reqHeaders = await request.allHeaders();\n delete reqHeaders['host']; // \u5220\u9664 host \u9632\u6B62\u51B2\u7A81\n const resolvedAcceptLanguage = reqHeaders['accept-language'] || '';\n\n // \u83B7\u53D6 User-Agent \u7528\u4E8E TLS \u6307\u7EB9\n const userAgent = reqHeaders['user-agent'] || '';\n\n // \u51C6\u5907 POST \u6570\u636E\n const method = request.method();\n const postData = (method !== 'GET' && method !== 'HEAD')\n ? request.postDataBuffer()\n : undefined;\n\n // \u53D1\u8D77\u76F4\u8FDE\u8BF7\u6C42\n const response = await gotScraping({\n ...SHARED_GOT_OPTIONS, // \u5E94\u7528\u901A\u7528\u914D\u7F6E\n url: url,\n method: method,\n headers: reqHeaders,\n body: postData,\n responseType: 'buffer', // \u5F3A\u5236\u83B7\u53D6 Buffer\n\n // \u79FB\u9664\u624B\u52A8 TLS \u6307\u7EB9\u914D\u7F6E\uFF0C\u4F7F\u7528 got-scraping \u9ED8\u8BA4\u7684\u9AD8\u8D28\u91CF\u6307\u7EB9\n // headerGeneratorOptions: ... \n\n // \u4F7F\u7528\u5171\u4EAB\u7684 Agent \u5355\u4F8B\uFF08keepAlive: false\uFF0C\u4E0D\u4F1A\u6C60\u5316\u8FDE\u63A5\uFF09\n agent: {\n http: SHARED_HTTP_AGENT,\n https: SHARED_HTTPS_AGENT,\n },\n\n // \u8D85\u65F6\u65F6\u95F4\n timeout: { request: DirectConfig.directTimeout * 1000 },\n });\n\n // \u51C6\u5907\u54CD\u5E94\u5934\n const resHeaders = {};\n for (const [key, value] of Object.entries(response.headers)) {\n if (Array.isArray(value)) {\n resHeaders[key] = value.join(', ');\n } else if (value) {\n resHeaders[key] = String(value);\n }\n }\n\n // \u3010\u6838\u5FC3\u4FEE\u590D 2\u3011: \u5F7B\u5E95\u6E05\u7406\u534F\u8BAE\u5934\n // \u79FB\u9664\u53EF\u80FD\u5BFC\u81F4\u6D4F\u89C8\u5668\u8BA4\u4E3A\u6570\u636E\u4F20\u8F93\u672A\u5B8C\u6210\u7684\u5934\n delete resHeaders['content-encoding'];\n delete resHeaders['content-length'];\n delete resHeaders['transfer-encoding']; // \u5173\u952E\uFF1A\u79FB\u9664 chunked\n delete resHeaders['connection'];\n delete resHeaders['keep-alive'];\n\n\n // \u9759\u9ED8\u8D44\u6E90\u7528 debug \u7EA7\u522B\uFF0C\u964D\u4F4E\u65E5\u5FD7\u9891\u7387\n isSilent ? logger.debug(`\u76F4\u8FDE\u6210\u529F: ${urlPath}`) : logger.info(`\u76F4\u8FDE\u6210\u529F: ${urlPath}`);\n\n // \u5B89\u5168\u5730\u8FD4\u56DE\u6570\u636E\n await safeFulfill(route, {\n status: response.statusCode,\n headers: resHeaders,\n body: response.body,\n });\n handled = true;\n return;\n\n } catch (e) {\n // \u5224\u65AD\u662F\u5426\u4E3A\u8D85\u65F6\u9519\u8BEF\n const isTimeout = e.code === 'ETIMEDOUT' || e.message.toLowerCase().includes('timeout');\n const action = fallbackToProxy ? '\u56DE\u9000\u4EE3\u7406' : '\u5DF2\u653E\u5F03';\n const reason = isTimeout ? `\u8D85\u65F6(${DirectConfig.directTimeout}s)` : `\u5F02\u5E38: ${e.message}`;\n\n logger.warn(`\u76F4\u8FDE${reason}\uFF0C${action}: ${urlPath}`);\n\n if (fallbackToProxy) {\n await safeContinue(route);\n } else {\n await route.abort();\n }\n handled = true;\n return;\n }\n }\n\n // ----------------------------------------------------------------\n // Step 3: \u5176\u4ED6\u8BF7\u6C42\u6B63\u5E38\u8D70\u4EE3\u7406\n // ----------------------------------------------------------------\n await safeContinue(route);\n handled = true;\n\n } catch (err) {\n // \u6700\u540E\u7684\u9632\u7EBF\uFF1A\u9632\u6B62 Route \u5904\u7406\u8FC7\u7A0B\u4E2D\u53D1\u751F\u672A\u6355\u83B7\u5F02\u5E38\u5BFC\u81F4\u6D4F\u89C8\u5668\u5361\u6B7B\n logger.warn(`\u8DEF\u7531\u5904\u7406\u5F02\u5E38: ${err.message}`);\n\n // \u4F7F\u7528 handled flag \u5224\u65AD\u662F\u5426\u9700\u8981\u515C\u5E95\u5904\u7406\n if (!handled) {\n try {\n await route.continue();\n } catch (_) {\n // \u5FFD\u7565\u8FD9\u91CC\u7684\u9519\u8BEF\uFF0C\u56E0\u4E3A\u901A\u5E38\u610F\u5473\u7740\u9875\u9762\u5DF2\u5173\u95ED\u6216\u8BF7\u6C42\u5DF2\u5931\u6548\n }\n }\n }\n });\n },\n};\n\n// ============================================================================\n// \u8F85\u52A9\u51FD\u6570\uFF1A\u5B89\u5168\u64CD\u4F5C Route\n// \u89E3\u51B3 \"Route is already handled\" \u6216 \"Target closed\" \u5BFC\u81F4\u7684\u5D29\u6E83\n// ============================================================================\n\n/**\n * \u5B89\u5168\u5730\u6267\u884C route.fulfill\n */\nasync function safeFulfill(route, options) {\n try {\n await route.fulfill(options);\n } catch (error) {\n // \u53EA\u6709\u5F53\u4E0D\u662F \"\u5DF2\u7ECF\u5904\u7406\" \u6216 \"\u9875\u9762\u5173\u95ED\" \u9519\u8BEF\u65F6\u624D\u6253\u5370\n if (!isIgnorableError(error)) {\n console.error(`[Interception] Fulfill Error: ${error.message}`);\n }\n }\n}\n\n/**\n * \u5B89\u5168\u5730\u6267\u884C route.continue\n */\nasync function safeContinue(route) {\n try {\n await route.continue();\n } catch (error) {\n if (!isIgnorableError(error)) {\n // continue \u5931\u8D25\u901A\u5E38\u4E0D\u9700\u8981\u6253\u5370\uFF0C\u53EF\u80FD\u662F\u7F51\u7EDC\u77AC\u95F4\u65AD\u5F00\n }\n }\n}\n\n/**\n * \u5224\u65AD\u662F\u5426\u4E3A\u53EF\u5FFD\u7565\u7684 Playwright \u8DEF\u7531\u9519\u8BEF\n */\nfunction isIgnorableError(error) {\n const msg = error.message;\n return msg.includes('already handled') ||\n msg.includes('Target closed') ||\n msg.includes('closed');\n}\n", "import { v4 as uuidv4 } from 'uuid';\nimport { createInternalLogger } from './internals/logger.js';\n\nconst logger = createInternalLogger('Mutation');\n\nconst MUTATION_MONITOR_MODE = Object.freeze({\n Added: 'added',\n Changed: 'changed',\n All: 'all',\n});\n\n/**\n * \u751F\u6210\u552F\u4E00\u7684 key \u540D\u79F0\uFF0C\u907F\u514D\u51B2\u7A81\n * @returns {string}\n */\nfunction generateKey(prefix) {\n return `__${prefix}_${uuidv4().replace(/-/g, '_')}`;\n}\n\nexport const Mutation = {\n Mode: MUTATION_MONITOR_MODE,\n /**\n * \u7B49\u5F85 DOM \u5143\u7D20\u7A33\u5B9A\uFF08\u65E0\u53D8\u5316\uFF09\n * \u4F7F\u7528 MutationObserver \u76D1\u63A7\u6307\u5B9A\u5143\u7D20\uFF0C\u5F53\u5143\u7D20\u6301\u7EED\u4E00\u6BB5\u65F6\u95F4\u65E0\u53D8\u5316\u65F6 resolve\n * \n * @param {import('playwright').Page} page - Playwright page \u5BF9\u8C61\n * @param {string | string[]} selectors - \u8981\u76D1\u63A7\u7684 CSS \u9009\u62E9\u5668\uFF0C\u5355\u4E2A\u6216\u591A\u4E2A\n * @param {Object} [options] - \u914D\u7F6E\u9009\u9879\n * @param {number} [options.initialTimeout] - \u7B49\u5F85\u5143\u7D20\u51FA\u73B0\u7684\u8D85\u65F6 (\u6BEB\u79D2, \u9ED8\u8BA4: 30000)\n * @param {number} [options.stableTime] - \u65E0\u53D8\u5316\u6301\u7EED\u65F6\u95F4\u540E resolve (\u6BEB\u79D2, \u9ED8\u8BA4: 5000)\n * @param {number} [options.timeout] - \u6574\u4F53\u8D85\u65F6\u65F6\u95F4 (\u6BEB\u79D2, \u9ED8\u8BA4: 120000)\n * @param {Function} [options.onMutation] - \u53D8\u5316\u65F6\u7684\u56DE\u8C03\u94A9\u5B50\n * \u7B7E\u540D: ({ mutationCount, html, text, mutationNodes }) => any\n * \u8FD4\u56DE null/undefined: \u6B63\u5E38\u91CD\u7F6E\u7A33\u5B9A\u8BA1\u65F6\n * \u8FD4\u56DE\u5176\u4ED6\u503C: \u6682\u505C\u7A33\u5B9A\u8BA1\u65F6\uFF08timeout \u4ECD\u7136\u751F\u6548\uFF09\n * @returns {Promise<{ mutationCount: number, stableTime: number, wasPaused: boolean }>}\n */\n async waitForStable(page, selectors, options = {}) {\n const selectorList = Array.isArray(selectors) ? selectors : [selectors];\n const initialTimeout = options.initialTimeout ?? 30 * 1000;\n const stableTime = options.stableTime ?? 5 * 1000;\n const timeout = options.timeout ?? 120 * 1000;\n const onMutation = options.onMutation;\n\n logger.start('waitForStable', `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);\n\n if (initialTimeout > 0) {\n const selectorQuery = selectorList.join(',');\n try {\n await page.waitForSelector(selectorQuery, { timeout: initialTimeout });\n logger.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);\n } catch (e) {\n logger.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);\n throw e;\n }\n }\n\n // \u751F\u6210\u552F\u4E00\u7684\u56DE\u8C03\u540D\n const callbackName = generateKey('pk_mut_cb');\n\n // \u5982\u679C\u6709 onMutation \u56DE\u8C03\uFF0C\u66B4\u9732\u51FD\u6570\u5E76\u8FD4\u56DE\u7ED3\u679C\n if (onMutation) {\n try {\n await page.exposeFunction(callbackName, async (context) => {\n try {\n const result = await onMutation(context);\n const paused = !(result === null || result === undefined);\n // \u8FD4\u56DE null/undefined \u8868\u793A\u6B63\u5E38\u8BA1\u65F6\uFF0C\u5176\u4ED6\u503C\u8868\u793A\u6682\u505C\n return paused ? '__PAUSE__' : '__CONTINUE__';\n } catch (e) {\n // \u56DE\u8C03\u51FA\u9519\u65F6\u9ED8\u8BA4\u7EE7\u7EED\u8BA1\u65F6\n return '__CONTINUE__';\n }\n });\n logger.info('waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03');\n } catch (e) {\n // \u53EF\u80FD\u5DF2\u7ECF\u66B4\u9732\u8FC7\uFF0C\u5FFD\u7565\n }\n }\n\n const result = await page.evaluate(\n async ({ selectorList, stableTime, timeout, callbackName, hasCallback }) => {\n return new Promise((resolve, reject) => {\n let mutationCount = 0;\n let stableTimer = null;\n let timeoutTimer = null;\n let isPaused = false;\n let wasPaused = false;\n const observers = [];\n\n // \u6E05\u7406\u51FD\u6570\n const cleanup = () => {\n observers.forEach(obs => obs.disconnect());\n if (stableTimer) clearTimeout(stableTimer);\n if (timeoutTimer) clearTimeout(timeoutTimer);\n };\n\n // \u91CD\u7F6E\u7A33\u5B9A\u8BA1\u65F6\u5668\n const resetStableTimer = () => {\n if (stableTimer) clearTimeout(stableTimer);\n if (isPaused) return;\n stableTimer = setTimeout(() => {\n cleanup();\n resolve({ mutationCount, stableTime, wasPaused });\n }, stableTime);\n };\n\n const setPaused = (nextPaused) => {\n if (isPaused === nextPaused) return;\n isPaused = nextPaused;\n if (isPaused) {\n if (stableTimer) clearTimeout(stableTimer);\n stableTimer = null;\n wasPaused = true;\n return;\n }\n resetStableTimer();\n };\n\n // \u6574\u4F53\u8D85\u65F6\uFF08\u59CB\u7EC8\u751F\u6548\uFF0C\u4E0D\u53D7\u6682\u505C\u5F71\u54CD\uFF09\n timeoutTimer = setTimeout(() => {\n cleanup();\n reject(new Error(`waitForStable \u8D85\u65F6 (${timeout}ms), \u5DF2\u68C0\u6D4B\u5230 ${mutationCount} \u6B21\u53D8\u5316, isPaused=${isPaused}`));\n }, timeout);\n\n // \u4E3A\u6BCF\u4E2A\u9009\u62E9\u5668\u521B\u5EFA MutationObserver\n selectorList.forEach(selector => {\n const elements = document.querySelectorAll(selector);\n elements.forEach(element => {\n const observer = new MutationObserver(async (mutations) => {\n mutationCount += mutations.length;\n\n if (hasCallback && window[callbackName]) {\n // \u83B7\u53D6\u5143\u7D20\u5185\u5BB9\n const html = element.outerHTML || '';\n const text = element.innerText || element.textContent || '';\n const mutationNodes = [{ html, text, mutationType: 'stable' }];\n\n try {\n const signal = await window[callbackName]({\n mutationCount,\n html,\n text,\n mutationNodes\n });\n\n const shouldPause = signal === '__PAUSE__';\n setPaused(shouldPause);\n if (!shouldPause) {\n resetStableTimer();\n }\n } catch (e) {\n // \u56DE\u8C03\u51FA\u9519\u65F6\u7EE7\u7EED\u8BA1\u65F6\n setPaused(false);\n resetStableTimer();\n }\n } else {\n // \u6CA1\u6709\u56DE\u8C03\uFF0C\u4FDD\u6301\u539F\u6709\u884C\u4E3A\n resetStableTimer();\n }\n });\n\n observer.observe(element, {\n childList: true,\n subtree: true,\n characterData: true,\n attributes: true\n });\n\n observers.push(observer);\n });\n });\n\n // \u5982\u679C\u6CA1\u6709\u627E\u5230\u4EFB\u4F55\u5143\u7D20\uFF0C\u76F4\u63A5\u8FD4\u56DE\n if (observers.length === 0) {\n cleanup();\n resolve({ mutationCount: 0, stableTime: 0, wasPaused: false });\n return;\n }\n\n // \u521D\u59CB\u68C0\u67E5\uFF1A\u6302\u8F7D\u540E\u7ACB\u5373\u6267\u884C\u4E00\u6B21\u56DE\u8C03\uFF0C\u5224\u65AD\u662F\u5426\u9700\u8981\u6682\u505C\n const runInitialCheck = async () => {\n if (hasCallback && window[callbackName]) {\n // \u83B7\u53D6\u7B2C\u4E00\u4E2A\u76D1\u63A7\u5143\u7D20\u7684\u5185\u5BB9\n const firstSelector = selectorList[0];\n const firstElement = document.querySelector(firstSelector);\n if (firstElement) {\n const html = firstElement.outerHTML || '';\n const text = firstElement.innerText || firstElement.textContent || '';\n const mutationNodes = [{ html, text, mutationType: 'stable' }];\n\n try {\n const signal = await window[callbackName]({\n mutationCount: 0,\n html,\n text,\n mutationNodes\n });\n\n if (signal === '__PAUSE__') {\n setPaused(true);\n return; // \u6682\u505C\u65F6\u4E0D\u542F\u52A8\u521D\u59CB\u8BA1\u65F6\n }\n } catch (e) {\n // \u56DE\u8C03\u51FA\u9519\u65F6\u7EE7\u7EED\n }\n }\n }\n // \u542F\u52A8\u521D\u59CB\u7A33\u5B9A\u8BA1\u65F6\u5668\n resetStableTimer();\n };\n\n runInitialCheck();\n });\n },\n { selectorList, stableTime, timeout, callbackName, hasCallback: !!onMutation }\n );\n\n if (result.mutationCount === 0 && result.stableTime === 0) {\n logger.warning('waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20');\n }\n logger.success('waitForStable', `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ', \u66FE\u6682\u505C\u8BA1\u65F6' : ''}`);\n return result;\n },\n\n /**\n * \u521B\u5EFA\u4E00\u4E2A\u6301\u7EED\u76D1\u63A7 DOM \u53D8\u5316\u7684\u76D1\u63A7\u5668\uFF08\u9ED8\u8BA4\u4EC5\u76D1\u542C\u65B0\u589E DOM\uFF09\n *\n * @param {import('playwright').Page} page - Playwright page \u5BF9\u8C61\n * @param {string | string[]} selectors - \u8981\u76D1\u63A7\u7684 CSS \u9009\u62E9\u5668\uFF0C\u652F\u6301 'document.documentElement'\n * @param {Object} [options] - \u914D\u7F6E\u9009\u9879\n * @param {Function} [options.onMutation] - \u53D8\u5316\u65F6\u7684\u56DE\u8C03\n * \u7B7E\u540D: ({ mutationCount, html, text, mutationNodes }) => void\n * \u6240\u6709\u6A21\u5F0F\u90FD\u8FD4\u56DE\u672C\u6B21\u5168\u90E8\u53D8\u5316\u8282\u70B9\u5FEB\u7167 mutationNodes\n * @param {'added' | 'changed' | 'all'} [options.mode='added'] - \u76D1\u63A7\u6A21\u5F0F\n * @returns {Promise<{ stop: () => Promise<{ totalMutations: number }> }>} - \u8FD4\u56DE\u505C\u6B62\u51FD\u6570\n */\n async useMonitor(page, selectors, options = {}) {\n const selectorList = Array.isArray(selectors) ? selectors : [selectors];\n const onMutation = options.onMutation;\n const rawMode = String(options.mode || MUTATION_MONITOR_MODE.Added).toLowerCase();\n const mode = [MUTATION_MONITOR_MODE.Added, MUTATION_MONITOR_MODE.Changed, MUTATION_MONITOR_MODE.All].includes(rawMode)\n ? rawMode\n : MUTATION_MONITOR_MODE.Added;\n\n logger.start('useMonitor', `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode}`);\n\n const monitorKey = generateKey('pk_mon');\n const callbackName = generateKey('pk_mon_cb');\n const cleanerName = generateKey('pk_mon_clean');\n\n if (onMutation) {\n try {\n await page.exposeFunction(callbackName, (payload) => {\n try {\n onMutation(payload);\n } catch (e) {\n // \u5FFD\u7565\u56DE\u8C03\u9519\u8BEF\n }\n });\n } catch (e) {\n // \u53EF\u80FD\u5DF2\u7ECF\u66B4\u9732\u8FC7\uFF0C\u5FFD\u7565\n }\n }\n\n await page.evaluate(({ selectorList, monitorKey, callbackName, cleanerName, hasCallback, mode }) => {\n const monitor = {\n observers: [],\n totalMutations: 0,\n running: true,\n };\n\n const resolveTargets = (selector) => {\n const key = String(selector || '').trim();\n if (!key) return [];\n\n if (key === 'document.documentElement' || key === 'documentElement' || key === 'document') {\n return document.documentElement ? [document.documentElement] : [];\n }\n\n if (key === 'document.body') {\n return document.body ? [document.body] : [];\n }\n\n return Array.from(document.querySelectorAll(key));\n };\n\n const serializeNode = (node, mutationType = 'unknown') => {\n if (!node) {\n return { html: '', text: '', mutationType };\n }\n\n if (node.nodeType === Node.ELEMENT_NODE) {\n return {\n html: node.outerHTML || '',\n text: node.innerText || node.textContent || '',\n mutationType,\n };\n }\n\n if (node.nodeType === Node.TEXT_NODE) {\n const text = node.textContent || '';\n return { html: text, text, mutationType };\n }\n\n if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {\n const nodes = Array.from(node.childNodes || []);\n const html = nodes\n .map(item => item?.nodeType === Node.ELEMENT_NODE ? (item.outerHTML || '') : (item?.textContent || ''))\n .join('\\n');\n const text = node.textContent || '';\n return { html: html || text, text, mutationType };\n }\n\n const text = node.textContent || '';\n return { html: text, text, mutationType };\n };\n\n const collectMutationNodes = (mutations) => {\n const mutationNodes = [];\n\n for (const mutation of mutations) {\n if (mode === 'added') {\n if (mutation.type !== 'childList') continue;\n const added = Array.from(mutation.addedNodes || []);\n for (const node of added) {\n mutationNodes.push(serializeNode(node, 'added'));\n }\n continue;\n }\n\n if (mode === 'changed') {\n if (mutation.type === 'attributes' || mutation.type === 'characterData') {\n mutationNodes.push(serializeNode(mutation.target, mutation.type));\n } else if (mutation.type === 'childList') {\n const added = Array.from(mutation.addedNodes || []);\n const removed = Array.from(mutation.removedNodes || []);\n\n for (const node of added) {\n mutationNodes.push(serializeNode(node, 'added'));\n }\n for (const node of removed) {\n mutationNodes.push(serializeNode(node, 'removed'));\n }\n\n if (added.length === 0 && removed.length === 0) {\n mutationNodes.push(serializeNode(mutation.target, 'childList'));\n }\n }\n continue;\n }\n\n if (mutation.type === 'childList') {\n const added = Array.from(mutation.addedNodes || []);\n const removed = Array.from(mutation.removedNodes || []);\n\n for (const node of added) {\n mutationNodes.push(serializeNode(node, 'added'));\n }\n for (const node of removed) {\n mutationNodes.push(serializeNode(node, 'removed'));\n }\n\n if (added.length === 0 && removed.length === 0) {\n mutationNodes.push(serializeNode(mutation.target, 'childList'));\n }\n } else if (mutation.type === 'attributes' || mutation.type === 'characterData') {\n mutationNodes.push(serializeNode(mutation.target, mutation.type));\n } else {\n mutationNodes.push(serializeNode(mutation.target, mutation.type || 'unknown'));\n }\n }\n\n return mutationNodes;\n };\n\n selectorList.forEach(selector => {\n const elements = resolveTargets(selector);\n elements.forEach(element => {\n const observer = new MutationObserver((mutations) => {\n if (!monitor.running) return;\n\n const mutationNodes = collectMutationNodes(mutations);\n if (mutationNodes.length <= 0) return;\n\n monitor.totalMutations += mutationNodes.length;\n\n if (hasCallback && window[callbackName]) {\n const html = mutationNodes.map(item => item.html || '').join('\\n');\n const text = mutationNodes.map(item => item.text || '').join('\\n');\n\n window[callbackName]({\n mutationCount: monitor.totalMutations,\n html,\n text,\n mutationNodes,\n });\n }\n });\n\n observer.observe(element, {\n childList: true,\n subtree: true,\n characterData: mode !== 'added',\n attributes: mode !== 'added',\n });\n\n monitor.observers.push(observer);\n });\n });\n\n window[monitorKey] = monitor;\n window[cleanerName] = () => {\n monitor.running = false;\n monitor.observers.forEach(obs => obs.disconnect());\n const total = monitor.totalMutations;\n delete window[monitorKey];\n delete window[cleanerName];\n return total;\n };\n }, { selectorList, monitorKey, callbackName, cleanerName, hasCallback: !!onMutation, mode });\n\n logger.success('useMonitor', '\u76D1\u63A7\u5668\u5DF2\u542F\u52A8');\n\n return {\n stop: async () => {\n let totalMutations = 0;\n try {\n totalMutations = await page.evaluate((cleanerName) => {\n if (window[cleanerName]) {\n return window[cleanerName]();\n }\n return 0;\n }, cleanerName);\n } catch (e) {\n // \u9875\u9762\u53EF\u80FD\u5DF2\u5173\u95ED\uFF0C\u5FFD\u7565\n }\n logger.success('useMonitor.stop', `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);\n return { totalMutations };\n }\n };\n }\n};\n", "export const Display = {\n parseTokenDisplayName(value) {\n if (!value) {\n return { owner: '', accountType: '', note: '' };\n }\n const parts = String(value).split(':');\n const owner = (parts[0] || '').trim();\n const accountType = (parts[1] || '').trim();\n const note = parts.length > 2 ? parts.slice(2).join(':').trim() : '';\n return { owner, accountType, note };\n },\n\n parseAccountDisplayName(value) {\n if (!value) {\n return { account: '', owner: '', accountType: '', note: '' };\n }\n const parts = String(value).split(':');\n const account = (parts[0] || '').trim();\n const owner = (parts[1] || '').trim();\n const accountType = (parts[2] || '').trim();\n const note = parts.length > 3 ? parts.slice(3).join(':').trim() : '';\n return { account, owner, accountType, note };\n },\n\n buildTokenDisplayName({ owner, accountType, note } = {}) {\n const trimmedOwner = owner?.trim() || '';\n const trimmedType = accountType?.trim() || '';\n const trimmedNote = note?.trim() || '';\n const parts = [trimmedOwner, trimmedType];\n if (trimmedNote) {\n parts.push(trimmedNote);\n }\n return parts.filter(Boolean).join(':');\n },\n\n shortId(value, max = 8) {\n const clean = String(value || '').trim();\n if (!clean) return '';\n if (clean.length <= max) return clean;\n return clean.slice(0, max);\n },\n\n resolveTokenIdentity(displayName, tokenId) {\n const cleanName = String(displayName || '').trim();\n const cleanId = String(tokenId || '').trim();\n const short = this.shortId(cleanId, 8);\n const hasName = cleanName !== '' && cleanName !== cleanId;\n const primary = hasName ? cleanName : (short || '-');\n const secondary = hasName && short ? short : '';\n return { primary, secondary, fullId: cleanId, shortId: short };\n },\n\n resolveAccountIdentity(displayName, accountId) {\n const parts = this.parseAccountDisplayName(displayName);\n const cleanId = String(accountId || '').trim();\n const short = this.shortId(cleanId, 8);\n const hasName = parts.account !== '' && parts.account !== cleanId;\n const primary = hasName ? parts.account : (short || '-');\n const secondary = hasName && short ? short : '';\n return { primary, secondary, parts, fullId: cleanId, shortId: short };\n },\n};\n", "import { createBaseLogger, setDefaultLogger } from './internals/logger.js';\n\nexport const stripAnsi = (input) => {\n if (!input) return '';\n return String(input).replace(/\\x1b\\[[0-9;]*m/g, '');\n};\n\n// =============================================================================\n// Log Templates & Definitions\n// =============================================================================\n\nconst STEP_PREFIX = '\u6B65\u9AA4:';\nconst STEP_SEPARATOR = ' | ';\nconst STEP_EMOJIS = [\n { match: '\u4EFB\u52A1', emoji: '\uD83E\uDDED' },\n { match: '\u8FD0\u884C\u6A21\u5F0F', emoji: '\uD83E\uDDE9' },\n { match: '\u767B\u5F55', emoji: '\uD83D\uDD10' },\n { match: '\u73AF\u5883', emoji: '\uD83E\uDDEA' },\n { match: '\u8F93\u5165', emoji: '\u2328\uFE0F' },\n { match: '\u53D1\u9001', emoji: '\uD83D\uDCE4' },\n { match: '\u54CD\u5E94\u76D1\u542C', emoji: '\uD83D\uDCE1' },\n { match: '\u7B49\u5F85\u54CD\u5E94', emoji: '\u23F3' },\n { match: '\u6D41\u5F0F', emoji: '\uD83E\uDDF5' },\n { match: '\u5F15\u7528', emoji: '\uD83D\uDCCE' },\n { match: '\u622A\u56FE', emoji: '\uD83D\uDDBC\uFE0F' },\n { match: '\u5206\u4EAB\u94FE\u63A5', emoji: '\uD83D\uDD17' },\n { match: '\u6570\u636E\u63A8\u9001', emoji: '\uD83D\uDCE6' },\n { match: '\u5F39\u7A97', emoji: '\uD83E\uDE9F' },\n];\nconst STATUS_EMOJIS = [\n { match: '\u5F00\u59CB', emoji: '\uD83D\uDE80' },\n { match: '\u5B8C\u6210', emoji: '\u2705' },\n { match: '\u6210\u529F', emoji: '\u2705' },\n { match: '\u5931\u8D25', emoji: '\u274C' },\n { match: '\u8DF3\u8FC7', emoji: '\u23ED\uFE0F' },\n { match: '\u8D85\u65F6', emoji: '\u23F1\uFE0F' },\n { match: '\u91CD\u8BD5', emoji: '\uD83D\uDD01' },\n { match: '\u7ED3\u675F', emoji: '\uD83C\uDFC1' },\n { match: '\u5DF2\u914D\u7F6E', emoji: '\uD83E\uDDF7' },\n { match: '\u5DF2\u68C0\u6D4B', emoji: '\uD83D\uDD0E' },\n];\n\nconst toErrorMessage = (error) => {\n if (!error) return '';\n if (error instanceof Error) return error.message;\n if (typeof error === 'string') return error;\n try {\n return JSON.stringify(error);\n } catch {\n return String(error);\n }\n};\n\nconst decorateLabel = (label, mappings) => {\n if (!label) return '';\n const mapping = mappings.find((item) => label.includes(item.match));\n if (!mapping) return label;\n return `${mapping.emoji} ${label}`;\n};\n\nconst normalizeSnippet = (snippet, maxLen = 120) => {\n if (!snippet) return '';\n const text = String(snippet).replace(/\\s+/g, ' ').trim();\n if (!text) return '';\n const cleaned = text.replace(/\"/g, \"'\");\n if (cleaned.length <= maxLen) return cleaned;\n return `${cleaned.slice(0, maxLen)}...`;\n};\n\nconst LOG_TAG_PREFIX = '[#log:';\nconst LOG_TAG_SUFFIX = ']';\n\nconst buildLogTag = (key) => `${LOG_TAG_PREFIX}${key}${LOG_TAG_SUFFIX}`;\n\nconst escapeRegExp = (value) => String(value).replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\nconst buildStepPattern = (step, status) => {\n if (!step) return null;\n let pattern = `\u6B65\u9AA4: .*${escapeRegExp(step)}`;\n if (status) {\n pattern += `.*${escapeRegExp(status)}`;\n }\n return new RegExp(pattern);\n};\n\nconst buildDefinitionPatterns = (definition) => {\n const patterns = [new RegExp(`\\\\[#log:${escapeRegExp(definition.key)}\\\\]`)];\n const fallback = buildStepPattern(definition.step, definition.status);\n if (fallback) patterns.push(fallback);\n if (Array.isArray(definition.extraPatterns)) {\n patterns.push(...definition.extraPatterns);\n }\n return patterns;\n};\n\nconst ATTENTION_RANK = {\n low: 1,\n medium: 2,\n high: 3,\n critical: 4,\n};\nconst DEFAULT_ATTENTION_RANK = ATTENTION_RANK.high;\n\nconst LOG_DEFINITIONS = [\n {\n key: 'task_start',\n method: 'taskStart',\n label: '\u4EFB\u52A1\u5F00\u59CB',\n group: '\u4EFB\u52A1',\n step: '\u4EFB\u52A1',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n buildDetails: (url) => [url ? `url=${url}` : ''],\n },\n {\n key: 'task_success',\n method: 'taskSuccess',\n label: '\u4EFB\u52A1\u5B8C\u6210',\n group: '\u4EFB\u52A1',\n step: '\u4EFB\u52A1',\n status: '\u5B8C\u6210',\n level: 'success',\n attention: 'high',\n },\n {\n key: 'task_fail',\n method: 'taskFail',\n label: '\u4EFB\u52A1\u5931\u8D25',\n group: '\u4EFB\u52A1',\n step: '\u4EFB\u52A1',\n status: '\u5931\u8D25',\n level: 'error',\n attention: 'critical',\n buildDetails: (url, err) => [\n url ? `url=${url}` : '',\n err ? `err=${toErrorMessage(err)}` : ''\n ],\n },\n {\n key: 'runtime_headless',\n method: 'runtimeHeadless',\n label: '\u8FD0\u884C\u6A21\u5F0F\u5F3A\u5236\u65E0\u5934',\n group: '\u8FD0\u884C\u6A21\u5F0F',\n step: '\u8FD0\u884C\u6A21\u5F0F',\n status: 'Apify \u73AF\u5883\u5F3A\u5236\u65E0\u5934',\n level: 'warning',\n attention: 'medium',\n },\n {\n key: 'login_inject_success',\n method: 'loginInjectSuccess',\n label: '\u767B\u5F55\u6001\u6CE8\u5165\u6210\u529F',\n group: '\u767B\u5F55',\n step: '\u767B\u5F55\u6001\u6CE8\u5165',\n status: '\u6210\u529F',\n level: 'success',\n attention: 'medium',\n buildDetails: (detail) => [detail ? `detail=${detail}` : ''],\n },\n {\n key: 'login_inject_skip',\n method: 'loginInjectSkip',\n label: '\u767B\u5F55\u6001\u6CE8\u5165\u8DF3\u8FC7',\n group: '\u767B\u5F55',\n step: '\u767B\u5F55\u6001\u6CE8\u5165',\n status: '\u8DF3\u8FC7',\n level: 'warning',\n attention: 'medium',\n buildDetails: (reason) => [reason ? `\u539F\u56E0=${reason}` : ''],\n },\n {\n key: 'login_inject_fail',\n method: 'loginInjectFail',\n label: '\u767B\u5F55\u6001\u6CE8\u5165\u5931\u8D25',\n group: '\u767B\u5F55',\n step: '\u767B\u5F55\u6001\u6CE8\u5165',\n status: '\u5931\u8D25',\n level: 'error',\n attention: 'high',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n {\n key: 'login_verify_success',\n method: 'loginVerifySuccess',\n label: '\u767B\u5F55\u9A8C\u8BC1\u6210\u529F',\n group: '\u767B\u5F55',\n step: '\u767B\u5F55\u9A8C\u8BC1',\n status: '\u6210\u529F',\n level: 'success',\n attention: 'high',\n buildDetails: (detail) => [detail ? `detail=${detail}` : ''],\n },\n {\n key: 'login_verify_skip',\n method: 'loginVerifySkip',\n label: '\u767B\u5F55\u9A8C\u8BC1\u8DF3\u8FC7',\n group: '\u767B\u5F55',\n step: '\u767B\u5F55\u9A8C\u8BC1',\n status: '\u8DF3\u8FC7',\n level: 'warning',\n attention: 'medium',\n buildDetails: (reason) => [reason ? `\u539F\u56E0=${reason}` : ''],\n },\n {\n key: 'login_verify_fail',\n method: 'loginVerifyFail',\n label: '\u767B\u5F55\u9A8C\u8BC1\u5931\u8D25',\n group: '\u767B\u5F55',\n step: '\u767B\u5F55\u9A8C\u8BC1',\n status: '\u5931\u8D25',\n level: 'error',\n attention: 'critical',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n {\n key: 'env_check_success',\n method: 'envCheckSuccess',\n label: '\u73AF\u5883\u68C0\u67E5\u6210\u529F',\n group: '\u73AF\u5883',\n step: '\u73AF\u5883\u68C0\u67E5',\n status: '\u6210\u529F',\n level: 'success',\n attention: 'medium',\n buildDetails: (detail) => [detail ? `detail=${detail}` : ''],\n },\n {\n key: 'env_check_fail',\n method: 'envCheckFail',\n label: '\u73AF\u5883\u68C0\u67E5\u5931\u8D25',\n group: '\u73AF\u5883',\n step: '\u73AF\u5883\u68C0\u67E5',\n status: '\u5931\u8D25',\n level: 'error',\n attention: 'high',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n {\n key: 'input_query_start',\n method: 'inputQuery',\n label: '\u8F93\u5165\u67E5\u8BE2\u5F00\u59CB',\n group: '\u8F93\u5165',\n step: '\u8F93\u5165\u67E5\u8BE2',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n buildDetails: (query) => [query ? `query=${query}` : ''],\n },\n {\n key: 'send_action',\n method: 'sendAction',\n label: '\u53D1\u9001\u8BF7\u6C42',\n group: '\u53D1\u9001',\n step: '\u53D1\u9001\u8BF7\u6C42',\n status: '\u70B9\u51FB\u53D1\u9001',\n level: 'info',\n attention: 'low',\n },\n {\n key: 'response_listen_start',\n method: 'responseListenStart',\n label: '\u54CD\u5E94\u76D1\u542C\u5F00\u59CB',\n group: '\u54CD\u5E94\u76D1\u542C',\n step: '\u54CD\u5E94\u76D1\u542C',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n buildDetails: (label, timeoutSec) => [\n label ? `\u76EE\u6807=${label}` : '',\n timeoutSec ? `timeout=${timeoutSec}s` : ''\n ],\n },\n {\n key: 'response_listen_ready',\n method: 'responseListenReady',\n label: '\u54CD\u5E94\u76D1\u542C\u5DF2\u914D\u7F6E',\n group: '\u54CD\u5E94\u76D1\u542C',\n step: '\u54CD\u5E94\u76D1\u542C',\n status: '\u5DF2\u914D\u7F6E',\n level: 'info',\n attention: 'medium',\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\n },\n {\n key: 'response_listen_detected',\n method: 'responseListenDetected',\n label: '\u54CD\u5E94\u76D1\u542C\u5DF2\u68C0\u6D4B',\n group: '\u54CD\u5E94\u76D1\u542C',\n step: '\u54CD\u5E94\u76D1\u542C',\n status: '\u5DF2\u68C0\u6D4B',\n level: 'success',\n attention: 'medium',\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\n },\n {\n key: 'response_listen_timeout',\n method: 'responseListenTimeout',\n label: '\u54CD\u5E94\u76D1\u542C\u8D85\u65F6',\n group: '\u54CD\u5E94\u76D1\u542C',\n step: '\u54CD\u5E94\u76D1\u542C',\n status: '\u8D85\u65F6',\n level: 'error',\n attention: 'high',\n buildDetails: (label, err) => [\n label ? `\u76EE\u6807=${label}` : '',\n err ? `err=${toErrorMessage(err)}` : ''\n ],\n },\n {\n key: 'response_listen_end',\n method: 'responseListenEnd',\n label: '\u54CD\u5E94\u76D1\u542C\u7ED3\u675F',\n group: '\u54CD\u5E94\u76D1\u542C',\n step: '\u54CD\u5E94\u76D1\u542C',\n status: '\u7ED3\u675F',\n level: 'info',\n attention: 'low',\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\n },\n {\n key: 'response_wait_start',\n method: 'responseWaitStart',\n label: '\u7B49\u5F85\u54CD\u5E94\u5F00\u59CB',\n group: '\u7B49\u5F85\u54CD\u5E94',\n step: '\u7B49\u5F85\u54CD\u5E94',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\n },\n {\n key: 'response_wait_success',\n method: 'responseWaitSuccess',\n label: '\u7B49\u5F85\u54CD\u5E94\u5B8C\u6210',\n group: '\u7B49\u5F85\u54CD\u5E94',\n step: '\u7B49\u5F85\u54CD\u5E94',\n status: '\u5B8C\u6210',\n level: 'success',\n attention: 'medium',\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\n },\n {\n key: 'response_wait_fail',\n method: 'responseWaitFail',\n label: '\u7B49\u5F85\u54CD\u5E94\u5931\u8D25',\n group: '\u7B49\u5F85\u54CD\u5E94',\n step: '\u7B49\u5F85\u54CD\u5E94',\n status: '\u5931\u8D25',\n level: 'warning',\n attention: 'high',\n buildDetails: (label, err) => [\n label ? `\u76EE\u6807=${label}` : '',\n err ? `err=${toErrorMessage(err)}` : ''\n ],\n },\n {\n key: 'response_wait_retry',\n method: 'responseWaitRetry',\n label: '\u7B49\u5F85\u54CD\u5E94\u91CD\u8BD5',\n group: '\u7B49\u5F85\u54CD\u5E94',\n step: '\u7B49\u5F85\u54CD\u5E94',\n status: '\u91CD\u8BD5',\n level: 'warning',\n attention: 'medium',\n buildDetails: (label, attempt) => [\n label ? `\u76EE\u6807=${label}` : '',\n attempt !== undefined ? `\u5C1D\u8BD5=${attempt}` : ''\n ],\n },\n {\n key: 'dom_wait_start',\n method: 'domWaitStart',\n label: 'DOM\u7A33\u5B9A\u7B49\u5F85\u5F00\u59CB',\n group: 'DOM',\n step: 'DOM\u7A33\u5B9A',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\n },\n {\n key: 'dom_wait_fail',\n method: 'domWaitFail',\n label: 'DOM\u7A33\u5B9A\u7B49\u5F85\u5931\u8D25',\n group: 'DOM',\n step: 'DOM\u7A33\u5B9A',\n status: '\u5931\u8D25',\n level: 'warning',\n attention: 'high',\n buildDetails: (label, err) => [\n label ? `\u76EE\u6807=${label}` : '',\n err ? `err=${toErrorMessage(err)}` : ''\n ],\n },\n {\n key: 'dom_chunk',\n method: 'domChunk',\n label: 'DOM\u7247\u6BB5',\n group: 'DOM',\n step: 'DOM\u7247\u6BB5',\n status: '',\n level: 'info',\n attention: 'low',\n throttleKey: 'dom-chunk',\n throttleMs: 2000,\n buildDetails: (length, snippet, paused) => [\n length !== undefined ? `len=${length}` : '',\n snippet ? `preview=\"${normalizeSnippet(snippet)}\"` : '',\n paused ? 'paused=1' : ''\n ],\n },\n {\n key: 'dom_wait_success',\n method: 'domWaitSuccess',\n label: 'DOM\u7A33\u5B9A\u7B49\u5F85\u5B8C\u6210',\n group: 'DOM',\n step: 'DOM\u7A33\u5B9A',\n status: '\u5B8C\u6210',\n level: 'success',\n attention: 'medium',\n buildDetails: (mutationCount, stableTime, wasPaused) => [\n mutationCount !== undefined ? `mutations=${mutationCount}` : '',\n stableTime !== undefined ? `stableTime=${stableTime}ms` : '',\n wasPaused ? 'paused=1' : ''\n ],\n },\n {\n key: 'stream_chunk',\n method: 'streamChunk',\n label: '\u6D41\u5F0F\u7247\u6BB5',\n group: '\u6D41\u5F0F',\n step: '\u6D41\u5F0F\u7247\u6BB5',\n status: '',\n level: 'info',\n attention: 'low',\n throttleKey: 'stream-chunk',\n throttleMs: 2000,\n buildDetails: (length, snippet) => [\n length !== undefined ? `len=${length}` : '',\n snippet ? `preview=\"${normalizeSnippet(snippet)}\"` : ''\n ],\n },\n {\n key: 'stream_events_parsed',\n method: 'streamEventsParsed',\n label: '\u6D41\u5F0F\u4E8B\u4EF6\u89E3\u6790\u5B8C\u6210',\n group: '\u6D41\u5F0F',\n step: '\u6D41\u5F0F\u4E8B\u4EF6\u89E3\u6790',\n status: '\u5B8C\u6210',\n level: 'info',\n attention: 'low',\n throttleKey: 'stream-events',\n throttleMs: 4000,\n buildDetails: (count) => [count !== undefined ? `count=${count}` : ''],\n },\n {\n key: 'stream_complete_event',\n method: 'streamCompleteEvent',\n label: '\u6D41\u5F0F\u5B8C\u6210\u4E8B\u4EF6\u6355\u83B7',\n group: '\u6D41\u5F0F',\n step: '\u6D41\u5F0F\u4E8B\u4EF6',\n status: '\u5B8C\u6210\u4E8B\u4EF6\u5DF2\u6355\u83B7',\n level: 'success',\n attention: 'medium',\n },\n {\n key: 'stream_end',\n method: 'streamEnd',\n label: '\u6D41\u5F0F\u54CD\u5E94\u7ED3\u675F',\n group: '\u6D41\u5F0F',\n step: '\u6D41\u5F0F\u54CD\u5E94',\n status: '\u7ED3\u675F',\n level: 'info',\n attention: 'low',\n },\n {\n key: 'reference_expand_start',\n method: 'referenceExpandStart',\n label: '\u5F15\u7528\u5C55\u5F00\u5F00\u59CB',\n group: '\u5F15\u7528',\n step: '\u5F15\u7528\u5C55\u5F00',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\n },\n {\n key: 'reference_expand_fail',\n method: 'referenceExpandFail',\n label: '\u5F15\u7528\u5C55\u5F00\u5931\u8D25',\n group: '\u5F15\u7528',\n step: '\u5F15\u7528\u5C55\u5F00',\n status: '\u5931\u8D25',\n level: 'warning',\n attention: 'medium',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n {\n key: 'screenshot_start',\n method: 'screenshotStart',\n label: '\u622A\u56FE\u5F00\u59CB',\n group: '\u622A\u56FE',\n step: '\u622A\u56FE',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n },\n {\n key: 'screenshot_success',\n method: 'screenshotSuccess',\n label: '\u622A\u56FE\u6210\u529F',\n group: '\u622A\u56FE',\n step: '\u622A\u56FE',\n status: '\u6210\u529F',\n level: 'success',\n attention: 'high',\n },\n {\n key: 'screenshot_fail',\n method: 'screenshotFail',\n label: '\u622A\u56FE\u5931\u8D25',\n group: '\u622A\u56FE',\n step: '\u622A\u56FE',\n status: '\u5931\u8D25',\n level: 'warning',\n attention: 'high',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n {\n key: 'share_start',\n method: 'shareStart',\n label: '\u5206\u4EAB\u94FE\u63A5\u5F00\u59CB',\n group: '\u5206\u4EAB',\n step: '\u5206\u4EAB\u94FE\u63A5',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n },\n {\n key: 'share_progress',\n method: 'shareProgress',\n label: '\u5206\u4EAB\u94FE\u63A5\u6B65\u9AA4',\n group: '\u5206\u4EAB',\n step: '\u5206\u4EAB\u94FE\u63A5',\n status: '\u6B65\u9AA4',\n level: 'info',\n attention: 'low',\n buildDetails: (label) => [label ? `\u6B65\u9AA4=${label}` : ''],\n },\n {\n key: 'share_dom_hit',\n method: 'shareDomHit',\n label: '\u5206\u4EAB\u94FE\u63A5DOM\u547D\u4E2D',\n group: '\u5206\u4EAB',\n step: '\u5206\u4EAB\u94FE\u63A5',\n status: 'DOM\u547D\u4E2D',\n level: 'info',\n attention: 'low',\n buildDetails: (link, domSnapshot) => [\n link ? `\u94FE\u63A5=${link}` : '',\n domSnapshot ? `DOM=${normalizeSnippet(domSnapshot, 220)}` : ''\n ],\n },\n {\n key: 'share_source',\n method: 'shareSource',\n label: '\u5206\u4EAB\u94FE\u63A5\u6765\u6E90',\n group: '\u5206\u4EAB',\n step: '\u5206\u4EAB\u94FE\u63A5',\n status: '\u6765\u6E90',\n level: 'info',\n attention: 'low',\n buildDetails: (source, link, domSnapshot) => [\n source ? `\u6765\u6E90=${source}` : '',\n link ? `\u94FE\u63A5=${link}` : '',\n source === 'dom' && domSnapshot ? `DOM=${normalizeSnippet(domSnapshot, 220)}` : ''\n ],\n },\n {\n key: 'share_success',\n method: 'shareSuccess',\n label: '\u5206\u4EAB\u94FE\u63A5\u6210\u529F',\n group: '\u5206\u4EAB',\n step: '\u5206\u4EAB\u94FE\u63A5',\n status: '\u6210\u529F',\n level: 'success',\n attention: 'high',\n buildDetails: (link) => [link ? `\u94FE\u63A5=${link}` : ''],\n },\n {\n key: 'share_fail',\n method: 'shareFail',\n label: '\u5206\u4EAB\u94FE\u63A5\u5931\u8D25',\n group: '\u5206\u4EAB',\n step: '\u5206\u4EAB\u94FE\u63A5',\n status: '\u5931\u8D25',\n level: 'warning',\n attention: 'high',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n {\n key: 'share_skip',\n method: 'shareSkip',\n label: '\u5206\u4EAB\u94FE\u63A5\u8DF3\u8FC7',\n group: '\u5206\u4EAB',\n step: '\u5206\u4EAB\u94FE\u63A5',\n status: '\u8DF3\u8FC7',\n level: 'warning',\n attention: 'medium',\n buildDetails: (reason) => [reason ? `\u539F\u56E0=${reason}` : ''],\n },\n {\n key: 'data_push_success',\n method: 'dataPushSuccess',\n label: '\u6570\u636E\u63A8\u9001\u6210\u529F',\n group: '\u6570\u636E\u63A8\u9001',\n step: '\u6570\u636E\u63A8\u9001',\n status: '\u6210\u529F',\n level: 'success',\n attention: 'medium',\n buildDetails: (label) => [label ? `\u8BF4\u660E=${label}` : ''],\n },\n {\n key: 'data_push_fail',\n method: 'dataPushFail',\n label: '\u6570\u636E\u63A8\u9001\u5931\u8D25',\n group: '\u6570\u636E\u63A8\u9001',\n step: '\u6570\u636E\u63A8\u9001',\n status: '\u5931\u8D25',\n level: 'error',\n attention: 'high',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n {\n key: 'popup_detected',\n method: 'popupDetected',\n label: '\u5F39\u7A97\u68C0\u6D4B',\n group: '\u5F39\u7A97',\n step: '\u5F39\u7A97\u5904\u7406',\n status: '\u68C0\u6D4B\u5230\u906E\u7F69',\n level: 'warning',\n attention: 'medium',\n buildDetails: (detail) => [detail ? `detail=${detail}` : ''],\n },\n {\n key: 'popup_close_attempt',\n method: 'popupCloseAttempt',\n label: '\u5F39\u7A97\u5173\u95ED\u5C1D\u8BD5',\n group: '\u5F39\u7A97',\n step: '\u5F39\u7A97\u5904\u7406',\n status: '\u5C1D\u8BD5\u5173\u95ED',\n level: 'info',\n attention: 'low',\n buildDetails: (detail) => [detail ? `detail=${detail}` : ''],\n },\n {\n key: 'popup_close_success',\n method: 'popupCloseSuccess',\n label: '\u5F39\u7A97\u5173\u95ED\u5B8C\u6210',\n group: '\u5F39\u7A97',\n step: '\u5F39\u7A97\u5904\u7406',\n status: '\u5173\u95ED\u5B8C\u6210',\n level: 'success',\n attention: 'medium',\n },\n {\n key: 'popup_close_fail',\n method: 'popupCloseFail',\n label: '\u5F39\u7A97\u5173\u95ED\u5931\u8D25',\n group: '\u5F39\u7A97',\n step: '\u5F39\u7A97\u5904\u7406',\n status: '\u5173\u95ED\u5931\u8D25',\n level: 'warning',\n attention: 'medium',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n];\n\nexport const LOG_TEMPLATES = LOG_DEFINITIONS.map((definition) => {\n const attention = definition.attention || 'medium';\n const attentionRank = ATTENTION_RANK[attention] || ATTENTION_RANK.medium;\n const defaultSelected = attentionRank >= DEFAULT_ATTENTION_RANK;\n return {\n key: definition.key,\n label: definition.label,\n group: definition.group,\n attention,\n patterns: buildDefinitionPatterns(definition),\n defaultSelected,\n };\n});\n\nconst buildStepLine = (step, status, details = []) => {\n const parts = [];\n const decoratedStep = step ? decorateLabel(step, STEP_EMOJIS) : '';\n const base = decoratedStep ? `${STEP_PREFIX} ${decoratedStep}` : STEP_PREFIX;\n parts.push(base.trim());\n if (status) parts.push(decorateLabel(status, STATUS_EMOJIS));\n const detailParts = details.filter(Boolean);\n if (detailParts.length > 0) {\n parts.push(...detailParts);\n }\n return parts.join(STEP_SEPARATOR);\n};\n\nconst createThrottle = () => {\n const lastMap = new Map();\n return (key, intervalMs, fn) => {\n const now = Date.now();\n const last = lastMap.get(key) || 0;\n if (now - last >= intervalMs) {\n lastMap.set(key, now);\n fn();\n }\n };\n};\n\nexport const createTemplateLogger = (baseLogger = createBaseLogger()) => {\n const throttle = createThrottle();\n\n const info = (line) => baseLogger.info(line);\n const success = (line) => baseLogger.success(line);\n const warning = (line) => baseLogger.warning(line);\n const error = (line) => baseLogger.error(line);\n const debug = (line) => baseLogger.debug(line);\n const start = (line) => baseLogger.start(line);\n\n const stepInfo = (step, status, details = []) => info(buildStepLine(step, status, details));\n const stepSuccess = (step, status, details = []) => success(buildStepLine(step, status, details));\n const stepWarn = (step, status, details = []) => warning(buildStepLine(step, status, details));\n const stepError = (step, status, details = []) => error(buildStepLine(step, status, details));\n const stepStart = (step, status, details = []) => start(buildStepLine(step, status, details));\n\n const stepHandlers = {\n info: stepInfo,\n success: stepSuccess,\n warning: stepWarn,\n error: stepError,\n start: stepStart,\n };\n\n const logFromDefinition = (definition, details = []) => {\n const handler = stepHandlers[definition.level] || stepInfo;\n const payload = [...details, buildLogTag(definition.key)];\n const emit = () => handler(definition.step, definition.status, payload);\n if (definition.throttleMs) {\n throttle(definition.throttleKey || definition.key, definition.throttleMs, emit);\n return;\n }\n emit();\n };\n\n const definitionMethods = {};\n LOG_DEFINITIONS.forEach((definition) => {\n if (!definition.method) return;\n definitionMethods[definition.method] = (...args) => {\n const details = definition.buildDetails ? definition.buildDetails(...args) : [];\n logFromDefinition(definition, details);\n };\n });\n\n return {\n step: (step, status, details, level = 'info') => {\n if (level === 'error') return stepError(step, status, details);\n if (level === 'warn' || level === 'warning') return stepWarn(step, status, details);\n if (level === 'start') return stepStart(step, status, details);\n if (level === 'success') return stepSuccess(step, status, details);\n return stepInfo(step, status, details);\n },\n info: (message) => info(message),\n success: (message) => success(message),\n warning: (message) => warning(message),\n warn: (message) => warning(message),\n error: (message) => error(message),\n debug: (message) => debug(message),\n start: (message) => start(message),\n ...definitionMethods,\n };\n};\n\nconst getDefaultBaseLogger = () => createBaseLogger('');\n\nexport const Logger = {\n setLogger: (logger) => setDefaultLogger(logger),\n info: (message) => getDefaultBaseLogger().info(message),\n success: (message) => getDefaultBaseLogger().success(message),\n warning: (message) => getDefaultBaseLogger().warning(message),\n warn: (message) => getDefaultBaseLogger().warning(message),\n error: (message) => getDefaultBaseLogger().error(message),\n debug: (message) => getDefaultBaseLogger().debug(message),\n start: (message) => getDefaultBaseLogger().start(message),\n useTemplate: (logger) => {\n if (logger) return createTemplateLogger(createBaseLogger('', logger));\n return createTemplateLogger();\n },\n};\n", "import delay from 'delay';\nimport { Utils } from './utils.js';\nimport { Mutation } from './mutation.js';\nimport { createInternalLogger } from './internals/logger.js';\n\nconst logger = createInternalLogger('Share');\n\nconst DEFAULT_TIMEOUT_MS = 50 * 1000;\nconst DEFAULT_PAYLOAD_SNAPSHOT_MAX_LEN = 500;\nconst DEFAULT_POLL_INTERVAL_MS = 120;\n\nconst normalizePrefix = (value) => String(value || '').trim();\n\nconst toSnapshot = (value, maxLen) => {\n const text = String(value || '');\n if (!text) return '';\n return text.replace(/\\s+/g, ' ').trim().slice(0, maxLen);\n};\n\nconst toInline = (value, maxLen = 200) => {\n const text = String(value || '');\n if (!text) return '';\n return text.replace(/\\s+/g, ' ').trim().slice(0, maxLen);\n};\n\nconst toJsonInline = (value, maxLen = 260) => {\n try {\n return toInline(JSON.stringify(value), maxLen);\n } catch {\n return '[\u4E0D\u53EF\u5E8F\u5217\u5316]';\n }\n};\n\nconst normalizeXurl = (value) => {\n if (!Array.isArray(value)) return [];\n\n const normalizeMatcherList = (input) => {\n if (Array.isArray(input)) {\n return input\n .map((item) => String(item || '').trim().replace(/\\.+$/, ''))\n .filter(Boolean);\n }\n\n const single = String(input || '').trim().replace(/\\.+$/, '');\n return single ? [single] : [];\n };\n\n const normalizeSegments = (input) => {\n if (Array.isArray(input)) {\n return input\n .map((item) => String(item || '').trim().replace(/\\.+$/, ''))\n .filter(Boolean);\n }\n\n const raw = String(input || '').trim();\n if (!raw) return [];\n\n return raw\n .split('.')\n .map((item) => String(item || '').trim().replace(/\\.+$/, ''))\n .filter(Boolean);\n };\n\n const normalized = [];\n\n const apiMatchers = normalizeMatcherList(value[0]);\n if (apiMatchers.length > 0) {\n normalized.push(apiMatchers);\n }\n\n const flattenedPath = [];\n const extraPaths = [];\n\n value.slice(1).forEach((item) => {\n if (Array.isArray(item)) {\n const segments = normalizeSegments(item);\n if (segments.length > 0) {\n extraPaths.push(segments);\n }\n return;\n }\n\n const segments = normalizeSegments(item);\n if (segments.length > 0) {\n flattenedPath.push(...segments);\n }\n });\n\n if (flattenedPath.length > 0) {\n normalized.push(flattenedPath);\n }\n\n if (extraPaths.length > 0) {\n normalized.push(...extraPaths);\n }\n\n return normalized;\n};\n\nconst normalizeShare = (share) => {\n const source = share && typeof share === 'object' ? share : {};\n const modeRaw = String(source.mode || 'dom').trim().toLowerCase();\n const mode = modeRaw === 'response' ? 'response' : 'dom';\n\n return {\n mode,\n prefix: normalizePrefix(source.prefix),\n xurl: normalizeXurl(source.xurl),\n };\n};\n\nconst getByPathSegments = (source, pathSegments) => {\n if (!Array.isArray(pathSegments) || pathSegments.length === 0) return undefined;\n\n let current = source;\n\n for (const rawSegment of pathSegments) {\n const segment = String(rawSegment || '').trim();\n if (!segment) return undefined;\n if (current == null) return undefined;\n\n if (Array.isArray(current) && /^\\d+$/.test(segment)) {\n current = current[Number(segment)];\n continue;\n }\n\n current = current[segment];\n }\n\n return current;\n};\n\nconst buildShareLink = (prefix, value) => {\n const raw = String(value || '').trim();\n if (!raw) return '';\n\n if (/^https?:\\/\\//i.test(raw)) {\n return raw;\n }\n\n const safePrefix = normalizePrefix(prefix);\n if (!safePrefix) return '';\n\n const prefixNoSlash = safePrefix.endsWith('/') ? safePrefix.slice(0, -1) : safePrefix;\n const valueNoSlash = raw.replace(/^\\/+/, '');\n\n return `${prefixNoSlash}/${valueNoSlash}`;\n};\n\nconst parseJsonSafely = (text) => {\n const raw = String(text || '').trim();\n if (!raw) return null;\n\n try {\n return JSON.parse(raw);\n } catch {\n return null;\n }\n};\n\nconst createDomShareMonitor = async (page, options = {}) => {\n const prefix = normalizePrefix(options.prefix);\n const selectors = options.selectors ?? 'html';\n const mode = options.mode ?? Mutation.Mode.All;\n const onMatch = typeof options.onMatch === 'function' ? options.onMatch : null;\n const onTelemetry = typeof options.onTelemetry === 'function' ? options.onTelemetry : null;\n\n let matched = false;\n\n logger.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode}`);\n\n const monitor = await Mutation.useMonitor(page, selectors, {\n mode,\n onMutation: (context = {}) => {\n if (matched) return;\n\n const mutationCount = Number(context.mutationCount || 0);\n const mutationNodes = Array.isArray(context.mutationNodes) ? context.mutationNodes : [];\n const html = String(context.html || '');\n const text = String(context.text || '');\n const rawDom = `${html}\\n${text}`;\n\n if (onTelemetry) {\n onTelemetry({\n mutationCount,\n mutationNodesCount: mutationNodes.length,\n });\n }\n\n if (mutationCount <= 5 || mutationCount % 50 === 0) {\n logger.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);\n }\n\n const [candidate] = Utils.parseLinks(rawDom, { prefix }) || [];\n if (!candidate) return;\n\n matched = true;\n logger.success('captureLink.domHit', `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);\n\n if (onMatch) {\n onMatch({\n link: candidate,\n rawDom,\n mutationCount,\n html,\n text,\n mutationNodes,\n });\n }\n },\n });\n\n return {\n stop: async () => {\n const result = await monitor.stop();\n logger.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);\n return result;\n },\n };\n};\n\nexport const Share = {\n /**\n * \u6355\u83B7\u5206\u4EAB\u94FE\u63A5\uFF08\u5355\u6A21\u5F0F\uFF09\n * - mode='dom': \u4EC5 DOM \u76D1\u542C\n * - mode='response': \u4EC5\u63A5\u53E3\u76D1\u542C\n *\n * @param {import('playwright').Page} page\n * @param {Object} [options]\n * @param {{ mode?: 'dom' | 'response', prefix: string, xurl?: Array<string | string[]> }} options.share\n * @param {number} [options.timeoutMs=50000]\n * @param {number} [options.payloadSnapshotMaxLen=500]\n * @param {string | string[]} [options.domSelectors='html']\n * @param {'added' | 'changed' | 'all'} [options.domMode='all']\n * @param {() => Promise<void>} [options.performActions]\n * @returns {Promise<{ link: string | null; payloadText: string; payloadSnapshot: string; source: 'dom' | 'response' | 'none' }>}\n */\n async captureLink(page, options = {}) {\n const share = normalizeShare(options.share);\n const timeoutMs = Math.max(0, Number(options.timeoutMs ?? DEFAULT_TIMEOUT_MS) || 0);\n const payloadSnapshotMaxLen = options.payloadSnapshotMaxLen ?? DEFAULT_PAYLOAD_SNAPSHOT_MAX_LEN;\n const domSelectors = options.domSelectors ?? 'html';\n const domMode = options.domMode ?? Mutation.Mode.All;\n const performActions = typeof options.performActions === 'function' ? options.performActions : async () => { };\n\n if (!share.prefix) {\n throw new Error('Share.captureLink requires options.share.prefix');\n }\n\n if (share.mode !== 'dom' && share.mode !== 'response') {\n throw new Error(`Share.captureLink unsupported share.mode: ${share.mode}`);\n }\n\n const apiMatchers = share.mode === 'response' ? (share.xurl[0] || []) : [];\n const fieldPaths = share.mode === 'response' ? share.xurl.slice(1) : [];\n\n if (share.mode === 'response' && apiMatchers.length === 0) {\n throw new Error('Share.captureLink requires share.xurl[0] api matcher when mode=response');\n }\n\n logger.start('captureLink', `mode=${share.mode}, timeoutMs=${timeoutMs}, prefix=${share.prefix}`);\n logger.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);\n\n const stats = {\n actionTimedOut: false,\n domMutationCount: 0,\n domMutationNodes: 0,\n responseObserved: 0,\n responseMatched: 0,\n responseResolved: 0,\n lastMatchedUrl: '',\n responseSampleUrls: [],\n };\n\n const candidates = {\n dom: null,\n response: null,\n };\n\n const setCandidate = (source, link, payloadText = '') => {\n const safe = String(link || '').trim();\n if (!safe) return false;\n\n const [validated] = Utils.parseLinks(safe, { prefix: share.prefix }) || [];\n if (!validated) return false;\n\n if (candidates[source]?.link) return false;\n\n candidates[source] = {\n link: validated,\n payloadText: String(payloadText || ''),\n };\n\n logger.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);\n return true;\n };\n\n const resolveResponseCandidate = (responseText) => {\n const rawText = String(responseText || '');\n if (!rawText) return null;\n\n const [direct] = Utils.parseLinks(rawText, { prefix: share.prefix }) || [];\n if (direct) {\n return { link: direct, payloadText: rawText };\n }\n\n if (fieldPaths.length === 0) return null;\n\n const payload = parseJsonSafely(rawText);\n if (!payload || typeof payload !== 'object') return null;\n\n for (const pathSegments of fieldPaths) {\n const value = getByPathSegments(payload, pathSegments);\n if (value == null || value === '') continue;\n\n const composed = buildShareLink(share.prefix, value);\n if (!composed) continue;\n\n const [validated] = Utils.parseLinks(composed, { prefix: share.prefix }) || [];\n if (!validated) continue;\n\n return {\n link: validated,\n payloadText: rawText,\n };\n }\n\n return null;\n };\n\n let domMonitor = null;\n\n const stopDomMonitor = async () => {\n if (!domMonitor) return;\n const monitor = domMonitor;\n domMonitor = null;\n try {\n await monitor.stop();\n } catch (error) {\n logger.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);\n }\n };\n\n const onResponse = async (response) => {\n if (share.mode !== 'response') return;\n if (candidates.response?.link) return;\n\n stats.responseObserved += 1;\n\n try {\n const url = String(response.url() || '');\n\n if (url && stats.responseSampleUrls.length < 8 && !stats.responseSampleUrls.includes(url)) {\n stats.responseSampleUrls.push(url);\n }\n\n if (stats.responseObserved <= 5) {\n logger.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);\n }\n\n if (!apiMatchers.some((matcher) => url.includes(matcher))) return;\n\n stats.responseMatched += 1;\n stats.lastMatchedUrl = url;\n logger.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);\n\n const text = await response.text();\n const hit = resolveResponseCandidate(text);\n if (!hit?.link) {\n if (stats.responseMatched <= 3) {\n logger.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);\n }\n return;\n }\n\n stats.responseResolved += 1;\n logger.success('captureLink.responseHit', `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);\n setCandidate('response', hit.link, hit.payloadText);\n } catch (error) {\n logger.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);\n }\n };\n\n if (share.mode === 'dom') {\n logger.info('\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C');\n domMonitor = await createDomShareMonitor(page, {\n prefix: share.prefix,\n selectors: domSelectors,\n mode: domMode,\n onTelemetry: ({ mutationCount, mutationNodesCount }) => {\n stats.domMutationCount = mutationCount;\n stats.domMutationNodes = mutationNodesCount;\n },\n onMatch: ({ link, rawDom }) => {\n setCandidate('dom', link, rawDom);\n },\n });\n }\n\n if (share.mode === 'response') {\n logger.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);\n page.on('response', onResponse);\n }\n\n const deadline = Date.now() + timeoutMs;\n const getRemainingMs = () => Math.max(0, deadline - Date.now());\n\n try {\n const actionTimeout = getRemainingMs();\n logger.start('captureLink.performActions', `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${actionTimeout}ms`);\n\n if (actionTimeout > 0) {\n let timer = null;\n let actionError = null;\n\n const actionPromise = Promise.resolve()\n .then(() => performActions())\n .then(() => '__ACTION_DONE__')\n .catch((error) => {\n actionError = error;\n return '__ACTION_ERROR__';\n });\n\n const timeoutPromise = new Promise((resolve) => {\n timer = setTimeout(() => resolve('__ACTION_TIMEOUT__'), actionTimeout);\n });\n\n const actionResult = await Promise.race([actionPromise, timeoutPromise]);\n if (timer) clearTimeout(timer);\n\n if (actionResult === '__ACTION_ERROR__') {\n logger.fail('captureLink.performActions', actionError);\n throw actionError;\n }\n\n if (actionResult === '__ACTION_TIMEOUT__') {\n stats.actionTimedOut = true;\n logger.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);\n } else {\n logger.success('captureLink.performActions', '\u6267\u884C\u52A8\u4F5C\u5B8C\u6210');\n }\n }\n\n let nextProgressLogTs = Date.now() + 3000;\n\n while (true) {\n const selected = share.mode === 'dom' ? candidates.dom : candidates.response;\n if (selected?.link) {\n logger.success('captureLink', `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);\n return {\n link: selected.link,\n payloadText: selected.payloadText,\n payloadSnapshot: toSnapshot(selected.payloadText, payloadSnapshotMaxLen),\n source: share.mode,\n };\n }\n\n const remaining = getRemainingMs();\n if (remaining <= 0) break;\n\n const now = Date.now();\n if (now >= nextProgressLogTs) {\n logger.info(\n `captureLink \u7B49\u5F85\u4E2D: remaining=${remaining}ms, domMutationCount=${stats.domMutationCount}, responseMatched=${stats.responseMatched}`\n );\n nextProgressLogTs = now + 5000;\n }\n\n await delay(Math.max(0, Math.min(DEFAULT_POLL_INTERVAL_MS, remaining)));\n }\n\n if (share.mode === 'response' && stats.responseMatched === 0) {\n logger.warning(\n `\u63A5\u53E3\u76D1\u542C\u672A\u547D\u4E2D: apiMatchers=${toJsonInline(apiMatchers, 220)}, \u54CD\u5E94\u6837\u672CURLs=${toJsonInline(stats.responseSampleUrls, 420)}`\n );\n }\n\n logger.warning(\n `captureLink \u8D85\u65F6\u672A\u62FF\u5230\u94FE\u63A5: mode=${share.mode}, actionTimedOut=${stats.actionTimedOut}, domMutationCount=${stats.domMutationCount}, responseObserved=${stats.responseObserved}, responseMatched=${stats.responseMatched}, lastMatchedUrl=${stats.lastMatchedUrl || 'none'}`\n );\n\n return {\n link: null,\n payloadText: '',\n payloadSnapshot: '',\n source: 'none',\n };\n } finally {\n if (share.mode === 'response') {\n page.off('response', onResponse);\n logger.info('response \u76D1\u542C\u5DF2\u5378\u8F7D');\n }\n await stopDomMonitor();\n }\n },\n\n\n /**\n * \u5168\u9875\u9762\u6EDA\u52A8\u622A\u56FE\uFF08\u57FA\u7840\u80FD\u529B\uFF09\n *\n * @param {import('playwright').Page} page\n * @param {Object} [options]\n * @param {number} [options.buffer]\n * @param {boolean} [options.restore]\n * @param {number} [options.maxHeight]\n * @returns {Promise<string>} base64 png\n */\n async captureScreen(page, options = {}) {\n const originalViewport = page.viewportSize();\n const defaultBuffer = Math.round((originalViewport?.height || 1080) / 2);\n const buffer = options.buffer ?? defaultBuffer;\n const restore = options.restore ?? false;\n const maxHeight = options.maxHeight ?? 8000;\n\n try {\n const maxScrollHeight = await page.evaluate(() => {\n let maxHeight = document.body.scrollHeight;\n\n document.querySelectorAll('*').forEach(el => {\n const style = window.getComputedStyle(el);\n const overflowY = style.overflowY;\n\n if ((overflowY === 'auto' || overflowY === 'scroll') &&\n el.scrollHeight > el.clientHeight) {\n if (el.scrollHeight > maxHeight) {\n maxHeight = el.scrollHeight;\n }\n\n el.dataset.pkOrigOverflow = el.style.overflow;\n el.dataset.pkOrigHeight = el.style.height;\n el.dataset.pkOrigMaxHeight = el.style.maxHeight;\n el.classList.add('__pk_expanded__');\n\n el.style.overflow = 'visible';\n el.style.height = 'auto';\n el.style.maxHeight = 'none';\n }\n });\n\n return maxHeight;\n });\n\n const targetHeight = Math.min(maxScrollHeight + buffer, maxHeight);\n\n await page.setViewportSize({\n width: originalViewport?.width || 1280,\n height: targetHeight,\n });\n\n await delay(1000);\n\n const buffer_ = await page.screenshot({\n fullPage: true,\n type: 'png',\n });\n\n return buffer_.toString('base64');\n } finally {\n if (restore) {\n await page.evaluate(() => {\n document.querySelectorAll('.__pk_expanded__').forEach(el => {\n el.style.overflow = el.dataset.pkOrigOverflow || '';\n el.style.height = el.dataset.pkOrigHeight || '';\n el.style.maxHeight = el.dataset.pkOrigMaxHeight || '';\n\n delete el.dataset.pkOrigOverflow;\n delete el.dataset.pkOrigHeight;\n delete el.dataset.pkOrigMaxHeight;\n el.classList.remove('__pk_expanded__');\n });\n });\n\n if (originalViewport) {\n await page.setViewportSize(originalViewport);\n }\n }\n }\n },\n};\n"],
4
+ "sourcesContent": ["import { log as crawleeLog } from 'crawlee';\nimport { ApifyKit } from '../src/apify-kit';\nimport { Utils } from '../src/utils';\nimport { AntiCheat } from '../src/anti-cheat';\nimport { Humanize } from '../src/humanize';\nimport { Launch } from '../src/launch';\nimport { LiveView } from '../src/live-view';\nimport { Captcha } from '../src/captcha-monitor';\nimport { Sse } from '../src/sse';\nimport { Interception } from '../src/interception';\nimport { Mutation } from '../src/mutation';\nimport { Display } from '../src/display.js';\nimport * as Constants from '../src/constants';\nimport * as Errors from '../src/errors';\nimport { Logger, LOG_TEMPLATES, stripAnsi } from '../src/logger';\nimport { Share } from '../src/share';\n\n// \u4FEE\u6539\u9ED8\u8BA4logger \u4ECEconsole.log \u5230 crawleeLog\nLogger.setLogger(crawleeLog);\n\n// Unified Entry Point\nexport const usePlaywrightToolKit = () => {\n return {\n ApifyKit,\n AntiCheat,\n Humanize,\n Launch,\n LiveView,\n Constants,\n Utils,\n Captcha,\n Sse,\n Errors,\n Interception,\n Mutation,\n Display,\n Logger,\n Share,\n $Internals: { LOG_TEMPLATES, stripAnsi }\n };\n};\n", "export const Code = {\n Success: 0,\n UnknownError: -1,\n NotLogin: 30000001,\n Chaptcha: 30000002,\n Timeout: 30000003,\n InitialTimeout: 30000004,\n OverallTimeout: 30000005,\n}\n\nexport const Status = {\n Success: 'SUCCESS',\n Failed: 'FAILED'\n}\n\nexport const PresetOfLiveViewKey = 'LIVE_VIEW_SCREENSHOT';\n\n\nconst createActorInfo = (info) => {\n const normalizeDomain = (value) => {\n if (!value) return '';\n return String(value).trim().replace(/^https?:\\/\\//, '').replace(/\\/.*$/, '');\n };\n\n const normalizePath = (value) => {\n if (!value) return '/';\n const raw = String(value).trim();\n if (!raw) return '/';\n return raw.startsWith('/') ? raw : `/${raw}`;\n };\n\n const normalizeShare = (value) => {\n const raw = value && typeof value === 'object' ? value : {};\n\n const modeRaw = String(raw.mode || 'dom').trim().toLowerCase();\n const mode = modeRaw === 'response' ? 'response' : 'dom';\n\n const prefix = String(raw.prefix || '').trim();\n\n const rawXurl = Array.isArray(raw.xurl)\n ? raw.xurl\n : [];\n\n const normalizeMatcherList = (input) => {\n if (Array.isArray(input)) {\n return input\n .map((item) => String(item || '').trim().replace(/\\.+$/, ''))\n .filter(Boolean);\n }\n\n const single = String(input || '').trim().replace(/\\.+$/, '');\n return single ? [single] : [];\n };\n\n const normalizeSegments = (input) => {\n if (Array.isArray(input)) {\n return input\n .map((item) => String(item || '').trim().replace(/\\.+$/, ''))\n .filter(Boolean);\n }\n\n const rawPath = String(input || '').trim();\n if (!rawPath) return [];\n\n return rawPath\n .split('.')\n .map((segment) => String(segment || '').trim().replace(/\\.+$/, ''))\n .filter(Boolean);\n };\n\n const xurl = [];\n\n const matcherList = normalizeMatcherList(rawXurl[0]);\n if (matcherList.length > 0) {\n xurl.push(matcherList);\n }\n\n const flatPath = [];\n const extraPaths = [];\n\n rawXurl.slice(1).forEach((item) => {\n if (Array.isArray(item)) {\n const segments = normalizeSegments(item);\n if (segments.length > 0) {\n extraPaths.push(segments);\n }\n return;\n }\n\n const segments = normalizeSegments(item);\n if (segments.length > 0) {\n flatPath.push(...segments);\n }\n });\n\n if (flatPath.length > 0) {\n xurl.push(flatPath);\n }\n\n if (extraPaths.length > 0) {\n xurl.push(...extraPaths);\n }\n\n return {\n mode,\n prefix,\n xurl,\n };\n };\n\n const buildLandingUrl = ({ protocol, domain, path }) => {\n const safeProtocol = String(protocol).trim();\n const safeDomain = normalizeDomain(domain);\n const safePath = normalizePath(path);\n return `${safeProtocol}://${safeDomain}${safePath}`;\n };\n\n const buildIcon = ({ key }) => {\n return `https://heartbitai.com/general/actors/${key}.png`;\n }\n\n\n const protocol = info.protocol || 'https';\n const domain = normalizeDomain(info.domain);\n const path = normalizePath(info.path);\n const share = normalizeShare(info.share);\n\n return {\n ...info,\n protocol,\n domain,\n path,\n share,\n get icon() {\n if (info.icon) return info.icon;\n return buildIcon(this);\n },\n get landingUrl() {\n return buildLandingUrl(this);\n },\n };\n};\n\nexport const ActorInfo = {\n doubao: createActorInfo({\n key: 'doubao',\n name: '\u8C46\u5305',\n domain: 'www.doubao.com',\n path: '/',\n share: {\n mode: 'response',\n prefix: 'https://www.doubao.com/thread/',\n xurl: [\n '/samantha/thread/share/save',\n 'data', 'share_id',\n ],\n },\n }),\n deepseek: createActorInfo({\n key: 'deepseek',\n name: 'DeepSeek',\n domain: 'chat.deepseek.com',\n path: '/',\n share: {\n mode: 'response',\n prefix: 'https://chat.deepseek.com/share/',\n xurl: [\n '/api/v0/share/create',\n 'data', 'biz_data', 'share_id',\n ],\n },\n }),\n erine: createActorInfo({\n key: 'erine',\n name: '\u6587\u5FC3\u4E00\u8A00',\n domain: 'yiyan.baidu.com',\n path: '/',\n share: {\n mode: 'response',\n prefix: 'https://yiyan.baidu.com/share/',\n xurl: [\n '/eb/share/key/gen',\n 'data', 'key',\n ],\n },\n }),\n erinechat: createActorInfo({\n key: 'erinechat',\n name: '\u6587\u5FC3\u52A9\u624B',\n domain: 'chat.baidu.com',\n path: '/',\n share: {\n mode: 'response',\n prefix: '',\n xurl: [\n '/aichat/api/shortURL',\n 'data', 'short_url',\n ],\n },\n }),\n yuanbao: createActorInfo({\n key: 'yuanbao',\n name: '\u5143\u5B9D',\n domain: 'yuanbao.tencent.com',\n path: '/chat/',\n share: {\n mode: 'response',\n prefix: 'https://yb.tencent.com/s/',\n xurl: [\n '/api/conversations/v2/share', 'shareId',\n ],\n },\n }),\n kimi: createActorInfo({\n key: 'kimi',\n name: 'Kimi',\n domain: 'www.kimi.com',\n path: '/',\n share: {\n mode: 'response',\n prefix: 'https://www.kimi.com/share/',\n xurl: [\n '/kimi.gateway.chat.v1.ChatService/CreateChatShare', 'share', 'id'\n ],\n },\n }),\n qwen: createActorInfo({\n key: 'qwen',\n name: '\u901A\u4E49\u5343\u95EE',\n domain: 'www.qianwen.com',\n path: '/chat',\n share: {\n mode: 'response',\n prefix: 'https://www.qianwen.com/share/',\n xurl: [\n '/api/v1/share/create', 'data', 'share_id'\n ],\n },\n }),\n}\n", "\n// =============================================================================\n// Core Helpers & State\n// =============================================================================\n\nconst pad = (value, size = 2) => String(value).padStart(size, '0');\n\nconst FORCED_TIMEZONE_OFFSET_MINUTES = -8 * 60;\n\nconst formatTimestamp = (date = new Date()) => {\n const source = date instanceof Date ? date : new Date(date);\n const forcedDate = new Date(source.getTime() - (FORCED_TIMEZONE_OFFSET_MINUTES * 60 * 1000));\n\n const year = forcedDate.getUTCFullYear();\n const month = pad(forcedDate.getUTCMonth() + 1);\n const day = pad(forcedDate.getUTCDate());\n const hours = pad(forcedDate.getUTCHours());\n const minutes = pad(forcedDate.getUTCMinutes());\n const seconds = pad(forcedDate.getUTCSeconds());\n const millis = pad(forcedDate.getUTCMilliseconds(), 3);\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${millis}`;\n};\n\nconst formatLine = (prefix, icon, message) => {\n const parts = [];\n if (prefix) parts.push(`[${prefix}]`);\n if (icon) parts.push(icon);\n if (message) parts.push(message);\n return parts.join(' ').trim();\n};\n\nconst fallbackLog = {\n info: (...args) => console.log(...args),\n warning: (...args) => (console.warn ? console.warn(...args) : console.log(...args)),\n error: (...args) => console.error(...args),\n debug: (...args) => (console.debug ? console.debug(...args) : console.log(...args)),\n};\n\nconst resolveLogMethod = (logger, name) => {\n if (logger && typeof logger[name] === 'function') {\n return logger[name].bind(logger);\n }\n if (name === 'warning' && logger && typeof logger.warn === 'function') {\n return logger.warn.bind(logger);\n }\n return fallbackLog[name];\n};\n\nlet defaultLogger = null;\n\nexport const setDefaultLogger = (logger) => {\n defaultLogger = logger;\n};\n\n// Lazy resolver: always checks current state\nconst resolveLogger = (explicitLogger) => {\n if (explicitLogger && typeof explicitLogger.info === 'function') {\n return explicitLogger;\n }\n if (defaultLogger && typeof defaultLogger.info === 'function') {\n return defaultLogger;\n }\n return fallbackLog;\n};\n\nconst ANSI = {\n reset: '\\x1b[0m',\n gray: '\\x1b[90m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n cyan: '\\x1b[36m',\n};\n\nconst colorize = (text, color) => {\n if (!text || !color) return text;\n return `${color}${text}${ANSI.reset}`;\n};\n\nexport const createBaseLogger = (prefix = '', explicitLogger) => {\n const name = prefix ? String(prefix) : '';\n\n const dispatch = (methodName, icon, message, color) => {\n const logger = resolveLogger(explicitLogger);\n const logFn = resolveLogMethod(logger, methodName);\n const timestamp = colorize(`[${formatTimestamp()}]`, ANSI.gray);\n const line = formatLine(name, icon, message);\n const coloredLine = colorize(line, color);\n logFn(`${timestamp} ${coloredLine}`.trim());\n };\n\n return {\n info: (message) => dispatch('info', '\uD83D\uDCD6', message, ANSI.cyan),\n success: (message) => dispatch('info', '\u2705', message, ANSI.green),\n warning: (message) => dispatch('warning', '\u26A0\uFE0F', message, ANSI.yellow),\n warn: (message) => dispatch('warning', '\u26A0\uFE0F', message, ANSI.yellow),\n error: (message) => dispatch('error', '\u274C', message, ANSI.red),\n debug: (message) => dispatch('debug', '\uD83D\uDD39', message, ANSI.gray),\n start: (message) => dispatch('info', '\uD83D\uDD37', message, ANSI.blue),\n };\n};\n\n/**\n * \u521B\u5EFA\u6A21\u5757\u7EA7\u65E5\u5FD7\u5668\n * @param {string} moduleName - \u6A21\u5757\u540D\u79F0\n * @param {object} [logger] - \u53EF\u9009\u7684\u663E\u5F0F\u65E5\u5FD7\u5668\uFF0C\u901A\u5E38\u4E0D\u9700\u8981\u4F20\uFF0C\u4F1A\u81EA\u52A8\u4F7F\u7528 setDefaultLogger \u8BBE\u7F6E\u7684\u5168\u5C40\u65E5\u5FD7\u5668\n */\nexport function createInternalLogger(moduleName, explicitLogger) {\n const baseLogger = createBaseLogger(moduleName, explicitLogger);\n\n return {\n start(methodName, params = '') {\n const paramStr = params ? ` (${params})` : '';\n baseLogger.start(`${methodName} \u5F00\u59CB${paramStr}`);\n },\n success(methodName, result = '') {\n const resultStr = result ? ` (${result})` : '';\n baseLogger.success(`${methodName} \u5B8C\u6210${resultStr}`);\n },\n fail(methodName, error) {\n const message = error instanceof Error ? error.message : error;\n baseLogger.error(`${methodName} \u5931\u8D25: ${message}`);\n },\n debug(message) {\n baseLogger.debug(message);\n },\n warn(message) {\n baseLogger.warning(message);\n },\n warning(message) {\n baseLogger.warning(message);\n },\n info(message) {\n baseLogger.info(message);\n }\n };\n}\n", "/**\n * \u722C\u866B\u81EA\u5B9A\u4E49\u9519\u8BEF\u7C7B\n * \u7528\u4E8E\u643A\u5E26\u4E0A\u4E0B\u6587\u4FE1\u606F\uFF0C\u5728 pushFailed \u65F6\u81EA\u52A8\u89E3\u6790\n */\n\nimport { serializeError } from \"serialize-error\";\nimport { Code } from \"./constants\";\n\n/**\n * CrawlerError - \u81EA\u5B9A\u4E49\u722C\u866B\u9519\u8BEF\u7C7B\n * \n * @example\n * // \u7B80\u5355\u7528\u6CD5 (\u53EA\u6709 message)\n * throw new CrawlerError('\u672A\u6355\u83B7 Feed \u63A5\u53E3\u54CD\u5E94');\n * \n * @example\n * // \u5B8C\u6574\u7528\u6CD5 (\u5E26 code \u548C context)\n * throw new CrawlerError({\n * message: '\u767B\u5F55\u5931\u8D25',\n * code: ErrorKeygen.NotLogin,\n * context: { url: currentUrl, userId: '123' }\n * });\n */\nexport class CrawlerError extends Error {\n /**\n * @param {string|Object} info - \u9519\u8BEF\u4FE1\u606F\u5B57\u7B26\u4E32\u6216\u914D\u7F6E\u5BF9\u8C61\n * @param {string} info.message - \u9519\u8BEF\u4FE1\u606F\n * @param {number} [info.code] - ErrorKeygen \u679A\u4E3E\u503C\uFF08\u7528\u4E8E\u9519\u8BEF\u5206\u7C7B\uFF09\n * @param {Object} [info.context] - \u4E0A\u4E0B\u6587\u4FE1\u606F\u5BF9\u8C61\n */\n constructor(info) {\n // \u517C\u5BB9 string\n if (typeof info === 'string') {\n info = { message: info };\n }\n\n // \u26A0\uFE0F super() \u5FC5\u987B\u5728\u8BBF\u95EE this \u4E4B\u524D\u8C03\u7528\n super(info.message);\n\n this.name = 'CrawlerError';\n this.code = info.code ?? Code.UnknownError;\n this.context = info.context ?? {};\n this.timestamp = new Date().toISOString();\n\n // \u7EF4\u62A4\u6B63\u786E\u7684\u5806\u6808\u8DDF\u8E2A\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, CrawlerError);\n }\n }\n\n /**\n * \u8F6C\u6362\u4E3A\u53EF\u63A8\u9001\u7684\u6570\u636E\u5BF9\u8C61\n * @returns {Object}\n */\n toJSON() {\n return serializeError(this)\n }\n\n /**\n * \u68C0\u67E5\u4E00\u4E2A error \u662F\u5426\u662F CrawlerError\n * @param {Error} error\n * @returns {boolean}\n */\n static isCrawlerError(error) {\n return error instanceof CrawlerError || error?.name === 'CrawlerError';\n }\n\n /**\n * \u4ECE\u666E\u901A Error \u521B\u5EFA CrawlerError\n * @param {Error} error - \u539F\u59CB\u9519\u8BEF\n * @param {Object} [options={}] - \u9009\u9879\u5BF9\u8C61 (\u5305\u542B code \u548C context)\n * @returns {CrawlerError}\n */\n static from(error, options = {}) {\n const crawlerError = new CrawlerError({\n message: error.message,\n ...options\n });\n crawlerError.stack = error.stack;\n return crawlerError;\n }\n}\n\n\n", "import { Status, Code } from './constants';\nimport { createInternalLogger } from './internals/logger';\nimport { CrawlerError } from './errors';\nimport { serializeError } from 'serialize-error';\n\nconst logger = createInternalLogger('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 * \u6838\u5FC3\u5C01\u88C5\uFF1A\u6267\u884C\u6B65\u9AA4\uFF0C\u5E26\u81EA\u52A8\u65E5\u5FD7\u786E\u8BA4\u3001\u5931\u8D25\u622A\u56FE\u5904\u7406\u548C\u91CD\u8BD5\u673A\u5236\n * \n * @param {string} step - \u6B65\u9AA4\u540D\u79F0\n * @param {import('playwright').Page} page - Playwright page \u5BF9\u8C61\n * @param {Function} actionFn - \u6267\u884C\u7684\u5F02\u6B65\u64CD\u4F5C\n * @param {Object} [options] - \u914D\u7F6E\u9009\u9879\n * @param {boolean} [options.failActor=true] - \u5931\u8D25\u65F6\u662F\u5426\u8C03\u7528 Actor.fail\n * @param {Object} [options.retry] - \u91CD\u8BD5\u914D\u7F6E\n * @param {number} [options.retry.times=0] - \u91CD\u8BD5\u6B21\u6570\n * @param {'direct'|'refresh'} [options.retry.mode='direct'] - \u91CD\u8BD5\u6A21\u5F0F\n * @param {Function} [options.retry.before] - \u91CD\u8BD5\u524D\u94A9\u5B50\uFF0C\u53EF\u8986\u76D6\u9ED8\u8BA4\u7B49\u5F85\u884C\u4E3A\n */\n async runStep(step, page, actionFn, options = {}) {\n const { failActor = true, retry = {} } = options;\n const { times: retryTimes = 0, mode: retryMode = 'direct', before: beforeRetry } = retry;\n\n // \u5185\u90E8\u6267\u884C\u51FD\u6570\n const executeAction = async (attemptNumber) => {\n const attemptLabel = attemptNumber > 0 ? ` (\u91CD\u8BD5 #${attemptNumber})` : '';\n logger.start(`[Step] ${step}${attemptLabel}`);\n\n try {\n const result = await actionFn();\n logger.success(`[Step] ${step}${attemptLabel}`);\n return { success: true, result };\n } catch (error) {\n logger.fail(`[Step] ${step}${attemptLabel}`, error);\n return { success: false, error };\n }\n };\n\n // \u91CD\u8BD5\u524D\u7684\u51C6\u5907\u64CD\u4F5C\n const prepareForRetry = async (attemptNumber) => {\n if (typeof beforeRetry === 'function') {\n // \u4F7F\u7528\u81EA\u5B9A\u4E49\u94A9\u5B50\n logger.start(`[RetryStep] \u6267\u884C\u81EA\u5B9A\u4E49 before \u94A9\u5B50 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);\n await beforeRetry(page, attemptNumber);\n logger.success(`[RetryStep] before \u94A9\u5B50\u5B8C\u6210`);\n } else if (retryMode === 'refresh') {\n // \u5237\u65B0\u6A21\u5F0F\uFF1A\u5237\u65B0\u9875\u9762\u5E76\u7B49\u5F85 DOMContentLoaded\n logger.start(`[RetryStep] \u5237\u65B0\u9875\u9762 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);\n await page.reload({ waitUntil: 'domcontentloaded' });\n logger.success(`[RetryStep] \u9875\u9762\u5237\u65B0\u5B8C\u6210`);\n } else {\n // direct \u6A21\u5F0F\uFF1A\u9ED8\u8BA4\u7B49\u5F85 3 \u79D2\n logger.start(`[RetryStep] \u7B49\u5F85 3 \u79D2 (\u7B2C ${attemptNumber} \u6B21\u91CD\u8BD5)`);\n await new Promise(resolve => setTimeout(resolve, 3000));\n logger.success(`[RetryStep] \u7B49\u5F85\u5B8C\u6210`);\n }\n };\n\n // \u9996\u6B21\u6267\u884C\n let lastResult = await executeAction(0);\n\n // \u5982\u679C\u9996\u6B21\u6210\u529F\uFF0C\u76F4\u63A5\u8FD4\u56DE\n if (lastResult.success) {\n return lastResult.result;\n }\n\n // \u91CD\u8BD5\u903B\u8F91\n for (let attempt = 1; attempt <= retryTimes; attempt++) {\n logger.start(`[RetryStep] \u51C6\u5907\u7B2C ${attempt}/${retryTimes} \u6B21\u91CD\u8BD5: ${step}`);\n\n try {\n await prepareForRetry(attempt);\n } catch (prepareError) {\n logger.warn(`[RetryStep] \u91CD\u8BD5\u51C6\u5907\u5931\u8D25: ${prepareError.message}`);\n // \u51C6\u5907\u5931\u8D25\uFF0C\u7EE7\u7EED\u5C1D\u8BD5\u4E0B\u4E00\u6B21\u91CD\u8BD5\n continue;\n }\n\n lastResult = await executeAction(attempt);\n if (lastResult.success) {\n return lastResult.result;\n }\n }\n\n // \u6240\u6709\u91CD\u8BD5\u90FD\u5931\u8D25\uFF0C\u5904\u7406\u6700\u7EC8\u9519\u8BEF\n const finalError = lastResult.error;\n if (failActor) {\n let base64 = '\u622A\u56FE\u5931\u8D25';\n try {\n if (page) {\n const buffer = await page.screenshot({ fullPage: true, type: 'jpeg', quality: 60 });\n base64 = `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 await this.pushFailed(finalError, {\n step,\n page,\n options,\n base64,\n retryAttempts: retryTimes\n });\n await Actor.fail(`Run Step ${step} \u5931\u8D25 (\u5DF2\u91CD\u8BD5 ${retryTimes} \u6B21): ${finalError.message}`);\n } else {\n throw finalError;\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(step, page, fn) {\n return await this.runStep(step, 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 // \u56FA\u5B9A\u4E3A0\n code: Code.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 * \u81EA\u52A8\u89E3\u6790 CrawlerError \u7684 code \u548C context\n * @param {Error|CrawlerError} error - \u9519\u8BEF\u5BF9\u8C61\n * @param {Object} [meta] - \u989D\u5916\u7684\u6570\u636E\uFF08\u5982failedStep, screenshotBase64\u7B49\uFF09\n * @private\n */\n async pushFailed(error, meta = {}) {\n // \u5982\u679C\u662F CrawlerError\uFF0C\u63D0\u53D6\u5176 key \u548C context\n const isCrawlerError = CrawlerError.isCrawlerError(error);\n const code = isCrawlerError ? error.code : Code.UnknownError;\n const context = isCrawlerError ? error.context : {};\n\n await Actor.pushData({\n // \u5982\u679C\u662F CrawlerError\uFF0C\u4F7F\u7528\u5176 code\uFF0C\u5426\u5219\u4F7F\u7528\u9ED8\u8BA4 Failed code\n code,\n status: Status.Failed,\n error: serializeError(error),\n meta,\n context,\n timestamp: new Date().toISOString(),\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", "import { createInternalLogger } from './logger.js';\n\nconst logger = createInternalLogger('InternalUtils');\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 */\nexport const 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", "import { createInternalLogger } from './internals/logger.js';\nimport { parseCookies as internalParseCookies } from './internals/utils.js';\nimport delay from 'delay';\n\nconst logger = createInternalLogger('Utils');\n\nexport const Utils = {\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 return internalParseCookies(cookieString, domain);\n },\n\n /**\n * \u4ECE\u5B57\u7B26\u4E32\u4E2D\u63D0\u53D6 URL \u94FE\u63A5\n * @param {string} text\n * @param {Object} [options]\n * @param {string} [options.prefix] - \u4EC5\u8FD4\u56DE\u6B64\u524D\u7F00\u5F00\u5934\uFF0C\u4E14\u524D\u7F00\u540E\u81F3\u5C11 1 \u4F4D\u5B57\u7B26\u7684\u94FE\u63A5\n * @returns {string[]}\n */\n parseLinks(text, options = {}) {\n const raw = String(text || '');\n if (!raw) return [];\n\n const opts = options && typeof options === 'object' ? options : {};\n const prefix = String(opts.prefix || '').trim();\n\n const matched = raw.match(/https?:\\/\\/[\\w\\-._~:/?#[\\]@!$&'()*+,;=%]+/g) || [];\n const unique = new Set();\n\n for (const item of matched) {\n const link = String(item || '').trim().replace(/[\"'\u201C\u201D\u2018\u2019>\\].,\uFF0C\u3002\uFF1B;!\uFF01?\uFF1F]+$/, '');\n if (!link || !/^https?:\\/\\//i.test(link)) continue;\n\n if (prefix) {\n if (!link.startsWith(prefix)) continue;\n if (link.length <= prefix.length) continue;\n }\n\n unique.add(link);\n }\n\n return Array.from(unique);\n },\n\n /**\n * \u5168\u9875\u9762\u6EDA\u52A8\u622A\u56FE\n * \u81EA\u52A8\u68C0\u6D4B\u9875\u9762\u6240\u6709\u53EF\u6EDA\u52A8\u5143\u7D20\uFF0C\u53D6\u6700\u5927\u9AD8\u5EA6\uFF0C\u5F3A\u5236\u5C55\u5F00\u540E\u622A\u56FE\n * \n * @param {import('playwright').Page} page - Playwright page \u5BF9\u8C61\n * @param {Object} [options] - \u914D\u7F6E\u9009\u9879\n * @param {number} [options.buffer] - \u989D\u5916\u7F13\u51B2\u9AD8\u5EA6 (\u9ED8\u8BA4: \u89C6\u53E3\u9AD8\u5EA6\u7684\u4E00\u534A)\n * @param {boolean} [options.restore] - \u622A\u56FE\u540E\u662F\u5426\u6062\u590D\u9875\u9762\u9AD8\u5EA6\u548C\u6837\u5F0F (\u9ED8\u8BA4: false)\n * @param {number} [options.maxHeight] - \u6700\u5927\u622A\u56FE\u9AD8\u5EA6 (\u9ED8\u8BA4: 8000px)\n * @returns {Promise<string>} - base64 \u7F16\u7801\u7684 PNG \u56FE\u7247\n */\n async fullPageScreenshot(page, options = {}) {\n logger.start('fullPageScreenshot', 'detecting scrollable elements');\n const originalViewport = page.viewportSize();\n const defaultBuffer = Math.round((originalViewport?.height || 1080) / 2);\n const buffer = options.buffer ?? defaultBuffer;\n const restore = options.restore ?? false;\n const maxHeight = options.maxHeight ?? 8000;\n\n try {\n // 1. \u81EA\u52A8\u627E\u51FA\u6240\u6709\u53EF\u6EDA\u52A8\u5143\u7D20\u5E76\u5C55\u5F00\uFF0C\u8FD4\u56DE\u6700\u5927\u9AD8\u5EA6\n const maxScrollHeight = await page.evaluate(() => {\n let maxHeight = document.body.scrollHeight;\n\n document.querySelectorAll('*').forEach(el => {\n const style = window.getComputedStyle(el);\n const overflowY = style.overflowY;\n\n if ((overflowY === 'auto' || overflowY === 'scroll') &&\n el.scrollHeight > el.clientHeight) {\n if (el.scrollHeight > maxHeight) {\n maxHeight = el.scrollHeight;\n }\n\n // Save original styles\n el.dataset.pkOrigOverflow = el.style.overflow;\n el.dataset.pkOrigHeight = el.style.height;\n el.dataset.pkOrigMaxHeight = el.style.maxHeight;\n el.classList.add('__pk_expanded__');\n\n el.style.overflow = 'visible';\n el.style.height = 'auto';\n el.style.maxHeight = 'none';\n }\n });\n\n return maxHeight;\n });\n\n // 2. \u8BA1\u7B97\u6700\u7EC8\u9AD8\u5EA6 (\u5E94\u7528 maxHeight \u9650\u5236)\n const targetHeight = Math.min(maxScrollHeight + buffer, maxHeight);\n\n // 3. \u8C03\u6574\u89C6\u53E3\u9AD8\u5EA6\n await page.setViewportSize({\n width: originalViewport?.width || 1280,\n height: targetHeight\n });\n\n // \u7B49\u5F85\u6E32\u67D3\n await delay(1000);\n\n // 4. \u622A\u56FE\n const buffer_ = await page.screenshot({\n fullPage: true,\n type: 'png'\n });\n\n logger.success('fullPageScreenshot', `captured ${Math.round(buffer_.length / 1024)} KB`);\n return buffer_.toString('base64');\n } finally {\n // \u4EC5\u5728 restore=true \u65F6\u6062\u590D\u6837\u5F0F\u548C\u89C6\u53E3\n if (restore) {\n await page.evaluate(() => {\n document.querySelectorAll('.__pk_expanded__').forEach(el => {\n el.style.overflow = el.dataset.pkOrigOverflow || '';\n el.style.height = el.dataset.pkOrigHeight || '';\n el.style.maxHeight = el.dataset.pkOrigMaxHeight || '';\n\n delete el.dataset.pkOrigOverflow;\n delete el.dataset.pkOrigHeight;\n delete el.dataset.pkOrigMaxHeight;\n el.classList.remove('__pk_expanded__');\n });\n });\n\n if (originalViewport) {\n await page.setViewportSize(originalViewport);\n }\n }\n }\n }\n}\n", "import { createInternalLogger } from './internals/logger';\n\nconst logger = createInternalLogger('AntiCheat');\n\nconst BASE_CONFIG = Object.freeze({\n locale: 'zh-CN',\n acceptLanguage: 'zh-CN,zh;q=0.9',\n timezoneId: 'Asia/Shanghai',\n timezoneOffset: -480,\n geolocation: null,\n});\n\n// \u6700\u5C0F\u5316\u542F\u52A8\u53C2\u6570\uFF0C\u4F9D\u8D56 Crawlee/Playwright \u9ED8\u8BA4\u884C\u4E3A\nconst DEFAULT_LAUNCH_ARGS = [\n // '--disable-blink-features=AutomationControlled', // Crawlee \u53EF\u80FD\u4F1A\u81EA\u52A8\u5904\u7406\uFF0C\u8FC7\u591A\u5E72\u9884\u53CD\u800C\u4F1A\u88AB\u8BC6\u522B\n '--no-sandbox',\n '--disable-setuid-sandbox',\n '--window-position=0,0',\n `--lang=${BASE_CONFIG.locale}`,\n];\n\nfunction buildFingerprintOptions(locale) {\n return {\n browsers: [{ name: 'chrome', minVersion: 110 }],\n devices: ['desktop'],\n operatingSystems: ['windows', 'macos', 'linux'],\n locales: [locale],\n };\n}\n\nexport const AntiCheat = {\n /**\n * \u83B7\u53D6\u7EDF\u4E00\u7684\u57FA\u7840\u914D\u7F6E\n */\n getBaseConfig() {\n return { ...BASE_CONFIG };\n },\n\n /**\n * \u7528\u4E8E Crawlee fingerprint generator \u7684\u7EDF\u4E00\u914D\u7F6E\uFF08\u684C\u9762\u7AEF\uFF09\u3002\n */\n getFingerprintGeneratorOptions() {\n return buildFingerprintOptions(BASE_CONFIG.locale);\n },\n\n /**\n * \u83B7\u53D6\u57FA\u7840\u542F\u52A8\u53C2\u6570\u3002\n */\n getLaunchArgs() {\n return [...DEFAULT_LAUNCH_ARGS];\n },\n\n /**\n * \u4E3A got-scraping \u751F\u6210\u4E0E\u6D4F\u89C8\u5668\u4E00\u81F4\u7684 TLS \u6307\u7EB9\u914D\u7F6E\uFF08\u684C\u9762\u7AEF\uFF09\u3002\n */\n getTlsFingerprintOptions(userAgent = '', acceptLanguage = '') {\n // \u7B80\u5316\u903B\u8F91\uFF0C\u4E0D\u518D\u89E3\u6790 acceptLanguage\uFF0C\u4EC5\u63D0\u4F9B\u57FA\u7840\u6307\u7EB9\u914D\u7F6E\n return buildFingerprintOptions(BASE_CONFIG.locale);\n },\n\n /**\n * \u89C4\u8303\u5316\u8BF7\u6C42\u5934\n */\n applyLocaleHeaders(headers, acceptLanguage = '') {\n if (!headers['accept-language']) {\n headers['accept-language'] = acceptLanguage || BASE_CONFIG.acceptLanguage;\n }\n return headers;\n },\n};\n", "import delay from 'delay';\nimport { createCursor } from 'ghost-cursor-playwright';\nimport { createInternalLogger } from './internals/logger.js';\n\nconst logger = createInternalLogger('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 * \u6E10\u8FDB\u5F0F\u6EDA\u52A8\u5230\u5143\u7D20\u53EF\u89C1\uFF08\u4EC5\u5904\u7406 Y \u8F74\u6EDA\u52A8\uFF09\n * \u8FD4\u56DE restore \u65B9\u6CD5\uFF0C\u7528\u4E8E\u5C06\u6EDA\u52A8\u5BB9\u5668\u6062\u590D\u5230\u539F\u4F4D\u7F6E\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.maxSteps=14] - \u6700\u5927\u6EDA\u52A8\u6B65\u6570\n * @param {number} [options.minStep=260] - \u5355\u6B21\u6EDA\u52A8\u6700\u5C0F\u6B65\u957F\n * @param {number} [options.maxStep=800] - \u5355\u6B21\u6EDA\u52A8\u6700\u5927\u6B65\u957F\n * @param {number} [options.maxDurationMs] - \u6700\u957F\u8017\u65F6\u4E0A\u9650 (\u9ED8\u8BA4\u968F maxSteps \u4F30\u7B97)\n */\n async humanScroll(page, target, options = {}) {\n const {\n maxSteps = 14,\n minStep = 260,\n maxStep = 800,\n maxDurationMs = maxSteps * 220 + 800\n } = options;\n const targetDesc = typeof target === 'string' ? target : 'ElementHandle';\n\n logger.start('humanScroll', `target=${targetDesc}`);\n\n let element;\n if (typeof target === 'string') {\n element = await page.$(target);\n if (!element) {\n logger.warn(`humanScroll | \u5143\u7D20\u672A\u627E\u5230: ${target}`);\n return { element: null, didScroll: false };\n }\n } else {\n element = target;\n }\n\n const cursor = $GetCursor(page);\n let didScroll = false;\n\n // \u8F85\u52A9\u51FD\u6570\uFF1A\u68C0\u67E5\u53EF\u89C1\u6027\u548C\u906E\u6321\n const checkVisibility = async () => {\n return await element.evaluate((el) => {\n const rect = el.getBoundingClientRect();\n if (!rect || rect.width === 0 || rect.height === 0) {\n return { code: 'ZERO_DIMENSIONS', reason: '\u5C3A\u5BF8\u4E3A\u96F6' };\n }\n\n const cx = rect.left + rect.width / 2;\n const cy = rect.top + rect.height / 2;\n const viewH = window.innerHeight;\n const viewW = window.innerWidth;\n let isFixed = false;\n\n for (let node = el; node && node !== document.body; node = node.parentElement) {\n const style = window.getComputedStyle(node);\n if (style && style.position === 'fixed') {\n isFixed = true;\n break;\n }\n }\n\n // 1. \u68C0\u67E5\u662F\u5426\u5728\u51E0\u4F55\u89C6\u53E3\u5185\n if (cy < 0 || cy > viewH || cx < 0 || cx > viewW) {\n // \u8BA1\u7B97\u6240\u9700\u65B9\u5411\n const direction = cy < 0 ? 'up' : (cy > viewH ? 'down' : 'unknown');\n return { code: 'OUT_OF_VIEWPORT', reason: '\u4E0D\u5728\u89C6\u53E3\u5185', direction, cy, viewH, isFixed };\n }\n\n // 2. \u68C0\u67E5\u906E\u6321\n const pointElement = document.elementFromPoint(cx, cy);\n if (pointElement && !el.contains(pointElement) && !pointElement.contains(el)) {\n return {\n code: 'OBSTRUCTED',\n reason: '\u88AB\u906E\u6321',\n obstruction: {\n tag: pointElement.tagName,\n id: pointElement.id,\n className: pointElement.className\n },\n cy, // Return Center Y for smart direction calculation\n viewH,\n isFixed\n };\n }\n\n return { code: 'VISIBLE', isFixed };\n });\n };\n\n const getScrollableRect = async () => {\n return await element.evaluate((el) => {\n const isScrollable = (node) => {\n const style = window.getComputedStyle(node);\n if (!style) return false;\n const overflowY = style.overflowY;\n if (!['auto', 'scroll', 'overlay'].includes(overflowY)) return false;\n return node.scrollHeight > node.clientHeight + 1;\n };\n\n let current = el;\n while (current && current !== document.body) {\n if (isScrollable(current)) {\n const rect = current.getBoundingClientRect();\n if (rect && rect.width > 0 && rect.height > 0) {\n return { x: rect.x, y: rect.y, width: rect.width, height: rect.height };\n }\n }\n current = current.parentElement;\n }\n\n return null;\n });\n };\n\n const startTime = Date.now();\n\n try {\n for (let i = 0; i < maxSteps; i++) {\n if (Date.now() - startTime > maxDurationMs) {\n logger.warn(`humanScroll | \u8D85\u65F6\u4FDD\u62A4\u89E6\u53D1 (${maxDurationMs}ms)`);\n return { element, didScroll };\n }\n\n const status = await checkVisibility();\n\n if (status.code === 'VISIBLE') {\n if (status.isFixed) {\n logger.info('humanScroll | fixed \u5BB9\u5668\u5185\uFF0C\u8DF3\u8FC7\u6EDA\u52A8');\n } else {\n logger.debug('humanScroll | \u5143\u7D20\u53EF\u89C1\u4E14\u65E0\u906E\u6321');\n }\n logger.success('humanScroll', didScroll ? '\u5DF2\u6EDA\u52A8' : '\u65E0\u9700\u6EDA\u52A8');\n return { element, didScroll };\n }\n\n logger.debug(`humanScroll | \u6B65\u9AA4 ${i + 1}/${maxSteps}: ${status.reason} ${status.direction ? `(${status.direction})` : ''}`);\n\n if (status.code === 'OBSTRUCTED' && status.obstruction) {\n logger.debug(`humanScroll | \u88AB\u4EE5\u4E0B\u5143\u7D20\u906E\u6321 <${status.obstruction.tag} id=\"${status.obstruction.id}\">`);\n }\n\n const scrollRect = await getScrollableRect();\n if (!scrollRect && status.isFixed) {\n logger.warn('humanScroll | fixed \u5BB9\u5668\u5185\u4E14\u65E0\u53EF\u6EDA\u52A8\u7956\u5148\uFF0C\u8DF3\u8FC7\u6EDA\u52A8');\n return { element, didScroll };\n }\n\n const stepMin = scrollRect ? Math.min(minStep, Math.max(60, scrollRect.height * 0.4)) : minStep;\n const stepMax = scrollRect ? Math.min(maxStep, Math.max(stepMin + 40, scrollRect.height * 0.8)) : maxStep;\n\n // \u786E\u5B9A\u6EDA\u52A8\u65B9\u5411\u548C\u8DDD\u79BB\n let deltaY = 0;\n if (status.code === 'OUT_OF_VIEWPORT') {\n if (status.direction === 'down') {\n deltaY = stepMin + Math.random() * (stepMax - stepMin);\n } else if (status.direction === 'up') {\n deltaY = -(stepMin + Math.random() * (stepMax - stepMin));\n } else {\n // \u6C34\u5E73\u95EE\u9898\u6216\u5947\u602A\u72B6\u6001\uFF0C\u5C1D\u8BD5\u5411\u4E0B\u6EDA\u52A8\u4E00\u70B9\n deltaY = 100;\n }\n } else if (status.code === 'OBSTRUCTED') {\n // \u667A\u80FD\u907F\u8BA9\u906E\u6321\n // \u5982\u679C\u5143\u7D20\u5728\u89C6\u53E3\u4E0B\u534A\u90E8\u5206\u88AB\u906E\u6321\uFF0C\u901A\u5E38\u662F\u88AB\u5E95\u90E8\u56FA\u5B9A\u5143\u7D20\uFF08\u5982 Footer\uFF09\u906E\u6321 -> \u9700\u8981\u5411\u4E0B\u6EDA\u52A8\u66F4\u591A\uFF08\u5185\u5BB9\u4E0A\u79FB\uFF09\n // \u5982\u679C\u5143\u7D20\u5728\u89C6\u53E3\u4E0A\u534A\u90E8\u5206\u88AB\u906E\u6321\uFF0C\u901A\u5E38\u662F\u88AB\u9876\u90E8\u56FA\u5B9A\u5143\u7D20\uFF08\u5982 Header\uFF09\u906E\u6321 -> \u9700\u8981\u5411\u4E0A\u6EDA\u52A8\u66F4\u591A\uFF08\u5185\u5BB9\u4E0B\u79FB\uFF09\n const halfY = scrollRect ? (scrollRect.y + scrollRect.height / 2) : (status.viewH / 2);\n const isBottomHalf = status.cy > halfY;\n const direction = isBottomHalf ? 1 : -1;\n\n // \u57FA\u7840\u6EDA\u52A8\u91CF + \u968F\u673A\u6CE2\u52A8\n deltaY = direction * (stepMin + Math.random() * 50);\n }\n\n // \u5C06\u9F20\u6807\u79FB\u52A8\u5230\u53EF\u6EDA\u52A8\u5BB9\u5668\uFF08\u4F18\u5148\uFF09\uFF0C\u5426\u5219\u79FB\u52A8\u5230\u89C6\u53E3\u4E2D\u5FC3\n if (i === 0) {\n const viewSize = page.viewportSize();\n if (scrollRect) {\n const safeX = scrollRect.x + scrollRect.width * 0.5 + (Math.random() - 0.5) * Math.min(80, scrollRect.width * 0.4);\n const safeY = scrollRect.y + scrollRect.height * 0.5 + (Math.random() - 0.5) * Math.min(80, scrollRect.height * 0.4);\n await cursor.actions.move({ x: safeX, y: safeY });\n } else if (viewSize) {\n const safeX = viewSize.width * 0.5 + (Math.random() - 0.5) * 80;\n const safeY = viewSize.height * 0.5 + (Math.random() - 0.5) * 80;\n await cursor.actions.move({ x: safeX, y: safeY });\n }\n }\n\n // \u6267\u884C\u6EDA\u52A8\n await page.mouse.wheel(0, deltaY);\n didScroll = true;\n\n // \u7B49\u5F85\u6EDA\u52A8\u7A33\u5B9A - \u7D27\u51D1\u8282\u594F (20ms - 60ms)\n await delay(this.jitterMs(20 + Math.random() * 40, 0.2));\n }\n\n logger.warn(`humanScroll | \u5728 ${maxSteps} \u6B65\u540E\u65E0\u6CD5\u786E\u4FDD\u53EF\u89C1\u6027`);\n return { element, didScroll };\n\n } catch (error) {\n logger.fail('humanScroll', 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\u3002\u5982\u679C\u4E3A\u7A7A\uFF0C\u5219\u70B9\u51FB\u5F53\u524D\u9F20\u6807\u4F4D\u7F6E\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 * @param {boolean} [options.scrollIfNeeded=true] - \u5143\u7D20\u4E0D\u5728\u89C6\u53E3\u65F6\u662F\u5426\u81EA\u52A8\u6EDA\u52A8\n */\n async humanClick(page, target, options = {}) {\n const cursor = $GetCursor(page);\n\n // \u589E\u52A0 restore \u9009\u9879\uFF0C\u9ED8\u8BA4 false (\u4E0D\u8FD8\u539F\u6EDA\u52A8\u4F4D\u7F6E)\n const { reactionDelay = 250, throwOnMissing = true, scrollIfNeeded = true, restore = false } = options;\n\n const targetDesc = target == null ? 'Current Position' : (typeof target === 'string' ? target : 'ElementHandle');\n logger.start('humanClick', `target=${targetDesc}`);\n\n\n const restoreOnce = async () => {\n if (restoreOnce.restored) return;\n restoreOnce.restored = true;\n\n if (typeof restoreOnce.do !== 'function') return;\n try {\n await delay(this.jitterMs(1000));\n await restoreOnce.do();\n } catch (restoreError) {\n logger.warn(`humanClick: \u6062\u590D\u6EDA\u52A8\u4F4D\u7F6E\u5931\u8D25: ${restoreError.message}`);\n }\n };\n\n\n try {\n // Case 1: \u70B9\u51FB\u5F53\u524D\u4F4D\u7F6E (target \u4E3A null/undefined)\n if (target == null) {\n // \u4EC5\u6267\u884C\u53CD\u5E94\u5EF6\u8FDF + \u70B9\u51FB\n await delay(this.jitterMs(reactionDelay, 0.4));\n await cursor.actions.click();\n logger.success('humanClick', 'Clicked current position');\n return true;\n }\n\n // Case 2: \u70B9\u51FB\u6307\u5B9A\u76EE\u6807\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 if (scrollIfNeeded) {\n const { restore: restoreFn, didScroll } = await this.humanScroll(page, element);\n // \u4EC5\u5728 didScroll \u4E3A true \u4E14 options.restore \u4E3A true \u65F6\u624D\u8FD8\u539F\n restoreOnce.do = (didScroll && restore) ? restoreFn : null;\n }\n\n const box = await element.boundingBox();\n if (!box) {\n await restoreOnce();\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 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 delay(this.jitterMs(reactionDelay, 0.4));\n await cursor.actions.click();\n\n await restoreOnce();\n\n logger.success('humanClick');\n return true;\n } catch (error) {\n await restoreOnce();\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 Humanize.humanClick(page, locator);\n\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\u53CD\u722C\u53C2\u6570\u4E0E\u6307\u7EB9\u914D\u7F6E\u7EDF\u4E00\u7531 AntiCheat \u63D0\u4F9B\nimport { AntiCheat } from './anti-cheat';\n\nexport const Launch = {\n getLaunchOptions(customArgs = []) {\n return {\n args: [\n ...AntiCheat.getLaunchArgs(),\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 AntiCheat.getFingerprintGeneratorOptions();\n },\n};\n", "import express from 'express';\nimport { Actor } from 'apify';\nimport { PresetOfLiveViewKey } from './constants';\nimport { createInternalLogger } from './internals/logger';\n\nconst logger = createInternalLogger('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 { v4 as uuidv4 } from 'uuid';\nimport { createInternalLogger } from './internals/logger';\n\nconst logger = createInternalLogger('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 await onDetected();\n };\n\n const cleanupFns = [];\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_${uuidv4().replace(/-/g, '_')}`;\n // \u751F\u6210\u552F\u4E00\u7684\u6E05\u7406\u51FD\u6570\u540D (\u6302\u8F7D\u5728 window \u4E0A)\n const cleanerName = `__c_cleaner_${uuidv4().replace(/-/g, '_')}`;\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, cleanerName }) => {\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 // 4. \u6CE8\u518C\u6E05\u7406\u51FD\u6570\n window[cleanerName] = () => {\n if (observer) {\n observer.disconnect();\n observer = null;\n }\n };\n })();\n }, { selector: domSelector, callbackName: exposedFunctionName, cleanerName });\n\n logger.success('useCaptchaMonitor', `DOM \u76D1\u63A7\u5DF2\u542F\u7528: ${domSelector}`);\n\n // \u6DFB\u52A0\u6E05\u7406\u903B\u8F91\n cleanupFns.push(async () => {\n try {\n // \u8C03\u7528\u9875\u9762\u5185\u7684\u6E05\u7406\u51FD\u6570\n await page.evaluate((name) => {\n if (window[name]) {\n window[name]();\n delete window[name];\n }\n }, cleanerName);\n } catch (e) {\n // \u9875\u9762\u53EF\u80FD\u5DF2\u5173\u95ED\u6216\u8DF3\u8F6C\uFF0C\u5FFD\u7565\u9519\u8BEF\n }\n });\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 // \u6DFB\u52A0\u6E05\u7406\u903B\u8F91\n cleanupFns.push(async () => {\n page.off('framenavigated', frameHandler);\n });\n }\n\n // \u8FD4\u56DE\u63A7\u5236\u53E5\u67C4\n return {\n stop: async () => {\n logger.info('useCaptchaMonitor', '\u6B63\u5728\u505C\u6B62\u76D1\u63A7...');\n for (const fn of cleanupFns) {\n await fn();\n }\n isHandled = true; // \u9632\u6B62\u540E\u7EED\u89E6\u53D1\n }\n };\n}\n\n// \u6309\u7167 toolkit \u7EDF\u4E00\u7684\u5BFC\u51FA\u6A21\u5F0F\nexport const Captcha = {\n useCaptchaMonitor\n};\n", "import https from 'https';\nimport { URL } from 'url';\nimport { createInternalLogger } from './internals/logger';\nimport { CrawlerError } from './errors';\nimport { Code } from './constants';\n\nconst logger = createInternalLogger('Sse');\n\nexport const Sse = {\n /**\n * \u89E3\u6790 SSE \u6D41\u6587\u672C\n * \u652F\u6301 `data: {...}` \u548C `data:{...}` \u4E24\u79CD\u683C\u5F0F\n * @param {string} sseStreamText\n * @returns {Array<Object>} events\n */\n parseSseStream(sseStreamText) {\n const events = [];\n const lines = sseStreamText.split('\\n');\n for (const line of lines) {\n // \u517C\u5BB9\u4E24\u79CD\u683C\u5F0F: \"data: {...}\" \u548C \"data:{...}\"\n if (line.startsWith('data:')) {\n try {\n // \u79FB\u9664 \"data:\" \u524D\u7F00\u5E76 trim\uFF0C\u7EDF\u4E00\u5904\u7406\u6709\u65E0\u7A7A\u683C\u7684\u60C5\u51B5\n const jsonContent = line.substring(5).trim();\n if (jsonContent) {\n events.push(JSON.parse(jsonContent));\n }\n } catch (e) {\n // \u5FFD\u7565\u975E\u6709\u6548 JSON \u7684\u884C\n logger.debug('parseSseStream', `JSON \u89E3\u6790\u5931\u8D25: ${e.message}, line: ${line.substring(0, 100)}...`);\n }\n }\n }\n logger.success('parseSseStream', `\u89E3\u6790\u5B8C\u6210, events \u6570\u91CF: ${events.length}`);\n return events;\n },\n\n /**\n * \u62E6\u622A\u7F51\u7EDC\u8BF7\u6C42\u5E76\u4F7F\u7528 Node.js \u539F\u751F https \u6A21\u5757\u8F6C\u53D1\uFF0C\u4EE5\u89E3\u51B3\u6D41\u5F0F\u6570\u636E\u6355\u83B7\u95EE\u9898\u3002\n * @param {import('playwright').Page} page\n * @param {string|RegExp} urlPattern - \u62E6\u622A\u7684 URL \u6A21\u5F0F\n * @param {object} options\n * @param {function(string, function, string): void} [options.onData] - (textChunk, resolve, accumulatedText) => void\n * @param {function(string, function): void} [options.onEnd] - (fullText, resolve) => void\n * @param {function(Error, function): void} [options.onTimeout] - (error, reject) => void\n * @param {number} [options.initialTimeout=90000] - \u521D\u59CB\u6570\u636E\u63A5\u6536\u8D85\u65F6 (ms)\uFF0C\u9ED8\u8BA4 90s\n * @param {number} [options.overallTimeout=180000] - \u6574\u4F53\u8BF7\u6C42\u8D85\u65F6\u65F6\u95F4 (ms)\uFF0C\u9ED8\u8BA4 180s\n * @param {boolean} [options.autoUnroute=true] - resolve/reject \u540E\u662F\u5426\u81EA\u52A8\u53D6\u6D88\u62E6\u622A\n * @param {boolean} [options.firstMatchOnly=true] - \u53EA\u62E6\u622A\u7B2C\u4E00\u4E2A\u547D\u4E2D\u7684\u8BF7\u6C42\uFF0C\u540E\u7EED\u8BF7\u6C42\u5168\u90E8\u653E\u884C\n * @returns {Promise<any>} - \u8FD4\u56DE Promise\uFF0C\u5F53\u6D41\u6EE1\u8DB3\u6761\u4EF6\u65F6 resolve\n */\n async intercept(page, urlPattern, options = {}) {\n const {\n onData,\n onEnd,\n onTimeout,\n initialTimeout = 90000,\n overallTimeout = 180000,\n autoUnroute = true,\n firstMatchOnly = true\n } = options;\n\n let initialTimer = null;\n let overallTimer = null;\n let hasReceivedInitialData = false;\n\n const clearAllTimers = () => {\n if (initialTimer) clearTimeout(initialTimer);\n if (overallTimer) clearTimeout(overallTimer);\n initialTimer = null;\n overallTimer = null;\n };\n\n // \u5148\u58F0\u660E\uFF0C\u907F\u514D\u8D85\u65F6\u903B\u8F91\u8BBF\u95EE\u4E0D\u5230\n let safeResolve = () => { };\n let safeReject = () => { };\n let safeUnroute = () => { };\n\n // 1. \u6838\u5FC3\u62E6\u622A\u903B\u8F91\n const workPromise = new Promise((resolve, reject) => {\n let finished = false;\n let unrouteRequested = false;\n let hasMatchedOnce = false;\n\n safeUnroute = () => {\n if (!autoUnroute) return;\n if (unrouteRequested) return;\n unrouteRequested = true;\n logger.info('[MITM] autoUnroute: \u53D6\u6D88\u540E\u7EED\u62E6\u622A');\n page.unroute(urlPattern, routeHandler).catch(() => { });\n };\n\n safeResolve = (value) => {\n if (finished) return;\n finished = true;\n clearAllTimers();\n safeUnroute();\n resolve(value);\n };\n\n safeReject = (error) => {\n if (finished) return;\n finished = true;\n clearAllTimers();\n safeUnroute();\n reject(error);\n };\n\n const routeHandler = async (route) => {\n if (firstMatchOnly && hasMatchedOnce) {\n logger.info(`[MITM] firstMatchOnly: \u653E\u884C\u540E\u7EED\u8BF7\u6C42: ${route.request().url()}`);\n route.continue().catch(() => { });\n return;\n }\n\n if (firstMatchOnly && !hasMatchedOnce) {\n hasMatchedOnce = true;\n logger.info('[MITM] firstMatchOnly: \u547D\u4E2D\u9996\u4E2A\u8BF7\u6C42\uFF0C\u53D6\u6D88\u540E\u7EED\u62E6\u622A');\n page.unroute(urlPattern, routeHandler).catch(() => { });\n }\n\n const request = route.request();\n logger.info(`[MITM] \u5DF2\u62E6\u622A\u8BF7\u6C42: ${request.url()}`);\n\n try {\n const headers = await request.allHeaders();\n const postData = request.postData();\n const urlObj = new URL(request.url());\n\n delete headers['accept-encoding'];\n delete headers['content-length'];\n\n const reqOptions = {\n hostname: urlObj.hostname,\n port: 443,\n path: urlObj.pathname + urlObj.search,\n method: request.method(),\n headers: headers,\n timeout: overallTimeout\n };\n\n const req = https.request(reqOptions, (res) => {\n const chunks = [];\n let accumulatedText = \"\";\n\n res.on('data', (chunk) => {\n if (!hasReceivedInitialData) {\n hasReceivedInitialData = true;\n if (initialTimer) {\n clearTimeout(initialTimer);\n initialTimer = null;\n }\n logger.debug('[Intercept] \u5DF2\u63A5\u6536\u521D\u59CB\u6570\u636E');\n }\n\n chunks.push(chunk);\n const textChunk = chunk.toString('utf-8');\n accumulatedText += textChunk;\n\n if (onData) {\n try {\n onData(textChunk, safeResolve, accumulatedText);\n } catch (e) {\n logger.fail(`onData \u9519\u8BEF`, e);\n }\n }\n });\n\n res.on('end', () => {\n logger.info('[MITM] \u4E0A\u6E38\u54CD\u5E94\u7ED3\u675F');\n clearAllTimers();\n if (onEnd) {\n try {\n onEnd(accumulatedText, safeResolve);\n } catch (e) {\n logger.fail(`onEnd \u9519\u8BEF`, e);\n }\n } else if (!onData) {\n safeResolve(accumulatedText);\n }\n route.fulfill({\n status: res.statusCode,\n headers: res.headers,\n body: Buffer.concat(chunks)\n }).catch(() => { });\n });\n });\n\n req.on('error', (e) => {\n clearAllTimers();\n route.abort().catch(() => { });\n safeReject(e);\n });\n\n if (postData) req.write(postData);\n req.end();\n } catch (e) {\n clearAllTimers();\n route.continue().catch(() => { });\n safeReject(e);\n }\n };\n\n page.route(urlPattern, routeHandler).catch(safeReject); // \u6355\u83B7 page.route \u521D\u59CB\u5316\u9519\u8BEF\n });\n\n // 2. \u8D85\u65F6\u8BA1\u901F\u903B\u8F91\n const timeoutPromise = new Promise((_, reject) => {\n initialTimer = setTimeout(() => {\n if (!hasReceivedInitialData) {\n const error = new CrawlerError({\n message: `\u521D\u59CB\u6570\u636E\u63A5\u6536\u8D85\u65F6 (${initialTimeout}ms)`,\n code: Code.InitialTimeout,\n context: { timeout: initialTimeout }\n });\n clearAllTimers();\n if (onTimeout) {\n try {\n onTimeout(error, (err) => safeReject(err));\n } catch (e) {\n safeReject(e);\n }\n } else {\n safeReject(error);\n }\n }\n }, initialTimeout);\n\n overallTimer = setTimeout(() => {\n const error = new CrawlerError({\n message: `\u6574\u4F53\u8BF7\u6C42\u8D85\u65F6 (${overallTimeout}ms)`,\n code: Code.OverallTimeout,\n context: { timeout: overallTimeout }\n });\n clearAllTimers();\n if (onTimeout) {\n try {\n onTimeout(error, (err) => safeReject(err));\n } catch (e) {\n safeReject(e);\n }\n } else {\n safeReject(error);\n }\n }, overallTimeout);\n });\n\n // 3. \u7ADE\u901F\u8FD4\u56DE\n // \u5173\u952E\uFF1A\u9632\u6B62 race \u7ED3\u679C\u672A\u88AB\u7ACB\u5373 await \u65F6\u7684\u5D29\u6E83\uFF0C\u4EE5\u53CA\u9632\u6B62\u975E\u83B7\u80DC Promise \u540E\u7EED reject \u5BFC\u81F4\u7684\u5D29\u6E83\n workPromise.catch(() => { });\n timeoutPromise.catch(() => { });\n\n const racePromise = Promise.race([workPromise, timeoutPromise]);\n racePromise.catch(() => { }); // \u5173\u952E\uFF1A\u9632\u6B62 race \u7ED3\u679C\u672A\u88AB\u7ACB\u5373 await \u65F6\u7684\u5D29\u6E83\n\n return racePromise;\n }\n};\n", "import { createInternalLogger } from './internals/logger';\nimport { gotScraping } from 'got-scraping';\nimport { Agent as HttpAgent } from 'http';\nimport { Agent as HttpsAgent } from 'https';\n\nconst logger = createInternalLogger('Interception');\n\n// ============================================================================\n// \u907F\u514D\u6BCF\u6B21\u8BF7\u6C42\u90FD\u521B\u5EFA\u65B0\u5B9E\u4F8B\uFF0C\u51CF\u5C11 GC \u538B\u529B\n// ============================================================================\nconst SHARED_HTTP_AGENT = new HttpAgent({\n keepAlive: true,\n keepAliveMsecs: 15000,\n maxSockets: 30,\n maxFreeSockets: 10,\n});\nconst SHARED_HTTPS_AGENT = new HttpsAgent({\n keepAlive: true,\n keepAliveMsecs: 15000,\n maxSockets: 30,\n maxFreeSockets: 10,\n rejectUnauthorized: false,\n});\n\n/** \u76F4\u8FDE\u914D\u7F6E */\nconst DirectConfig = {\n /** \u76F4\u8FDE\u8BF7\u6C42\u8D85\u65F6\u65F6\u95F4\uFF08\u79D2\uFF09 */\n directTimeout: 12,\n /** \u9759\u9ED8\u6269\u5C55\u540D\uFF1A\u8FD9\u4E9B\u6269\u5C55\u540D\u7684\u76F4\u8FDE\u6210\u529F\u65E5\u5FD7\u7528 debug \u7EA7\u522B */\n silentExtensions: ['.js'],\n};\n\n// ============================================================================\n// \u8D44\u6E90\u5C4F\u853D\u6269\u5C55\u540D\u5E38\u91CF\n// ============================================================================\n\n/** \u538B\u7F29\u5305\u7C7B\u6269\u5C55\u540D */\nconst ARCHIVE_EXTENSIONS = ['.7z', '.zip', '.rar', '.gz', '.bz2', '.tar', '.zst'];\n\n/** \u53EF\u6267\u884C/\u5B89\u88C5\u5305\u7C7B\u6269\u5C55\u540D */\nconst EXECUTABLE_EXTENSIONS = ['.exe', '.apk', '.bin', '.dmg', '.jar', '.class'];\n\n/** \u529E\u516C\u6587\u6863\u7C7B\u6269\u5C55\u540D */\nconst DOCUMENT_EXTENSIONS = ['.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.pdf', '.csv'];\n\n/** \u56FE\u7247\u7C7B\u6269\u5C55\u540D */\nconst IMAGE_EXTENSIONS = [\n '.jpg', '.jpeg', '.png', '.gif', '.bmp', '.ico',\n '.svg', '.svgz', '.webp', '.avif', '.pis', '.pict',\n '.tif', '.tiff', '.eps', '.ejs', '.eot'\n];\n\n/** \u97F3\u89C6\u9891\u7C7B\u6269\u5C55\u540D */\nconst MEDIA_EXTENSIONS = ['.mp3', '.mp4', '.avi', '.mkv', '.webm', '.midi', '.mid', '.ogg', '.flac', '.swf'];\n\n/** \u5B57\u4F53\u7C7B\u6269\u5C55\u540D */\nconst FONT_EXTENSIONS = ['.woff', '.woff2', '.ttf', '.otf'];\n\n/** CSS \u6837\u5F0F\u7C7B\u6269\u5C55\u540D */\nconst CSS_EXTENSIONS = ['.css'];\n\n/** \u5176\u4ED6\u8D44\u6E90\u7C7B\u6269\u5C55\u540D */\nconst OTHER_EXTENSIONS = ['.ps', '.iso'];\n\n// ============================================================================\n// \u9ED8\u8BA4\u914D\u7F6E\n// ============================================================================\n\n/** \u9ED8\u8BA4\u5C4F\u853D\u914D\u7F6E */\nconst DEFAULT_BLOCKING_CONFIG = {\n /** \u5C4F\u853D\u538B\u7F29\u5305 */\n blockArchive: true,\n /** \u5C4F\u853D\u53EF\u6267\u884C\u6587\u4EF6 */\n blockExecutable: true,\n /** \u5C4F\u853D\u529E\u516C\u6587\u6863 */\n blockDocument: true,\n /** \u5C4F\u853D\u56FE\u7247 */\n blockImage: true,\n /** \u5C4F\u853D\u97F3\u89C6\u9891 */\n blockMedia: true,\n /** \u5C4F\u853D\u5B57\u4F53 */\n blockFont: true,\n /** \u5C4F\u853D CSS (\u6CE8\u610F\uFF1A\u53EF\u80FD\u5F71\u54CD\u9875\u9762\u89C6\u89C9\u6548\u679C) */\n blockCss: false,\n /** \u5C4F\u853D\u5176\u4ED6\u8D44\u6E90 */\n blockOther: true,\n /** \u989D\u5916\u81EA\u5B9A\u4E49\u6269\u5C55\u540D\u5217\u8868 */\n customExtensions: [],\n};\n\n// ============================================================================\n// \u5171\u4EAB\u7684\u8BF7\u6C42\u914D\u7F6E\uFF08\u51CF\u5C11\u5783\u573E\u56DE\u6536\u538B\u529B\uFF09\n// ============================================================================\nconst SHARED_GOT_OPTIONS = {\n http2: false, // \u7981\u7528 HTTP2 \u907F\u514D\u5728\u62E6\u622A\u573A\u666F\u4E0B\u7684\u63E1\u624B\u517C\u5BB9\u6027\u95EE\u9898\n retry: { limit: 0 }, // \u8BA9 Playwright \u6216\u5916\u5C42\u903B\u8F91\u5904\u7406\u91CD\u8BD5\n throwHttpErrors: false, // 404/500 \u7B49\u9519\u8BEF\u4E0D\u629B\u51FA\u5F02\u5E38\uFF0C\u76F4\u63A5\u900F\u4F20\u7ED9\u6D4F\u89C8\u5668\n};\n\nexport const Interception = {\n /**\n * \u6839\u636E\u914D\u7F6E\u751F\u6210\u9700\u8981\u5C4F\u853D\u7684\u6269\u5C55\u540D\u5217\u8868\n * \n * @param {Object} [config] - \u5C4F\u853D\u914D\u7F6E\n * @returns {string[]} \u9700\u8981\u5C4F\u853D\u7684\u6269\u5C55\u540D\u5217\u8868\n */\n getBlockedExtensions(config = {}) {\n const mergedConfig = { ...DEFAULT_BLOCKING_CONFIG, ...config };\n const extensions = [];\n\n if (mergedConfig.blockArchive) extensions.push(...ARCHIVE_EXTENSIONS);\n if (mergedConfig.blockExecutable) extensions.push(...EXECUTABLE_EXTENSIONS);\n if (mergedConfig.blockDocument) extensions.push(...DOCUMENT_EXTENSIONS);\n if (mergedConfig.blockImage) extensions.push(...IMAGE_EXTENSIONS);\n if (mergedConfig.blockMedia) extensions.push(...MEDIA_EXTENSIONS);\n if (mergedConfig.blockFont) extensions.push(...FONT_EXTENSIONS);\n if (mergedConfig.blockCss) extensions.push(...CSS_EXTENSIONS);\n if (mergedConfig.blockOther) extensions.push(...OTHER_EXTENSIONS);\n\n if (mergedConfig.customExtensions?.length > 0) {\n extensions.push(...mergedConfig.customExtensions);\n }\n\n return [...new Set(extensions)];\n },\n\n /**\n * \u83B7\u53D6\u6240\u6709\u53EF\u7528\u7684\u6269\u5C55\u540D\u5206\u7C7B\u4FE1\u606F\n * \n * @returns {Object} \u5206\u7C7B\u4FE1\u606F\n */\n getExtensionCategories() {\n return {\n archive: { name: '\u538B\u7F29\u5305', extensions: ARCHIVE_EXTENSIONS },\n executable: { name: '\u53EF\u6267\u884C\u6587\u4EF6', extensions: EXECUTABLE_EXTENSIONS },\n document: { name: '\u529E\u516C\u6587\u6863', extensions: DOCUMENT_EXTENSIONS },\n image: { name: '\u56FE\u7247', extensions: IMAGE_EXTENSIONS },\n media: { name: '\u97F3\u89C6\u9891', extensions: MEDIA_EXTENSIONS },\n font: { name: '\u5B57\u4F53', extensions: FONT_EXTENSIONS },\n css: { name: 'CSS \u6837\u5F0F', extensions: CSS_EXTENSIONS },\n other: { name: '\u5176\u4ED6\u8D44\u6E90', extensions: OTHER_EXTENSIONS },\n };\n },\n\n /**\n * \u8BBE\u7F6E\u7F51\u7EDC\u62E6\u622A\u89C4\u5219\uFF08\u8D44\u6E90\u5C4F\u853D + CDN \u76F4\u8FDE\uFF09\n * \n * @param {import('playwright').Page} page - Playwright Page \u5BF9\u8C61\n * @param {Object} [options] - \u914D\u7F6E\u9009\u9879\n * @param {string[]} [options.directDomains] - \u9700\u8981\u76F4\u8FDE\u7684\u57DF\u540D\u5217\u8868\n * @param {Object} [options.blockingConfig] - \u8D44\u6E90\u5C4F\u853D\u914D\u7F6E\n * @param {boolean} [options.fallbackToProxy] - \u76F4\u8FDE\u5931\u8D25\u65F6\u662F\u5426\u56DE\u9000\u5230\u4EE3\u7406\uFF08\u9ED8\u8BA4 true\uFF09\n * @returns {Promise<void>}\n */\n async setup(page, options = {}) {\n const {\n directDomains = [],\n blockingConfig = {},\n fallbackToProxy = true,\n } = options;\n\n const mergedBlockingConfig = { ...DEFAULT_BLOCKING_CONFIG, ...blockingConfig };\n const blockedExtensions = this.getBlockedExtensions(mergedBlockingConfig);\n const hasDirectDomains = directDomains.length > 0;\n\n // \u6784\u5EFA\u65E5\u5FD7\u4FE1\u606F\n const enabledCategories = [];\n if (mergedBlockingConfig.blockArchive) enabledCategories.push('\u538B\u7F29\u5305');\n if (mergedBlockingConfig.blockExecutable) enabledCategories.push('\u53EF\u6267\u884C\u6587\u4EF6');\n if (mergedBlockingConfig.blockDocument) enabledCategories.push('\u529E\u516C\u6587\u6863');\n if (mergedBlockingConfig.blockImage) enabledCategories.push('\u56FE\u7247');\n if (mergedBlockingConfig.blockMedia) enabledCategories.push('\u97F3\u89C6\u9891');\n if (mergedBlockingConfig.blockFont) enabledCategories.push('\u5B57\u4F53');\n if (mergedBlockingConfig.blockCss) enabledCategories.push('CSS');\n if (mergedBlockingConfig.blockOther) enabledCategories.push('\u5176\u4ED6');\n\n logger.start('setup', hasDirectDomains\n ? `\u76F4\u8FDE\u57DF\u540D: [${directDomains.length} \u4E2A] | \u5C4F\u853D: [${enabledCategories.join(', ')}]`\n : `\u4EC5\u8D44\u6E90\u5C4F\u853D\u6A21\u5F0F | \u5C4F\u853D: [${enabledCategories.join(', ')}]`);\n\n await page.route('**/*', async (route) => {\n // \u4F7F\u7528 handled flag \u8DDF\u8E2A route \u662F\u5426\u5DF2\u5904\u7406\uFF0C\u907F\u514D\u91CD\u590D\u64CD\u4F5C\n let handled = false;\n\n try {\n const request = route.request();\n const url = request.url();\n const urlLower = url.toLowerCase();\n const urlPath = urlLower.split('?')[0];\n\n // \u5224\u65AD\u662F\u5426\u4E3A\u9759\u9ED8\u8D44\u6E90\uFF08\u7528\u4E8E\u964D\u4F4E\u65E5\u5FD7\u9891\u7387\uFF09\n const isSilent = DirectConfig.silentExtensions.some(ext => urlPath.endsWith(ext));\n\n // ----------------------------------------------------------------\n // Step 1: \u68C0\u67E5\u662F\u5426\u5728\u5C4F\u853D\u5217\u8868\u4E2D\n // ----------------------------------------------------------------\n const shouldBlock = blockedExtensions.some(ext => urlPath.endsWith(ext));\n if (shouldBlock) {\n await route.abort();\n handled = true;\n return;\n }\n\n // ----------------------------------------------------------------\n // Step 2: \u68C0\u67E5\u662F\u5426\u5339\u914D\u76F4\u8FDE\u57DF\u540D\n // ----------------------------------------------------------------\n let isDirect = false;\n if (hasDirectDomains) {\n try {\n const hostname = new URL(url).hostname;\n isDirect = directDomains.some(domain => hostname.startsWith(domain));\n } catch (e) {\n // ignore invalid url\n }\n }\n\n if (isDirect) {\n try {\n const reqHeaders = await request.allHeaders();\n delete reqHeaders['host']; // \u5220\u9664 host \u9632\u6B62\u51B2\u7A81\n const resolvedAcceptLanguage = reqHeaders['accept-language'] || '';\n\n // \u83B7\u53D6 User-Agent \u7528\u4E8E TLS \u6307\u7EB9\n const userAgent = reqHeaders['user-agent'] || '';\n\n // \u51C6\u5907 POST \u6570\u636E\n const method = request.method();\n const postData = (method !== 'GET' && method !== 'HEAD')\n ? request.postDataBuffer()\n : undefined;\n\n // \u53D1\u8D77\u76F4\u8FDE\u8BF7\u6C42\n const response = await gotScraping({\n ...SHARED_GOT_OPTIONS, // \u5E94\u7528\u901A\u7528\u914D\u7F6E\n url: url,\n method: method,\n headers: reqHeaders,\n body: postData,\n responseType: 'buffer', // \u5F3A\u5236\u83B7\u53D6 Buffer\n\n // \u79FB\u9664\u624B\u52A8 TLS \u6307\u7EB9\u914D\u7F6E\uFF0C\u4F7F\u7528 got-scraping \u9ED8\u8BA4\u7684\u9AD8\u8D28\u91CF\u6307\u7EB9\n // headerGeneratorOptions: ... \n\n // \u4F7F\u7528\u5171\u4EAB\u7684 Agent \u5355\u4F8B\uFF08keepAlive: false\uFF0C\u4E0D\u4F1A\u6C60\u5316\u8FDE\u63A5\uFF09\n agent: {\n http: SHARED_HTTP_AGENT,\n https: SHARED_HTTPS_AGENT,\n },\n\n // \u8D85\u65F6\u65F6\u95F4\n timeout: { request: DirectConfig.directTimeout * 1000 },\n });\n\n // \u51C6\u5907\u54CD\u5E94\u5934\n const resHeaders = {};\n for (const [key, value] of Object.entries(response.headers)) {\n if (Array.isArray(value)) {\n resHeaders[key] = value.join(', ');\n } else if (value) {\n resHeaders[key] = String(value);\n }\n }\n\n // \u3010\u6838\u5FC3\u4FEE\u590D 2\u3011: \u5F7B\u5E95\u6E05\u7406\u534F\u8BAE\u5934\n // \u79FB\u9664\u53EF\u80FD\u5BFC\u81F4\u6D4F\u89C8\u5668\u8BA4\u4E3A\u6570\u636E\u4F20\u8F93\u672A\u5B8C\u6210\u7684\u5934\n delete resHeaders['content-encoding'];\n delete resHeaders['content-length'];\n delete resHeaders['transfer-encoding']; // \u5173\u952E\uFF1A\u79FB\u9664 chunked\n delete resHeaders['connection'];\n delete resHeaders['keep-alive'];\n\n\n // \u9759\u9ED8\u8D44\u6E90\u7528 debug \u7EA7\u522B\uFF0C\u964D\u4F4E\u65E5\u5FD7\u9891\u7387\n isSilent ? logger.debug(`\u76F4\u8FDE\u6210\u529F: ${urlPath}`) : logger.info(`\u76F4\u8FDE\u6210\u529F: ${urlPath}`);\n\n // \u5B89\u5168\u5730\u8FD4\u56DE\u6570\u636E\n await safeFulfill(route, {\n status: response.statusCode,\n headers: resHeaders,\n body: response.body,\n });\n handled = true;\n return;\n\n } catch (e) {\n // \u5224\u65AD\u662F\u5426\u4E3A\u8D85\u65F6\u9519\u8BEF\n const isTimeout = e.code === 'ETIMEDOUT' || e.message.toLowerCase().includes('timeout');\n const action = fallbackToProxy ? '\u56DE\u9000\u4EE3\u7406' : '\u5DF2\u653E\u5F03';\n const reason = isTimeout ? `\u8D85\u65F6(${DirectConfig.directTimeout}s)` : `\u5F02\u5E38: ${e.message}`;\n\n logger.warn(`\u76F4\u8FDE${reason}\uFF0C${action}: ${urlPath}`);\n\n if (fallbackToProxy) {\n await safeContinue(route);\n } else {\n await route.abort();\n }\n handled = true;\n return;\n }\n }\n\n // ----------------------------------------------------------------\n // Step 3: \u5176\u4ED6\u8BF7\u6C42\u6B63\u5E38\u8D70\u4EE3\u7406\n // ----------------------------------------------------------------\n await safeContinue(route);\n handled = true;\n\n } catch (err) {\n // \u6700\u540E\u7684\u9632\u7EBF\uFF1A\u9632\u6B62 Route \u5904\u7406\u8FC7\u7A0B\u4E2D\u53D1\u751F\u672A\u6355\u83B7\u5F02\u5E38\u5BFC\u81F4\u6D4F\u89C8\u5668\u5361\u6B7B\n logger.warn(`\u8DEF\u7531\u5904\u7406\u5F02\u5E38: ${err.message}`);\n\n // \u4F7F\u7528 handled flag \u5224\u65AD\u662F\u5426\u9700\u8981\u515C\u5E95\u5904\u7406\n if (!handled) {\n try {\n await route.continue();\n } catch (_) {\n // \u5FFD\u7565\u8FD9\u91CC\u7684\u9519\u8BEF\uFF0C\u56E0\u4E3A\u901A\u5E38\u610F\u5473\u7740\u9875\u9762\u5DF2\u5173\u95ED\u6216\u8BF7\u6C42\u5DF2\u5931\u6548\n }\n }\n }\n });\n },\n};\n\n// ============================================================================\n// \u8F85\u52A9\u51FD\u6570\uFF1A\u5B89\u5168\u64CD\u4F5C Route\n// \u89E3\u51B3 \"Route is already handled\" \u6216 \"Target closed\" \u5BFC\u81F4\u7684\u5D29\u6E83\n// ============================================================================\n\n/**\n * \u5B89\u5168\u5730\u6267\u884C route.fulfill\n */\nasync function safeFulfill(route, options) {\n try {\n await route.fulfill(options);\n } catch (error) {\n // \u53EA\u6709\u5F53\u4E0D\u662F \"\u5DF2\u7ECF\u5904\u7406\" \u6216 \"\u9875\u9762\u5173\u95ED\" \u9519\u8BEF\u65F6\u624D\u6253\u5370\n if (!isIgnorableError(error)) {\n console.error(`[Interception] Fulfill Error: ${error.message}`);\n }\n }\n}\n\n/**\n * \u5B89\u5168\u5730\u6267\u884C route.continue\n */\nasync function safeContinue(route) {\n try {\n await route.continue();\n } catch (error) {\n if (!isIgnorableError(error)) {\n // continue \u5931\u8D25\u901A\u5E38\u4E0D\u9700\u8981\u6253\u5370\uFF0C\u53EF\u80FD\u662F\u7F51\u7EDC\u77AC\u95F4\u65AD\u5F00\n }\n }\n}\n\n/**\n * \u5224\u65AD\u662F\u5426\u4E3A\u53EF\u5FFD\u7565\u7684 Playwright \u8DEF\u7531\u9519\u8BEF\n */\nfunction isIgnorableError(error) {\n const msg = error.message;\n return msg.includes('already handled') ||\n msg.includes('Target closed') ||\n msg.includes('closed');\n}\n", "import { v4 as uuidv4 } from 'uuid';\nimport { createInternalLogger } from './internals/logger.js';\n\nconst logger = createInternalLogger('Mutation');\n\nconst MUTATION_MONITOR_MODE = Object.freeze({\n Added: 'added',\n Changed: 'changed',\n All: 'all',\n});\n\n/**\n * \u751F\u6210\u552F\u4E00\u7684 key \u540D\u79F0\uFF0C\u907F\u514D\u51B2\u7A81\n * @returns {string}\n */\nfunction generateKey(prefix) {\n return `__${prefix}_${uuidv4().replace(/-/g, '_')}`;\n}\n\nexport const Mutation = {\n Mode: MUTATION_MONITOR_MODE,\n /**\n * \u7B49\u5F85 DOM \u5143\u7D20\u7A33\u5B9A\uFF08\u65E0\u53D8\u5316\uFF09\n * \u4F7F\u7528 MutationObserver \u76D1\u63A7\u6307\u5B9A\u5143\u7D20\uFF0C\u5F53\u5143\u7D20\u6301\u7EED\u4E00\u6BB5\u65F6\u95F4\u65E0\u53D8\u5316\u65F6 resolve\n * \n * @param {import('playwright').Page} page - Playwright page \u5BF9\u8C61\n * @param {string | string[]} selectors - \u8981\u76D1\u63A7\u7684 CSS \u9009\u62E9\u5668\uFF0C\u5355\u4E2A\u6216\u591A\u4E2A\n * @param {Object} [options] - \u914D\u7F6E\u9009\u9879\n * @param {number} [options.initialTimeout] - \u7B49\u5F85\u5143\u7D20\u51FA\u73B0\u7684\u8D85\u65F6 (\u6BEB\u79D2, \u9ED8\u8BA4: 30000)\n * @param {number} [options.stableTime] - \u65E0\u53D8\u5316\u6301\u7EED\u65F6\u95F4\u540E resolve (\u6BEB\u79D2, \u9ED8\u8BA4: 5000)\n * @param {number} [options.timeout] - \u6574\u4F53\u8D85\u65F6\u65F6\u95F4 (\u6BEB\u79D2, \u9ED8\u8BA4: 120000)\n * @param {Function} [options.onMutation] - \u53D8\u5316\u65F6\u7684\u56DE\u8C03\u94A9\u5B50\n * \u7B7E\u540D: ({ mutationCount, html, text, mutationNodes }) => any\n * \u8FD4\u56DE null/undefined: \u6B63\u5E38\u91CD\u7F6E\u7A33\u5B9A\u8BA1\u65F6\n * \u8FD4\u56DE\u5176\u4ED6\u503C: \u6682\u505C\u7A33\u5B9A\u8BA1\u65F6\uFF08timeout \u4ECD\u7136\u751F\u6548\uFF09\n * @returns {Promise<{ mutationCount: number, stableTime: number, wasPaused: boolean }>}\n */\n async waitForStable(page, selectors, options = {}) {\n const selectorList = Array.isArray(selectors) ? selectors : [selectors];\n const initialTimeout = options.initialTimeout ?? 30 * 1000;\n const stableTime = options.stableTime ?? 5 * 1000;\n const timeout = options.timeout ?? 120 * 1000;\n const onMutation = options.onMutation;\n\n logger.start('waitForStable', `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, \u7A33\u5B9A\u65F6\u95F4=${stableTime}ms`);\n\n if (initialTimeout > 0) {\n const selectorQuery = selectorList.join(',');\n try {\n await page.waitForSelector(selectorQuery, { timeout: initialTimeout });\n logger.info(`waitForStable \u5DF2\u68C0\u6D4B\u5230\u5143\u7D20: ${selectorQuery}`);\n } catch (e) {\n logger.warning(`waitForStable \u521D\u59CB\u7B49\u5F85\u8D85\u65F6 (${initialTimeout}ms): ${selectorQuery}`);\n throw e;\n }\n }\n\n // \u751F\u6210\u552F\u4E00\u7684\u56DE\u8C03\u540D\n const callbackName = generateKey('pk_mut_cb');\n\n // \u5982\u679C\u6709 onMutation \u56DE\u8C03\uFF0C\u66B4\u9732\u51FD\u6570\u5E76\u8FD4\u56DE\u7ED3\u679C\n if (onMutation) {\n try {\n await page.exposeFunction(callbackName, async (context) => {\n try {\n const result = await onMutation(context);\n const paused = !(result === null || result === undefined);\n // \u8FD4\u56DE null/undefined \u8868\u793A\u6B63\u5E38\u8BA1\u65F6\uFF0C\u5176\u4ED6\u503C\u8868\u793A\u6682\u505C\n return paused ? '__PAUSE__' : '__CONTINUE__';\n } catch (e) {\n // \u56DE\u8C03\u51FA\u9519\u65F6\u9ED8\u8BA4\u7EE7\u7EED\u8BA1\u65F6\n return '__CONTINUE__';\n }\n });\n logger.info('waitForStable \u5DF2\u542F\u7528 onMutation \u56DE\u8C03');\n } catch (e) {\n // \u53EF\u80FD\u5DF2\u7ECF\u66B4\u9732\u8FC7\uFF0C\u5FFD\u7565\n }\n }\n\n const result = await page.evaluate(\n async ({ selectorList, stableTime, timeout, callbackName, hasCallback }) => {\n return new Promise((resolve, reject) => {\n let mutationCount = 0;\n let stableTimer = null;\n let timeoutTimer = null;\n let isPaused = false;\n let wasPaused = false;\n const observers = [];\n\n // \u6E05\u7406\u51FD\u6570\n const cleanup = () => {\n observers.forEach(obs => obs.disconnect());\n if (stableTimer) clearTimeout(stableTimer);\n if (timeoutTimer) clearTimeout(timeoutTimer);\n };\n\n // \u91CD\u7F6E\u7A33\u5B9A\u8BA1\u65F6\u5668\n const resetStableTimer = () => {\n if (stableTimer) clearTimeout(stableTimer);\n if (isPaused) return;\n stableTimer = setTimeout(() => {\n cleanup();\n resolve({ mutationCount, stableTime, wasPaused });\n }, stableTime);\n };\n\n const setPaused = (nextPaused) => {\n if (isPaused === nextPaused) return;\n isPaused = nextPaused;\n if (isPaused) {\n if (stableTimer) clearTimeout(stableTimer);\n stableTimer = null;\n wasPaused = true;\n return;\n }\n resetStableTimer();\n };\n\n // \u6574\u4F53\u8D85\u65F6\uFF08\u59CB\u7EC8\u751F\u6548\uFF0C\u4E0D\u53D7\u6682\u505C\u5F71\u54CD\uFF09\n timeoutTimer = setTimeout(() => {\n cleanup();\n reject(new Error(`waitForStable \u8D85\u65F6 (${timeout}ms), \u5DF2\u68C0\u6D4B\u5230 ${mutationCount} \u6B21\u53D8\u5316, isPaused=${isPaused}`));\n }, timeout);\n\n // \u4E3A\u6BCF\u4E2A\u9009\u62E9\u5668\u521B\u5EFA MutationObserver\n selectorList.forEach(selector => {\n const elements = document.querySelectorAll(selector);\n elements.forEach(element => {\n const observer = new MutationObserver(async (mutations) => {\n mutationCount += mutations.length;\n\n if (hasCallback && window[callbackName]) {\n // \u83B7\u53D6\u5143\u7D20\u5185\u5BB9\n const html = element.outerHTML || '';\n const text = element.innerText || element.textContent || '';\n const mutationNodes = [{ html, text, mutationType: 'stable' }];\n\n try {\n const signal = await window[callbackName]({\n mutationCount,\n html,\n text,\n mutationNodes\n });\n\n const shouldPause = signal === '__PAUSE__';\n setPaused(shouldPause);\n if (!shouldPause) {\n resetStableTimer();\n }\n } catch (e) {\n // \u56DE\u8C03\u51FA\u9519\u65F6\u7EE7\u7EED\u8BA1\u65F6\n setPaused(false);\n resetStableTimer();\n }\n } else {\n // \u6CA1\u6709\u56DE\u8C03\uFF0C\u4FDD\u6301\u539F\u6709\u884C\u4E3A\n resetStableTimer();\n }\n });\n\n observer.observe(element, {\n childList: true,\n subtree: true,\n characterData: true,\n attributes: true\n });\n\n observers.push(observer);\n });\n });\n\n // \u5982\u679C\u6CA1\u6709\u627E\u5230\u4EFB\u4F55\u5143\u7D20\uFF0C\u76F4\u63A5\u8FD4\u56DE\n if (observers.length === 0) {\n cleanup();\n resolve({ mutationCount: 0, stableTime: 0, wasPaused: false });\n return;\n }\n\n // \u521D\u59CB\u68C0\u67E5\uFF1A\u6302\u8F7D\u540E\u7ACB\u5373\u6267\u884C\u4E00\u6B21\u56DE\u8C03\uFF0C\u5224\u65AD\u662F\u5426\u9700\u8981\u6682\u505C\n const runInitialCheck = async () => {\n if (hasCallback && window[callbackName]) {\n // \u83B7\u53D6\u7B2C\u4E00\u4E2A\u76D1\u63A7\u5143\u7D20\u7684\u5185\u5BB9\n const firstSelector = selectorList[0];\n const firstElement = document.querySelector(firstSelector);\n if (firstElement) {\n const html = firstElement.outerHTML || '';\n const text = firstElement.innerText || firstElement.textContent || '';\n const mutationNodes = [{ html, text, mutationType: 'stable' }];\n\n try {\n const signal = await window[callbackName]({\n mutationCount: 0,\n html,\n text,\n mutationNodes\n });\n\n if (signal === '__PAUSE__') {\n setPaused(true);\n return; // \u6682\u505C\u65F6\u4E0D\u542F\u52A8\u521D\u59CB\u8BA1\u65F6\n }\n } catch (e) {\n // \u56DE\u8C03\u51FA\u9519\u65F6\u7EE7\u7EED\n }\n }\n }\n // \u542F\u52A8\u521D\u59CB\u7A33\u5B9A\u8BA1\u65F6\u5668\n resetStableTimer();\n };\n\n runInitialCheck();\n });\n },\n { selectorList, stableTime, timeout, callbackName, hasCallback: !!onMutation }\n );\n\n if (result.mutationCount === 0 && result.stableTime === 0) {\n logger.warning('waitForStable \u672A\u627E\u5230\u53EF\u76D1\u63A7\u7684\u5143\u7D20');\n }\n logger.success('waitForStable', `DOM \u7A33\u5B9A, \u603B\u5171 ${result.mutationCount} \u6B21\u53D8\u5316${result.wasPaused ? ', \u66FE\u6682\u505C\u8BA1\u65F6' : ''}`);\n return result;\n },\n\n /**\n * \u521B\u5EFA\u4E00\u4E2A\u6301\u7EED\u76D1\u63A7 DOM \u53D8\u5316\u7684\u76D1\u63A7\u5668\uFF08\u9ED8\u8BA4\u4EC5\u76D1\u542C\u65B0\u589E DOM\uFF09\n *\n * @param {import('playwright').Page} page - Playwright page \u5BF9\u8C61\n * @param {string | string[]} selectors - \u8981\u76D1\u63A7\u7684 CSS \u9009\u62E9\u5668\uFF0C\u652F\u6301 'document.documentElement'\n * @param {Object} [options] - \u914D\u7F6E\u9009\u9879\n * @param {Function} [options.onMutation] - \u53D8\u5316\u65F6\u7684\u56DE\u8C03\n * \u7B7E\u540D: ({ mutationCount, html, text, mutationNodes }) => void\n * \u6240\u6709\u6A21\u5F0F\u90FD\u8FD4\u56DE\u672C\u6B21\u5168\u90E8\u53D8\u5316\u8282\u70B9\u5FEB\u7167 mutationNodes\n * @param {'added' | 'changed' | 'all'} [options.mode='added'] - \u76D1\u63A7\u6A21\u5F0F\n * @returns {Promise<{ stop: () => Promise<{ totalMutations: number }> }>} - \u8FD4\u56DE\u505C\u6B62\u51FD\u6570\n */\n async useMonitor(page, selectors, options = {}) {\n const selectorList = Array.isArray(selectors) ? selectors : [selectors];\n const onMutation = options.onMutation;\n const rawMode = String(options.mode || MUTATION_MONITOR_MODE.Added).toLowerCase();\n const mode = [MUTATION_MONITOR_MODE.Added, MUTATION_MONITOR_MODE.Changed, MUTATION_MONITOR_MODE.All].includes(rawMode)\n ? rawMode\n : MUTATION_MONITOR_MODE.Added;\n\n logger.start('useMonitor', `\u76D1\u63A7 ${selectorList.length} \u4E2A\u9009\u62E9\u5668, mode=${mode}`);\n\n const monitorKey = generateKey('pk_mon');\n const callbackName = generateKey('pk_mon_cb');\n const cleanerName = generateKey('pk_mon_clean');\n\n if (onMutation) {\n try {\n await page.exposeFunction(callbackName, (payload) => {\n try {\n onMutation(payload);\n } catch (e) {\n // \u5FFD\u7565\u56DE\u8C03\u9519\u8BEF\n }\n });\n } catch (e) {\n // \u53EF\u80FD\u5DF2\u7ECF\u66B4\u9732\u8FC7\uFF0C\u5FFD\u7565\n }\n }\n\n await page.evaluate(({ selectorList, monitorKey, callbackName, cleanerName, hasCallback, mode }) => {\n const monitor = {\n observers: [],\n totalMutations: 0,\n running: true,\n };\n\n const resolveTargets = (selector) => {\n const key = String(selector || '').trim();\n if (!key) return [];\n\n if (key === 'document.documentElement' || key === 'documentElement' || key === 'document') {\n return document.documentElement ? [document.documentElement] : [];\n }\n\n if (key === 'document.body') {\n return document.body ? [document.body] : [];\n }\n\n return Array.from(document.querySelectorAll(key));\n };\n\n const serializeNode = (node, mutationType = 'unknown') => {\n if (!node) {\n return { html: '', text: '', mutationType };\n }\n\n if (node.nodeType === Node.ELEMENT_NODE) {\n return {\n html: node.outerHTML || '',\n text: node.innerText || node.textContent || '',\n mutationType,\n };\n }\n\n if (node.nodeType === Node.TEXT_NODE) {\n const text = node.textContent || '';\n return { html: text, text, mutationType };\n }\n\n if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {\n const nodes = Array.from(node.childNodes || []);\n const html = nodes\n .map(item => item?.nodeType === Node.ELEMENT_NODE ? (item.outerHTML || '') : (item?.textContent || ''))\n .join('\\n');\n const text = node.textContent || '';\n return { html: html || text, text, mutationType };\n }\n\n const text = node.textContent || '';\n return { html: text, text, mutationType };\n };\n\n const collectMutationNodes = (mutations) => {\n const mutationNodes = [];\n\n for (const mutation of mutations) {\n if (mode === 'added') {\n if (mutation.type !== 'childList') continue;\n const added = Array.from(mutation.addedNodes || []);\n for (const node of added) {\n mutationNodes.push(serializeNode(node, 'added'));\n }\n continue;\n }\n\n if (mode === 'changed') {\n if (mutation.type === 'attributes' || mutation.type === 'characterData') {\n mutationNodes.push(serializeNode(mutation.target, mutation.type));\n } else if (mutation.type === 'childList') {\n const added = Array.from(mutation.addedNodes || []);\n const removed = Array.from(mutation.removedNodes || []);\n\n for (const node of added) {\n mutationNodes.push(serializeNode(node, 'added'));\n }\n for (const node of removed) {\n mutationNodes.push(serializeNode(node, 'removed'));\n }\n\n if (added.length === 0 && removed.length === 0) {\n mutationNodes.push(serializeNode(mutation.target, 'childList'));\n }\n }\n continue;\n }\n\n if (mutation.type === 'childList') {\n const added = Array.from(mutation.addedNodes || []);\n const removed = Array.from(mutation.removedNodes || []);\n\n for (const node of added) {\n mutationNodes.push(serializeNode(node, 'added'));\n }\n for (const node of removed) {\n mutationNodes.push(serializeNode(node, 'removed'));\n }\n\n if (added.length === 0 && removed.length === 0) {\n mutationNodes.push(serializeNode(mutation.target, 'childList'));\n }\n } else if (mutation.type === 'attributes' || mutation.type === 'characterData') {\n mutationNodes.push(serializeNode(mutation.target, mutation.type));\n } else {\n mutationNodes.push(serializeNode(mutation.target, mutation.type || 'unknown'));\n }\n }\n\n return mutationNodes;\n };\n\n selectorList.forEach(selector => {\n const elements = resolveTargets(selector);\n elements.forEach(element => {\n const observer = new MutationObserver((mutations) => {\n if (!monitor.running) return;\n\n const mutationNodes = collectMutationNodes(mutations);\n if (mutationNodes.length <= 0) return;\n\n monitor.totalMutations += mutationNodes.length;\n\n if (hasCallback && window[callbackName]) {\n const html = mutationNodes.map(item => item.html || '').join('\\n');\n const text = mutationNodes.map(item => item.text || '').join('\\n');\n\n window[callbackName]({\n mutationCount: monitor.totalMutations,\n html,\n text,\n mutationNodes,\n });\n }\n });\n\n observer.observe(element, {\n childList: true,\n subtree: true,\n characterData: mode !== 'added',\n attributes: mode !== 'added',\n });\n\n monitor.observers.push(observer);\n });\n });\n\n window[monitorKey] = monitor;\n window[cleanerName] = () => {\n monitor.running = false;\n monitor.observers.forEach(obs => obs.disconnect());\n const total = monitor.totalMutations;\n delete window[monitorKey];\n delete window[cleanerName];\n return total;\n };\n }, { selectorList, monitorKey, callbackName, cleanerName, hasCallback: !!onMutation, mode });\n\n logger.success('useMonitor', '\u76D1\u63A7\u5668\u5DF2\u542F\u52A8');\n\n return {\n stop: async () => {\n let totalMutations = 0;\n try {\n totalMutations = await page.evaluate((cleanerName) => {\n if (window[cleanerName]) {\n return window[cleanerName]();\n }\n return 0;\n }, cleanerName);\n } catch (e) {\n // \u9875\u9762\u53EF\u80FD\u5DF2\u5173\u95ED\uFF0C\u5FFD\u7565\n }\n logger.success('useMonitor.stop', `\u76D1\u63A7\u5DF2\u505C\u6B62, \u5171 ${totalMutations} \u6B21\u53D8\u5316`);\n return { totalMutations };\n }\n };\n }\n};\n", "export const Display = {\n parseTokenDisplayName(value) {\n if (!value) {\n return { owner: '', accountType: '', note: '' };\n }\n const parts = String(value).split(':');\n const owner = (parts[0] || '').trim();\n const accountType = (parts[1] || '').trim();\n const note = parts.length > 2 ? parts.slice(2).join(':').trim() : '';\n return { owner, accountType, note };\n },\n\n parseAccountDisplayName(value) {\n if (!value) {\n return { account: '', owner: '', accountType: '', note: '' };\n }\n const parts = String(value).split(':');\n const account = (parts[0] || '').trim();\n const owner = (parts[1] || '').trim();\n const accountType = (parts[2] || '').trim();\n const note = parts.length > 3 ? parts.slice(3).join(':').trim() : '';\n return { account, owner, accountType, note };\n },\n\n buildTokenDisplayName({ owner, accountType, note } = {}) {\n const trimmedOwner = owner?.trim() || '';\n const trimmedType = accountType?.trim() || '';\n const trimmedNote = note?.trim() || '';\n const parts = [trimmedOwner, trimmedType];\n if (trimmedNote) {\n parts.push(trimmedNote);\n }\n return parts.filter(Boolean).join(':');\n },\n\n shortId(value, max = 8) {\n const clean = String(value || '').trim();\n if (!clean) return '';\n if (clean.length <= max) return clean;\n return clean.slice(0, max);\n },\n\n resolveTokenIdentity(displayName, tokenId) {\n const cleanName = String(displayName || '').trim();\n const cleanId = String(tokenId || '').trim();\n const short = this.shortId(cleanId, 8);\n const hasName = cleanName !== '' && cleanName !== cleanId;\n const primary = hasName ? cleanName : (short || '-');\n const secondary = hasName && short ? short : '';\n return { primary, secondary, fullId: cleanId, shortId: short };\n },\n\n resolveAccountIdentity(displayName, accountId) {\n const parts = this.parseAccountDisplayName(displayName);\n const cleanId = String(accountId || '').trim();\n const short = this.shortId(cleanId, 8);\n const hasName = parts.account !== '' && parts.account !== cleanId;\n const primary = hasName ? parts.account : (short || '-');\n const secondary = hasName && short ? short : '';\n return { primary, secondary, parts, fullId: cleanId, shortId: short };\n },\n};\n", "import { createBaseLogger, setDefaultLogger } from './internals/logger.js';\n\nexport const stripAnsi = (input) => {\n if (!input) return '';\n return String(input).replace(/\\x1b\\[[0-9;]*m/g, '');\n};\n\n// =============================================================================\n// Log Templates & Definitions\n// =============================================================================\n\nconst STEP_PREFIX = '\u6B65\u9AA4:';\nconst STEP_SEPARATOR = ' | ';\nconst STEP_EMOJIS = [\n { match: '\u4EFB\u52A1', emoji: '\uD83E\uDDED' },\n { match: '\u8FD0\u884C\u6A21\u5F0F', emoji: '\uD83E\uDDE9' },\n { match: '\u767B\u5F55', emoji: '\uD83D\uDD10' },\n { match: '\u73AF\u5883', emoji: '\uD83E\uDDEA' },\n { match: '\u8F93\u5165', emoji: '\u2328\uFE0F' },\n { match: '\u53D1\u9001', emoji: '\uD83D\uDCE4' },\n { match: '\u54CD\u5E94\u76D1\u542C', emoji: '\uD83D\uDCE1' },\n { match: '\u7B49\u5F85\u54CD\u5E94', emoji: '\u23F3' },\n { match: '\u6D41\u5F0F', emoji: '\uD83E\uDDF5' },\n { match: '\u5F15\u7528', emoji: '\uD83D\uDCCE' },\n { match: '\u622A\u56FE', emoji: '\uD83D\uDDBC\uFE0F' },\n { match: '\u5206\u4EAB\u94FE\u63A5', emoji: '\uD83D\uDD17' },\n { match: '\u6570\u636E\u63A8\u9001', emoji: '\uD83D\uDCE6' },\n { match: '\u5F39\u7A97', emoji: '\uD83E\uDE9F' },\n];\nconst STATUS_EMOJIS = [\n { match: '\u5F00\u59CB', emoji: '\uD83D\uDE80' },\n { match: '\u5B8C\u6210', emoji: '\u2705' },\n { match: '\u6210\u529F', emoji: '\u2705' },\n { match: '\u5931\u8D25', emoji: '\u274C' },\n { match: '\u8DF3\u8FC7', emoji: '\u23ED\uFE0F' },\n { match: '\u8D85\u65F6', emoji: '\u23F1\uFE0F' },\n { match: '\u91CD\u8BD5', emoji: '\uD83D\uDD01' },\n { match: '\u7ED3\u675F', emoji: '\uD83C\uDFC1' },\n { match: '\u5DF2\u914D\u7F6E', emoji: '\uD83E\uDDF7' },\n { match: '\u5DF2\u68C0\u6D4B', emoji: '\uD83D\uDD0E' },\n];\n\nconst toErrorMessage = (error) => {\n if (!error) return '';\n if (error instanceof Error) return error.message;\n if (typeof error === 'string') return error;\n try {\n return JSON.stringify(error);\n } catch {\n return String(error);\n }\n};\n\nconst decorateLabel = (label, mappings) => {\n if (!label) return '';\n const mapping = mappings.find((item) => label.includes(item.match));\n if (!mapping) return label;\n return `${mapping.emoji} ${label}`;\n};\n\nconst normalizeSnippet = (snippet, maxLen = 120) => {\n if (!snippet) return '';\n const text = String(snippet).replace(/\\s+/g, ' ').trim();\n if (!text) return '';\n const cleaned = text.replace(/\"/g, \"'\");\n if (cleaned.length <= maxLen) return cleaned;\n return `${cleaned.slice(0, maxLen)}...`;\n};\n\nconst LOG_TAG_PREFIX = '[#log:';\nconst LOG_TAG_SUFFIX = ']';\n\nconst buildLogTag = (key) => `${LOG_TAG_PREFIX}${key}${LOG_TAG_SUFFIX}`;\n\nconst escapeRegExp = (value) => String(value).replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\nconst buildStepPattern = (step, status) => {\n if (!step) return null;\n let pattern = `\u6B65\u9AA4: .*${escapeRegExp(step)}`;\n if (status) {\n pattern += `.*${escapeRegExp(status)}`;\n }\n return new RegExp(pattern);\n};\n\nconst buildDefinitionPatterns = (definition) => {\n const patterns = [new RegExp(`\\\\[#log:${escapeRegExp(definition.key)}\\\\]`)];\n const fallback = buildStepPattern(definition.step, definition.status);\n if (fallback) patterns.push(fallback);\n if (Array.isArray(definition.extraPatterns)) {\n patterns.push(...definition.extraPatterns);\n }\n return patterns;\n};\n\nconst ATTENTION_RANK = {\n low: 1,\n medium: 2,\n high: 3,\n critical: 4,\n};\nconst DEFAULT_ATTENTION_RANK = ATTENTION_RANK.high;\n\nconst LOG_DEFINITIONS = [\n {\n key: 'task_start',\n method: 'taskStart',\n label: '\u4EFB\u52A1\u5F00\u59CB',\n group: '\u4EFB\u52A1',\n step: '\u4EFB\u52A1',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n buildDetails: (url) => [url ? `url=${url}` : ''],\n },\n {\n key: 'task_success',\n method: 'taskSuccess',\n label: '\u4EFB\u52A1\u5B8C\u6210',\n group: '\u4EFB\u52A1',\n step: '\u4EFB\u52A1',\n status: '\u5B8C\u6210',\n level: 'success',\n attention: 'high',\n },\n {\n key: 'task_fail',\n method: 'taskFail',\n label: '\u4EFB\u52A1\u5931\u8D25',\n group: '\u4EFB\u52A1',\n step: '\u4EFB\u52A1',\n status: '\u5931\u8D25',\n level: 'error',\n attention: 'critical',\n buildDetails: (url, err) => [\n url ? `url=${url}` : '',\n err ? `err=${toErrorMessage(err)}` : ''\n ],\n },\n {\n key: 'runtime_headless',\n method: 'runtimeHeadless',\n label: '\u8FD0\u884C\u6A21\u5F0F\u5F3A\u5236\u65E0\u5934',\n group: '\u8FD0\u884C\u6A21\u5F0F',\n step: '\u8FD0\u884C\u6A21\u5F0F',\n status: 'Apify \u73AF\u5883\u5F3A\u5236\u65E0\u5934',\n level: 'warning',\n attention: 'medium',\n },\n {\n key: 'login_inject_success',\n method: 'loginInjectSuccess',\n label: '\u767B\u5F55\u6001\u6CE8\u5165\u6210\u529F',\n group: '\u767B\u5F55',\n step: '\u767B\u5F55\u6001\u6CE8\u5165',\n status: '\u6210\u529F',\n level: 'success',\n attention: 'medium',\n buildDetails: (detail) => [detail ? `detail=${detail}` : ''],\n },\n {\n key: 'login_inject_skip',\n method: 'loginInjectSkip',\n label: '\u767B\u5F55\u6001\u6CE8\u5165\u8DF3\u8FC7',\n group: '\u767B\u5F55',\n step: '\u767B\u5F55\u6001\u6CE8\u5165',\n status: '\u8DF3\u8FC7',\n level: 'warning',\n attention: 'medium',\n buildDetails: (reason) => [reason ? `\u539F\u56E0=${reason}` : ''],\n },\n {\n key: 'login_inject_fail',\n method: 'loginInjectFail',\n label: '\u767B\u5F55\u6001\u6CE8\u5165\u5931\u8D25',\n group: '\u767B\u5F55',\n step: '\u767B\u5F55\u6001\u6CE8\u5165',\n status: '\u5931\u8D25',\n level: 'error',\n attention: 'high',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n {\n key: 'login_verify_success',\n method: 'loginVerifySuccess',\n label: '\u767B\u5F55\u9A8C\u8BC1\u6210\u529F',\n group: '\u767B\u5F55',\n step: '\u767B\u5F55\u9A8C\u8BC1',\n status: '\u6210\u529F',\n level: 'success',\n attention: 'high',\n buildDetails: (detail) => [detail ? `detail=${detail}` : ''],\n },\n {\n key: 'login_verify_skip',\n method: 'loginVerifySkip',\n label: '\u767B\u5F55\u9A8C\u8BC1\u8DF3\u8FC7',\n group: '\u767B\u5F55',\n step: '\u767B\u5F55\u9A8C\u8BC1',\n status: '\u8DF3\u8FC7',\n level: 'warning',\n attention: 'medium',\n buildDetails: (reason) => [reason ? `\u539F\u56E0=${reason}` : ''],\n },\n {\n key: 'login_verify_fail',\n method: 'loginVerifyFail',\n label: '\u767B\u5F55\u9A8C\u8BC1\u5931\u8D25',\n group: '\u767B\u5F55',\n step: '\u767B\u5F55\u9A8C\u8BC1',\n status: '\u5931\u8D25',\n level: 'error',\n attention: 'critical',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n {\n key: 'env_check_success',\n method: 'envCheckSuccess',\n label: '\u73AF\u5883\u68C0\u67E5\u6210\u529F',\n group: '\u73AF\u5883',\n step: '\u73AF\u5883\u68C0\u67E5',\n status: '\u6210\u529F',\n level: 'success',\n attention: 'medium',\n buildDetails: (detail) => [detail ? `detail=${detail}` : ''],\n },\n {\n key: 'env_check_fail',\n method: 'envCheckFail',\n label: '\u73AF\u5883\u68C0\u67E5\u5931\u8D25',\n group: '\u73AF\u5883',\n step: '\u73AF\u5883\u68C0\u67E5',\n status: '\u5931\u8D25',\n level: 'error',\n attention: 'high',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n {\n key: 'input_query_start',\n method: 'inputQuery',\n label: '\u8F93\u5165\u67E5\u8BE2\u5F00\u59CB',\n group: '\u8F93\u5165',\n step: '\u8F93\u5165\u67E5\u8BE2',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n buildDetails: (query) => [query ? `query=${query}` : ''],\n },\n {\n key: 'send_action',\n method: 'sendAction',\n label: '\u53D1\u9001\u8BF7\u6C42',\n group: '\u53D1\u9001',\n step: '\u53D1\u9001\u8BF7\u6C42',\n status: '\u70B9\u51FB\u53D1\u9001',\n level: 'info',\n attention: 'low',\n },\n {\n key: 'response_listen_start',\n method: 'responseListenStart',\n label: '\u54CD\u5E94\u76D1\u542C\u5F00\u59CB',\n group: '\u54CD\u5E94\u76D1\u542C',\n step: '\u54CD\u5E94\u76D1\u542C',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n buildDetails: (label, timeoutSec) => [\n label ? `\u76EE\u6807=${label}` : '',\n timeoutSec ? `timeout=${timeoutSec}s` : ''\n ],\n },\n {\n key: 'response_listen_ready',\n method: 'responseListenReady',\n label: '\u54CD\u5E94\u76D1\u542C\u5DF2\u914D\u7F6E',\n group: '\u54CD\u5E94\u76D1\u542C',\n step: '\u54CD\u5E94\u76D1\u542C',\n status: '\u5DF2\u914D\u7F6E',\n level: 'info',\n attention: 'medium',\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\n },\n {\n key: 'response_listen_detected',\n method: 'responseListenDetected',\n label: '\u54CD\u5E94\u76D1\u542C\u5DF2\u68C0\u6D4B',\n group: '\u54CD\u5E94\u76D1\u542C',\n step: '\u54CD\u5E94\u76D1\u542C',\n status: '\u5DF2\u68C0\u6D4B',\n level: 'success',\n attention: 'medium',\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\n },\n {\n key: 'response_listen_timeout',\n method: 'responseListenTimeout',\n label: '\u54CD\u5E94\u76D1\u542C\u8D85\u65F6',\n group: '\u54CD\u5E94\u76D1\u542C',\n step: '\u54CD\u5E94\u76D1\u542C',\n status: '\u8D85\u65F6',\n level: 'error',\n attention: 'high',\n buildDetails: (label, err) => [\n label ? `\u76EE\u6807=${label}` : '',\n err ? `err=${toErrorMessage(err)}` : ''\n ],\n },\n {\n key: 'response_listen_end',\n method: 'responseListenEnd',\n label: '\u54CD\u5E94\u76D1\u542C\u7ED3\u675F',\n group: '\u54CD\u5E94\u76D1\u542C',\n step: '\u54CD\u5E94\u76D1\u542C',\n status: '\u7ED3\u675F',\n level: 'info',\n attention: 'low',\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\n },\n {\n key: 'response_wait_start',\n method: 'responseWaitStart',\n label: '\u7B49\u5F85\u54CD\u5E94\u5F00\u59CB',\n group: '\u7B49\u5F85\u54CD\u5E94',\n step: '\u7B49\u5F85\u54CD\u5E94',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\n },\n {\n key: 'response_wait_success',\n method: 'responseWaitSuccess',\n label: '\u7B49\u5F85\u54CD\u5E94\u5B8C\u6210',\n group: '\u7B49\u5F85\u54CD\u5E94',\n step: '\u7B49\u5F85\u54CD\u5E94',\n status: '\u5B8C\u6210',\n level: 'success',\n attention: 'medium',\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\n },\n {\n key: 'response_wait_fail',\n method: 'responseWaitFail',\n label: '\u7B49\u5F85\u54CD\u5E94\u5931\u8D25',\n group: '\u7B49\u5F85\u54CD\u5E94',\n step: '\u7B49\u5F85\u54CD\u5E94',\n status: '\u5931\u8D25',\n level: 'warning',\n attention: 'high',\n buildDetails: (label, err) => [\n label ? `\u76EE\u6807=${label}` : '',\n err ? `err=${toErrorMessage(err)}` : ''\n ],\n },\n {\n key: 'response_wait_retry',\n method: 'responseWaitRetry',\n label: '\u7B49\u5F85\u54CD\u5E94\u91CD\u8BD5',\n group: '\u7B49\u5F85\u54CD\u5E94',\n step: '\u7B49\u5F85\u54CD\u5E94',\n status: '\u91CD\u8BD5',\n level: 'warning',\n attention: 'medium',\n buildDetails: (label, attempt) => [\n label ? `\u76EE\u6807=${label}` : '',\n attempt !== undefined ? `\u5C1D\u8BD5=${attempt}` : ''\n ],\n },\n {\n key: 'dom_wait_start',\n method: 'domWaitStart',\n label: 'DOM\u7A33\u5B9A\u7B49\u5F85\u5F00\u59CB',\n group: 'DOM',\n step: 'DOM\u7A33\u5B9A',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\n },\n {\n key: 'dom_wait_fail',\n method: 'domWaitFail',\n label: 'DOM\u7A33\u5B9A\u7B49\u5F85\u5931\u8D25',\n group: 'DOM',\n step: 'DOM\u7A33\u5B9A',\n status: '\u5931\u8D25',\n level: 'warning',\n attention: 'high',\n buildDetails: (label, err) => [\n label ? `\u76EE\u6807=${label}` : '',\n err ? `err=${toErrorMessage(err)}` : ''\n ],\n },\n {\n key: 'dom_chunk',\n method: 'domChunk',\n label: 'DOM\u7247\u6BB5',\n group: 'DOM',\n step: 'DOM\u7247\u6BB5',\n status: '',\n level: 'info',\n attention: 'low',\n throttleKey: 'dom-chunk',\n throttleMs: 2000,\n buildDetails: (length, snippet, paused) => [\n length !== undefined ? `len=${length}` : '',\n snippet ? `preview=\"${normalizeSnippet(snippet)}\"` : '',\n paused ? 'paused=1' : ''\n ],\n },\n {\n key: 'dom_wait_success',\n method: 'domWaitSuccess',\n label: 'DOM\u7A33\u5B9A\u7B49\u5F85\u5B8C\u6210',\n group: 'DOM',\n step: 'DOM\u7A33\u5B9A',\n status: '\u5B8C\u6210',\n level: 'success',\n attention: 'medium',\n buildDetails: (mutationCount, stableTime, wasPaused) => [\n mutationCount !== undefined ? `mutations=${mutationCount}` : '',\n stableTime !== undefined ? `stableTime=${stableTime}ms` : '',\n wasPaused ? 'paused=1' : ''\n ],\n },\n {\n key: 'stream_chunk',\n method: 'streamChunk',\n label: '\u6D41\u5F0F\u7247\u6BB5',\n group: '\u6D41\u5F0F',\n step: '\u6D41\u5F0F\u7247\u6BB5',\n status: '',\n level: 'info',\n attention: 'low',\n throttleKey: 'stream-chunk',\n throttleMs: 2000,\n buildDetails: (length, snippet) => [\n length !== undefined ? `len=${length}` : '',\n snippet ? `preview=\"${normalizeSnippet(snippet)}\"` : ''\n ],\n },\n {\n key: 'stream_events_parsed',\n method: 'streamEventsParsed',\n label: '\u6D41\u5F0F\u4E8B\u4EF6\u89E3\u6790\u5B8C\u6210',\n group: '\u6D41\u5F0F',\n step: '\u6D41\u5F0F\u4E8B\u4EF6\u89E3\u6790',\n status: '\u5B8C\u6210',\n level: 'info',\n attention: 'low',\n throttleKey: 'stream-events',\n throttleMs: 4000,\n buildDetails: (count) => [count !== undefined ? `count=${count}` : ''],\n },\n {\n key: 'stream_complete_event',\n method: 'streamCompleteEvent',\n label: '\u6D41\u5F0F\u5B8C\u6210\u4E8B\u4EF6\u6355\u83B7',\n group: '\u6D41\u5F0F',\n step: '\u6D41\u5F0F\u4E8B\u4EF6',\n status: '\u5B8C\u6210\u4E8B\u4EF6\u5DF2\u6355\u83B7',\n level: 'success',\n attention: 'medium',\n },\n {\n key: 'stream_end',\n method: 'streamEnd',\n label: '\u6D41\u5F0F\u54CD\u5E94\u7ED3\u675F',\n group: '\u6D41\u5F0F',\n step: '\u6D41\u5F0F\u54CD\u5E94',\n status: '\u7ED3\u675F',\n level: 'info',\n attention: 'low',\n },\n {\n key: 'reference_expand_start',\n method: 'referenceExpandStart',\n label: '\u5F15\u7528\u5C55\u5F00\u5F00\u59CB',\n group: '\u5F15\u7528',\n step: '\u5F15\u7528\u5C55\u5F00',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n buildDetails: (label) => [label ? `\u76EE\u6807=${label}` : ''],\n },\n {\n key: 'reference_expand_fail',\n method: 'referenceExpandFail',\n label: '\u5F15\u7528\u5C55\u5F00\u5931\u8D25',\n group: '\u5F15\u7528',\n step: '\u5F15\u7528\u5C55\u5F00',\n status: '\u5931\u8D25',\n level: 'warning',\n attention: 'medium',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n {\n key: 'screenshot_start',\n method: 'screenshotStart',\n label: '\u622A\u56FE\u5F00\u59CB',\n group: '\u622A\u56FE',\n step: '\u622A\u56FE',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n },\n {\n key: 'screenshot_success',\n method: 'screenshotSuccess',\n label: '\u622A\u56FE\u6210\u529F',\n group: '\u622A\u56FE',\n step: '\u622A\u56FE',\n status: '\u6210\u529F',\n level: 'success',\n attention: 'high',\n },\n {\n key: 'screenshot_fail',\n method: 'screenshotFail',\n label: '\u622A\u56FE\u5931\u8D25',\n group: '\u622A\u56FE',\n step: '\u622A\u56FE',\n status: '\u5931\u8D25',\n level: 'warning',\n attention: 'high',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n {\n key: 'share_start',\n method: 'shareStart',\n label: '\u5206\u4EAB\u94FE\u63A5\u5F00\u59CB',\n group: '\u5206\u4EAB',\n step: '\u5206\u4EAB\u94FE\u63A5',\n status: '\u5F00\u59CB',\n level: 'start',\n attention: 'low',\n },\n {\n key: 'share_progress',\n method: 'shareProgress',\n label: '\u5206\u4EAB\u94FE\u63A5\u6B65\u9AA4',\n group: '\u5206\u4EAB',\n step: '\u5206\u4EAB\u94FE\u63A5',\n status: '\u6B65\u9AA4',\n level: 'info',\n attention: 'low',\n buildDetails: (label) => [label ? `\u6B65\u9AA4=${label}` : ''],\n },\n {\n key: 'share_dom_hit',\n method: 'shareDomHit',\n label: '\u5206\u4EAB\u94FE\u63A5DOM\u547D\u4E2D',\n group: '\u5206\u4EAB',\n step: '\u5206\u4EAB\u94FE\u63A5',\n status: 'DOM\u547D\u4E2D',\n level: 'info',\n attention: 'low',\n buildDetails: (link, domSnapshot) => [\n link ? `\u94FE\u63A5=${link}` : '',\n domSnapshot ? `DOM=${normalizeSnippet(domSnapshot, 220)}` : ''\n ],\n },\n {\n key: 'share_source',\n method: 'shareSource',\n label: '\u5206\u4EAB\u94FE\u63A5\u6765\u6E90',\n group: '\u5206\u4EAB',\n step: '\u5206\u4EAB\u94FE\u63A5',\n status: '\u6765\u6E90',\n level: 'info',\n attention: 'low',\n buildDetails: (source, link, domSnapshot) => [\n source ? `\u6765\u6E90=${source}` : '',\n link ? `\u94FE\u63A5=${link}` : '',\n source === 'dom' && domSnapshot ? `DOM=${normalizeSnippet(domSnapshot, 220)}` : ''\n ],\n },\n {\n key: 'share_success',\n method: 'shareSuccess',\n label: '\u5206\u4EAB\u94FE\u63A5\u6210\u529F',\n group: '\u5206\u4EAB',\n step: '\u5206\u4EAB\u94FE\u63A5',\n status: '\u6210\u529F',\n level: 'success',\n attention: 'high',\n buildDetails: (link) => [link ? `\u94FE\u63A5=${link}` : ''],\n },\n {\n key: 'share_fail',\n method: 'shareFail',\n label: '\u5206\u4EAB\u94FE\u63A5\u5931\u8D25',\n group: '\u5206\u4EAB',\n step: '\u5206\u4EAB\u94FE\u63A5',\n status: '\u5931\u8D25',\n level: 'warning',\n attention: 'high',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n {\n key: 'share_skip',\n method: 'shareSkip',\n label: '\u5206\u4EAB\u94FE\u63A5\u8DF3\u8FC7',\n group: '\u5206\u4EAB',\n step: '\u5206\u4EAB\u94FE\u63A5',\n status: '\u8DF3\u8FC7',\n level: 'warning',\n attention: 'medium',\n buildDetails: (reason) => [reason ? `\u539F\u56E0=${reason}` : ''],\n },\n {\n key: 'data_push_success',\n method: 'dataPushSuccess',\n label: '\u6570\u636E\u63A8\u9001\u6210\u529F',\n group: '\u6570\u636E\u63A8\u9001',\n step: '\u6570\u636E\u63A8\u9001',\n status: '\u6210\u529F',\n level: 'success',\n attention: 'medium',\n buildDetails: (label) => [label ? `\u8BF4\u660E=${label}` : ''],\n },\n {\n key: 'data_push_fail',\n method: 'dataPushFail',\n label: '\u6570\u636E\u63A8\u9001\u5931\u8D25',\n group: '\u6570\u636E\u63A8\u9001',\n step: '\u6570\u636E\u63A8\u9001',\n status: '\u5931\u8D25',\n level: 'error',\n attention: 'high',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n {\n key: 'popup_detected',\n method: 'popupDetected',\n label: '\u5F39\u7A97\u68C0\u6D4B',\n group: '\u5F39\u7A97',\n step: '\u5F39\u7A97\u5904\u7406',\n status: '\u68C0\u6D4B\u5230\u906E\u7F69',\n level: 'warning',\n attention: 'medium',\n buildDetails: (detail) => [detail ? `detail=${detail}` : ''],\n },\n {\n key: 'popup_close_attempt',\n method: 'popupCloseAttempt',\n label: '\u5F39\u7A97\u5173\u95ED\u5C1D\u8BD5',\n group: '\u5F39\u7A97',\n step: '\u5F39\u7A97\u5904\u7406',\n status: '\u5C1D\u8BD5\u5173\u95ED',\n level: 'info',\n attention: 'low',\n buildDetails: (detail) => [detail ? `detail=${detail}` : ''],\n },\n {\n key: 'popup_close_success',\n method: 'popupCloseSuccess',\n label: '\u5F39\u7A97\u5173\u95ED\u5B8C\u6210',\n group: '\u5F39\u7A97',\n step: '\u5F39\u7A97\u5904\u7406',\n status: '\u5173\u95ED\u5B8C\u6210',\n level: 'success',\n attention: 'medium',\n },\n {\n key: 'popup_close_fail',\n method: 'popupCloseFail',\n label: '\u5F39\u7A97\u5173\u95ED\u5931\u8D25',\n group: '\u5F39\u7A97',\n step: '\u5F39\u7A97\u5904\u7406',\n status: '\u5173\u95ED\u5931\u8D25',\n level: 'warning',\n attention: 'medium',\n buildDetails: (err) => [err ? `err=${toErrorMessage(err)}` : ''],\n },\n];\n\nexport const LOG_TEMPLATES = LOG_DEFINITIONS.map((definition) => {\n const attention = definition.attention || 'medium';\n const attentionRank = ATTENTION_RANK[attention] || ATTENTION_RANK.medium;\n const defaultSelected = attentionRank >= DEFAULT_ATTENTION_RANK;\n return {\n key: definition.key,\n label: definition.label,\n group: definition.group,\n attention,\n patterns: buildDefinitionPatterns(definition),\n defaultSelected,\n };\n});\n\nconst buildStepLine = (step, status, details = []) => {\n const parts = [];\n const decoratedStep = step ? decorateLabel(step, STEP_EMOJIS) : '';\n const base = decoratedStep ? `${STEP_PREFIX} ${decoratedStep}` : STEP_PREFIX;\n parts.push(base.trim());\n if (status) parts.push(decorateLabel(status, STATUS_EMOJIS));\n const detailParts = details.filter(Boolean);\n if (detailParts.length > 0) {\n parts.push(...detailParts);\n }\n return parts.join(STEP_SEPARATOR);\n};\n\nconst createThrottle = () => {\n const lastMap = new Map();\n return (key, intervalMs, fn) => {\n const now = Date.now();\n const last = lastMap.get(key) || 0;\n if (now - last >= intervalMs) {\n lastMap.set(key, now);\n fn();\n }\n };\n};\n\nexport const createTemplateLogger = (baseLogger = createBaseLogger()) => {\n const throttle = createThrottle();\n\n const info = (line) => baseLogger.info(line);\n const success = (line) => baseLogger.success(line);\n const warning = (line) => baseLogger.warning(line);\n const error = (line) => baseLogger.error(line);\n const debug = (line) => baseLogger.debug(line);\n const start = (line) => baseLogger.start(line);\n\n const stepInfo = (step, status, details = []) => info(buildStepLine(step, status, details));\n const stepSuccess = (step, status, details = []) => success(buildStepLine(step, status, details));\n const stepWarn = (step, status, details = []) => warning(buildStepLine(step, status, details));\n const stepError = (step, status, details = []) => error(buildStepLine(step, status, details));\n const stepStart = (step, status, details = []) => start(buildStepLine(step, status, details));\n\n const stepHandlers = {\n info: stepInfo,\n success: stepSuccess,\n warning: stepWarn,\n error: stepError,\n start: stepStart,\n };\n\n const logFromDefinition = (definition, details = []) => {\n const handler = stepHandlers[definition.level] || stepInfo;\n const payload = [...details, buildLogTag(definition.key)];\n const emit = () => handler(definition.step, definition.status, payload);\n if (definition.throttleMs) {\n throttle(definition.throttleKey || definition.key, definition.throttleMs, emit);\n return;\n }\n emit();\n };\n\n const definitionMethods = {};\n LOG_DEFINITIONS.forEach((definition) => {\n if (!definition.method) return;\n definitionMethods[definition.method] = (...args) => {\n const details = definition.buildDetails ? definition.buildDetails(...args) : [];\n logFromDefinition(definition, details);\n };\n });\n\n return {\n step: (step, status, details, level = 'info') => {\n if (level === 'error') return stepError(step, status, details);\n if (level === 'warn' || level === 'warning') return stepWarn(step, status, details);\n if (level === 'start') return stepStart(step, status, details);\n if (level === 'success') return stepSuccess(step, status, details);\n return stepInfo(step, status, details);\n },\n info: (message) => info(message),\n success: (message) => success(message),\n warning: (message) => warning(message),\n warn: (message) => warning(message),\n error: (message) => error(message),\n debug: (message) => debug(message),\n start: (message) => start(message),\n ...definitionMethods,\n };\n};\n\nconst getDefaultBaseLogger = () => createBaseLogger('');\n\nexport const Logger = {\n setLogger: (logger) => setDefaultLogger(logger),\n info: (message) => getDefaultBaseLogger().info(message),\n success: (message) => getDefaultBaseLogger().success(message),\n warning: (message) => getDefaultBaseLogger().warning(message),\n warn: (message) => getDefaultBaseLogger().warning(message),\n error: (message) => getDefaultBaseLogger().error(message),\n debug: (message) => getDefaultBaseLogger().debug(message),\n start: (message) => getDefaultBaseLogger().start(message),\n useTemplate: (logger) => {\n if (logger) return createTemplateLogger(createBaseLogger('', logger));\n return createTemplateLogger();\n },\n};\n", "import delay from 'delay';\nimport { Utils } from './utils.js';\nimport { Mutation } from './mutation.js';\nimport { createInternalLogger } from './internals/logger.js';\n\nconst logger = createInternalLogger('Share');\n\nconst DEFAULT_TIMEOUT_MS = 50 * 1000;\nconst DEFAULT_PAYLOAD_SNAPSHOT_MAX_LEN = 500;\nconst DEFAULT_POLL_INTERVAL_MS = 120;\n\nconst normalizePrefix = (value) => String(value || '').trim();\n\nconst toSnapshot = (value, maxLen) => {\n const text = String(value || '');\n if (!text) return '';\n return text.replace(/\\s+/g, ' ').trim().slice(0, maxLen);\n};\n\nconst toInline = (value, maxLen = 200) => {\n const text = String(value || '');\n if (!text) return '';\n return text.replace(/\\s+/g, ' ').trim().slice(0, maxLen);\n};\n\nconst toJsonInline = (value, maxLen = 260) => {\n try {\n return toInline(JSON.stringify(value), maxLen);\n } catch {\n return '[\u4E0D\u53EF\u5E8F\u5217\u5316]';\n }\n};\n\nconst normalizeXurl = (value) => {\n if (!Array.isArray(value)) return [];\n\n const normalizeMatcherList = (input) => {\n if (Array.isArray(input)) {\n return input\n .map((item) => String(item || '').trim().replace(/\\.+$/, ''))\n .filter(Boolean);\n }\n\n const single = String(input || '').trim().replace(/\\.+$/, '');\n return single ? [single] : [];\n };\n\n const normalizeSegments = (input) => {\n if (Array.isArray(input)) {\n return input\n .map((item) => String(item || '').trim().replace(/\\.+$/, ''))\n .filter(Boolean);\n }\n\n const raw = String(input || '').trim();\n if (!raw) return [];\n\n return raw\n .split('.')\n .map((item) => String(item || '').trim().replace(/\\.+$/, ''))\n .filter(Boolean);\n };\n\n const normalized = [];\n\n const apiMatchers = normalizeMatcherList(value[0]);\n if (apiMatchers.length > 0) {\n normalized.push(apiMatchers);\n }\n\n const flattenedPath = [];\n const extraPaths = [];\n\n value.slice(1).forEach((item) => {\n if (Array.isArray(item)) {\n const segments = normalizeSegments(item);\n if (segments.length > 0) {\n extraPaths.push(segments);\n }\n return;\n }\n\n const segments = normalizeSegments(item);\n if (segments.length > 0) {\n flattenedPath.push(...segments);\n }\n });\n\n if (flattenedPath.length > 0) {\n normalized.push(flattenedPath);\n }\n\n if (extraPaths.length > 0) {\n normalized.push(...extraPaths);\n }\n\n return normalized;\n};\n\nconst normalizeShare = (share) => {\n const source = share && typeof share === 'object' ? share : {};\n const modeRaw = String(source.mode || 'dom').trim().toLowerCase();\n const mode = modeRaw === 'response' ? 'response' : 'dom';\n\n return {\n mode,\n prefix: normalizePrefix(source.prefix),\n xurl: normalizeXurl(source.xurl),\n };\n};\n\nconst getByPathSegments = (source, pathSegments) => {\n if (!Array.isArray(pathSegments) || pathSegments.length === 0) return undefined;\n\n let current = source;\n\n for (const rawSegment of pathSegments) {\n const segment = String(rawSegment || '').trim();\n if (!segment) return undefined;\n if (current == null) return undefined;\n\n if (Array.isArray(current) && /^\\d+$/.test(segment)) {\n current = current[Number(segment)];\n continue;\n }\n\n current = current[segment];\n }\n\n return current;\n};\n\nconst buildShareLink = (prefix, value) => {\n const raw = String(value || '').trim();\n if (!raw) return '';\n\n if (/^https?:\\/\\//i.test(raw)) {\n return raw;\n }\n\n const safePrefix = normalizePrefix(prefix);\n if (!safePrefix) return '';\n\n const prefixNoSlash = safePrefix.endsWith('/') ? safePrefix.slice(0, -1) : safePrefix;\n const valueNoSlash = raw.replace(/^\\/+/, '');\n\n return `${prefixNoSlash}/${valueNoSlash}`;\n};\n\nconst parseJsonSafely = (text) => {\n const raw = String(text || '').trim();\n if (!raw) return null;\n\n try {\n return JSON.parse(raw);\n } catch {\n return null;\n }\n};\n\nconst createDomShareMonitor = async (page, options = {}) => {\n const prefix = normalizePrefix(options.prefix);\n const selectors = options.selectors ?? 'html';\n const mode = options.mode ?? Mutation.Mode.All;\n const onMatch = typeof options.onMatch === 'function' ? options.onMatch : null;\n const onTelemetry = typeof options.onTelemetry === 'function' ? options.onTelemetry : null;\n\n let matched = false;\n\n logger.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode}`);\n\n const monitor = await Mutation.useMonitor(page, selectors, {\n mode,\n onMutation: (context = {}) => {\n if (matched) return;\n\n const mutationCount = Number(context.mutationCount || 0);\n const mutationNodes = Array.isArray(context.mutationNodes) ? context.mutationNodes : [];\n const html = String(context.html || '');\n const text = String(context.text || '');\n const rawDom = `${html}\\n${text}`;\n\n if (onTelemetry) {\n onTelemetry({\n mutationCount,\n mutationNodesCount: mutationNodes.length,\n });\n }\n\n if (mutationCount <= 5 || mutationCount % 50 === 0) {\n logger.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);\n }\n\n const [candidate] = Utils.parseLinks(rawDom, { prefix }) || [];\n if (!candidate) return;\n\n matched = true;\n logger.success('captureLink.domHit', `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);\n\n if (onMatch) {\n onMatch({\n link: candidate,\n rawDom,\n mutationCount,\n html,\n text,\n mutationNodes,\n });\n }\n },\n });\n\n return {\n stop: async () => {\n const result = await monitor.stop();\n logger.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);\n return result;\n },\n };\n};\n\nexport const Share = {\n /**\n * \u6355\u83B7\u5206\u4EAB\u94FE\u63A5\uFF08\u5355\u6A21\u5F0F\uFF09\n * - mode='dom': \u4EC5 DOM \u76D1\u542C\n * - mode='response': \u4EC5\u63A5\u53E3\u76D1\u542C\n *\n * @param {import('playwright').Page} page\n * @param {Object} [options]\n * @param {{ mode?: 'dom' | 'response', prefix: string, xurl?: Array<string | string[]> }} options.share\n * @param {number} [options.timeoutMs=50000]\n * @param {number} [options.payloadSnapshotMaxLen=500]\n * @param {string | string[]} [options.domSelectors='html']\n * @param {'added' | 'changed' | 'all'} [options.domMode='all']\n * @param {() => Promise<void>} [options.performActions]\n * @returns {Promise<{ link: string | null; payloadText: string; payloadSnapshot: string; source: 'dom' | 'response' | 'none' }>}\n */\n async captureLink(page, options = {}) {\n const share = normalizeShare(options.share);\n const timeoutMs = Math.max(0, Number(options.timeoutMs ?? DEFAULT_TIMEOUT_MS) || 0);\n const payloadSnapshotMaxLen = options.payloadSnapshotMaxLen ?? DEFAULT_PAYLOAD_SNAPSHOT_MAX_LEN;\n const domSelectors = options.domSelectors ?? 'html';\n const domMode = options.domMode ?? Mutation.Mode.All;\n const performActions = typeof options.performActions === 'function' ? options.performActions : async () => { };\n\n if (!share.prefix) {\n throw new Error('Share.captureLink requires options.share.prefix');\n }\n\n if (share.mode !== 'dom' && share.mode !== 'response') {\n throw new Error(`Share.captureLink unsupported share.mode: ${share.mode}`);\n }\n\n const apiMatchers = share.mode === 'response' ? (share.xurl[0] || []) : [];\n const fieldPaths = share.mode === 'response' ? share.xurl.slice(1) : [];\n\n if (share.mode === 'response' && apiMatchers.length === 0) {\n throw new Error('Share.captureLink requires share.xurl[0] api matcher when mode=response');\n }\n\n logger.start('captureLink', `mode=${share.mode}, timeoutMs=${timeoutMs}, prefix=${share.prefix}`);\n logger.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);\n\n const stats = {\n actionTimedOut: false,\n domMutationCount: 0,\n domMutationNodes: 0,\n responseObserved: 0,\n responseMatched: 0,\n responseResolved: 0,\n lastMatchedUrl: '',\n responseSampleUrls: [],\n };\n\n const candidates = {\n dom: null,\n response: null,\n };\n\n const setCandidate = (source, link, payloadText = '') => {\n const safe = String(link || '').trim();\n if (!safe) return false;\n\n const [validated] = Utils.parseLinks(safe, { prefix: share.prefix }) || [];\n if (!validated) return false;\n\n if (candidates[source]?.link) return false;\n\n candidates[source] = {\n link: validated,\n payloadText: String(payloadText || ''),\n };\n\n logger.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);\n return true;\n };\n\n const resolveResponseCandidate = (responseText) => {\n const rawText = String(responseText || '');\n if (!rawText) return null;\n\n const [direct] = Utils.parseLinks(rawText, { prefix: share.prefix }) || [];\n if (direct) {\n return { link: direct, payloadText: rawText };\n }\n\n if (fieldPaths.length === 0) return null;\n\n const payload = parseJsonSafely(rawText);\n if (!payload || typeof payload !== 'object') return null;\n\n for (const pathSegments of fieldPaths) {\n const value = getByPathSegments(payload, pathSegments);\n if (value == null || value === '') continue;\n\n const composed = buildShareLink(share.prefix, value);\n if (!composed) continue;\n\n const [validated] = Utils.parseLinks(composed, { prefix: share.prefix }) || [];\n if (!validated) continue;\n\n return {\n link: validated,\n payloadText: rawText,\n };\n }\n\n return null;\n };\n\n let domMonitor = null;\n\n const stopDomMonitor = async () => {\n if (!domMonitor) return;\n const monitor = domMonitor;\n domMonitor = null;\n try {\n await monitor.stop();\n } catch (error) {\n logger.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);\n }\n };\n\n const onResponse = async (response) => {\n if (share.mode !== 'response') return;\n if (candidates.response?.link) return;\n\n stats.responseObserved += 1;\n\n try {\n const url = String(response.url() || '');\n\n if (url && stats.responseSampleUrls.length < 8 && !stats.responseSampleUrls.includes(url)) {\n stats.responseSampleUrls.push(url);\n }\n\n if (stats.responseObserved <= 5) {\n logger.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);\n }\n\n if (!apiMatchers.some((matcher) => url.includes(matcher))) return;\n\n stats.responseMatched += 1;\n stats.lastMatchedUrl = url;\n logger.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);\n\n const text = await response.text();\n const hit = resolveResponseCandidate(text);\n if (!hit?.link) {\n if (stats.responseMatched <= 3) {\n logger.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);\n }\n return;\n }\n\n stats.responseResolved += 1;\n logger.success('captureLink.responseHit', `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);\n setCandidate('response', hit.link, hit.payloadText);\n } catch (error) {\n logger.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);\n }\n };\n\n if (share.mode === 'dom') {\n logger.info('\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C');\n domMonitor = await createDomShareMonitor(page, {\n prefix: share.prefix,\n selectors: domSelectors,\n mode: domMode,\n onTelemetry: ({ mutationCount, mutationNodesCount }) => {\n stats.domMutationCount = mutationCount;\n stats.domMutationNodes = mutationNodesCount;\n },\n onMatch: ({ link, rawDom }) => {\n setCandidate('dom', link, rawDom);\n },\n });\n }\n\n if (share.mode === 'response') {\n logger.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);\n page.on('response', onResponse);\n }\n\n const deadline = Date.now() + timeoutMs;\n const getRemainingMs = () => Math.max(0, deadline - Date.now());\n\n try {\n const actionTimeout = getRemainingMs();\n logger.start('captureLink.performActions', `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${actionTimeout}ms`);\n\n if (actionTimeout > 0) {\n let timer = null;\n let actionError = null;\n\n const actionPromise = Promise.resolve()\n .then(() => performActions())\n .then(() => '__ACTION_DONE__')\n .catch((error) => {\n actionError = error;\n return '__ACTION_ERROR__';\n });\n\n const timeoutPromise = new Promise((resolve) => {\n timer = setTimeout(() => resolve('__ACTION_TIMEOUT__'), actionTimeout);\n });\n\n const actionResult = await Promise.race([actionPromise, timeoutPromise]);\n if (timer) clearTimeout(timer);\n\n if (actionResult === '__ACTION_ERROR__') {\n logger.fail('captureLink.performActions', actionError);\n throw actionError;\n }\n\n if (actionResult === '__ACTION_TIMEOUT__') {\n stats.actionTimedOut = true;\n logger.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);\n } else {\n logger.success('captureLink.performActions', '\u6267\u884C\u52A8\u4F5C\u5B8C\u6210');\n }\n }\n\n let nextProgressLogTs = Date.now() + 3000;\n\n while (true) {\n const selected = share.mode === 'dom' ? candidates.dom : candidates.response;\n if (selected?.link) {\n logger.success('captureLink', `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);\n return {\n link: selected.link,\n payloadText: selected.payloadText,\n payloadSnapshot: toSnapshot(selected.payloadText, payloadSnapshotMaxLen),\n source: share.mode,\n };\n }\n\n const remaining = getRemainingMs();\n if (remaining <= 0) break;\n\n const now = Date.now();\n if (now >= nextProgressLogTs) {\n logger.info(\n `captureLink \u7B49\u5F85\u4E2D: remaining=${remaining}ms, domMutationCount=${stats.domMutationCount}, responseMatched=${stats.responseMatched}`\n );\n nextProgressLogTs = now + 5000;\n }\n\n await delay(Math.max(0, Math.min(DEFAULT_POLL_INTERVAL_MS, remaining)));\n }\n\n if (share.mode === 'response' && stats.responseMatched === 0) {\n logger.warning(\n `\u63A5\u53E3\u76D1\u542C\u672A\u547D\u4E2D: apiMatchers=${toJsonInline(apiMatchers, 220)}, \u54CD\u5E94\u6837\u672CURLs=${toJsonInline(stats.responseSampleUrls, 420)}`\n );\n }\n\n logger.warning(\n `captureLink \u8D85\u65F6\u672A\u62FF\u5230\u94FE\u63A5: mode=${share.mode}, actionTimedOut=${stats.actionTimedOut}, domMutationCount=${stats.domMutationCount}, responseObserved=${stats.responseObserved}, responseMatched=${stats.responseMatched}, lastMatchedUrl=${stats.lastMatchedUrl || 'none'}`\n );\n\n return {\n link: null,\n payloadText: '',\n payloadSnapshot: '',\n source: 'none',\n };\n } finally {\n if (share.mode === 'response') {\n page.off('response', onResponse);\n logger.info('response \u76D1\u542C\u5DF2\u5378\u8F7D');\n }\n await stopDomMonitor();\n }\n },\n\n\n /**\n * \u5168\u9875\u9762\u6EDA\u52A8\u622A\u56FE\uFF08\u57FA\u7840\u80FD\u529B\uFF09\n *\n * @param {import('playwright').Page} page\n * @param {Object} [options]\n * @param {number} [options.buffer]\n * @param {boolean} [options.restore]\n * @param {number} [options.maxHeight]\n * @returns {Promise<string>} base64 png\n */\n async captureScreen(page, options = {}) {\n const originalViewport = page.viewportSize();\n const defaultBuffer = Math.round((originalViewport?.height || 1080) / 2);\n const buffer = options.buffer ?? defaultBuffer;\n const restore = options.restore ?? false;\n const maxHeight = options.maxHeight ?? 8000;\n\n try {\n const maxScrollHeight = await page.evaluate(() => {\n let maxHeight = document.body.scrollHeight;\n\n document.querySelectorAll('*').forEach(el => {\n const style = window.getComputedStyle(el);\n const overflowY = style.overflowY;\n\n if ((overflowY === 'auto' || overflowY === 'scroll') &&\n el.scrollHeight > el.clientHeight) {\n if (el.scrollHeight > maxHeight) {\n maxHeight = el.scrollHeight;\n }\n\n el.dataset.pkOrigOverflow = el.style.overflow;\n el.dataset.pkOrigHeight = el.style.height;\n el.dataset.pkOrigMaxHeight = el.style.maxHeight;\n el.classList.add('__pk_expanded__');\n\n el.style.overflow = 'visible';\n el.style.height = 'auto';\n el.style.maxHeight = 'none';\n }\n });\n\n return maxHeight;\n });\n\n const targetHeight = Math.min(maxScrollHeight + buffer, maxHeight);\n\n await page.setViewportSize({\n width: originalViewport?.width || 1280,\n height: targetHeight,\n });\n\n await delay(1000);\n\n const buffer_ = await page.screenshot({\n fullPage: true,\n type: 'png',\n });\n\n return buffer_.toString('base64');\n } finally {\n if (restore) {\n await page.evaluate(() => {\n document.querySelectorAll('.__pk_expanded__').forEach(el => {\n el.style.overflow = el.dataset.pkOrigOverflow || '';\n el.style.height = el.dataset.pkOrigHeight || '';\n el.style.maxHeight = el.dataset.pkOrigMaxHeight || '';\n\n delete el.dataset.pkOrigOverflow;\n delete el.dataset.pkOrigHeight;\n delete el.dataset.pkOrigMaxHeight;\n el.classList.remove('__pk_expanded__');\n });\n });\n\n if (originalViewport) {\n await page.setViewportSize(originalViewport);\n }\n }\n }\n },\n};\n"],
5
5
  "mappings": "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",
6
6
  "names": ["normalizeShare", "segments", "protocol", "domain", "path", "logger", "serializeError", "Actor", "logger", "logger", "maxHeight", "logger", "delay", "logger", "delay", "logger", "logger", "cleanerName", "URL", "logger", "URL", "logger", "uuidv4", "logger", "uuidv4", "result", "selectorList", "stableTime", "timeout", "callbackName", "monitorKey", "cleanerName", "mode", "text", "logger", "delay", "logger", "segments", "delay", "maxHeight"]
7
7
  }