Fork me on GitHub

Midscene.js - 开源的 AI 操作助手

开源的 AI 操作助手,适用于 Web、移动端、自动化和测试

功能特性

  • 使用 Javascript SDK 或 YAML 格式编写自动化脚本。
  • 网页或移动应用
  • 用于调试的可视化报告:通过我们的测试报告和 Playground,可以轻松理解、回放和调试整个过程。
  • 允许其他 MCP Client 直接使用 Midscene 的能力:Web MCPAndroid MCP
  • 三种 API 类型:交互 API(与用户界面交互)、数据提取 API(从用户界面和 DOM 中提取数据)、实用 API: 实用函数(如 aiAssert() (断言), aiLocate() (定位), aiWaitFor() (等待))

使用Midscene有两种方式:chrome插件、集成到代码 

一、Chrome安装使用

1. 前往 Chrome 扩展商店安装 Midscene 扩展
2. 启动扩展(可能默认折叠在 Chrome 扩展列表中),通过粘贴 Key=Value 格式配置插件环境:

OPENAI_API_KEY="sk-replace-by-your-own"
# ...可能还有其他配置项,一并贴入

 

开始体验

它一共有三个关键操作 Tab:

  • Action: 与网页进行交互,这就是所谓的自动规划(Auto Planning)。比如(在搜索框中输入 Midscene 点击登录按钮)
  • Query: 从界面中提取 JSON 数据(提取页面中的用户 ID,返回 \{ id: string \})
  • Assert: 验证页面(页面标题是 Midscene)
  • Tap: 在某个元素上点击,这就是所谓的即时操作(Instant Action)。


二、将 Midscene 集成到代码

官方提供了4种方式:

这里有几种不同集成形式的文档:

  • 使用 YAML 格式的自动化脚本
  • 使用 Chrome 插件的桥接模式
  • 与 Puppeteer 集成
  • 与 Playwright 集成

 

 

一)使用 YAML 格式的自动化脚本

全局安装 @midscene/cli

npm i -g @midscene/cli
# 或在项目中安装
npm i @midscene/cli --save-dev
基于 .yaml 文件的自动化测试方法,编写一个名为 bing-search.yaml
web:
  url: https://www.bing.com

tasks:
  - name: 搜索天气
    flow:
      - ai: 搜索 "今日天气"
      - sleep: 3000

  - name: 检查结果
    flow:
      - aiAssert: 结果中展示了天气信息
或者驱动安卓设备的自动化任务(需要使用 adb 连接安卓设备)
android:
  # launch: https://www.bing.com
  deviceId: s4ey59

tasks:
  - name: 搜索天气
    flow:
      - ai: 打开浏览器并导航到 bing.com
      - ai: 搜索 "今日天气"
      - sleep: 3000
      - aiAssert: 结果显示天气信息

运行脚本

midscene ./bing-search.yaml
# 或者如果你在项目中安装了 midscene
npx midscene ./bing-search.yaml

一个标准的 .yaml 脚本文件包含 web 或 android 部分配置环境,以及一个 tasks 部分来定义自动化任务。

web:
  url: https://www.bing.com

# tasks 部分定义了要执行的一系列步骤
tasks:
  - name: 搜索天气
    flow:
      - ai: 搜索 "今日天气"
      - sleep: 3000
      - aiAssert: 结果显示天气信息

web 部分

web:
  # 访问的 URL,必填。如果提供了 `serve` 参数,则提供相对路径
  url: <url>

  # 在本地路径下启动一个静态服务,可选
  serve: <root-directory>

  # 浏览器 UA,可选
  userAgent: <ua>

  # 浏览器视口宽度,可选,默认 1280
  viewportWidth: <width>

  # 浏览器视口高度,可选,默认 960
  viewportHeight: <height>

  # 浏览器设备像素比,可选,默认 1
  deviceScaleFactor: <scale>

  # JSON 格式的浏览器 Cookie 文件路径,可选
  cookie: <path-to-cookie-file>

  # 等待网络空闲的策略,可选
  waitForNetworkIdle:
    # 等待超时时间,可选,默认 2000ms
    timeout: <ms>
    # 是否在等待超时后继续,可选,默认 true
    continueOnNetworkIdleError: <boolean>

  # 输出 aiQuery/aiAssert 结果的 JSON 文件路径,可选
  output: <path-to-output-file>

  # 是否保存日志内容到 JSON 文件,可选,默认 `false`。如果为 true,保存到 `unstableLogContent.json` 文件中。如果为字符串,则保存到该字符串指定的路径中。日志内容的结构可能会在未来发生变化。
  unstableLogContent: <boolean | path-to-unstable-log-file>

  # 是否限制页面在当前 tab 打开,可选,默认 true
  forceSameTabNavigation: <boolean>

  # 桥接模式,可选,默认 false,可以为 'newTabWithUrl''currentTab'。更多详情请参阅后文
  bridgeMode: false | 'newTabWithUrl' | 'currentTab'

  # 是否在桥接断开时关闭新创建的标签页,可选,默认 false
  closeNewTabsAfterDisconnect: <boolean>

  # 是否忽略 HTTPS 证书错误,可选,默认 false
  acceptInsecureCerts: <boolean>

  # 在调用 aiAction 时发送给 AI 模型的背景知识,可选
  aiActionContext: <string>

android 部分

android:
  # 设备 ID,可选,默认使用第一个连接的设备
  deviceId: <device-id>

  # 启动 URL,可选,默认使用设备当前页面
  launch: <url>

  # 输出 aiQuery/aiAssert 结果的 JSON 文件路径,可选
  output: <path-to-output-file>

tasks 部分

tasks 部分是一个数组,定义了脚本执行的步骤。记得在每个步骤前添加 - 符号,表明这些步骤是个数组。

flow 部分的接口与 API几乎相同,除了一些参数的嵌套层级。

tasks:
  - name: <name>
    continueOnError: <boolean> # 可选,错误时是否继续执行下一个任务,默认 false
    flow:
      # 自动规划(Auto Planning, .ai)
      # ----------------

      # 执行一个交互,`ai` 是 `aiAction` 的简写方式
      - ai: <prompt>
        cacheable: <boolean> # 可选,当启用 [缓存功能](./caching.mdx) 时,是否允许缓存当前 API 调用结果。默认值为 True

      # 这种用法与 `ai` 相同
      - aiAction: <prompt>
        cacheable: <boolean> # 可选,当启用 [缓存功能](./caching.mdx) 时,是否允许缓存当前 API 调用结果。默认值为 True

      # 即时操作(Instant Action, .aiTap, .aiHover, .aiInput, .aiKeyboardPress, .aiScroll)
      # ----------------

      # 点击一个元素,用 prompt 描述元素位置
      - aiTap: <prompt>
        deepThink: <boolean> # 可选,是否使用深度思考(deepThink)来精确定位元素。默认值为 False
        xpath: <xpath> # 可选,目标元素的 xpath 路径,用于执行当前操作。如果提供了这个 xpath,Midscene 会优先使用该 xpath 来找到元素,然后依次使用缓存和 AI 模型。默认值为空
        cacheable: <boolean> # 可选,当启用 [缓存功能](./caching.mdx) 时,是否允许缓存当前 API 调用结果。默认值为 True

      # 鼠标悬停一个元素,用 prompt 描述元素位置
      - aiHover: <prompt>
        deepThink: <boolean> # 可选,是否使用深度思考(deepThink)来精确定位元素。默认值为 False
        xpath: <xpath> # 可选,目标元素的 xpath 路径,用于执行当前操作。如果提供了这个 xpath,Midscene 会优先使用该 xpath 来找到元素,然后依次使用缓存和 AI 模型。默认值为空

        cacheable: <boolean> # 可选,当启用 [缓存功能](./caching.mdx) 时,是否允许缓存当前 API 调用结果。默认值为 True

      # 输入文本到一个元素,用 prompt 描述元素位置
      - aiInput: <输入框的最终文本内容>
        locate: <prompt>
        deepThink: <boolean> # 可选,是否使用深度思考(deepThink)来精确定位元素。默认值为 False
        xpath: <xpath> # 可选,目标元素的 xpath 路径,用于执行当前操作。如果提供了这个 xpath,Midscene 会优先使用该 xpath 来找到元素,然后依次使用缓存和 AI 模型。默认值为空
        cacheable: <boolean> # 可选,当启用 [缓存功能](./caching.mdx) 时,是否允许缓存当前 API 调用结果。默认值为 True

      # 在元素上按下某个按键(如 Enter,Tab,Escape 等),用 prompt 描述元素位置
      - aiKeyboardPress: <按键>
        locate: <prompt>
        deepThink: <boolean> # 可选,是否使用深度思考(deepThink)来精确定位元素。默认值为 False
        xpath: <xpath> # 可选,目标元素的 xpath 路径,用于执行当前操作。如果提供了这个 xpath,Midscene 会优先使用该 xpath 来找到元素,然后依次使用缓存和 AI 模型。默认值为空

        cacheable: <boolean> # 可选,当启用 [缓存功能](./caching.mdx) 时,是否允许缓存当前 API 调用结果。默认值为 True

      # 全局滚动,或滚动 prompt 描述的元素
      - aiScroll:
        direction: 'up' # 或 'down' | 'left' | 'right'
        scrollType: 'once' # 或 'untilTop' | 'untilBottom' | 'untilLeft' | 'untilRight'
        distance: <number> # 可选,滚动距离,单位为像素
        locate: <prompt> # 可选,执行滚动的元素
        deepThink: <boolean> # 可选,是否使用深度思考(deepThink)来精确定位元素。默认值为 False
        xpath: <xpath> # 可选,目标元素的 xpath 路径,用于执行当前操作。如果提供了这个 xpath,Midscene 会优先使用该 xpath 来找到元素,然后依次使用缓存和 AI 模型。默认值为空

        cacheable: <boolean> # 可选,当启用 [缓存功能](./caching.mdx) 时,是否允许缓存当前 API 调用结果。默认值为 True

      # 在报告文件中记录当前截图,并添加描述
      - logScreenshot: <title> # 可选,截图的标题,如果未提供,则标题为 'untitled'
        content: <content> # 可选,截图的描述

      # 数据提取
      # ----------------

      # 执行一个查询,返回一个 JSON 对象
      - aiQuery: <prompt> # 记得在提示词中描述输出结果的格式
        name: <name> # 查询结果在 JSON 输出中的 key

      # 更多 API
      # ----------------

      # 等待某个条件满足,并设置超时时间(ms,可选,默认 30000)
      - aiWaitFor: <prompt>
        timeout: <ms>

      # 执行一个断言
      - aiAssert: <prompt>
        errorMessage: <error-message> # 可选,当断言失败时打印的错误信息。
        name: <name> # 可选,给断言一个名称,会在 JSON 输出中作为 key 使用

      # 等待一定时间
      - sleep: <ms>

      # 在 web 页面上下文中执行一段 JavaScript 代码
      - javascript: <javascript>
        name: <name> # 可选,给返回值一个名称,会在 JSON 输出中作为 key 使用

  - name: <name>
    flow:
      # ...

 

二)使用 Chrome 插件的桥接模式

image

 

1. 配置 OpenAI API Key

# 更新为你自己的 Key
export OPENAI_API_KEY="sk-abcdefghijklmnopqrstuvwxyz"

2. 在 Chrome 应用商店安装 Midscene 浏览器插件

安装依赖

npm install @midscene/web tsx --save-dev
# or 
yarn add @midscene/web tsx --save-dev

3. 编写脚本

编写并保存以下代码为 ./demo-new-tab.ts

import { AgentOverChromeBridge } from "@midscene/web/bridge-mode";

const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
Promise.resolve(
  (async () => {
    const agent = new AgentOverChromeBridge();

    // 这个方法将连接到你的桌面 Chrome 的新标签页
    // 记得启动你的 Chrome 插件,并点击 'allow connection' 按钮。否则你会得到一个 timeout 错误
    await agent.connectNewTabWithUrl("https://www.bing.com");

    // 这些方法与普通 Midscene agent 相同
    await agent.ai('type "AI 101" and hit Enter');
    await sleep(3000);

    await agent.aiAssert("there are some search results");
    await agent.destroy();
  })()
);

4.启动 Chrome 插件

image

 启动桌面 Chrome 和 Midscene 插件,并切换到 'Bridge Mode' 标签页。点击 "Allow connection"。

 

5. 运行脚本

tsx demo-new-tab.ts

 

三)集成到 Puppeteer

Puppeteer 是一个 Node.js 库,它通过 DevTools 协议或 WebDriver BiDi 提供控制 Chrome 或 Firefox 的高级 API。
Puppeteer 默认在无界面模式(headless)下运行,但可以配置为在可见的浏览器模式(headed)中运行。

1)配置 AI 模型服务
# 替换为你的 API Key
export OPENAI_API_KEY="sk-abcdefghijklmnopqrstuvwxyz"

# 可能需要更多配置,如模型名称、接入点等,请参考 《选择 AI 模型》文档
export OPENAI_BASE_URL="..."

2)安装依赖
yarn add @midscene/web puppeteer tsx --save-dev
# or
npm install @midscene/web puppeteer tsx --save-dev

3)编写脚本
编写下方代码,保存为 ./demo.ts
import puppeteer from "puppeteer";
import { PuppeteerAgent } from "@midscene/web/puppeteer";

const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
Promise.resolve(
  (async () => {
    const browser = await puppeteer.launch({
      headless: false, // here we use headed mode to help debug
    });

    const page = await browser.newPage();
    await page.setViewport({
      width: 1280,
      height: 800,
      deviceScaleFactor: 1,
    });

    await page.goto("https://www.ebay.com");
    await sleep(5000);

    // 👀 初始化 Midscene agent 
    const agent = new PuppeteerAgent(page);

    // 👀 执行搜索
    // 注:尽管这是一个英文页面,你也可以用中文指令控制它
    await agent.aiAction('在搜索框输入 "Headphones" ,敲回车');
    await sleep(5000);

    // 👀 理解页面,提取数据
    const items = await agent.aiQuery(
      '{itemTitle: string, price: Number}[], 找到列表里的商品标题和价格',
    );
    console.log("耳机商品信息", items);

    // 👀 用 AI 断言
    await agent.aiAssert("界面左侧有类目筛选功能");

    await browser.close();
  })()
);

4)运行
使用 tsx 来运行,你会看到命令行打印出了耳机的商品信息:
# run
npx tsx demo.ts

# 命令行应该有如下输出
#  [
#   {
#     itemTitle: 'Beats by Dr. Dre Studio Buds Totally Wireless Noise Cancelling In Ear + OPEN BOX',
#     price: 505.15
#   },
#   {
#     itemTitle: 'Skullcandy Indy Truly Wireless Earbuds-Headphones Green Mint',
#     price: 186.69
#   }
# ]

5)查看运行报告
当上面的命令执行成功后,会在控制台输出:Midscene - report file updated: /path/to/report/some_id.html, 通过浏览器打开该文件即可看到报告。


四)集成到 Playwright

Playwright.js 是由微软开发的一个开源自动化库,主要用于对网络应用程序进行端到端测试(end-to-end test)和网页抓取。

与 Playwright 的集成方式有以下两种方式:

  • 直接用脚本方式集成和调用 Midscene Agent,适合快速体验、原型开发、数据抓取和自动化脚本等场景。
  • 在 Playwright 的测试用例中集成 Midscene,适合需要执行 UI 测试的场景。
1)配置 AI 模型服务
# 替换为你的 API Key
export OPENAI_API_KEY="sk-abcdefghijklmnopqrstuvwxyz"

# 可能需要更多配置,如模型名称、接入点等,请参考 《选择 AI 模型》文档
export OPENAI_BASE_URL="..."

2)安装依赖

npm install @midscene/web playwright @playwright/test tsx --save-dev
# or
yarn add @midscene/web playwright @playwright/test tsx --save-dev

3)编写脚本

编写下方代码,保存为 ./demo.ts

import { chromium } from 'playwright';
import { PlaywrightAgent } from '@midscene/web/playwright';
import 'dotenv/config'; // read environment variables from .env file

const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

Promise.resolve(
  (async () => {
    const browser = await chromium.launch({
      headless: true, // 'true' means we can't see the browser window
      args: ['--no-sandbox', '--disable-setuid-sandbox'],
    });

    const page = await browser.newPage();
    await page.setViewportSize({
      width: 1280,
      height: 768,
    });
    await page.goto('https://www.ebay.com');
    await sleep(5000); // 👀 init Midscene agent
    const agent = new PlaywrightAgent(page);

    // 👀 type keywords, perform a search
    await agent.aiAction('type "Headphones" in search box, hit Enter');

    // 👀 wait for the loading
    await agent.aiWaitFor('there is at least one headphone item on page');
    // or you may use a plain sleep:
    // await sleep(5000);

    // 👀 understand the page content, find the items
    const items = await agent.aiQuery(
      '{itemTitle: string, price: Number}[], find item in list and corresponding price',
    );
    console.log('headphones in stock', items);

    const isMoreThan1000 = await agent.aiBoolean(
      'Is the price of the headphones more than 1000?',
    );
    console.log('isMoreThan1000', isMoreThan1000);

    const price = await agent.aiNumber(
      'What is the price of the first headphone?',
    );
    console.log('price', price);

    const name = await agent.aiString(
      'What is the name of the first headphone?',
    );
    console.log('name', name);

    const location = await agent.aiLocate(
      'What is the location of the first headphone?',
    );
    console.log('location', location);

    // 👀 assert by AI
    await agent.aiAssert('There is a category filter on the left');

    // 👀 click on the first item
    await agent.aiTap('the first item in the list');

    await browser.close();
  })(),
);

 4)运行

使用 tsx 来运行,你会看到命令行打印出了耳机的商品信息:

# run
npx tsx demo.ts

# 命令行应该有如下输出
#  [
#   {
#     itemTitle: 'JBL Tour Pro 2 - True wireless Noise Cancelling earbuds with Smart Charging Case',
#     price: 551.21
#   },
#   {
#     itemTitle: 'Soundcore Space One无线耳机40H ANC播放时间2XStronger语音还原',
#     price: 543.94
#   }
# ]

 

5) 查看运行报告

当上面的命令执行成功后,会在控制台输出:Midscene - report file updated: /path/to/report/some_id.html, 通过浏览器打开该文件即可看到报告。

 

 

 

posted @ 2025-09-23 09:55  广东靓仔-啊锋  阅读(1258)  评论(0)    收藏  举报