test1.mp4
test2.mp4
如果视频无法播放,请访问 Releases 页面 下载观看
GUIAgent 是一个网页自动化系统,技术栈为:
- 后端:
FastAPI + Playwright + VLM/LLM - 前端:
React + Vite - 执行模式:SSE 流式任务执行、反思重试、DOM 标注、文件导出
当前支持两类任务:
- 普通网页任务(如百度、B 站、豆瓣)
- 钢铁专用任务(历史记录筛选、导出 Excel、下载图片包、嵌图)
UI(React) -> /run_task_stream (SSE)
|
v
backend/server.py
|- 普通任务分支: ReflectionEngine + VLMService
|- 钢铁任务分支: _run_steel_download_pipeline
|- 定时任务分支: task_scheduler -> _run_scheduled_task
|
v
Executor(Playwright)
|- 导航/点击/输入/滚动/截图
|- DOM 标注(mark_page_elements)
|
v
下载与后处理(download_skill/postprocess_skill/mapper)
conda create -n agent_env python=3.10 -y
conda activate agent_env
pip install -r requirements.txt
playwright installcopy .env_temple .env关键项(最小可运行):
VLM_PROVIDERVLM_BASE_URLVLM_MODELVLM_API_KEYDISABLE_TEXT_LLM=1(推荐)USE_DOM_ANNOTATION=1(推荐)
uvicorn backend.server:app --host 127.0.0.1 --port 8000 --reload
cd ui
npm install
npm run dev钢铁网站通常需要登录态。项目通过 auth_data_*.json 自动注入:
- cookies
- localStorage
- sessionStorage
- url(目标站点)
在目标网站登录后,打开 F12 Console 执行:
const authData = {
url: location.href,
timestamp: new Date().toISOString(),
cookies: document.cookie || null,
localStorage: { ...localStorage },
sessionStorage: { ...sessionStorage }
};
const blob = new Blob([JSON.stringify(authData, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `auth_data_${location.hostname}_${Date.now()}.json`;
a.click();
URL.revokeObjectURL(url);把下载的 json 放到项目目录 cookies/ 下。
见 backend/server.py 的 _resolve_auth_data_file:
- 若请求显式传
auth_data_file,用它。 - 否则看环境变量
STEEL_AUTH_DATA_FILE。 - 否则自动在
cookies/里找最近的auth_data_*.json。
如果 cookies/ 里只有钢铁站点的 auth_data,那么普通任务也可能被误判为钢铁流。
这就是“让它去百度却进了钢铁 history 页”的根因之一。
- 跑普通任务前:临时移走钢铁
auth_data_*.json。 - 跑钢铁任务前:放回对应 auth_data。
- 长期方案:后续代码改为“仅钢铁任务才读取钢铁 auth_data”。
PLAYWRIGHT_USER_DATA_DIR 是 Playwright 持久化浏览器配置目录。启用后可保留:
- 登录状态
- 浏览器偏好(例如下载栏相关设置)
- 站点缓存
在 .env 中设置:
PLAYWRIGHT_PERSISTENT_CONTEXT=1
PLAYWRIGHT_USER_DATA_DIR=data/playwright_user_data
PLAYWRIGHT_CHANNEL=msedge
PLAYWRIGHT_EXECUTABLE=C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe- 启动后端。
- 执行任意任务,系统会自动创建该目录并拉起浏览器。
- 在弹出的浏览器里手动完成一次登录(如果需要)。
- 手动设置你希望长期保留的浏览器选项(如下载提示行为)。
- 关闭并重新执行任务,确认设置已被复用。
如果浏览器状态异常,删除 PLAYWRIGHT_USER_DATA_DIR 指向目录,再重新初始化。
不是“写死坐标点击”,而是:
- 先抓 DOM 元素列表(可交互元素、文本、bbox、中心点)
- 再截图并标注
- 决策层根据任务 + 元素语义做动作
- 执行层按元素信息点击/输入/滚动
核心文件:
backend/dom_service.pybackend/executor.py(mark_page_elements与交互)backend/visualizer.py(标注渲染)
run_task_stream收到任务ReflectionEngine请求当前页面观测executor.mark_page_elements()返回元素- 截图 + elements 传给模型生成下一步动作
actions/handler执行动作- 反思验证,继续下一步
- 调
POST /mark_elements看是否返回元素列表 - 看
data/screenshots/和标注图是否生成 - 看 SSE 里每步动作是否引用了合理元素
范围:根目录脚本 +
backend/。
skyvern/、browser-use-main/、Open-AutoGLM/是参考代码区,不是本系统主执行链。
_date_parse_smoke.py:日期解析烟测脚本。
backend/__init__.py:包初始化。backend/server.py:主入口;路由、分流、钢铁流水线、调度执行、SSE。backend/executor.py:Playwright 执行器;浏览器生命周期、页面操作、DOM 标注。backend/reflection_engine.py:普通任务反思执行循环。backend/vlm_service.py:模型调用、计划、意图抽取。backend/planner.py:任务拆解与提取规格解析。backend/extraction_engine.py:结构化抽取执行。backend/dom_service.py:DOM 抓取与元素标准化。backend/omniparser_service.py:视觉解析兼容服务。backend/visualizer.py:截图标注可视化。backend/scrolling_screenshot.py:滚动截图。backend/storage.py:目录/文件名工具。backend/output_store.py:输出索引与管理。backend/schemas.py:API schema。backend/task_scheduler.py:定时任务管理器(daily/interval)。backend/workflow_profiles.py:站点 profile 匹配与关键词策略。backend/steel_workflow.py:钢铁流程配置构建。backend/download_skill.py:下载技能(点击/回退/命名)。backend/postprocess_skill.py:解压、图片目录定位、Excel 嵌图。backend/steel_excel_image_mapper.py:Excel 行与图片映射规则。backend/web_agent.py:历史兼容封装层。
backend/actions/__init__.py:导出入口。backend/actions/action_types.py:动作类型定义。backend/actions/actions.py:动作对象定义。backend/actions/parser.py:模型动作解析。backend/actions/handler.py:动作执行分发。
- 注入登录态(auth_data)
- 导航并守护到历史记录页
- 设置时间范围
- 设置状态筛选(异常/正常/全部)
- 下载原始 Excel
- 下载图片(原始/渲染/全部)
- 解压并生成带图 Excel
- 输出文件与状态回传
输出命名约定:
- 文件夹:
YYYY-MM-DD-HH-MM-SS_YYYY-MM-DD-HH-MM-SS - 原始 Excel:保持站点原文件名
- 处理后 Excel:
_orgin.xlsx_render.xlsx_orgin_render.xlsx
优先级应为:
- profile 配置化
- DOM+模型决策
- 通用 skill 复用
- 最后才是站点专用分支
- 在
workflow_profiles.py增加新站点匹配规则。 - 在
steel_workflow.py增加新站点阶段配置(日期、筛选、下载、校验)。 - 在
vlm_service.py强化意图抽取 schema(时间窗、筛选、下载模式)。 - 优先复用
download_skill.py,减少站点写死点击。 - 如果输出结构不同,再改
postprocess_skill.py/ mapper。 - 增加 smoke 任务用例并回归。
建议借鉴:
- 状态机与动作协议
- DOM 观测与动作执行分层
- 模型输出 schema 化(强约束 JSON)
- 失败重试与恢复策略
不建议直接照抄:
- 大而全的项目脚手架
- 与本项目运行模型冲突的基础设施代码
- 我们的
backend/actions/*≈ Skyvern 的 action 系统 - 我们的
dom_service + executor≈ browser-use 的 dom/service + tools - 我们的
reflection_engine≈ 参考项目中的 agent loop/retry loop - 我们的
download_skill/postprocess_skill≈ 站点任务 skill 层
先读本项目:
backend/server.pybackend/executor.pybackend/download_skill.pybackend/steel_workflow.pybackend/reflection_engine.py
再对照参考:
- Skyvern:
skyvern/skyvern/webeye/actions/*、skyvern/skyvern/library/* - browser-use:
browser-use-main/browser_use/dom/*、browser-use-main/browser_use/tools/*
- 自动 schedule 触发依赖任务文本有“每天/定时/每隔”等语义。
- 当前调度执行链路主要用于钢铁流。
- 时间窗支持示例:
- “昨天一整天”
- “昨天8:00-16:00”
- “昨天0点到昨天下午四点”
检查顺序:
- 请求是否传了钢铁
target_url .env是否设置STEEL_TARGET_URL/STEEL_AUTH_DATA_FILEcookies/下是否只有钢铁 auth_data(被自动回填)
检查顺序:
- 是否启用 persistent context
- 下载栏/下载气泡是否遮挡页面交互
- 空白页清理逻辑是否生效
检查顺序:
- before/after observe 的状态值
- DOM probe 是否拿到筛选结果
- recover 阶段是否正确回放
conda run -n agent_env python -m py_compile backend/server.py backend/executor.py backend/download_skill.py backend/task_scheduler.py
cd ui
npm run build当前状态:系统仍有“普通流 / 钢铁流”分支。
最终目标:把“下载、导出 Excel、筛选、提取、后处理”等能力做成通用 skill,由 LLM 按任务选择性调用,实现跨网站复用。
- 单一 Agent Runtime(不按网站写大量分叉逻辑)
- LLM 负责:
- 选择 skill
- 填写 skill 参数
- 给出预期验证条件
- 后端负责:
- 执行 skill
- 做结果校验
- 失败恢复与重试
navigate_skill:导航与页面就绪检测date_range_skill:设置时间范围filter_skill:筛选(状态、关键字、下拉选项)export_excel_skill:触发导出并确认文件download_asset_skill:图片/附件下载(含候选点击与回退)extract_table_skill:表格/卡片结构化提取postprocess_skill:解压、重命名、嵌图、映射
每一步固定 5 个阶段:
- 观察(DOM + 页面状态)
- 决策(LLM 输出
skill + args + success_criteria) - 执行(skill 运行)
- 验证(是否满足 success_criteria)
- 失败恢复(重试/换 skill/回退路径)
-
阶段 A(收敛分叉)
把钢铁流内部动作替换为 skill 调用,保留现有 API,不改前端。 -
阶段 B(统一调度)
定时任务与即时任务都走同一 skill runtime,调度只负责触发,不负责业务分流。 -
阶段 C(配置化扩站)
新网站仅新增 profile + 少量提示词/映射配置,不改核心执行器。
- 新增网站时,不改
executor/server主流程代码即可完成基础任务。 - 同类任务(下载、导出、筛选)在不同网站复用同一 skill。
- LLM 输出均可被 schema 校验,不依赖自由文本猜测。
- 失败路径可追踪:每次失败都能定位到 skill、参数、验证点。