# Playwright 定位器指南

116 阅读3分钟

基础定位器方法

通过文本定位

# 精确匹配文本
page.get_by_text("点击我")

# 大小写不敏感匹配
page.get_by_text("点击我", exact=False)

通过测试ID定位

# 匹配 data-testid 属性
page.get_by_test_id("submit-button")

通过占位符定位

# 匹配 placeholder 属性
page.get_by_placeholder("输入用户名")

通过标签定位

# 匹配 label 文本
page.get_by_label("密码")

通过角色定位

# 匹配 ARIA 角色
page.get_by_role("button")
page.get_by_role("button", name="提交")

通过标准CSS选择器定位

# CSS 选择器
page.locator("div.user-panel")
page.locator("#login-button")
page.locator("css=button")

通过 XPath 定位

page.locator("xpath=//button")

元素关系选择器

定位包含特定子元素的父元素

# 找到包含指定子元素的父元素
page.locator('div', has=page.locator('.child-class'))
page.locator('ul', has=page.locator('li.special'))

# 找到包含特定文本的父元素
page.locator('section', has=page.get_by_text('特定文本'))

从父元素定位子元素

# 从父元素开始定位子元素
parent = page.locator('.parent-class')
child = parent.locator('.child-class')

# 链式定位多层嵌套元素
page.locator('.grandparent').locator('.parent').locator('.child')

兄弟元素定位

# 使用CSS选择器定位相邻兄弟元素
page.locator('h2 + p')  # 选择紧跟在h2后面的p元素

# 使用CSS选择器定位后续所有兄弟元素
page.locator('h2 ~ p')  # 选择h2后的所有p元素

复杂关系选择

# 组合使用多种关系选择器
page.locator('.parent', has=page.locator('span', has=page.locator('.icon')))

# 使用has_not排除包含特定子元素的父元素
page.locator('div.card', has_not=page.locator('.disabled'))

模糊匹配

包含xxx

# 属性包含某值
page.locator("[attr*='xxx']")

# 文本包含某值
page.get_by_text(re.compile(r"xxx"))

以xxx开头

# 属性以某值开头
page.locator("[attr^='xxx']")

# 文本以某值开头
page.get_by_text(re.compile(r"^xxx"))

以xxx结尾

# 属性以某值结尾
page.locator("[attr$='xxx']")

# 文本以某值结尾
page.get_by_text(re.compile(r"xxx$"))

高级选择器

包含完整单词xxx

page.locator("[attr~='xxx']")

以完整单词xxx开头

page.locator("[attr|='xxx']")

iframe 操作

# 在 iframe 中定位元素
locator = page.frame_locator("my-frame").get_by_text("Submit")
locator.click()

# 通过 iframe 的 name 属性
frame = page.frame("frame-name")
frame.get_by_role("button").click()

链式组合

# 组合多种定位方法
page.get_by_role("button").filter(has_text="登录")
page.locator("li").filter(has_text="项目").nth(2)

多元素选择和操作

获取多个元素

# 获取所有匹配的元素
all_buttons = page.get_by_role("button").all()

# 获取匹配元素的数量
count = await page.get_by_role("button").count()

# 遍历所有匹配元素
for i in range(await page.locator("li").count()):
    text = await page.locator("li").nth(i).text_content()
    print(f"项目 {i}: {text}")

选择特定位置的元素

# 选择第一个元素
first = page.locator("li").first

# 选择最后一个元素
last = page.locator("li").last

# 选择第n个元素(从0开始)
nth = page.locator("li").nth(2)  # 第3个元素

元素筛选

# 基于文本内容筛选
page.locator("div").filter(has_text="欢迎")

# 基于其他定位器筛选
page.locator("section").filter(has=page.locator(".highlighted"))

# 排除符合条件的元素
buttons_without_icon = page.locator("button").filter(has_not=page.locator("i.icon"))

快速查找多个元素

# 查找表格中的所有行
rows = page.locator("table tr")

# 查找特定类中的所有项目
list_items = page.locator("ul.menu > li")

# 查找所有可见的链接
visible_links = page.locator("a:visible")

多元素断言

# 断言至少有5个元素
await expect(page.locator("li")).to_have_count(5)

# 断言所有元素都可见
await expect(page.locator(".item")).to_be_visible()

元素索引选择技巧

# 使用nth选择指定索引的元素(从0开始)
second_item = page.locator("div.item").nth(1)  # 选择第2个元素

# 使用first()和last()的完整写法
first_item = page.locator("li").nth(0)  # 等同于first
last_item = page.locator("li").nth(-1)  # 等同于last

# 从末尾开始计数的写法
second_last = page.locator("tr").nth(-2)  # 倒数第2个元素

多选择器组合

# 使用逗号组合多个选择器(满足任一即可)
buttons = page.locator("button.primary, button.secondary")

# 选择多个同类元素中的特定位置
menu_items = page.locator("nav li")
third_menu = menu_items.nth(2)

按顺序操作多个元素

# 获取所有匹配元素并按顺序操作
elements = await page.locator("input[type='checkbox']").all()
for element in elements:
    await element.check()
    
# 先筛选后选择特定索引
filtered = page.locator("option").filter(has_text=re.compile(r"产品"))
third_product = filtered.nth(2)

复杂场景示例

# 表格中选择第3行第2列的单元格
cell = page.locator("table tr").nth(2).locator("td").nth(1)

# 选择具有特定属性的第n个元素
second_enabled = page.locator("button:not([disabled])").nth(1)

# 在列表中使用索引选择特定分组的元素
items_in_second_group = page.locator("div.group").nth(1).locator("li")

# 动态索引选择(使用nth而不是硬编码)
for i in range(5):  # 操作前5个元素
    item = page.locator(".item").nth(i)
    await item.click()