Midscene.js 教程:让 AI 接管你的浏览器 5 分钟上手
【免费下载链接】midsceneGUI Agent for E2E Testing项目地址: https://gitcode.com/GitHub_Trending/mid/midscene
上周我又中招了:回归脚本卡在第 7 步——前端顺手改了按钮的 class,我守了三个月的 XPath 一夜作废,差点回去手动点点点。后来我用了 Midscene.js,这个 GUI 自动化项目把操作写成大白话,它看截图就能找到元素、执行动作,不再依赖选择器。浏览器自动化从此不必再维护一堆 CSS 路径。
它凭什么行
核心思路一句话:不读 DOM,只看截图。你把界面截图交给一个多模态大模型,说一句"点右上角的蓝色搜索按钮",模型从像素里认出元素并返回坐标,Midscene 再把坐标还原成真实的鼠标点击。
所以判断标准很简单:人眼能看见的,它就够得着。没有 class 的纯图标按钮、canvas 里画的控件、跨域 iframe 中的表单,这些让传统选择器集体失明的地方,恰恰是它的舒适区。
⚡️ 5 分钟跑通
先装依赖,再配一个有 UI 定位能力的模型(以 Qwen-VL 为例,换成你手头任意模型服务即可):
npm i -D @midscene/web playwright tsx export MIDSCENE_MODEL_BASE_URL="https://dashscope.aliyuncs.com/compatible-mode/v1" \ MIDSCENE_MODEL_API_KEY="your-api-key" \ MIDSCENE_MODEL_NAME="qwen3-vl-plus" \ MIDSCENE_MODEL_FAMILY="qwen3-vl"把下面 5 行存成demo.ts,然后npx tsx demo.ts跑起来:
import { chromium } from 'playwright'; import { PlaywrightAgent } from '@midscene/web/playwright'; const page = await (await chromium.launch()).newPage(); await page.goto('https://www.bing.com'); new PlaywrightAgent(page).aiAct('搜索 midscene 并回车');怎么算跑通:终端会打印一个report file updated: .../xxx.html的报告路径,用浏览器打开,能看到每一步的截图和 AI 的思考过程——这说明截图、定位、点击全链路都通了。
🔍 三个提效技巧
入门:用 aiWaitFor 替换 sleep
原理:别猜等待时间,让 AI 看图判断"目标状态出现了没有"。
// 老写法 sleep(3000) 时快时慢,改为等页面真的就绪 await agent.aiWaitFor('页面中至少出现一个耳机商品');效果:时序抖动的 flaky 基本消失,脚本也不会多等一秒。
进阶:让 aiAct 自己规划,复杂时开 deepThink
原理:aiAct会自己拆解目标,并跟着最新界面状态重新规划;deepThink让它先多思考一轮再动手。
// 多步骤 + 有弹窗的任务,开 deepThink 换稳定性 await agent.aiAct('完成结账表单,在下单前停止', { deepThink: true });效果:一行顶十几行 if/else,中途弹出的确认框也不会把流程打断。
高阶:开缓存,让第二次运行复用第一次的结果
原理:同样的指令落在相似的页面上时,直接复用已缓存的 AI 规划和元素定位,跳过模型调用。
// 回归脚本固定 cache id,命中率最高 const agent = new PlaywrightAgent(page, { cache: { id: 'ebay-search' } });效果:官方实测的同一脚本执行耗时从 51 秒降到 28 秒,模型账单也跟着缩水。
真实场景走一遍
给电商团队写个"搜耳机、扒价格"的脚本,完整流程其实就四步,而且每步的决策都是 AI 替你做掉的:
await page.goto('https://www.ebay.com'); const agent = new PlaywrightAgent(page); // AI 自己认搜索框、输入、回车,全程不写选择器 await agent.aiAct('type "Headphones" in search box, hit Enter'); await agent.aiWaitFor('there is at least one headphone item on page'); // 结构化提取:哪条商品对哪个价格,由模型在图里对齐 const items = await agent.aiQuery('{itemTitle: string, price: number}[]'); // 断言也看图:验证的是用户真实看到的界面 await agent.aiAssert('there is a category filter on the left'); console.log(items);注意这里 AI 替你做了三个决策:它判断哪个框是搜索框而不是页面上随便一个输入框;提取数据时它自己在图里把商品标题和价格配对,而不是靠 CSS 结构猜层级;最后aiAssert校验的是"左侧确实渲染出了分类筛选器",这是 DOM 存在性检查做不到的。你只描述了"要什么","怎么做到"全部交给它。
📌 别踩这三个坑
点偏了,坐标有固定比例偏移
现象:同一份脚本在 A 模型上点得准,换到某云厂商 API 后整体偏移。根因:厂商对大图做了二次压缩,模型在缩小后的坐标系里作答,坐标就对不上了。解法:换模型,或者用screenshotShrinkFactor预先缩小截图绕开压缩阈值。
new PlaywrightAgent(page, { screenshotShrinkFactor: 0.8 });元素找不到,报 not found
现象:aiTap反复失败,模型说"找不到这个元素"。根因:描述太泛(就写了"点按钮"),而元素小、又长得像邻居。解法:描述里补上视觉特征,再开deepLocate做多轮精定位。
await agent.aiTap('右上角的购物车图标', { deepLocate: true });第一次运行就报模型相关错误
现象:脚本刚跑起来就抛"缺少模型配置"之类的错。根因:MIDSCENE_MODEL_*环境变量没设,或选了一个没有 UI 定位能力的模型。解法:先把四个环境变量配齐,模型认准 Qwen-VL、UI-TARS、Doubao-Seed 这类带定位能力的。
export MIDSCENE_MODEL_NAME="qwen3-vl-plus" # 必须是支持 UI 定位的模型✅ 效果说话
| 对比项 | 传统选择器方案 | Midscene.js | 谁占优 |
|---|---|---|---|
| 简单固定元素点击 | 毫秒级 | 秒级模型推理 | 传统 |
| 前端改版后维护 | 选择器失效逐个修 | 改一句自然语言描述 | Midscene |
| canvas / 跨域 iframe | 基本够不着 | 截图可见即可点 | Midscene |
| 视觉效果断言 | 写不出来 | 一行 aiAssert | Midscene |
| 单次执行成本 | 接近零 | 有模型 API 费用 | 传统 |
速度项传统方案确实更快,这点不藏着;但在 AppControlBench 的 60 个任务实测里,Midscene 走纯视觉路线的通过率依然能打:
收尾
下一步,把 agent 指向你公司后台里 iframe 最多的那个页面,给它写一条视觉断言试试。跑完打开midscene_run里的报告,看看 AI 每一步到底看见了什么——看完你就明白它为什么敢这么用了。
【免费下载链接】midsceneGUI Agent for E2E Testing项目地址: https://gitcode.com/GitHub_Trending/mid/midscene
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考