Playwright 和 Selenium 的元素定位方式**不完全相同,**Selenium的定位策略有8种,Playwright拥有独特的 Role、Text、Label 等定位方式
1. locator() -- CSS 选择器
HTML 示例:
html
<div id="app">
<input type="text" class="username-input" placeholder="用户名">
<button class="btn-primary">登录</button>
<ul class="menu">
<li><a href="/home">首页</a></li>
<li><a href="/profile">个人信息</a></li>
</ul>
</div>
python 代码:
python
# 通过 id 定位
page.locator("#app").click()
# 通过 class 定位
page.locator(".username-input").fill("admin")
# 通过标签 + 属性组合
page.locator("button.btn-primary").click()
# 通过层级关系
page.locator("ul.menu li:first-child a").click()
2. locator() -- XPath(需加 xpath= 前缀)
HTML 示例:
html
<div class="container">
<form>
<div class="form-group">
<label>邮箱</label>
<input type="email" name="email">
</div>
<div class="form-group">
<label>密码</label>
<input type="password" name="password">
</div>
<button>提交</button>
</form>
</div>
python 代码:
python
# 使用绝对 XPath(脆弱,不推荐)
page.locator("xpath=/html/body/div/form/div[1]/input").fill("test@example.com")
# 使用相对 XPath(推荐)
page.locator("xpath=//input[@name='email']").fill("test@example.com")
page.locator("xpath=//button[text()='提交']").click()
3. get_by_text() -- 文本内容
HTML 示例:
html
<nav>
<a href="/">首页</a>
<a href="/about">关于我们</a>
<button>点击关闭</button>
</nav>
<div class="notice">系统维护通知</div>
python 代码:
python
# 精确匹配文本
page.get_by_text("首页", exact=True).click()
# 包含子串(默认行为)
page.get_by_text("维护").click()
# 忽略大小写
page.get_by_text("CLOSE", exact=False).click() # 匹配 "点击关闭"
4. get_by_role() -- ARIA 角色(最稳定)
HTML 示例:
html
<button aria-label="提交表单">Submit</button>
<input type="text" role="textbox" name="username" placeholder="用户名">
<a href="/login">去登录</a>
python 代码:
python
# 定位按钮
page.get_by_role("button", name="提交表单").click()
page.get_by_role("button", name="Submit").click()
# 定位文本框
page.get_by_role("textbox", name="用户名").fill("zhangsan")
# 定位链接
page.get_by_role("link", name="去登录").click()
5. get_by_placeholder() -- 占位符文本
HTML 示例:
html
<input type="text" placeholder="请输入手机号/邮箱">
<input type="password" placeholder="密码">
python 代码:
python
page.get_by_placeholder("请输入手机号/邮箱").fill("13800000000")
page.get_by_placeholder("密码").fill("123456")
6. get_by_label() -- 关联的 <label> 文本
HTML 示例:
html
<label>用户名 <input type="text" id="username"></label>
<label for="email">电子邮箱</label>
<input type="email" id="email">
python 代码:
python
# 嵌套 label
page.get_by_label("用户名").fill("alice")
# 通过 for 属性
page.get_by_label("电子邮箱").fill("alice@example.com")
7. get_by_title() -- title 属性
HTML 示例:
html
<button title="关闭弹窗">X</button>
<img src="logo.png" title="公司Logo">
python 代码:
python
page.get_by_title("关闭弹窗").click()
logo = page.get_by_title("公司Logo")
8. get_by_alt_text() -- 图片的 alt 文本
HTML 示例:
html
<img src="avatar.jpg" alt="用户头像">
<img src="banner.png" alt="宣传横幅">
python 代码:
python
page.get_by_alt_text("用户头像").click()
banner = page.get_by_alt_text("宣传横幅")
9. 链式过滤 -- 在已定位元素中缩小范围
HTML 示例:
html
<ul>
<li><input type="checkbox"> 选项A</li>
<li><input type="checkbox"> 选项B</li>
<li><input type="checkbox" checked> 选项C</li>
</ul>
python 代码:
python
# 获取所有 li,再筛选出包含已勾选 checkbox 的
checked_li = page.locator("li").filter(has=page.locator("input:checked"))
print(checked_li.inner_text()) # 输出 "选项C"
# 筛选出文本包含"选项A"的 li
option_a = page.locator("li").filter(has_text="选项A")
option_a.locator("input").check()
10. 定位 iframe 中的元素
HTML 示例:
html
<iframe id="loginFrame" src="/login.html">
<html>
<body>
<input name="user" placeholder="用户名">
<button>登录</button>
</body>
</html>
</iframe>
python 代码:
python
# 方法一:通过 frame_locator(推荐)
frame = page.frame_locator("#loginFrame")
frame.get_by_placeholder("用户名").fill("admin")
frame.get_by_role("button", name="登录").click()
# 方法二:先获取 frame 对象
iframe = page.frame(name="loginFrame") # 或 page.frame(url=r".*login.*")
iframe.get_by_placeholder("用户名").fill("admin")
综合实战:登录表单
HTML 综合示例:
html
<form id="loginForm">
<label for="username">用户名</label>
<input type="text" id="username" placeholder="手机/邮箱">
<label for="password">密码</label>
<input type="password" id="password" placeholder="密码">
<button type="submit" class="login-btn">登 录</button>
</form>
python 代码(多种定位方式均可):
python
# 方式一:get_by_label + get_by_placeholder
page.get_by_label("用户名").fill("admin")
page.get_by_placeholder("密码").fill("123456")
page.get_by_role("button", name="登录").click()
# 方式二:CSS 选择器
page.locator("#username").fill("admin")
page.locator("#password").fill("123456")
page.locator(".login-btn").click()
# 方式三:XPath
page.locator("xpath=//input[@id='username']").fill("admin")
page.locator("xpath=//button[contains(text(),'登录')]").click()