• 问题:Agent-browser如何动态获取页面元素,如最上面一层的元素?

       agent-browser 获取页面元素的核心机制,我可以用一句话概括:它不解析整个DOM树,而是扫描页面的“无障碍树”(Accessibility Tree),生成一份仅包含可交互元素的精简清单,并为每个元素打上 @e1、@e2 这样的唯一标签。

         这就解决了你说的“获取最上面一层元素”的需求——snapshot 命令返回的正是页面上所有“可交互”的表层元素清单。

    一,核心机制:Snapshot(快照)

    agent-browser 的设计哲学是为 AI Agent 提供“所见即所得”的确定性操作,它通过以下三步完成元素的发现和定位:

    步骤

    命令/操作

    作用与原理

    输出示例

    1. 生成快照

    agent-browser snapshot -i

    扫描页面的无障碍树,过滤掉纯文本或装饰性元素,只提取按钮、输入框、链接等可交互元素。

    - textbox "用户名" [ref=e1]

    - button "登录" [ref=e2]

    2. 分配引用

    工具自动完成

    为快照中的每个元素分配一个以 @e

     开头的唯一ID(ref)。这个ID在当前页面状态下是稳定的。

    ref=e1

    ref=e2

    3. 操作元素

    agent-browser click @e1

    AI Agent 直接使用 ref进行操作,完全不需要关心元素的id、class或 XPath。

    执行点击、填表等操作

    特别注意(v0.22.0版本更新):从v0.22.0开始,snapshot -i 命令默认会包含所有鼠标可交互的元素(如可点击的div),不再需要额外的 -C 标志,进一步降低了AI的认知负担。

    🔄 动态获取元素的关键:Snapshot-Action 循环

       你提到的“动态获取”,关键在于理解 snapshot 是一个状态性的、会过期的快照。

    工作流遵循一个严格的循环:生成快照 → 基于引用操作 → 状态失效 → 重新生成快照。

    0

    二,为什么必须重新快照?

     一旦你点击了一个链接或提交了一个表单,页面跳转或DOM结构发生重大变化,之前所有的 @e1、@e2 引用都会指向旧页面的元素,在新页面上完全失效。因此,每次页面状态改变后,AI Agent必须重新执行 snapshot 命令,获取一份新的元素清单。

    💡 实战示例:获取并操作顶层元素

    # 1. 打开目标网页
    agent-browser open https://example.com/login
    # 2. 获取当前页面的可交互元素快照
    agent-browser snapshot -i
    # 👇 命令输出(AI 看到的“最上面一层元素”)
    # - textbox "Email address" [ref=e1]
    # - textbox "Password" [ref=e2]
    # - button "Sign in" [ref=e3]
    # - link "Forgot password?" [ref=e4]
    # 3. AI 决定操作这些元素
    agent-browser fill @e1 "user@example.com"
    agent-browser fill @e2 "mySecurePassword"
    agent-browser click @e3
    # 4. 点击登录后,页面跳转,旧的 refs 失效,需要重新获取快照
    agent-browser snapshot -i
    # 现在会返回新页面(如用户仪表盘)的可交互元素清单

三,总结与建议

agent-browser 的动态元素获取机制,核心就是 snapshot + ref。与传统方式相比,它有以下几个显著优势:

  • 低Token消耗:无障碍树比完整DOM树小得多,对AI Agent非常友好。

  • 高稳定性:不依赖易变的CSS/XPath,只要元素的可访问性属性(如role, name)不变,ref就能稳定定位。

  • 自愈能力:如果页面发生变化导致元素失效,Agent只需重新执行 snapshot,就能获得新的有效引用,完美契合你之前提到的“低维护成本”和“自愈能力”需求。

    建议你后续在进行自动化编排时,务必在每次可能引起页面变化的操作(如点击、表单提交)之后,立即加入一个 snapshot 调用来刷新AI对页面的“认知”。

四,如何获取最上层元素?

   由于Agent-browser获取的是整体页面元素,如果页面上有弹层,抽屉,你就会发现内容会非常多。而我们要操作的只是抽屉或是弹层上的元素,从snapshot输出来看,最上面的元素内容在最后面输出,所我们需要想办法动态截取最上面的元素内容。

我们可以通过下面的函数来实现:


def splitSnapShot(self,snapshot):
        """
        按指定的规则拆分snapshot
        :param snapshot:
        :param specnum:
        :return:
        """
        lines = snapshot.splitlines()
        spline=list()
        tmpline=list()
        ckline=1
        for line in lines:
            stripped_line = line.lstrip()
            leading_whitespace = line[:len(line) - len(stripped_line)]
            if len(leading_whitespace)==2 :
                # tmpline.append(line)
                tsline="".join(tmpline)
                if len(tsline)>0:
                    tsline="\n".join(tmpline)
                    tmpck=tsline.replace("- generic","").strip()
                    if len(tmpck)>0:
                        spline.append(tsline)
                tmpline[:] = []
                #把等于2的信息拼到下个数据字段中 2026-04-17
                tmpline.append(line)
            # if len(leading_whitespace)>=specnum:
            else:
                tmpline.append(line)
            ckline=ckline+1
        if len(tmpline)>0:
            tsline="\n".join(tmpline)
            tmpck=tsline.replace("- generic","").strip()
            if len(tmpck)>0:
                spline.append(tsline)
        return spline

 def getTopLaySnap(self,sessionid):
        """
        获取一个页面最上层的页面布局
        :param testurl:
        :return:
        """
        snapshot = self.run_command("snapshot", [],sessionid)
        specsnap=self.splitSnapShot(snapshot)
        if len(specsnap)<=2:
            return specsnap[-1]
        else:
            tmplist=list()
            index=1
            for parline in specsnap:
                if index>2:
                    tmplist.append(parline)
                index=index+1
            finalsnapshot="\n".join(tmplist)
            return finalsnapshot

在合适的地方,动态调用这个函数即可。而函数参数sessionid是为了支持多线程执行程序而传入的信息。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐