feature: действие typing — ввод как у человека, кириллица (#14)

fill остаётся мгновенным. typing подводит курсор по кривой, кликает в поле, стирает
старое значение и набирает текст посимвольно с паузами; символы вне раскладки
(кириллица) больше не роняют ввод. Значение typing маскируется в логах.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
protokeyandClaude Opus 5.5 committed 2026-10-13 20:58:09 +04:00
1 parent 49a2f3024a
commit 1075267d27
8 files changed
+74 -25

No files matched your search

+41 -21
View File
@@ -124,28 +124,48 @@ async def wait_for_page_stability(page: Page, load_dom: bool, network_idle: bool
await wait_for_networkidle(page)
async def typing(page: Page, locator: str, text: str):
element = page.locator(locator)
def _key_delay_ms(char: str) -> float:
"""Пауза после символа: строчные латинские набираются быстрее всего, остальное — медленнее."""
if char in string.ascii_lowercase:
delays = (50, 100)
elif char in string.ascii_uppercase or char in string.digits:
delays = (100, 150)
elif char in string.punctuation:
delays = (100, 200)
else:
# кириллица и прочие символы, пробел
delays = (60, 160)
return random.uniform(*delays)
async def typing(page: Page, locator: str, text: str) -> None:
"""Ввод как у человека: курсор подводится к полю по кривой, клик в случайную точку поля,
старое значение стирается, текст набирается посимвольно с паузами."""
element = page.locator(locator).first
await element.scroll_into_view_if_needed()
assert await element.is_visible()
assert await element.is_enabled()
assert await element.is_editable()
await element.focus()
await element.click()
if not await element.is_visible():
raise ValueError(f"element is not visible: {locator}")
if not await element.is_editable():
raise ValueError(f"element is not editable: {locator}")
box = await element.bounding_box()
if box is None:
raise ValueError(f"element has no box: {locator}")
await click_human(
page,
box["x"] + box["width"] * random.uniform(0.2, 0.8),
box["y"] + box["height"] * random.uniform(0.3, 0.7),
)
if await element.input_value():
await page.keyboard.press("ControlOrMeta+A")
await page.wait_for_timeout(random.uniform(80, 200))
await page.keyboard.press("Backspace")
await page.wait_for_timeout(random.uniform(100, 250))
for char in text:
await page.keyboard.press(char)
if char in string.ascii_lowercase:
delays = (50, 100)
elif char in string.ascii_uppercase:
delays = (100, 150)
elif char in string.digits:
delays = (100, 150)
elif char in string.punctuation:
delays = (100, 200)
else:
raise SystemError("character not supported: {}".format(char))
await page.wait_for_timeout(random.uniform(*delays))
# keyboard.type даёт keydown/keypress/keyup для клавиш раскладки и insertText для остальных
# символов (кириллица и т.п.); press() на них падал
await page.keyboard.type(char)
await page.wait_for_timeout(_key_delay_ms(char))