diff --git a/scripts/service/rpa_helpers/human.py b/scripts/service/rpa_helpers/human.py new file mode 100644 index 0000000..6a9a8d1 --- /dev/null +++ b/scripts/service/rpa_helpers/human.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +"""Human-like interaction primitives for Playwright locators (no logging).""" +from __future__ import annotations + +import random +import time + + +def pause(min_ms: int = 200, max_ms: int = 800) -> None: + """随机停顿 min_ms ~ max_ms 毫秒。""" + lo = min(min_ms, max_ms) / 1000.0 + hi = max(min_ms, max_ms) / 1000.0 + time.sleep(random.uniform(lo, hi)) + + +def human_type( + locator, + text: str, + *, + per_char_ms_range: tuple[int, int] = (50, 200), + pre_pause: bool = True, +) -> None: + """逐字符输入(locator.type + delay);locator 为 Playwright Locator。""" + locator.scroll_into_view_if_needed() + if pre_pause: + pause() + locator.click() + pause() + lo, hi = per_char_ms_range + delay_ms = random.uniform(float(lo), float(hi)) + locator.type(text, delay=int(delay_ms)) + + +def human_click(locator) -> None: + """人类化点击:scroll_into_view → pause → click → pause""" + locator.scroll_into_view_if_needed() + pause() + locator.click() + pause() + + +def human_select(locator, value_or_label: str) -> None: + """人类化下拉选择:scroll_into_view → pause → click → pause → select_option""" + locator.scroll_into_view_if_needed() + pause() + locator.click() + pause() + try: + locator.select_option(value=value_or_label) + except Exception: + locator.select_option(label=value_or_label) + + +def human_scroll_to(locator) -> None: + """滚动到元素并稍作停顿。""" + locator.scroll_into_view_if_needed() + pause()