75 lines
3.0 KiB
Python
75 lines
3.0 KiB
Python
"""技术验证:browser-use 通过 CDP 连接 Electron 自带 Chromium 里的 WebContentsView 并跑一个小任务。
|
||
|
||
先启动:npx electron spike/embed/main.js
|
||
再运行:.venv/Scripts/python.exe spike/embed/probe.py
|
||
"""
|
||
|
||
import asyncio
|
||
import json
|
||
import os
|
||
import sys
|
||
import urllib.request
|
||
from pathlib import Path
|
||
|
||
ROOT = Path(__file__).resolve().parents[2]
|
||
sys.path.insert(0, str(ROOT))
|
||
from dotenv import load_dotenv # noqa: E402
|
||
|
||
load_dotenv(ROOT / ".env")
|
||
|
||
CDP = f"http://127.0.0.1:{os.environ.get('SPIKE_CDP_PORT', '9333')}"
|
||
|
||
|
||
def targets() -> list[dict]:
|
||
return json.loads(urllib.request.urlopen(CDP + "/json", timeout=5).read().decode())
|
||
|
||
|
||
async def main() -> int:
|
||
from browser_use import Agent, Browser, Tools
|
||
|
||
from backend.browser.llm_factory import create_llm
|
||
|
||
before = targets()
|
||
print("targets before:", [(t["type"], t["url"][:60], t.get("title", "")[:20], t["id"][-6:]) for t in before])
|
||
view = next((t for t in before if t["type"] == "page" and t["url"] == "about:blank"), None)
|
||
if not view:
|
||
print("no about:blank page target found")
|
||
return 1
|
||
|
||
# 内嵌模式不传 allowed_domains:browser-use 的安全看门狗会处理不在白名单里的标签页(含我们的界面页),
|
||
# 域名限制改由 Electron 在导航层面执行
|
||
# 白名单里带上界面页的主机名 ui(app://ui/...),学校域名照常;Electron 侧另做导航拦截
|
||
browser = Browser(cdp_url=CDP, keep_alive=True, allowed_domains=["ui", "school.miaopinai.com", "*.miaopinai.com"])
|
||
print("connecting...", flush=True)
|
||
await browser.start()
|
||
print("connected", flush=True)
|
||
print("focus after start:", (browser.agent_focus_target_id or "")[-6:], "| want:", view["id"][-6:])
|
||
await browser.get_or_create_cdp_session(view["id"], focus=True)
|
||
print("focus after steer :", (browser.agent_focus_target_id or "")[-6:])
|
||
|
||
tools = Tools(exclude_actions=["switch", "close", "search", "upload_file", "write_file", "replace_file", "read_file"])
|
||
agent = Agent(
|
||
task="打开 https://school.miaopinai.com:29800/xuegong/ ,读出页面标题,以及登录页「测试环境快捷登录」区域有哪些按钮,用 done 汇报。只读,不要点击任何按钮。",
|
||
llm=create_llm(),
|
||
browser=browser,
|
||
tools=tools,
|
||
use_vision=False,
|
||
max_actions_per_step=2,
|
||
step_timeout=90,
|
||
use_judge=False,
|
||
)
|
||
history = await agent.run(max_steps=6)
|
||
print("steps:", history.number_of_steps(), "| done:", history.is_done(), "| ok:", history.is_successful())
|
||
print("urls:", history.urls())
|
||
print("final:", str(history.final_result())[:400])
|
||
shots = [s for s in (history.screenshots() or []) if s]
|
||
print("screenshots captured:", len(shots))
|
||
after = targets()
|
||
print("targets after:", [(t["type"], t["url"][:60], t["id"][-6:]) for t in after])
|
||
print("page targets before/after:", sum(t["type"] == "page" for t in before), "/", sum(t["type"] == "page" for t in after))
|
||
return 0
|
||
|
||
|
||
if __name__ == "__main__":
|
||
raise SystemExit(asyncio.run(main()))
|