Selenium系列(2)- 定位方式详解
定位方式
以我们万能的百度页面为例来展开!
ID
# 找到搜索框
inputele = driver.find_element_by_id("kw")
⏰ ATTENTION:一般来说,ID是唯一的(但是不排除这种情况——开发写代码的时候不规范🤣)
CLASS
# 通过class查找元素,返回匹配到的第一个元素
# 搜索框
inputele = driver.find_element_by_class_name("s_ipt")
# 假如页面上存在多个class为s_ipt的元素则可用以下方式
input_list = driver.find_elements_by_class_name("s_ipt")
for i in input_list:
print(i)
⏰ ATTENTION:
- 一般而言,class不唯一
find_element_by_class_name只返回匹配到的第一个class元素,找不到元素会报错find_elements_by_class_name返回所有匹配到的元素列表,找不到元素会返回一个空列表
NAME
# 通过name查找元素
# 搜索框
inputele = driver.find_element_by_name("wd")
# 若页面存在多个name相同的元素则可用以下方式
input_list = driver.find_elements_by_name("wd")
for i in input_list:
print(i)
⏰ ATTENTION:
- name方式与class定位方式类似,不赘述
LINK_TEXT
# 用于定位文本链接
# 例如定位百度页面的新闻链接
driver.find_element_by_link_text('新闻')
⏰ ATTENTION:
- 用于定位文本链接
- 相当于超链接文本完全匹配
PARTIAL_LINK_TEXT
# 通过partial_link定位"新闻"这个链接
driver.find_element_by_partial_link_text('闻')
⏰ ATTENTION:
- 超链接很长时,可用partial_link定位方式
- 相当于超链接文本模糊匹配
XPATH
xpath全称是XML Path Language,用于解析html与xml,由于xpath定位方式是从头到尾遍历页面,所以速度较慢,下面介绍一下xpath比较常用的一些定位方式
那么在了解xpaht之前,我们先看一下xpath常见表达式以及通配符的含义
通配符:
-
nodename选取此节点的所有子节点 -
/当前节点的子元素 -
//从匹配选择的当前节点选择文档中的节点,不考虑位置(从任何地方选取);也可代表当前节点下的子孙元素 -
.选取当前节点 -
..选取当前节点的父节点 -
@选取属性
常用表达式:
# 选取属于bookstore子元素的第一个book元素
/bookstore/book[1]
#选取属于bookstore子元素的最后一个book元素
/bookstore/book[last()]
# 选取属于bookstore子元素的倒数第二个book元素
/bookstore/book[last()-1]
# 选取最前面的两个属于bookstore元素的子元素的book元素
/bookstore/book[position()<3]
# 选取所有title元素,且这些元素拥有值为eng的lang元素
//title[@lang='eng']
# 选取bookstore元素的所有book元素,且其中的price元素值大于35.5
/bookstore/book[price>35.5]
# 选取bookstore元素中的book元素的所有title元素,且其中的price元素值大于35.5
/bookstore/book[price>35.5]/title
了解了上述基本内容之后,我们来看下xpath几种常用的方法👇👇👇
绝对路径定位
将xpath表达式从HTML的最外层节点,逐层填写,最后定位到操作元素
# 例如百度页面的“百度一下”按钮,绝对路径的xpath为:
xpath = "/html/body/div[1]/div[2]/div[5]/div[1]/div/form/span[2]/input"
driver.find_element_by_xpath(xpath)
特点:一旦路径变化,会导致定位失败,不推荐
相对路径定位
给出元素路径的部分信息,在HTML的任意层次中寻找符合条件的元素
# 例如百度页面的“百度一下”按钮,相对路径的xpath为:
xpath = '//*[@id="su"]'
driver.find_element_by_xpath(xpath)
特点:相对路径提取的是元素的部分特征,可结合其他的属性共同定位,方式较灵活
索引定位
语法://标签名[下标值] ,索引的初始值为1
# 第二个子元素的div元素
xpath = '//div[2]'
# 父元素为div的第二个子元素,不区分类型
xpath = '//div/*[2]'
# 某类型倒数第几个子元素
xpath = '//div[last()]' # 定位到div类型最后一个元素
xpath = '//div[last()-1]'
xpath = '//div[last()-n]'
# 范围选择
xpath = '//ul/li[position()<=2]' # 定位ul类型下前两个li元素
xpath = '//ul/li[position()>=last()-1]' # 定位ul类型下的最后2个li元素
属性值定位
元素中比较常见的属性有id、name、class等,若没有这些常用的属性值,也可以查找元素中有其他唯一标识的属性,用@ 选取元素
<!-- 百度搜索输入框 -->
<input type="text" class="s_ipt" name="wd" id="kw" maxlength="100" autocomplete="off">
# 百度的输入框属性有class、name、id,可以通过属性值定位输入框
xpath1 = '//*[@class="s_ipt"]'
xpath2 = '//*[@name="wd"]'
xpath3 = '//*[@id="kw"]'
逻辑运算
xpath支持逻辑运算符and与or
<!-- 还是以百度搜索框为例 -->
<input type="text" class="s_ipt" name="wd" id="kw" maxlength="100" autocomplete="off">
# 通过逻辑运算符,可定位到输入框
xpath1 = '//*[@name="wd" and @id="kw"]'
特点:多个属性值联合定位,可以使定位更加准确;对于存在多个相同标签的元素,如果存在不同的属性值,也可以用这个方式区别开来
属性值匹配
start-with() :属性值以XX开头
ends-with():属性值以XX结尾
contains() :属性值包含
<!-- 例如 -->
<input type="text" class="s_ipt" name="wd ipt er" id="kw" maxlength="100" autocomplete="off">
xpath1 = '//input[starts-with(@name,"wd")]'
xpath2 = '//input[ends-with(@id,"er")]'
xpath3 = '//input[contains(@id,"ipt")]'
# 任意匹配
xpath4 = '//input[@*="s_ipt"]'
特点:可以用来定位属性值不太规律/存在部分变动/属性中间有空格的情况
⏰ ATTENTION:
- 如果属性值中间包含空格,Webdriver定位的时候容易出错,有时定位不到,可以使用属性值匹配的方式去定位元素
- 属性任意值匹配相当于模糊查询,只要目标元素中任意属性值匹配成功就能定位成功,但要注意这个元素值在页面中的唯一性
那么以上,就是xpath常用的一些定位方式,以上这些,基本能解决工作中大部分的元素定位问题;当日还有其他的一些函数定位啦、轴定位啦等等,由于这些我本人在工作中比较少用,所以就没有写到这里面,感兴趣的盆友可以自行了解凹~
CSS_SELECTOR
老规矩,我们还是先来了解一下css_selector的基本语法,然鹅我CSS用得还不是很⑥, O_O...(先记下来,方便以后查找)
. 代表class;.intro 选择class="intro"的所有元素
# 代表ID
* 代表选择所有元素;
element 代表选择所有element元素;p 选择所有
元素
element1,element2代表选择所有element1元素和所有element2元素;例如div,p
element1 emelent2代表选择element1内部的所有element2元素;例如div p
element1>element2选择父元素为element1的所有element2元素;例如div>p
element1+element2选择紧接在element1元素之后的所有element2元素;例如div+p
单一属性定位
css_selector定位方式与xpath类似,也可通过元素的属性来定位
通过类型
# 通过类型
driver.find_element_by_css_selector('input')
通过ID
# 通过ID
driver.find_element_by_css_selector('#kw')
通过class
# 通过class
driver.find_element_by_css_selector('.s_ipt')
其他属性
# 其他属性
driver.find_element_by_css_selector("[name='wd']")
driver.find_element_by_css_selector("[type='text']")
组合属性定位
ID组合属性
# ID组合属性
driver.find_element_by_css_selector("input#kw")
CLASS组合属性
# class组合属性
driver.find_element_by_css_selector("input.s_ipt")
其他属性组合
# 其他属性组合定位
driver.find_element_by_css_selector("input[name='wd']")
# 其他的两个属性组合
driver.find_element_by_css_selector("[name='wd'][type='text']")
模糊匹配属性值
<!-- 以百度首页搜索按钮为例 -->
<input type="submit" value="百度一下" id="su" class="btn self-btn bg s_btn">
~=匹配属性值包含XX(属性值中有空格)
driver.find_element_by_css_selector("input[class~='btn']")
^=匹配属性值以XX开头
driver.find_element_by_css_selector("input[class^='btn']")
$=匹配属性值以XX结尾
driver.find_element_by_css_selector("input[class$='btn']")
*=匹配包含XX属性的值
driver.find_element_by_css_selector("input[*='百度一下']")
层级定位
element1>element2
element1下的element2元素
# 定位百度首页的输入框
driver.find_element_by_css_selector("span#s_kw_wrap>input")
父子兄弟节点定位
element:nth-child(n)第几个element标签
element:nth-last-child(n)倒数第几个element标签
element:first-child第一个element标签
element:last-child最后一个element标签
element:only-child唯一的element标签

# 定位百度首页的新闻超链接
driver.find_element_by_css_selector("#s-top-left>a:nth-child(1)")
总结
推荐定位方式优先级
- 优先级最高:ID
- 优先级其次:name
- 优先级再次:CSS selector
- 优先级再次:Xpath
CSS优先于xpath的原因:
- CSS配合HTML,原理是匹配对象;xpath配合XML,原理是遍历,css的性能更加优秀
- CSS语法比Xpath简洁
- 前端用CSS
⏰ ATTENTION:
- 定位的时候,要找元素的唯一属性
- 如果元素没有唯一属性,可以先找到能被定位到具有唯一属性的父/子/兄弟等等的元素,再进行辅助定位
- 千万不用用随机的唯一属性定位!!!!o(╥﹏╥)o
- 最重要的是,跟开发沟通,让开发大佬们把元素加上唯一的name或者ID🤣🤣🤣

浙公网安备 33010602011771号