《最新出炉》系列初窥篇-Python+Playwright自动化测试-6-元素定位大法-下篇
1.简介
上一篇主要是讲解我们日常工作中在使用Playwright进行元素定位的一些比较常用的定位方法的理论基础知识以及在什么情况下推荐使用。今天这一篇讲解和分享一下,在日常中很少用到或者很少见的定位,但是遇到了我们也要会,俗话说:手里有粮心里不慌。
2.阴影定位-Shadow DOM
在做web自动化的时候,一些元素在shadow-root的节点下,使得playwright中无法通过xpath来定位

上面所看到的shadow-root标签其实就是一个shadowDOM,那么什么是shadowDOM呢?
他是前端的一种页面封装技术,可以将shadowDOM视为“DOM中的DOM”(可以看成一个隐藏的DOM)
他是一个独立的DOM树,具有自己的元素和样式,与原始文档DOM完全隔离。
shadowDOM必须附在一个HTML元素中,存放shadowDOM的元素,我们可以把它称为宿主元素。在HTML5中有很多的标签样式都是通过shadowDOM来实现的。
比如:日期选择框,音频播放标签,视频播放标签都自带了样式;(这种封装对于前端开发来说虽好,但是我们测试人员在做web自动给的时候就会遇到一些问题,shadowDOM中的标签无法定位。)
默认情况下,Playwright 中的所有定位器都使用 Shadow DOM 中的元素。例外情况是:
- 通过 XPath 定位不会刺穿阴影根部。
- 不支持闭合模式影子根。
例如:以下示例和自定义 Web 组件:
<x-details role=button aria-expanded=true aria-controls=inner-details>
<div>Title</div>
#shadow-root
<div id=inner-details>Details</div>
</x-details>
您可以采用与影子根根本不存在相同的方式进行定位。
要单击 :<div>Details</div>
page.get_by_text("Details").click()
要单击 :<x-details>
page.locator("x-details", has_text="Details" ).click()
要确保包含文本“详细信息”,请执行以下操作:<x-details>
expect(page.locator("x-details")).to_contain_text("Details")
3.过滤器定位-Filtering
例如以下 DOM 结构,我们要在其中单击第二个产品卡的购买按钮。我们有几个选项来过滤定位器以获得正确的定位器。

3.1文本过滤
定位器可以使用 locator.filter()方法按文本进行过滤。它将搜索元素内某处的特定字符串,可能在后代元素中,不区分大小写。您还可以传递正则表达式。
1.使用文本
page.get_by_role("listitem").filter(has_text="Product 2").get_by_role(
"button", name="Add to cart"
).click()
2.使用正则表达式
page.get_by_role("listitem").filter(has_text=re.compile("Product 2")).get_by_role(
"button", name="Add to cart"
).click()
3.通过没有文本进行筛选
# 5 in-stock items
expect(page.get_by_role("listitem").filter(has_not_text="Out of stock")).to_have_count(5)
3.2子项/后代过滤
定位器支持仅选择具有或没有与其他定位器匹配的后代的元素的选项。因此,您可以按任何其他定位器进行过滤,例如 locator.get_by_role()、locator.get_by_test_id()、locator.get_by_text() 等。
1.使用子项
page.get_by_role("listitem").filter(
has=page.get_by_role("heading", name="Product 2")
).get_by_role("button", name="Add to cart").click()
2.使用产品卡断言,确保只有一个
expect(
page.get_by_role("listitem").filter(
has=page.get_by_role("heading", name="Product 2")
)
).to_have_count(1)
3.通过内部没有匹配的元素进行过滤
expect(
page.get_by_role("listitem").filter(
has_not=page.get_by_role("heading", name="Product 2")
)
).to_have_count(1)
敲黑板!!!!注意:内部定位器从外部定位器开始匹配,而不是从文档根目录匹配。
3.3匹配其他定位进行过滤
方法 locator.and_() 通过匹配其他定位器来缩小现有定位器的范围。例如,您可以组合 page.get_by_role() 和 page.get_by_title() 以按角色和头衔进行匹配。
button = page.get_by_role("button").and_(page.getByTitle("Subscribe"))
4.链接定位器
您可以链接创建定位器的方法(如 page.get_by_text() 或 locator.get_by_role()),以将搜索范围缩小到页面的特定部分。
在此示例中,我们首先通过定位其角色:listitem 来创建一个名为 product 的定位器。然后我们按文本过滤。我们可以再次使用产品定位器按按钮的角色获取并单击它,然后使用断言来确保只有一个带有文本“产品 2”的产品。
product = page.get_by_role("listitem").filter(has_text="Product 2")
product.get_by_role("button", name="Add to cart").click()
您还可以将两个定位器链接在一起,例如在特定对话框中查找“保存”按钮:
save_button = page.get_by_role("button", name="Save")
# ...
dialog = page.get_by_test_id("settings-dialog")
dialog.locator(save_button).click()
5.列表
5.1对列表中的项目进行计数
可以断言定位器以对列表中的项目进行计数。例如:一下DOM结构

使用计数断言确保列表包含 3 个项目。
expect(page.get_by_role("listitem")).to_have_count(3)
5.2断言列表中所有文本
可以断言定位器以查找列表中的所有文本。使用 expect(定位器).to_have_text() 确保列表包含文本“苹果”、“香蕉”和“橙色”。
expect(page.get_by_role("listitem")).to_have_text(["apple", "banana", "orange"])
5.3定位特定项目
有许多方法可以在列表中定位特定项目。
5.3.1通过文本定位
使用 page.get_by_text() 方法通过文本内容在列表中查找元素,然后单击它。

通过文本内容找到项目并单击它。
page.get_by_text("orange").click()
5.3.2通过文本过滤定位
使用 locator.filter() 在列表中查找特定项目。按“列表项”的角色找到一个项目,然后按“橙色”的文本进行筛选,然后单击它。
page.get_by_role("listitem").filter(has_text="orange").click()
5.3.3通过测试id定位
使用 page.get_by_test_id() 方法在列表中查找元素。如果您还没有测试 ID,则可能需要修改 html 并添加测试 ID。

通过测试ID“橙色”找到项目,然后单击它。
page.get_by_test_id("orange").click()
5.3.4通过第n项定位
如果你有一个相同元素的列表,并且区分它们的唯一方法是顺序,你可以从带有 locator.first、locator.last 或 locator.nth() 的列表中选择一个特定的元素。
banana = page.get_by_role("listitem").nth(1)
但是,请谨慎使用此方法。通常,页面可能会更改,并且定位器将指向与预期完全不同的元素。相反,尝试提出一个通过严格标准的独特定位器。
5.4链接过滤器
当您有各种相似性的元素时,可以使用 locator.filter()方法选择正确的元素。您还可以链接多个筛选器以缩小选择范围。

要截取带有“Mary”和“Say goodbye”的行的屏幕截图:
row_locator = page.get_by_role("listitem")
row_locator
.filter(has_text="Mary")
.filter(has=page.get_by_role("button", name="Say goodbye"))
.screenshot(path="screenshot.png")
5.5罕见例子
5.5.1对列表中每个元素执行操作
迭代元素
for row in page.get_by_role("listitem").all():
print(row.text_content())
使用常规 for 循环进行迭代:
rows = page.get_by_role("listitem")
count = rows.count()
for i in range(count):
print(rows.nth(i).text_content())
5.5.2在页面中评估
locator.evaluate_all()中的代码在页面中运行,您可以在那里调用任何 DOM API。
rows = page.get_by_role("listitem")
texts = rows.evaluate_all("list => list.map(element => element.textContent)")
6.小结
定位器是非常严格。这意味着,如果多个元素匹配,则对定位器执行暗示某些目标 DOM 元素的所有操作都将引发异常。例如,如果 DOM 中有多个按钮,则会引发以下调用:
如果有多个button,则引发错误
page.get_by_role("button").click()
另一方面,Playwright 了解何时执行多元素操作,因此当定位器解析为多个元素时,以下调用工作正常。
适用于多个元素
page.get_by_role("button").count()
您可以通过 locator.first、locator.last 和 locator.nth() 告诉 Playwright 在多个元素匹配时使用哪个元素来明确选择退出严格性检查。不建议使用这些方法,因为当您的页面更改时,Playwright 可能会单击您不想要的元素。相反,请按照上述最佳实践创建唯一标识目标元素的定位器。
6.1其他定位器
对于不太常用的定位器,请查看官网的其他定位器指南。由于时间关系,宏哥就不在这里对其进行展开介绍和讲解了。好了时间不早了,关于元素定位大法今天就分享到这里!!!仅供大家学习参考,感谢您耐心的阅读。
《最新出炉》系列初窥篇-Python+Playwright自动化测试-6-元素定位大法-下篇的更多相关文章
- 《手把手教你》系列技巧篇(十五)-java+ selenium自动化测试-元素定位大法之By xpath中卷(详细教程)
1.简介 按宏哥计划,本文继续介绍WebDriver关于元素定位大法,这篇介绍定位倒数二个方法:By xpath.xpath 的定位方法, 非常强大. 使用这种方法几乎可以定位到页面上的任意元素. ...
- 《手把手教你》系列技巧篇(八)-java+ selenium自动化测试-元素定位大法之By id(详细教程)
1.简介 从这篇文章开始,要介绍web自动化核心的内容,也是最困难的部分了,就是:定位元素,并去对定位到的元素进行一系列相关的操作.想要对元素进行操作,第一步,也是最重要的一步,就是要找到这个元素,如 ...
- 《手把手教你》系列技巧篇(十)-java+ selenium自动化测试-元素定位大法之By class name(详细教程)
1.简介 按宏哥计划,本文继续介绍WebDriver关于元素定位大法,这篇介绍By ClassName.看到ID,NAME这些方法的讲解,小伙伴们和童鞋们应该知道,要做好Web自动化测试,最好是需要了 ...
- 《手把手教你》系列技巧篇(十四)-java+ selenium自动化测试-元素定位大法之By xpath上卷(详细教程)
1.简介 按宏哥计划,本文继续介绍WebDriver关于元素定位大法,这篇介绍定位倒数二个方法:By xpath.xpath 的定位方法, 非常强大. 使用这种方法几乎可以定位到页面上的任意元素. ...
- 《手把手教你》系列技巧篇(十六)-java+ selenium自动化测试-元素定位大法之By xpath下卷(详细教程)
1.简介 按宏哥计划,本文继续介绍WebDriver关于元素定位大法,这篇介绍定位倒数二个方法:By xpath.xpath 的定位方法, 非常强大. 使用这种方法几乎可以定位到页面上的任意元素. ...
- 《手把手教你》系列技巧篇(十七)-java+ selenium自动化测试-元素定位大法之By css上卷(详细教程)
1.简介 CSS定位方式和xpath定位方式基本相同,只是CSS定位表达式有其自己的格式.CSS定位方式拥有比xpath定位速度快,且比CSS稳定的特性.下面详细介绍CSS定位方式的使用方法.xpat ...
- 《手把手教你》系列技巧篇(十八)-java+ selenium自动化测试-元素定位大法之By css中卷(详细教程)
1.简介 按计划今天宏哥继续讲解倚天剑-css的定位元素的方法:ID属性值定位.其他属性值定位和使用属性值的一部分定位(这个类似xpath的模糊定位). 2.常用定位方法(8种) (1)id(2)na ...
- 《手把手教你》系列技巧篇(十九)-java+ selenium自动化测试-元素定位大法之By css下卷(详细教程)
1.简介 按计划今天宏哥继续讲解css的定位元素的方法.但是今天最后一种宏哥介绍给大家,了解就可以了,因为实际中很少用. 2.常用定位方法(8种) (1)id(2)name(3)class name( ...
- 《手把手教你》系列技巧篇(十一)-java+ selenium自动化测试-元素定位大法之By tag name(详细教程)
1.简介 按宏哥计划,本文继续介绍WebDriver关于元素定位大法,这篇介绍By ClassName.看到ID,NAME这些方法的讲解,小伙伴们和童鞋们应该知道,要做好Web自动化测试,最好是需要了 ...
- [python爬虫] Selenium常见元素定位方法和操作的学习介绍(转载)
转载地址:[python爬虫] Selenium常见元素定位方法和操作的学习介绍 一. 定位元素方法 官网地址:http://selenium-python.readthedocs.org/locat ...
随机推荐
- 这个小项目,上周被国外 AI 新闻网站报道,前些天又上了 github 热榜
疫情期间在校花了几个月时间,写了这个小项目,是关于音频特征提取和分析的,自己是 AI 专业研究音频的,但受限于对音频特征的理解,做研究时总感觉缺乏"底料",所以当做是学习练手做了这 ...
- 如何实现 Java SpringBoot 自动验证入参数据的有效性
Java SpringBoot 通过javax.validation.constraints下的注解,实现入参数据自动验证 如果碰到 @NotEmpty 否则不生效,注意看下 @RequestBody ...
- PHP开发者交流群
PHP开发者交流群 欢迎大家加入学习讨论 QQ群(493834732)
- Ubuntu Server搭建个人服务器
Ubuntu Server20.04.5 LTS [参考资料] Ubuntu官方地址:https://www.ubuntu.com/ Ubuntu论坛地址:https://ubuntuforums.o ...
- API Gateway vs Load Balancer:选择适合你的网络流量管理组件
本文从对比了 API Gateway 和 Load Balancer 的功能区别,帮助读者更好地了解他们在系统架构中扮演的角色. 作者陈泵,API7.ai 技术工程师. 原文链接 由于互联网技术的发展 ...
- 【故障公告】被放出的 Bing 爬虫,又被爬宕机的园子
这些巨头爬虫们现在怎么了?记忆中2022年之前的十几年,园子没有遇到过被巨头爬虫们爬宕机的情况,巨头们都懂得爱护,都懂得控制节奏,都懂得在爬网时控制并发连接数以免给目标网站造成过大压力. 从去年开始, ...
- js给元素设置样式
一.style 利用 "[元素].style.[CSS属性名] = [属性值]" 的方法 1 var Box = document.getElementById('box') 2 ...
- Godot 4.0 文件系统特性的总结
关于文件系统,官方文档犹抱琵琶半遮面,有一些很独特的特性并没有集中地摆出来,导致用的时候晕头转向. 这里总结了目前我发现的Godot文件系统的一些特性. 这是专门针对导出后的,因为一些操作在编辑器里面 ...
- 机器学习07-(中文分词、样本类别均衡化、置信概率、k-means聚类算法、均值漂移聚类算法)
机器学习-07 机器学习-07 中文分词(jieba) 样本类别均衡化 置信概率 聚类模型 K均值算法 均值漂移算法 轮廓系数 DBSCAN算法 推荐引擎 代码总结 结巴分词 酒店评论舆情分析 针对测 ...
- Python分支结构之if语句
程序结构 程序三种结构 顺序 循环 分支 分支结构 分支结构基本语法 if 条件表达式: 语句1 语句2 语句3 ...... 条件表达式就是计算结果必须为布尔值的表达式 表达式后面的冒号不能少 注意 ...