
ego-browser 中 page.locator 与 getByRole 的自动等待与严格匹配怎么用非唯一匹配如何用 first 和 nth 消歧【免费下载链接】ego-liteThe fastest browser for AI agents to run browser automation, built for sharing your logged-in browser state with your AI agents, like Codex or Claude Code, without disturbing you. Zero cost, zero config.项目地址: https://gitcode.com/GitHub_Trending/eg/ego-lite在 ego-browser 的 heredoc 脚本里用 Playwright 风格的page.locator(...)和page.getByRole(...)操作页面时有两个默认行为直接决定脚本能否稳定跑通元素还没出现时读取操作会自动等待而一个选择器匹配到多个元素时操作会直接报matched 2 elements这类严格匹配错误而不是偷偷取第一个。本文基于 ego-browser 仓库内的实现、单元测试和真实浏览器回归用例说明这两种行为的具体表现以及确认页面里确实存在合法重复元素后如何用first()、nth(i)、last()消歧。前提ego lite 已安装且ego-browser命令可用安装见 SKILL.md 指向的skills/ego-browser/references/install.md。ego lite 当前在 macOS 上运行。运行方式与前置条件所有浏览器操作通过ego-browser nodejs EOF ... EOFheredoc 执行不要先写.js文件。heredoc 体内运行的是 Node.js 脚本page、page.locator、browser等 Playwright 风格 facade 已预加载无需 import见 package/ego-browser/README.md。脚本开头先复用或创建任务空间再打开页面ego-browser nodejs EOF const task await useOrCreateTaskSpace(inspect example page) await openOrReuseTab(https://example.com, { wait: true }) // 自动等待#main 还没出现时textContent() 会等待而不是立刻失败 const text await page.locator(#main).textContent() cliLog(text) // 严格匹配先确认匹配数量 const n await page.getByRole(button, { name: Submit }).count() cliLog(matched: n) EOFheredoc 里唯一可用的输出机制是cliLog(value)最终结果都要经过它打印。下面三个行为的具体数值和错误信息均取自仓库内的测试用例属于文档示例选择器、元素和期望值是针对仓库 fixture 页面的套用到你自己的页面时需要替换成实际元素。自动等待元素缺失时读取操作会轮询重试page.locator(...)返回的是一个 strict、auto-waiting 的 locator facade。对必需元素的读取如textContent()在元素暂时解析不到时会进入重试循环直到元素出现或超过默认超时实现上每轮最多休眠 100ms见 locator.ts 中readElement的循环以及 locator.test.mjs 中 required locator reads retry transient zero matches 用例超时设 500前两次查询为空、第三次命中最终成功返回休眠记录为[100, 100]。仓库回归用例 PWB-05playwright-locators.mjs展示了端到端行为先把#pwb05-delayed元素移除500ms 后再由页面脚本加回随后执行page.setDefaultTimeout(2500) const startedAt Date.now() assertEqual( await page.locator(#pwb05-delayed).textContent(), PWB-05 delayed status, PWB-05 delayed locator read completes ) assert(Date.now() - startedAt 300, PWB-05 locator waited for the missing element)用例的断言是读取最终返回文本PWB-05 delayed status文档示例并且整个调用耗时超过 300ms即它确实等到了延迟出现的元素而不是立即失败。超时值由page.setDefaultTimeout(value)调整上面用例用 2500 覆盖了 500ms 的延迟而运行时默认值定义为 10000见 state.ts。注意区分一类不等待的读取isVisible()这类可选状态读取在元素缺失时直接返回false而不等待或抛错locator.test.mjs 中isVisible(#missing)返回false。也就是说元素还没渲染和元素不可见要分开判断前者用会等待的读取后者用isVisible()这类即得即取的检查。严格匹配匹配到多个元素时操作直接报错严格匹配不止作用于getByRole对原生 CSS 和 XPath 字符串同样生效。PWB-06 用例同上文件在 fixture 页面上有三个选择器都命中 2 个元素const locator page.getByRole(button, { name: Duplicate action }) await assertRejects( () locator.click({ timeout: 1000 }), matched 2 elements, PWB-06 non-unique locator remains strict ) assertEqual(await locator.count(), 2, PWB-06 count exposes both matches) const rawCss page.locator(.duplicate-action) await assertRejects(() rawCss.click({ timeout: 1000 }), matched 2 elements) const rawXpath page.locator(xpath//button[contains(class, duplicate-action)]) await assertRejects(() rawXpath.innerText(), matched 2 elements)要点非唯一匹配时动作click和读取innerText都会拒绝执行错误信息包含matched 2 elements文档示例数字随实际匹配数变化。count()会如实暴露匹配数量该用例中断言count()为 2。page.getByRole(role, { name })按 role 和可访问名匹配。实现上locator-query.ts候选元素为button, a[href], input, textarea, select, img[alt], h1~h6, [role]优先读元素显式的role属性否则按标签推断隐式 role如a[href]为 link、textarea为 textbox可访问名依次取自aria-labelledby、aria-label、图片alt、按钮型input的 value、关联label或元素自身文本。name传字符串时做整体相等匹配传RegExp时做正则匹配locator.test.mjs 中 role locators use AX regex accessible names 用例用{ regex: checkout, flags: i }命中了 Proceed to Checkout。因此当操作报matched N elements时先别急着加first()这通常意味着选择器不够精确。先用count()和allTextContents()/allInnerTexts()看实际命中了哪些元素然后收紧选择器更具体的 CSS、getByRole的name、locator.filter({ hasText })等facade 完整方法清单见 helpers.ts 中page.locator(selector)的帮助文本。确认重复合法后用 first / nth / last 消歧facade 帮助文本的原文策略是Narrow multiple matches; use first()/nth() only for confirmed legitimate duplicates.——即只有在确认页面里就是存在合法的重复元素例如列表里多张结构相同的卡片各带一个按钮之后才用序号消歧。locator.first()等价于locator.nth(0)取第一个匹配locator.last()取最后一个locator.nth(index)取第index个0 起index必须是非负整数否则直接抛locator.nth requires a non-negative integer见 helpers.ts 的createLocator实现。返回的仍是 locator可以继续调用click()、innerText()等。PWB-06 用例的后半段演示了消歧后的成功路径fixture 页面的两个重复按钮文案都是 Duplicate action文档示例await rawCss.first().click({ timeout: 1000 }) assert(await rawCss.first().isVisible(), PWB-06 first resolves a confirmed legitimate duplicate) assertEqual( await rawXpath.nth(1).innerText(), Duplicate action, PWB-06 nth resolves a confirmed legitimate XPath duplicate )first()点击成功且元素可见nth(1)读到第二个重复按钮的文本两者都作为回归断言通过。结果验证对你自己的页面可按以下顺序核对自动等待生效在一个元素延迟出现或动态渲染的场景下await page.locator(sel).textContent()在默认超时10000内返回文本若元素在超时前始终不出现等待会结束并抛出解析错误此时检查选择器是否写错。唯一匹配await page.locator(sel).count()返回 1或getByRole的count()返回 1后续click/读取不再报matched N elements。消歧正确对first()/nth(i)结果调用isVisible()、innerText()或getAttribute()确认拿到的是预期那个元素而不只是操作没报错。仓库自身用npm run build、npm testbuild 类型检查 node --test维护这些行为入口和说明见 package/ego-browser/README.md真实浏览器端到端回归由npm run e2e驱动会在本机启动 ego-browser 并打开页面属于真实浏览器操作不要在不期望动浏览器的环境里顺手执行。边界与限制自动等待的重试只覆盖暂时解析不到的情况超过setDefaultTimeout设定的值仍解析不到就会抛错等待不会无限持续。isVisible()、isEnabled()、isEditable()等状态读取对缺失元素返回falseisHidden返回true不等待——不要把它当作等元素出现的手段。nth只接受非负整数first()/last()返回的子 locator 仍保持严格语义若底层选择器本身匹配 0 个元素读取行为遵循同一套自动等待规则。Nref 与 locator 是两套选择目标ref 只对最近一次snapshotText()有效且仅用于 ego-browser 原生 helperpage.locator里请用 CSS、xpath、loc...或文本选择器见 SKILL.md 的 Caveats。参考package/ego-browser/README.md — heredoc 运行方式、预加载 facade 与目录结构skills/ego-browser/SKILL.md — 任务空间、cliLog、选择器/ref 约定与注意事项playwright-locators.mjs — PWB-05 自动等待、PWB-06 严格匹配与 first/nth 消歧回归用例locator.ts — 读取重试循环与可选状态读取的回退逻辑locator.test.mjs — 单测层面的行为断言locator-query.ts — role/text/testid 等选择器的解析与匹配规则state.ts — 默认超时值定义【免费下载链接】ego-liteThe fastest browser for AI agents to run browser automation, built for sharing your logged-in browser state with your AI agents, like Codex or Claude Code, without disturbing you. Zero cost, zero config.项目地址: https://gitcode.com/GitHub_Trending/eg/ego-lite创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考