【Playwright+Python】系列之元素定位

news2024/12/22 19:43:38

 

一、常见元素定位

定位器是 Playwright 自动等待和重试能力的核心部分。简而言之,定位器代表了一种随时在页面上查找元素的方法,以下是常用的内置定位器。

 

1、按角色定位

按显式和隐式可访问性属性进行定位语法:page.get_by_role() Dom结构示例1:

图片

示例代码1:

page.get_by_role("button", name="Sign in").click()

说明:按名称为“Sign in”button的角色找到元素。Dom结构示例2:

图片

 

示例代码2

expect(page.get_by_role("heading", name="Sign up")).to_be_visible()

page.get_by_role("checkbox", name="Subscribe").check()

page.get_by_role("button", name=re.compile("submit", re.IGNORECASE)).click()

说明:

  • 角色定位器包括按钮、复选框、标题、链接、列表、表格等,并遵循 ARIA 角色、ARIA 属性和可访问名称的 W3C 规范。请注意,许多 html 元素(如)都具有隐式定义的角色,该角色可由角色定位器识别。

  • 建议优先考虑角色定位器来定位元素,因为这是最接近用户和辅助技术感知页面的方式。

page.get_by_label()

通过关联标签的文本查找表单控件。

2、按标签定位

通过关联标签的文本查找表单控件语法:page.get_by_label() Dom结构示例:

图片

示例代码:

page.get_by_label("Password").fill("secret")

 

3、按占位符定位

语法:page.get_by_placeholder()Dom结构示例:

图片

示例代码:

page.get_by_placeholder("name@example.com").fill("playwright@microsoft.com")

 

4、通过文本定位

按占位符查找输入语法:page.get_by_text()Dom结构示例:

图片

示例代码:

# 可以通过元素包含的文本找到该元素
page.get_by_text("Welcome, John")
# 设置完全匹配
page.get_by_text("Welcome, John", exact=True)
# 正则表达式匹配
page.get_by_text(re.compile("welcome, john", re.IGNORECASE))

说明:

  • 按文本匹配始终会规范化空格,即使完全匹配也是如此。例如,它将多个空格转换为一个空格,将换行符转换为空格,并忽略前导和尾随空格。

  • 建议使用文本定位器来查找非交互式元素,如 div、span、p 等。对于button、a、input等交互式元素,请使用角色定位器。

5、通过替代文本定位

通过其文本替代来定位元素(通常是图像),所有图片都应具有描述图像的 alt 属性。可以使用page.get_by_alt_text() 根据替代文本查找图片。语法:page.get_by_alt_text()Dom结构示例:

图片

示例代码:

page.get_by_alt_text("playwright logo").click()

说明:当元素支持替代文本(如 img 和 area 元素)时,建议使用此定位器

 

6、按标题定位

按元素的 title 属性查找元素语法:page.get_by_title()Dom结构示例:

图片

示例代码:

expect(page.get_by_title("Issues count")).to_have_text("25 issues")

说明:当元素具有 title 属性时,建议使用此定位器7、按测试 ID 查找根据元素data-testid 属性来定位元素(可以配置其他属性)语法:page.get_by_title()Dom结构示例:

图片

示例代码:

page.get_by_test_id("directions").click()
8、设置自定义测试 ID 属性

默认情况下,page.get_by_test_id() 将根据 data-testid 属性查找元素,但您可以在测试配置中或通过调用 selectors.set_test_id_attribute() 来配置它。将测试 ID 设置为对测试使用自定义数据属性,示例代码:

playwright.selectors.set_test_id_attribute("data-pw")

Dom结构:

图片

然后像往常一样找到该元素,示例代码如下:

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 定义显式测试协定。

 

二、在 Shadow DOM 中定位

1、什么是Shadow DOM?

Shadow DOM 是 Web Components 技术的一部分,它提供了一种将 HTML 结构、样式和行为封装在一个独立的、封闭的 DOM 中的机制。以下是一个使用 Shadow DOM 的例子,该例子展示了如何创建一个简单的自定义组件,并将内容、样式封装在 Shadow DOM 中。示例代码:

<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <meta name="viewport" content="width=device-width, initial-scale=1.0">  
    <title>Shadow DOM Example</title>  
    <style>  
        /* 外部样式,不会影响 Shadow DOM 内部 */  
        .container {  
            font-size: 20px;  
            color: red;  
        }  
    </style>  
</head>  
<body>  
    <div id="hostElement" class="container">Shadow Host (这里不会显示 Shadow DOM 的内容)</div>  
  
    <script>  
        // 自定义元素定义及 Shadow DOM 创建  
        class MyCustomElement extends HTMLElement {  
            constructor() {  
                super();  
                // 创建 Shadow Root  
                const shadowRoot = this.attachShadow({ mode: 'open' });  
  
                // Shadow DOM 内部样式和内容  
                shadowRoot.innerHTML = `  
                    <style>  
                        .shadow-content {  
                            font-size: 16px;  
                            color: blue;  
                        }  
                    </style>  
                    <div class="shadow-content">This is inside the Shadow DOM.</div>  
                `;  
            }  
        }  
  
        // 注册自定义元素  
        customElements.define('my-custom-element', MyCustomElement);  
  
        // 将自定义元素添加到文档中  
        const customElement = document.createElement('my-custom-element');  
        document.body.appendChild(customElement);  
  
        // 注意:在实际应用中,你可能会将自定义元素直接写在 HTML 中,如:<my-custom-element></my-custom-element>  
        // 而不是通过 JavaScript 动态创建和添加。  
    </script>  
</body>  
</html>

dom结构:

图片

 

2、如何查看Shadow DOM

首先打开浏览器控制台的设置选项

图片

 

然后再找到Preference -> Elements,把show user anent shadow dom勾上


这时候我们再来看一下此时的dom元素发生了什么变化

我们会发现这些标签内部都大有乾坤,在这些标签下面都多了一个shadow root,在它里面才是这些标签的真实布局。

3、在 Shadow DOM 中定位

默认情况下,Playwright 中的所有定位器都使用 Shadow DOM 中的元素。例外情况包括:

  • 通过 XPath 定位不会刺穿阴影根

  • 不支持闭合模式阴影根

要定位,使用page.get_by_text("")page.locator("", has_text="")都可以,要确保

包含文本“This is inside the Shadow DOM.”,示例代码如下:

page.goto("http://localhost:8080/shadowDOM.html")
expect(page.get_by_text("This is inside the Shadow DOM.")).to_contain_text("Shadow DOM")
expect(page.locator("div", has_text="This is inside the Shadow DOM.")).to_contain_text("This is inside")

 

三、筛选定位

1、dom结构

图片

2、按文本筛选定位

可以使用 locator.filter() 方法按文本过滤定位器。它将在不区分大小写的情况下搜索元素内部的某个特定字符串,可能在后代元素中。示例代码:

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()
2.1、按没有文本进行筛选
expect(page.get_by_role("listitem").filter(has_not_text="Out of stock")).to_have_count(2)
2.2、按子项/后代筛选

定位器支持仅选择具有或没有与另一个定位器匹配的后代的元素的选项。因此,您可以按任何其他定位器进行过滤,例如 locator.get_by_role()、locator.get_by_test_id()、locator.get_by_text() 等。示例代码:

page.get_by_role("listitem").filter(
    has=page.get_by_role("heading", name="Product 2")
).get_by_role("button", name="Add to cart").click()

断言产品卡,确保只有一个,示例代码如下:

expect(
    page.get_by_role("listitem").filter(
        has=page.get_by_role("heading", name="Product 2")
    )
).to_have_count(1)

过滤定位器必须相对于原始定位器,并且从原始定位器匹配项(而不是文档根节点)开始查询。

2.3、按没有子/后代进行筛选

通过内部没有匹配的元素进行过滤,示例代码:

expect(
    page.get_by_role("listitem").filter(
        has_not=page.get_by_role("heading", name="Product 2")
    )
).to_have_count(1)

注意,内部定位器是从外部定位器开始匹配的,而不是从文档根目节点开始匹配的。

 

四、使用约束条件定位

1、在定位器内匹配

就先定位元素,再去定位子节点元素,以将搜索范围缩小到页面的特定部分。示例代码

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()
2、使用and条件匹配

方法 locator.and_() 通过匹配其他定位器来缩小现有定位器的范围,可以理解为xpath的and使用方法,都是定位一个元素,示例代码如下:

page.get_by_role("link").and_(page.get_by_text("新闻")).click()
3、使用or条件匹配

如果您想定位两个或多个元素中的一个,但不知道会是哪一个,请使用 locator.or_() 创建与所有备选项匹配的定位器。示例代码如下:

def test_navigationCnblogs(page: Page):
    page.goto("https://www.baidu.com/")
    login=page.get_by_role("link").and_(page.get_by_text("登录"))
    message=page.get_by_text("短信登录")
    expect(message.or_(login).first).to_be_visible()
    if (login.is_visible()):
        login.click()
    message.click()

 

4、仅匹配可见元素

考虑一个有两个按钮的页面,第一个不可见,第二个可见,这时候就可以进行约束,示例代码如下:

page.locator("button").locator("visible=true").click()

五、列表元素操作

dom结构:

图片

1、使用 count 断言

使用 count 断言确保列表有 3 个项目,示例代码如下:

expect(page.get_by_role("listitem")).to_have_count(3)
2、断言列表中的所有文本

断言定位器以查找列表中的所有文本,示例代码如下:

expect(page.get_by_role("listitem")).to_have_text(["apple", "banana", "orange"])
3、定位某个列表元素

使用 page.get_by_text() 方法按文本内容在列表中查找元素,示例代码如下:

page.get_by_text("orange").click()

也可以使用 locator.filter() 查找列表中的特定元素,示例代码如下:

page.get_by_role("listitem").filter(has_text="orange").click()
4、按下标定位指定元素

您有一个相同元素的列表,并且区分它们的唯一方法是顺序,则可以使用 locator.firstlocator.last 或 locator.nth() 从列表中选择特定元素。

    banana = page.get_by_role("listitem").nth(1)
    expect(banana).to_have_text('banana')
5、链接筛选器定位元素

当您有具有各种相似性的元素时,使用 locator.filter() 方法选择正确的元素。还可以链接多个筛选器以缩小选择范,就是层级定位,个人感觉。DOM 结构

图片

示例代码

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")
6、遍历每个元素

对列表中的每个元素执行操作,示例代码如下:

for row in page.get_by_role("listitem").all():
    print(row.text_content())

rows = page.get_by_role("listitem")
count = rows.count()
for i in range(count):
    print(rows.nth(i).text_content())
7、Evaluate in the page在页面中评估

我觉得这个就是很ES6呀,示例代码如下:

rows = page.get_by_role("listitem")
# 很前端了吧
texts = rows.evaluate_all("list => list.map(element => element.textContent)")
8、检查定位元素的个数

定位元素如果出现定位多个元素,这个就很好用了,可以作为检验是否定位到唯一元素检测,示例代码如下:

print(page.get_by_role("button").count()) #2

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1926220.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

力扣经典题目之->删除有序数组中的重复项讲解 的讲解与实现

一&#xff1a;题目 二&#xff1a;思路讲解 第一步&#xff1a;创建两个下标&#xff0c;一个是第一个元素的&#xff08;start0&#xff09;&#xff0c;一个是第二个元素的&#xff08;end1&#xff09; 第二步&#xff1a; a&#xff1a;end移动&#xff0c;直到遇到不等…

Dify中Jieba类的create()方法实现过程

本文主要介绍Dify中Jieba类的create()方法执行过程&#xff0c;重点是段&#xff08;segment&#xff09;的关键词的生成。 一.create方法流程概述 整个create方法的目的是为了处理一批文本&#xff0c;提取它们的关键词&#xff0c;并更新关键词表&#xff0c;以便于后续的关…

Spark 实现自定义加密

文章目录 Spark 实现自定义加密一、建立加密和解密的自定义函数二、在 Spark 环境下导入对象实现的方法&#xff0c;并在 SparkSession 中注册 UDF 函数三、在SparkSQL中调用函数 Spark 实现自定义加密 一、建立加密和解密的自定义函数 import java.nio.charset.{StandardCha…

STM32+三色LED智能调光系统源程序 易安卓APP 原理图

资料下载地址&#xff1a;STM32三色LED智能调光系统源程序 易安卓APP 原理图 三色LED手机智能调光系统概述&#xff1a; 利用开发的智能手机软件&#xff0c;对照明三色LED进行智能调光。包含的功能有&#xff0c;支持多手机同时连接服务端&#xff0c;互动调光。支持关…

【数据结构】顺序表的应用

目录 一.引言 二.顺序表概念 三.顺序表的实现 1.定义顺序表 2.顺序表初始化 ​编辑 3.检查空间&#xff0c;如果满了&#xff0c;进行增容 4.顺序表尾插 5.顺序表尾删 6.顺序表头插 7.顺序表头删 ​编辑 8.顺序表查找 9.顺序表在pos位置插入x 10.顺序表删…

深入探讨:CPU问题的深度分析与调优

引言 你是否曾经遇到过这样的情况:系统运行突然变慢,用户抱怨不断,检查后发现CPU使用率居高不下?这时候,你会如何解决?本文将详细解析CPU问题的分析与调优方法,帮助你在面对类似问题时游刃有余。 案例分析:一次CPU性能瓶颈的解决过程 某知名互联网公司在一次促销活动…

Dubbo基础知识

1、什么是 Dubbo &#xff1f; Dubbo是基于Java的高性能轻量级的RPC分布式服务框架&#xff0c;致力于提供透明化的RPC远程服务调用方案&#xff0c;以及SOA服务治理方案。现已成为Apache 基金会孵化项目。 2、为什么要使用Dubbo? 背景: 随着互联网的快速发展&#xff0c;Web应…

JAVA毕业设计147—基于Java+Springboot的手机维修管理系统(源代码+数据库)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringboot的手机维修管理系统(源代码数据库)147 一、系统介绍 本项目分为用户、管理员、维修员三种角色 1、用户&#xff1a; 注册、登录、新闻公告、售后申请、申请列…

使用Samba或NFS实现文件共享

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 一、SAMBA文件共享服务 1987年&#xff0c;微软公司和英特尔公司共同定制了SMB&#xff08;Server Messages Block&#xff09;服务器消息块协议&am…

板级调试小助手(2)ZYNQ自定义IP核构建属于自己的DDS外设

一、前言 在上期文章中讲述了小助手的系统结构和原理。在PYNQ的框架开发中&#xff0c;我们一般可以将PL端当做PS端的一个外设&#xff0c;通过读写寄存器的方式来操作外设的功能&#xff0c;就类似于在开发ARM和DSP中操作外设一样&#xff0c;不同时的是&#xff0c;我们可以通…

关于前端数据库可视化库的选择,vue3+antd+g2plot录课计划

之前&#xff1a;antdv 现在&#xff1a;g2plot https://g2plot.antv.antgroup.com/manual/introduction 录课内容&#xff1a;快速入门 图表示例&#xff1a; 选择使用比较广泛的示例类型&#xff0c;录课顺序如下&#xff1a; 1、折线图2、面积图3、柱形图4、条形图5、饼…

[Qt] Qt Creator中,新建QT文件时选择界面模版下的各选项

在Qt Creator中&#xff0c;新建文件时选择界面模版下的各选项具有特定的意义&#xff0c;这些选项主要帮助开发者根据项目需求快速生成不同类型的文件。以下是对这些选项的详细解释&#xff1a; 0. Qt Item Model 意义&#xff1a;列表模型是Qt中用于表示和操作数据的强大抽…

Ubuntu下载安装chrome浏览器

方法一&#xff1a;wget下载并安装 1、创建文件夹存安装包 cd /root/Downloads mkdir chrome 2、下载安装包到文件夹内 wget -c https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb -P /root/Downloads/chrome 3、安装 cd chrome sudo dpkg -i go…

从0开始的STM32HAL库学习5

旋转编码计数器 修改中断代码 void EXTI0_IRQHandler(void) {/* USER CODE BEGIN EXTI0_IRQn 0 */if(__HAL_GPIO_EXTI_GET_FLAG(PB0_Pin)){if(HAL_GPIO_ReadPin(PB1_GPIO_Port, PB1_Pin)GPIO_PIN_RESET){count--;}/* USER CODE END EXTI0_IRQn 0 */HAL_GPIO_EXTI_IRQHandler…

【论文极速读】 可微分检索索引(Differential Search Index, DSI)

【论文极速读】 可微分检索索引&#xff08;Differential Search Index&#xff0c; DSI&#xff09; FesianXu 20240714 at WeChat Search Team 前言 最近从朋友处得知了DSI这个概念&#xff0c;所谓的可微分检索索引DSI&#xff0c;就是通过语言模型将检索过程中的索引和召回…

virtualbox的ubuntu默认ipv4地址为10.0.2.15的修改以及xshell和xftp的连接

virtualbox安装Ubuntu后&#xff0c;默认的地址为10.0.2.15 我们查看virtualbox的设置发现是NAT 学过计算机网络的应该了解NAT技术&#xff0c;为了安全以及缓解ip使用&#xff0c;我们留了部分私有ip地址。 私有IP地址网段如下&#xff1a; A类&#xff1a;1个A类网段&…

持续学习的综述: 理论、方法与应用(三:泛化分析)

前文连接&#xff1a;持续学习的综述: 理论、方法与应用&#xff08;一&#xff09; 前文连接&#xff1a;持续学习的综述: 理论、方法与应用&#xff08;二&#xff1a;理论基础&#xff09; 泛化分析 目前持续学习的理论研究主要是在增量任务的训练集上进行的&#xff0c;假…

Java面试题:MVCC

MVCC 保证事务的隔离性 排它锁: 一个事务获取了数据行的排他锁,其他事务就不能再获取该行的其他锁 MVCC: 多版本并发控制 维护一个数据的多个版本,使读写不存在冲突 具体实现依靠 隐藏字段 mysql中隐藏了三个隐藏字段 db_trx_id:最近修改事务 db_roll_ptr:指向上一个…

【Linux】Linux必备的基础指令

目录 Linux必备的基础指令一 、 什么是Linux二、 Linux常用命令2.1 ls2.2 pwd2.3 cd2.4 touch2.5 cat2.6 mkdir2.7 rm 三、 Linux重要指令3.1 cp3.2 mv3.3 tail3.4 vim3.5 grep3.6 ps3.7 netstat Linux必备的基础指令 一 、 什么是Linux 系统编程&⽹络编程 Linux⾃⾝提供…

适合创业公司使用的wordpress主题

对于创业公司来说&#xff0c;‌选择一个适合的WordPress主题至关重要&#xff0c;‌它不仅能够提升公司网站的外观和用户体验&#xff0c;‌还能帮助优化搜索引擎排名&#xff0c;‌从而吸引更多的潜在客户。‌以下是一些推荐的WordPress主题&#xff0c;‌特别适合创业公司使…