/** 填表后人类节奏延迟(毫秒):降低 WAF/Cloudflare 误触风险 */ export const RPA_HUMAN_PACING_MIN_MS = 100; export const RPA_HUMAN_PACING_MAX_MS = 300; function readPacingBounds(): { min: number; max: number } | null { if (process.env.RPA_HUMAN_PACING === "false") { return null; } const minRaw = process.env.RPA_HUMAN_PACING_MIN_MS?.trim(); const maxRaw = process.env.RPA_HUMAN_PACING_MAX_MS?.trim(); const min = minRaw && Number.isFinite(Number(minRaw)) ? Math.max(0, Number(minRaw)) : RPA_HUMAN_PACING_MIN_MS; const max = maxRaw && Number.isFinite(Number(maxRaw)) ? Math.max(min, Number(maxRaw)) : RPA_HUMAN_PACING_MAX_MS; return { min, max }; } /** 随机人类节奏等待时长;RPA_HUMAN_PACING=false 时返回 0 */ export function humanPacingDelayMs(): number { const bounds = readPacingBounds(); if (!bounds) { return 0; } const span = bounds.max - bounds.min; return bounds.min + Math.floor(Math.random() * (span + 1)); } /** 填表/点击后短暂停顿,模拟真人输入节奏 */ export async function awaitHumanPacing(page: { waitForTimeout: (ms: number) => Promise; }): Promise { const delay = humanPacingDelayMs(); if (delay <= 0) { return; } await page.waitForTimeout(delay); }