Browser Harness 实战:复用已登录 Chrome 完成后台数据查询

连接独立测试 Chrome,在保留人工登录态的情况下读取当前筛选订单表,生成状态汇总,并处理登录失效、错误标签页和字段变化。

亿牛云技术团队2026年10月28日5 分钟阅读

后台页面往往已经有人工完成的登录和筛选条件。为了读取一张表,重新启动一个没有 Cookie 的浏览器再做登录,会增加不必要的步骤。Browser Harness 可以连接现有 Chrome,让查询沿用该浏览器的状态。

本文面向维护自有后台的开发者。我们在独立测试浏览器中登录后台,读取当前筛选条件下的一页订单,保存记录和状态汇总。任务只读当前页,不代表导出了整个账户历史,也不会自动提交表单或修改订单。

准备一个明确的浏览器环境

使用 Python 3.12、uv 与受支持的 Chrome。uv 安装方式见 官方安装文档。安装工具:

uv tool install --python 3.12 'browser-harness==0.1.13'
browser-harness recordings disable

本地 Chrome 接入不需要 Browser Use 云端 key。保持录制关闭,当前任务只需要页面查询,不需要动作录像。

用单独的测试 Profile 打开 Chrome,在 chrome://inspect/#remote-debugging 中按浏览器提供的选项允许当前实例远程调试。然后在这个 Profile 中人工登录你自己的测试后台。不要假设另一个普通浏览器窗口的登录态会自动出现在当前连接里。

工具连接和 Chrome 权限相关步骤见 Browser Harness 安装说明。

先确认连接的是正确标签页

执行:

browser-harness <<'PY'
print(page_info())
print(list_tabs())
PY

比较页面标题和 URL,确认当前标签属于测试后台。若不是,使用 list_tabs 返回的实际目标标识调用 switch_tab(target);不要复制另一台机器的 tab ID。

只在普通网页标签上操作。Chrome 设置页、空白页或已经关闭的标签不是后台查询来源。连接可用只说明能控制这个标签,还要确认登录和筛选状态。

约定后台表格的字段

不同后台的 DOM 不一致,下面明确本文示例所依赖的结构。请把选择器映射到你自己的页面,不要原样假设目标系统存在这些属性:

<div data-testid="filter-summary">2026-10-01 至 2026-10-28,全部状态,当前页</div>
<table data-testid="orders">
  <tbody>
    <tr data-order-id="o-1001" data-total-minor="1290">
      <td data-field="status">paid</td>
    </tr>
    <tr data-order-id="o-1002" data-total-minor="2500">
      <td data-field="status">pending</td>
    </tr>
  </tbody>
</table>

订单 ID 是稳定标识;total-minor 是以分为单位的整数,不能拿展示的“¥12.90”直接转整数;filter-summary 说明当前页面范围。这里的 HTML 是数据合同示例,不是已部署或自动登录的演示后台。

在页面里人工设置所需日期和状态,等表格完成更新后再读取。对于正在维护的自有后台,增加稳定的测试属性通常比依赖第几个 td 更容易维护;无法改页面时,使用当前实际标签和列头完成映射。

一次完整的只读提取与汇总

保持已选择的后台标签,执行下面的 CLI 脚本。它不自动跳转到未知站点,也不清空当前 Cookie:

browser-harness <<'PY'
import json
from collections import Counter
from pathlib import Path
 
if not wait_for_element('table[data-testid="orders"]', timeout=15):
    raise RuntimeError("订单表未就绪;请检查当前标签、登录和加载状态")
 
result = js("""
(() => ({
  source_url: location.href,
  scope: document.querySelector('[data-testid="filter-summary"]')?.textContent?.trim(),
  rows: [...document.querySelectorAll('table[data-testid="orders"] tbody tr')].map(row => ({
    order_id: row.getAttribute('data-order-id'),
    total_minor: row.getAttribute('data-total-minor'),
    status: row.querySelector('[data-field="status"]')?.textContent?.trim()
  }))
}))()
""")
if not result.get("scope"):
    raise RuntimeError("缺少筛选范围说明")
seen = set()
totals = Counter()
for row in result["rows"]:
    if not row["order_id"] or row["order_id"] in seen:
        raise RuntimeError("订单 ID 缺失或重复")
    if row["status"] not in {"paid", "pending", "cancelled"}:
        raise RuntimeError("订单状态不在本次约定内")
    if not isinstance(row["total_minor"], str) or not row["total_minor"].isdigit():
        raise RuntimeError("金额必须是非负整数分")
    row["total_minor"] = int(row["total_minor"])
    seen.add(row["order_id"])
    totals[row["status"]] += row["total_minor"]
result["counts"] = dict(Counter(row["status"] for row in result["rows"]))
result["totals_minor_by_status"] = dict(totals)
Path("orders.json").write_text(
    json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8"
)
print({"scope": result["scope"], "rows": len(result["rows"]),
       "counts": result["counts"]})
PY

脚本读取浏览器中的 DOM,并在 CLI 工作目录写 orders.json。空表不会被当作全量订单已清空的证明;需要同时查看页面明确的空结果状态和筛选条件。跨页汇总应另加分页与覆盖检查,不能把本例的当前页金额当作整个日期范围总额。

怎样检查结果

对于上面两行 HTML,预期 paid 一条、pending 一条,相应金额分别为 1290 与 2500 分。真实页面输出应以当前 DOM 为准。

打开 orders.json,核对 source_url 是否属于后台订单页,scope 是否与你刚才设置的日期和状态相符。抽查两个订单 ID 和金额,再检查状态计数。若站点使用多币种,应把币种纳入记录并按币种分组,不能直接把它们相加。

读取完成不应关闭整个用户 Chrome。如果你为任务新建了标签,可以用工具关闭该标签;复用的后台标签由使用者保留。MCP 客户端断开、daemon 结束与 Chrome 退出是不同生命周期,不能用退出一个进程来推断所有浏览器资源都已经关闭。

登录失效和页面变化时怎样恢复

出现登录页。 停止读取,人工在同一测试 Profile 中重新登录,再确认当前 URL 和表格。不要把登录提示保存为“零订单”,也不要在脚本中回填真实密码来掩盖会话失效。

连接到错误标签。 重新列出标签,按实际 target 切换,然后检查 URL。多个窗口同名时不能只根据标题选择。

选择器一直等不到。 判断表格是否正在加载、是否在 iframe 中、是否已改版。若在 iframe,需采用工具支持的对应目标,而不是扩大根页面查询范围猜字段。

状态字段变了。 当前脚本明确拒绝未知状态。核对后台是否新增状态或只是展示文案变更,再修改映射;不要默认归到 paid。

工具异常的形状不同。 CLI 与 MCP 包装层可能把错误作为异常或工具错误返回,不能只检查结果中有没有 error 字段。没有拿到完整结果时,不继续写成功文件。

页面还是旧筛选数据。 确认筛选动作已经完成,等待表格的更新标记而不是固定睡眠。保存 scope,并抽查来源记录,避免在加载过渡时读取旧表。

复用已登录浏览器的价值在于保留当前会话,查询的可靠性仍依赖正确标签、明确范围和字段合同。把这三项保留下来,数据才便于回查。

需要企业代理方案?

我们可根据目标站点、并发规模与稳定性目标提供定制方案。