2、Selenium :元素定位的各种方法
一、常用简单的元素定位方式
Selenium 常用的元素定位方式包含:id、name、class。
前端工程师在编写 Web网站的时候,大部分的网页标签都会包含 id、name、class 中的其中一个或者多个。
其中,一个页面内的 id 一般具有唯一性,也是使用最多的一种元素定位方式;name、class 分别对应网页标签的name 属性、class 属性。
打开目标网页,按 F12 键打开开发者调试工具,定位到元素标签,如果存在 id 、name、class 属性,就可以使用 id 、name、class 中的其中一个来定位到元素
具体的使用方法如下:
# 使用 id 定位
driver.find_element_by_id("element_id")
# 使用 name 定位
driver.find_element_by_name("element_name")
# 使用 class 定位
driver.find_element_by_class_name("element_class")
二、Xpath
Xpath在 XML 文档中本身是一种元素定位语言,而 HTML 是 XML 是另外一种实现,在元素定位的时候会遍历页面的所有元素,所以查询效率不高,但是运用灵活,能够精确定位到绝大多数的页面元素,所以是使用最为广泛的定位方式。
Selenium 中 Xpath 定位方式包含:绝对路径定位、属性定位、元素关系定位、运算符、匹配等。
绝对路径定位
相当于从最顶部的 html 元素标签往子标签追加,一直定位到目标元素标签,这种方式不常用。
driver.find_element_by_xpath('/html/body/div/.../div/目标元素')
实际上在做 App 端自动化 的时候,Appium元素定位的时候,某些元素没有任何属性和可用的层级关系定位方式,这时候借助绝对定位是唯一的选择。
元素属性定位
对应网页元素标签的任意属性,只要能唯一标识目标元素即可。
属性定位很简单,可以显式的指定目标元素的标签名或用 * 号匹配任意标签名,使用格式是:'//元素标签[@属性名="属性值"]'
# 1、通过标签名来定位
driver.find_element_by_xpath('//div[@id="element_id"]')
# 2、也可以用*号代替
driver.find_element_by_xpath('//*[@name="element_name"]')
元素关系定位
当一个元素标签没有任何属性值,但是父元素标签存在唯一的属性值,这时候可以先找到父元素标签,然后再找到自己。
# 通过父元素标签找到自己
# 父元素标签含有属性值 class = parent_class
# 子元素标签为a
driver.find_element_by_xpath('//div[@class="parent_class"]/a")
匹配定位
主要是利用属性中包含某个字符串来定位元素标签,包含:contains、starts_with
# 匹配定位
# class属性值中包含:class
driver.find_element_by_xpath('//div[contains(@class,"part_str")]')
#元素的text包含某些内容
driver.find_element_by_xpath('//div[contains(text(),"XXXX")]')
# class属性值以part_start开头
//input[starts-with(@class,'part_start')]
text定位
利用元素的text内容来进行定位
# 元素的text内容
//*[@id="XXX"]//p[text()="text内容"]
运算符定位
页面可能多个元素包含同一个属性,这时候可以使用逻辑元素符 and 连接多个属性来定位元素标签。
# 通过多个属性值来唯一定位元素标签
driver.find_element_by_xpath('//div[@属性1="属性1的值" and @属性2="属性2的值"]')
# 通过属性值和匹配定位共同来定位元素
//div[@class="XXX" and contains(@style,"display:visibility")]
chrom自带的xpath获取插件
实际上,网页元素标签的 Xpath 表达式可以使用 Chrome 右键属性或者 Xpath Chrome 插件去快速获取,但有时获取到的复杂元素定位会很长或者层级很多,稳定性差,这时候往往需要我们自行选择最优的定位方式
image.png
三、轴定位
轴定位实际上是xpth定位的一种,也是利用元素的层级对指定元素进行定位,往往可以结合一般定位方式帮我们定位复杂元素
1、轴运算名称
- ancestor:祖先结点(包括父结点)
- parent:父结点
- preceding:当前元素节点标签之前的所有结点(html页面先后顺序)
- preceding-sibling:当前元素结点标签之前的所有兄弟结点(同级)
- following:当前元素结点标签之后的所有节点(html页面先后顺序)
- following-sibling:当前元素结点标签之后的所有兄弟结点(同级)
二、使用方法
轴名称::结点名称
举例说明:
如下图,如何通过①来定位到②呢?
image.png
分析:
元素①和元素②的关系:它们的父辈为兄弟关系
元素②位于元素①之后,选取轴运算名称为follow-sibling
元素①要先往父结点定位,选取轴运算名称为parent
得出定位表达式为:
//div[text()=' 服务端']/parent::div/following-sibling::div//div[text()=' 数据库']
image.png
四、CSS Selector
CSS Selector 是利用 CSS 选择器来定位元素,相比 Xpath,语法更简洁,元素定位速度更快一点。
常见的选择器包含:class、id 两种,使用方式如下
# 利用元素class来定位
driver.find_element_by_css_selector(".element_class")
# 利用元素id来定位
driver.find_element_by_css_selector("#element_id")
和 Xpath 一样,CSS Selector 元素没有任何可用的属性值时,可以使用 层级关系先定位 到父元素标签,然后再找到自己。
# 利用元素层级关系进行定位
driver.find_element_by_css_selector("parent_div > target_element_div")
属性定位:在 CSS Selector 中也很常见,使用方式如下:
# 属性定位
driver.find_element_by_css_selector('[属性名=属性值]')
需要注意的是,属性定位必须确保在当前页面内,这个属性具有唯一性。
组合定位:将上面的定位方式结合在一起,即可以加强元素的唯一性,精准快速地定位到元素标签。
# 组合定位
# 父元素:parent_div,class = parent_class
# 目标元素:targent_div,id = targent_id
driver.find_element_by_css_selector("parent_div.parent_class > targent_div#targent_id")
五、其他方式
上面的元素定位方式都很常用,下面这些定位方式几乎用不到,包含:
Tag 定位:利用 Tag 标签名去定位,一般网页中都会包含多个 Tag,所以利用 Tag 去元素定位不实用
# Tag定位,比如:tag为input
element_by_input_tag = driver.find_element_by_tag_name("input")
partial link 定位:相比 link 定位,相当于 a 标签内容局部匹配,只要包含待匹配的内容,即使要查找的元素。
# 比如:
# <a href="http://www.baidu.com">百度一下</a>
# 使用 partial link 来定位来定位
driver.find_element_by_link_text("百度")
六、 By + elements
Selenium 提供的查找方法还提供了另外一种形式,即通过:By( 定位方式,定位内容值 )
实际上,对自动化做 Page Object 设计 的时候,一般都会用 By 的方式来封装代码,更易于我们维护代码。
使用方式如下:
# 1、导入依赖类
from selenium.webdriver.common.by import By
# 2、使用
driver.find_element(By.ID, "element_id")
driver.find_element(By.NAME, "element_name")
driver.find_element(By.CLASS_NAME, "element_class_name")
driver.find_element(By.TAG_NAME, "element_tag_name")
driver.find_element(By.LINK_TEXT, "element_link_text")
driver.find_element(By.PARTIAL_LINK_TEXT, "element_partial_link_text")
driver.find_element(By.XPATH, "//*[@class='element_xpath']")
driver.find_element(By.CSS_SELECTOR, "element_css_selector")
上面查找元素的方法都是针对单个元素标签,如果要查找匹配多个元素,只需要将 element 改成 elements 即可。
# 单个元素
driver.find_element(By.ID, "element_id")
# 多个元素
driver.find_elements(By.ID, "element_id")