Python Playwright进阶教程:元素定位详解(二)
目录
常见的元素定位
5、通过替代文本定位
5.1 验证图片加载状态
5.2 操作带替代文本的图标/按钮
5.3 动态 alt 属性匹配
6、按标题定位
7、按测试 ID 查找
7.1 示例
7.2 对比其他定位方式
8、设置自定义测试 ID 属性
8.1 方法作用
9、通过 CSS 或 XPath 定位
10、XPath选择器
10.1 XPath 定位语法规则
1 基础定位
2 动态路径匹配
3 显式声明 XPath 前缀
4 隐式省略前缀
10.2 XPath 表达式规范
a. 路径表达式要求
b. 动态属性与文本匹配
c. 优先使用相对路径
d. 避免过度复杂表达式
10.3 高级场景与优化
10.4 与其他定位器对比
10.5 适用场景
11、CSS选择器 (locator(selector))
基础用法-基础选择器
11.1 元素选择器
11.2 类与 ID 选择器
11.3 属性选择器
11.4 层级关系定位
11.5 直接子代选择器(>分隔)
高级用法与优化
11.6 属性操作符
11.7 组合选择器
11.8 伪类与状态匹配
11.9 动态内容处理
11.10 列表项定位优化
与 XPath 的对比
12、Frame 内定位 (frame_locator())
13、链式选择器
14、过滤定位器
常见的元素定位
5、通过替代文本定位
通过其文本替代来定位元素(通常是图像),所有图片都应具有描述图像的 alt 属性。可以使用page.get_by_alt_text()
根据替代文本查找图片。
根据图片或媒体元素的 alt
属性定位元素,适用于图像或媒体内容。
基础语法:page.get_by_alt_text(alt_text, exact=False)
alt_text
:必填参数,指定元素的 alt
属性文本(支持字符串或正则表达式)。exact
:默认为 False
,控制是否精确匹配文本(True
为完全匹配,False
为模糊匹配示例1:
示例代码:
page.get_by_alt_text("playwright logo").click()
# 说明:当元素支持替代文本(如 img 和 area 元素)时,建议使用此定位器
示例2:
<img alt="playwright logo" src="/img/playwright-logo.svg" width="100" />
代码示例:
# 定位alt属性为“logo”的图片
page.get_by_alt_text("playwright logo")
5.1 验证图片加载状态
适用场景:验证图片是否正确加载或显示
# 断言页面中存在 alt 属性为“公司 Logo”的图片
expect(page.get_by_alt_text("公司 Logo")).to_be_visible()
5.2 操作带替代文本的图标/按钮
适用场景:图标按钮或可交互图片的点击操作
# 点击 alt 文本为“搜索图标”的图片按钮
page.get_by_alt_text("搜索图标").click()
5.3 动态 alt
属性匹配
适用场景:动态生成的图片或带参数的替代文本
# 使用正则表达式匹配动态生成的 alt 文本(如“用户头像_张三”)
page.get_by_alt_text(re.compile(r"用户头像_\w+")).hover()
注意:
1.alt
属性唯一性:确保目标 alt
文本在当前页面唯一,避免匹配多个元素导致操作异常。
2.非图片元素兼容性:仅适用于支持 alt
属性的元素(如 <img>
、<area>
),其他元素需结合 get_by_role()
或 CSS 选择器
3.优先使用正则表达式或模糊匹配
6、按标题定位
可以通过元素的 title
属性来定位元素。适用于有 title 提示的元素
语法:page.get_by_title()
说明:当元素具有 title 属性时,建议使用此定位器
示例1:
代码示例:
expect(page.get_by_title("Issues count")).to_have_text("25 issues")
<span title='用户设置'>用户设置</span>
```(
```python
# 定位标题为“用户设置”的按钮
page.get_by_title("用户设置")
示例2:
<title>百度一下,你就知道</title>
示例代码:
page.get_by_title("百度一下,你就知道").click()
7、按测试 ID 查找
根据元素data-testid 属性来定位元素(可以配置其他属性)
如果 HTML 元素中有 data-testid
属性,可以使用 get_by_test_id()
方法通过此属性进行定位。这种方式特别适合在前端开发中为测试提供稳定的定位
语法:page.get_by_test_id("test_id_value")
7.1 示例
代码示例:
page.get_by_test_id("directions").click()
# 定位data-testid属性为“submit-button”的按钮
page.get_by_test_id("submit-button")
# 定位并操作带有 data-testid="BookList-container" 的元素
page.get_by_test_id("BookList-container").click()
# 模糊匹配:支持正则表达式匹配部分 data-testid 值
page.get_by_test_id(re.compile(r"user-\d+")).hover()
注意:
data-testid
值在页面中唯一,避免匹配到多个元素data-testid
,防止测试中断data-testid
,避免过度标记导致维护成本增加7.2 对比其他定位方式
方法 | 特点 | 适用场景 |
---|---|---|
get_by_test_id() |
依赖专用测试属性,稳定性高 | 测试代码、动态内容 |
get_by_role() |
基于 ARIA 角色,强调可访问性 | 表单、按钮等标准组件 |
get_by_text() |
依赖文本内容,易受多语言影响 | 静态文本元素 |
8、设置自定义测试 ID 属性
默认情况下,page.get_by_test_id() 将根据 data-testid 属性查找元素,但您可以在测试配置中或通过调用 selectors.set_test_id_attribute() 来配置它。将测试 ID 设置为对测试使用自定义数据属性
8.1 方法作用
data-testid
替换为其他 HTML 属性(如 data-qa
、data-test-id
等)。get_by_test_id()
定位操作均使用新属性名,无需逐条修改定位器。from playwright.sync_api import sync_playwright
with sync_playwright() as p:
# 设置自定义测试 ID 属性为 "data-qa"
p.selectors.set_test_id_attribute("data-qa")
browser = p.chromium.launch()
page = browser.new_page()
page.goto("https://example.com")
# 定位带有 data-qa="login-button" 的元素
page.get_by_test_id("login-button").click()
示例代码:
playwright.selectors.set_test_id_attribute("data-pw")
示例代码:
page.get_by_test_id("directions").click()
注意:
9、通过 CSS 或 XPath 定位
如果绝对必须使用 CSS 或 XPath 定位器,则可以使用 page.locator() 创建一个定位器,该定位器采用一个选择器来描述如何在页面中查找元素。Playwright 支持 CSS 和 XPath 选择器,如果省略 css= 或 xpath= 前缀,则会自动检测它们
示例代码:
page.locator("css=button").click()
page.locator("xpath=//button").click()
page.locator("button").click()
page.locator("//button").click()
说明:
XPath 和 CSS 选择器可以绑定到 DOM 结构或实现。当 DOM 结构更改时,这些选择器可能会中断。
不建议使用 CSS 和 XPath,因为 DOM 经常会更改,从而导致无法复原的测试。相反,请尝试提供一个接近用户感知页面的定位器,例如角色定位器,或者使用测试 ID 定义显式测试协定。
10、XPath选择器
在 Playwright 中,locator("xpath=...")
是通过 XPath 表达式定位元素的核心方法,适用于复杂或动态元素的精准定位。
(locator("xpath=...")
)
示例代码:
# 定位“提交”按钮
page.locator("xpath=//button[text()='提交']")
# 定位父元素为 div 且子元素包含 span 的结构
page.locator("xpath=//div[span]")
10.1 XPath 定位语法规则
1 基础定位
page.locator("xpath=//button[@id='submit']").click() # 显式声明 XPath
page.locator("//div[contains(@class, 'menu-item')]").hover() # 隐式使用(自动识别)
2 动态路径匹配
a. 使用 contains()
或 starts-with()
处理动态属性:
page.locator("//input[contains(@placeholder, 'Search')]").fill("Playwright")
b. 结合文本内容定位:
page.locator("//a[text()='Sign In']").click()
3 显式声明 XPath 前缀
说明:Playwright 支持显式指定定位策略,避免与其他定位方式混淆
# 显式添加 "xpath=" 前缀(推荐)
page.locator("xpath=//div[@class='container']/button:ml-citation{ref="1" data="citationList"}")
4 隐式省略前缀
说明:当表达式以 //
或 .//
开头时,Playwright 自动识别为 XPath 定位
# 直接以 "//" 开头时,可省略 "xpath="
page.locator("//div[@class='container']/button:ml-citation{ref="1" data="citationList"}")
10.2 XPath 表达式规范
a. 路径表达式要求
XPath 表达式需以 //
开头,表示从根节点或任意位置开始匹配
# 正确写法
page.locator("xpath=//input[@id='username']")
# 错误写法(缺少 "//")
page.locator("xpath=input[@id='username']") # 无法生效
b. 动态属性与文本匹配
说明:支持 contains()
、starts-with()
等函数处理动态生成的属性或文本
# 结合属性与文本的复合定位
page.locator("xpath=//button[contains(@class, 'submit') and text()='保存']")
# 使用函数处理动态内容
page.locator("xpath=//div[starts-with(@id, 'item_')]")
c. 优先使用相对路径
# 推荐相对路径(减少对页面结构的依赖)
page.locator("xpath=//*[@data-test='login-button']")
# 避免完整路径(易受结构变动影响)
page.locator("xpath=/html/body/div:ml-citation{ref="3" data="citationList"}/div/button") # 维护成本高:ml-citation{ref="1,3" data="citationList"}
d. 避免过度复杂表达式
# 复杂表达式示例(可读性差)
page.locator("xpath=//div[not(@hidden)]/span[position()=2 and @role='text']")
# 可拆解为多条件组合或改用 CSS 选择器:ml-citation{ref="3,7" data="citationList"}
10.3 高级场景与优化
场景 | 示例 XPath | 说明 |
---|---|---|
多层级嵌套 | //form//input[@name='username'] |
跨层级定位表单输入框 2 |
索引定位 | (//ul/li):ml-citation{ref="3" data="citationList"} |
选择列表第三项 |
逻辑运算符 | //div[@class='card' and @data-type='VIP'] |
多条件组合筛选元素 2 |
轴定位(Axes) | //table//tr/td[following-sibling::td:ml-citation{ref="2" data="citationList"}] |
定位相邻单元格 |
10.4 与其他定位器对比
定位方式 | 优势 | 局限性 |
---|---|---|
XPath | 支持复杂路径、动态属性、跨层级定位 | 性能略低于 CSS 选择器 |
CSS 选择器 | 简洁高效,适合静态类名/ID 定位 | 对动态属性支持较弱 |
角色定位(Role) | 语义化强,强调可访问性 | 依赖 ARIA 属性规范 |
10.5 适用场景
:light
修饰符(Playwright 默认支持常规 DOM)。注意:
性能优化
//body/div:ml-citation{ref="2" data="citationList"}/section:ml-citation{ref="1" data="citationList"}/div[...]
),优先使用唯一属性或短路径 26。@id
、data-testid
等稳定属性替代依赖 DOM 结构的 XPath。11、CSS选择器 (locator(selector))
Playwright 的 CSS 选择器支持大多数 CSS 选择器功能,包括类名、ID、属性选择、子元素等。它是最常用的定位方法之一。
# 定位类名为“menu-link”的元素
page.locator(".menu-link")
# 定位ID为“username”的输入框
page.locator("#username")
# 组合选择器
page.locator("div.menu > a.link-item")
基础用法-基础选择器
11.1 元素选择器
直接通过标签名定位元素:
page.locator("button").click() # 点击所有按钮中的第一个
11.2 类与 ID 选择器
类选择器(.
前缀):
page.locator(".submit-btn").click() # 定位 class 包含 "submit-btn" 的元素
ID 选择器(#
前缀):
page.locator("#search-input").fill("test") # 定位 id="search-input" 的输入框
11.3 属性选择器
通过属性名或值精准定位:
page.locator("[type='submit']").click() # 定位 type="submit" 的元素
page.locator("[placeholder^='Search']").fill("test") # 匹配以 "Search" 开头的 placeholder
11.4 层级关系定位
后代选择器(空格分隔):
page.locator("body .menu-item") # 定位 body 内所有 .menu-item 元素
11.5 直接子代选择器(>
分隔)
page.locator("ul > li:first-child") # 定位 ul 下的第一个 li 子元素
高级用法与优化
11.6 属性操作符
^=
:匹配属性值开头(如 [href^='https']
)$=
:匹配属性值结尾(如 [src$='.png']
)*=
:包含子字符串(如 [class*='error']
)11.7 组合选择器
多条件叠加提升精准度:
page.locator("button.submit[disabled]") # 定位 class="submit" 且禁用的按钮
11.8 伪类与状态匹配
:hover
, :nth-child(n)
等:
page.locator("tr:nth-child(2)").hover() # 悬停表格第二行
:checked
, :disabled
等:
page.locator("input:checked").click() # 点击已勾选的复选框
11.9 动态内容处理
结合正则表达式或属性通配符应对动态生成的类名/ID:
page.locator("[class~='dynamic_']").click() # 匹配包含 "dynamic_" 片段的类名
11.10 列表项定位优化
使用 nth-child
或 nth-of-type
定位特定项:
page.locator("ul.items li:nth-of-type(3)") # 选择第三个列表项
与 XPath 的对比
场景 | CSS 选择器优势 | 注意事项 |
---|---|---|
静态属性定位 | 语法简洁,执行效率高(如 .class )16 |
避免过度依赖 DOM 结构层级 17 |
动态属性匹配 | 支持通配符(*= , ^= 等)78 |
需确保属性值唯一性 7 |
伪类与状态交互 | 直接匹配元素状态(如 :checked )27 |
部分伪类需结合 Playwright 等待机制 6 |
注意:
1. 优先短路径与唯一属性
body > div > form > input
),改用 #id
或 [data-testid]
直接定位。 12、Frame 内定位 (frame_locator()
)
如果元素位于 <iframe>
中,可以使用 frame_locator()
方法进入 iframe,再在其中定位元素。
# 定位嵌套在 iframe 中的元素
frame = page.frame_locator("#iframe-id")
frame.locator("button#submit").click()
13、链式选择器
Playwright 支持链式定位,使得在复杂页面结构中逐步定位更加灵活。
# 先找到父级菜单项,再找其中的子项链接
page.locator("nav.menu").locator("a.link-item").click()
14、过滤定位器
可以使用 locator.filter() 方法按文本过滤定位器。它将在元素内部的某个位置(可能在后代元素中)搜索特定字符串,不区分大小写。
注:过滤定位器必须相对于原始定位器,并且从原始定位器匹配开始查询,而不是从文档根开始。
<ul>
<li>
<h3>Product 1</h3>
<button>Add to cart</button>
</li>
<li>
<h3>Product 2</h3>
<button>Add to cart</button>
</li>
</ul>
# 点击第2个商品对应的按钮
page.get_by_role("listitem").filter(has_text="Product 2").get_by_role(
"button", name="Add to cart"
).click()
# 正则
page.get_by_role("listitem").filter(has_text=re.compile("Product 2")).get_by_role(
"button", name="Add to cart"
).click()
作者:黑米粥✎