89 lines
2.9 KiB
Python
89 lines
2.9 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""浏览器 RPA 最小用法示例(复制到新 skill 后按需改)。
|
||
|
||
演示标准流程:
|
||
1. config.ensure_env_file 首次落盘 .env
|
||
2. launch_persistent_browser 启动 stealth persistent context
|
||
3. 拟人操作(mouse_wiggle / human_type / human_click)
|
||
4. 验证码 HITL 等待
|
||
5. 失败 capture_failure 截图
|
||
|
||
运行(需系统 Chrome/Edge + playwright 包):
|
||
python scripts/service/example_browser_rpa.py
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import asyncio
|
||
import os
|
||
import sys
|
||
|
||
_scripts_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||
if _scripts_dir not in sys.path:
|
||
sys.path.insert(0, _scripts_dir)
|
||
|
||
from jiangchang_skill_core import config
|
||
from jiangchang_skill_core.rpa import (
|
||
anti_detect,
|
||
artifacts,
|
||
errors,
|
||
launch_persistent_browser,
|
||
wait_for_captcha_pass,
|
||
)
|
||
from util.constants import SKILL_SLUG
|
||
from util.runtime_paths import get_skill_data_dir, get_skill_root
|
||
|
||
|
||
async def demo() -> int:
|
||
example_path = os.path.join(get_skill_root(), ".env.example")
|
||
config.ensure_env_file(SKILL_SLUG, example_path)
|
||
|
||
url = config.get("TARGET_BASE_URL") or "https://example.com"
|
||
data_dir = get_skill_data_dir()
|
||
profile_dir = os.path.join(data_dir, "browser-profile")
|
||
os.makedirs(profile_dir, exist_ok=True)
|
||
batch_id = "demo"
|
||
|
||
try:
|
||
from playwright.async_api import async_playwright
|
||
except ImportError:
|
||
print("ERROR: playwright not installed")
|
||
return 1
|
||
|
||
async with async_playwright() as pw:
|
||
context = await launch_persistent_browser(
|
||
pw,
|
||
profile_dir=profile_dir,
|
||
headless=config.get_bool("OPENCLAW_BROWSER_HEADLESS"),
|
||
)
|
||
page = context.pages[0] if context.pages else await context.new_page()
|
||
try:
|
||
await page.goto(url, wait_until="domcontentloaded", timeout=60_000)
|
||
await anti_detect.human_mouse_wiggle(page)
|
||
|
||
search = page.locator('input[type="search"], input[name="q"]').first
|
||
if await search.count() > 0:
|
||
await anti_detect.human_type(page, search, "openclaw-rpa-demo")
|
||
await anti_detect.human_click(page, selector='input[type="search"]')
|
||
|
||
if not await wait_for_captcha_pass(
|
||
page,
|
||
timeout_sec=config.get_int("HUMAN_WAIT_TIMEOUT", 180),
|
||
):
|
||
shot = await artifacts.capture_failure(page, data_dir, batch_id, "captcha")
|
||
print(errors.ERR_CAPTCHA_NEED_HUMAN, shot or "")
|
||
return 1
|
||
|
||
print("OK browser RPA demo finished")
|
||
return 0
|
||
except Exception as exc:
|
||
shot = await artifacts.capture_failure(page, data_dir, batch_id, "error")
|
||
print(f"ERROR: {exc}", shot or "")
|
||
return 1
|
||
finally:
|
||
await context.close()
|
||
|
||
|
||
if __name__ == "__main__":
|
||
raise SystemExit(asyncio.run(demo()))
|