Playwright定位器表达式伪类
案例web页面中有多个相同属性的ul标签特点是仅有1个ul元素会展示在web页面中可见ul下还有子元素li如下假如有2个完全相同的下拉按钮其下拉值的ul标签也完全一样点击下拉按钮后仅会有1个ul标签会显示在页面上# 第一个 ul classel-dropdown-menu el-popper li>优化解决方案要解决这个问题我们可以使用Playwright的visible选择器来定位可见的UL元素然后根据LI的文本内容定位具体的LI元素。# 定位可见的UL元素使用:visible伪类visible_ulpage.locator(ul.el-dropdown-menu.el-popper:visible).first# 等待UL元素可见确保元素加载完成visible_ul.wait_for(statevisible)# 根据文本定位LI元素target_livisible_ul.locator(li,has_textxlsx)target_li.click()方案解析在 Playwright 中伪类如:visible被设计为放在 CSS 定位器表达式里这是 Playwright 定位系统的一个重要特性。这种设计有深刻的原理和实际考虑为什么伪类放在 CSS 表达式里统一选择器语法Playwright 使用标准 CSS 选择器语法作为基础伪类作为选择器的自然扩展符合开发者对 CSS 的认知示例button:visible比单独写选择器和状态检查更直观引擎优化Playwright 的 CSS 引擎在解析选择器时直接处理伪类相比单独过滤内置伪类处理更高效减少额外 DOM 查询原子操作保证将伪类整合到选择器中确保定位操作是原子的避免先查找元素后检查状态的竞态条件元素可能在查找后立即消失Playwright 的扩展能力虽然浏览器原生不支持某些伪类如:visiblePlaywright 在内部扩展了 CSS 引擎添加了这些增强伪类常用定位器伪类大全以下是可以直接放在 CSS 表达式中的伪类按功能分类1. 可见性相关伪类描述示例:visible仅匹配当前在页面上可见的元素过滤掉 display: none 等不可见元素。button:visible:hidden匹配隐藏元素.modal:hidden2. 文本内容匹配伪类描述示例:text(文本)包含匹配一是只要元素的可见文本中包含该字符串即可不区分大小写且会忽略首尾空白 二是也支持直接传入 JavaScript 风格的正则表达式用 / 包裹button:text(创建),:text(/Log\s*in/i):text-is(文本)精确匹配。元素的可见文本必须与括号内的字符串完全一致区分大小写。:text-is(创建):has-text(文本)子树文本匹配。匹配任何包含指定文本的元素即使该文本位于其子元素中常用于父级容器定位。div:has-text(订单详情):text-matches(正则表达式, 标志)正则匹配。匹配文本内容符合指定 JavaScript 风格正则表达式的最小元素。第二个参数为可选的标志如 “i” 表示忽略大小写。button:text-matches(Log\\s*in, i)3. 元素关系伪类描述示例:has()包含特定子元素section:has(h2.title):scope作用域元素。匹配当前定位器的作用域元素本身。通常与 :has() 结合使用用于判断当前元素自身是否满足条件。div:scope:has-text(标题):near()靠近其他元素button:near(.error):right-of()在右侧的元素save-btn:right-of(cancel-btn):left-of()在左侧的元素prev-btn:left-of(next-btn):above(selector)匹配在任何水平位置上位于内部选择器匹配元素上方的元素。button:above(#search):below(selector)匹配在任何水平位置上位于内部选择器匹配元素下方的元素。button:below(#search):near(selector)匹配与内部选择器匹配元素附近通常在 50 CSS 像素内的元素。button:near(#search):is(selector1, selector2)逻辑或OR操作。匹配符合其中任意一个选择器的元素。button:is(:text(sign in), :text(log in)):nth-match(selector, n)匹配满足特定条件的第 N 个元素注意索引是从 1 开始的。:nth-match(:text(Buy), 3),li:nth-match(:visible, 2)4. 状态伪类伪类描述示例:checked选中的复选框/单选input[typecheckbox]:checked:disabled匹配处于禁用状态的元素。input:disabled:enabled启用状态input:enabled:focus聚焦状态input:focus5. 结构伪类(不常用)伪类描述示例:first第一个匹配项tr:first:last最后一个匹配项li:last高级组合技巧# 组合多个伪类page.locator(button:visible:has-text(Confirm):not(:disabled))# 复杂关系定位page.locator(.modal:visible input:right-of(Username))# 动态文本匹配page.locator(div:has-text(/\\d new messages/))为什么不能单独使用伪类Playwright 要求伪类必须附加到选择器上因为伪类本身不是完整的定位器需要基础选择器作为查询起点伪类作为过滤器修饰基础选择器错误示例# 错误缺少基础选择器page.locator(:visible)# 无效# 正确附加到具体元素选择器page.locator(button:visible)性能最佳实践先具体后伪类# 好先缩小范围再应用伪类page.locator(.dialog:visible)# 差先伪类后过滤page.locator(:visible).filter(has_classdialog)避免过度复杂# 可接受page.locator(tr:visible:nth-match(:has(td button), 3))# 过于复杂 - 考虑拆分步骤rowspage.locator(tr:visible)targetrows.filter(haspage.locator(td button)).nth(2)这种设计使 Playwright 定位器既强大又高效同时保持了与 Web 标准的一致性。