Selenium 系列篇(二):元素定位
1. 元素定位的重要性
无论是做自动化测试,还是爬虫,页面元素定位 永远都是第一步,在没有定位到网页元素之前,任何自动化操作都没法进行。
Selenium WebDriver API 中提供了大量的方法帮助我们进行元素定位。
2. 常用方式
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")
3. Xpath
Xpath在 XML 文档中本身是一种元素定位语言,而 HTML 是 XML 是另外一种实现,在元素定位的时候会遍历页面的所有元素,所以查询效率不高。
Selenium 中 Xpath 定位方式包含:绝对路径定位、属性定位、元素关系定位、运算符、匹配等。
绝对路径定位:相当于从最顶部的 html 元素标签往子标签追加,一直定位到目标元素标签,这种方式不常用。
driver.find_element_by_xpath('/html/body/div/.../div/目标元素')
实际上在做 App 端自动化 的时候,Appium / Airtest 元素定位的时候,某些元素没有任何属性和可用的层级关系定位方式,这时候借助绝对定位是唯一的选择。
属性定位:对应网页元素标签的任意属性,只要能唯一标识目标元素即可。
属性定位很简单,可以显式的指定目标元素的标签名或用 * 号匹配任意标签名,使用格式是:'//元素标签[@属性名="属性值"]'
# 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")
运算符定位:页面可能多个元素包含同一个属性,这时候可以使用逻辑元素符 and 连接多个属性来定位元素标签。
# 通过多个属性值来唯一定位元素标签
driver.find_element_by_xpath('//div[@属性1="属性1的值" and @属性2="属性2的值"]')
匹配定位:匹配定位平常使用不多,主要是利用属性中包含某个字符串来定位元素标签,包含:contains、starts_with
# 匹配定位
# class属性值中包含:class
driver.find_element_by_xpath('//div[contains(@class,"part_str")]')
# class属性值以part_start开头
//input[starts-with(@class,'part_start')]
实际上,网页元素标签的 Xpath 表达式可以使用 Chrome 右键属性或者 Xpath Chrome 插件去快速获取。
4. 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")
5. 不常用方式
上面的元素定位方式都很常用,下面这些定位方式几乎用不到,包含:
Tag 定位:利用 Tag 标签名去定位,一般网页中都会包含多个 Tag,所以利用 Tag 去元素定位不实用。
# Tag定位,比如:tag为input
element_by_input_tag = driver.find_element_by_tag_name("input")
link 定位:link 定位是针对 a 标签中的文本匹配。
由于很多网页元素都是动态变化的,文本匹配经常需要修改,所以灵活性不高,很少使用。
# 比如:
# <a href="http://www.baidu.com">百度一下</a>
# 使用link来定位
driver.find_element_by_link_text("百度一下")
partial link 定位:相比 link 定位,相当于 a 标签内容局部匹配,只要包含待匹配的内容,即使要查找的元素。
# 比如:
# <a href="http://www.baidu.com">百度一下</a>
# 使用 partial link 来定位来定位
driver.find_element_by_link_text("百度")
6. 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")
Selenium 元素定位的内容差不多就这些了,下一篇将聊聊 Selenium 具体应用场景的使用方式。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 一个简单的C语言测试框架
- Let's Encrypt实践指北
- MassTransit Get Started->
- 一次性把所有普通和经典的网页布局讲得通通透透的,多图预警,建议收藏
- Github标星 8K+,免费又好用的Redis客户端工具!
- Python判断字符串是否包含特定子串的7种方法
- 用后台开发的逻辑理念学习VUE
- 进程管理-Linux每日一练(6)
- AkShare-能源数据-碳排放-国际行情
- Linux 【Shell脚本经典案例】
- 【Vulnhub】SecTalks: BNE0x00 - Minotaur
- Spring Boot扩展机制 - Spring Factories
- Google Analytics上实施透明度和用户意见征求框架
- 浅析鸿蒙 JavaScript GUI 技术栈
- C#串口操作类,包括串口读写操作