阅读视图

发现新文章,点击刷新页面。

【Playwright学习笔记 06】用户视觉定位的方法

根据文本内容定位

Page/Locator 对象的 get_by_text 方法

比如,

如果要获取 所有 文本内容包含 11 的元素,就可以这样

elements = page.get_by_text('11').all()

如果,你希望包含的内容是以 11 结尾的,就可以使用正则表达式对象 作为参数,如下

import re
elements = page.get_by_text(re.compile("11$")).all()

根据 元素 role 定位

web应用现在有一种标准 称之为: ARIA (Accessible Rich Internet Applications)

ARIA 根据web界面元素的用途,为这些元素定义了一套 角色( Role ) 信息,添加到页面中,

从而 让 残疾人士,或者 普通人在 某种环境下(比如夜里,太空中),不方便使用常规方法操作应用,使用辅助技术工具,来操作web应用的。

若想定位这个元素:

<div class="alert-message">
  您已成功注册,很快您将收到一封确认电子邮件
</div>

直接可以根据如下代码 定位该元素

# 根据 role 定位
lc = page.get_by_role('alert')

# 打印元素文本
print(lc.inner_text())

html元素中,有些 特定语义元素(semantic elements)被ARIA规范认定为自身就包含 ARIA role 信息,并不需要我们明显的加上 ARIA role 属性设置,

比如

<progress value="75" max="100">75 %</progress>

就等于隐含了如下信息

<progress value="75" max="100"
  role="progressbar"
  aria-valuenow="75"
  aria-valuemax="100">75 %</div>

所以,直接可以根据如下代码 定位该元素

# 根据 role 定位
lc = page.get_by_role('progressbar')

# 打印元素属性 value 的值
print(lc.get_attribute('value'))

再比如 search 类型的输入框,默认就有 searchbox role,

<input type="search">

ARIA Attribute

ARIA规范除了可以给元素添加 ARIA role ,还可以添加其它  ARIA属性(ARIA attributes) ,比如

<div role="heading" aria-level="1">白月黑羽标题1</div>
<div role="heading" aria-level="2">白月黑羽标题2</div>

aria-level 就是一个 ARIA 属性,表示 role 为 heading 时的 等级 信息

上面的定义,其实和下面的 html 元素 h1/h2 等价

<h1>白月黑羽标题1</h1>
<h2>白月黑羽标题2</h2>

上例中,h2 元素,隐含了 role="heading" aria-level="2" , 所以可以用下面代码定位

lc = page.get_by_role('heading',level=2)
print(lc.inner_text())

Accessible Name

只根据 ARIA roleARIA属性 往往并不能唯一定位元素。

role定位最常见的组合是 ARIA roleAccessible Name

因为,Accessible Name 就像元素的 名字 一样,往往可以唯一定位。

html 元素标准属性 name 是浏览器内部的,用户看不到,比如

Accessible Name 不一样,它是元素界面可见的文本名,

<a name='link2byhy' href="https://www.byhy.net">白月黑羽教程</a>

比如上面的元素,暗含的 Accessible Name 值就是 白月黑羽教程 , 当然也暗含了 ARIA role 值为 link

所以,可以这样定位

lc = page.get_by_role('link',name='白月黑羽教程')
print(lc.click())

上面的写法, 只要 Accessible Name 包含 参数name 的字符串内容即可,而且大小写不分, 并不需要完全一致。

所以,这样也可以定位到

lc = page.get_by_role('link',name='白月黑羽')

如果你需要 Accessible Name 和 参数name 的内容完全一致,可以指定 exact=True ,如下

lc = page.get_by_role('link',name='白月黑羽', exact=True)

name值还可以通过正则表达式,进行较复杂的匹配规则,比如

lc = page.get_by_role('link',name=re.compile("^白月.*羽"))

我们这里说一些常见的:

<a> <td> <button> Accessible Name 值 就是其内部的文本内容。

<textarea> <input> 这些输入框,它们的 Accessible Name 值 是和他们关联的 的文本。

比如:

<label>
  <input type="checkbox" /> Subscribe
</label>

这个 checkbox 的 Accessible Name 却是 Subscribe

一些元素 比如 <img> ,它的 Accessible Name 是其html 属性 alt 的值

比如

<img src="grape.jpg" alt="banana"/>

role定位代码复杂,建议使用codegen代码助手来完成

【Playwright 学习笔记 05】Xpath选择

XPath (XML Path Language) 是由国际标准化组织W3C指定的,用来在 XML 和 HTML 文档中选择节点的语言。

目前主流浏览器 (chrome、firefox,edge,safari) 都支持XPath语法,xpath有多个版本,目前浏览器支持的是 xpath 1的语法。

语法介绍

xpath 语法中,整个HTML文档根节点用'/'表示

绝对路径选择

从根节点开始的,到某个节点,每层都依次写下来,每层之间用 / 分隔的表达式,就是某元素的 绝对路径

上面的xpath表达式 /html/body/div ,就是一个绝对路径的xpath表达式, 类似 css表达式 html>body>div

相对路径选择

有的时候,我们需要选择网页中某个元素, 不管它在什么位置

xpath需要前面加 // , 表示从当前节点往下寻找所有的后代元素,不管它在什么位置。

所以xpath表达式,应该这样写: //div

通配符

如果要选择所有div节点的所有直接子节点,可以使用表达式 //div/*

* 是一个通配符,对应任意节点名的元素

根据属性选择

Xpath 可以根据属性来选择元素。

根据属性来选择元素 是通过 这种格式来的 [@属性名='属性值']

注意:

  • 属性名注意前面有个@
  • 属性值一定要用引号, 可以是单引号,也可以是双引号

根据id属性选择

选择 id 为 west 的元素,可以这样 //*[@id='west'] (选择任意元素中含有id=west的)

根据其他属性

同样的道理,我们也可以利用其它的属性选择

比如选择 具有multiple属性的所有页面元素 ,可以这样 //*[@multiple]

属性值包含字符串

要选择 style属性值 包含 color 字符串的 页面元素 ,可以这样 //*[contains(@style,'color')]

要选择 style属性值 以 color 字符串 开头 的 页面元素 ,可以这样 //*[starts-with(@style,'color')]

要选择 style属性值 以 某个 字符串 结尾 的 页面元素 ,大家可以推测是 //*[ends-with(@style,'color')] , 但是,很遗憾,这是xpath 2.0 的语法 ,目前浏览器都不支持

按次序选择

某类型 第几个 子元素

比如要选择 p类型第2个的子元素,就是

//p[2]

第几个子元素

也可以选择第2个子元素,不管是什么类型,采用通配符

比如 选择父元素为div的第2个子元素,不管是什么类型

//div/*[2]

某类型 倒数第几个 子元素

当然也可以选取倒数第几个子元素

比如:

  • 选取p类型倒数第1个子元素
//p[last()]

  • 选取p类型倒数第2个子元素
//p[last()-1]

范围选择

xpath还可以选择子元素的次序范围。

比如

  • 选取option类型第1到2个子元素
//option[position()<=2]

  • 选择class属性为multi_choice的后3个子元素
//*[@class='multi_choice']/*[position()>=last()-2]

组选择、父节点、兄弟节点

组选择

xpath也有组选择, 是用 竖线 隔开多个表达式

比如,要选所有的option元素 和所有的 h4 元素,可以使用

//option | //h4

选择父节点

xpath可以选择父节点, 这是css做不到的。

某个元素的父节点用 /.. 表示

要选择 id 为 china 的节点的父节点,可以这样写 //*[@id='china']/..

兄弟节点选择

xpath也可以选择 后续 兄弟节点,用这样的语法 following-sibling::

比如,要选择 class 为 single_choice 的元素的所有后续兄弟节点 //*[@class='single_choice']/following-sibling::*

等同于CSS选择器 .single_choice ~ *

如果,要选择后续节点中的div节点, 就应该这样写 //*[@class='single_choice']/following-sibling::div

xpath还可以选择 前面的 兄弟节点,用这样的语法 preceding-sibling::

比如,要选择 class 为 single_choice 的元素的 所有 前面的兄弟节点,这样写

//*[@class='single_choice']/preceding-sibling::*

❌