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定位方式类似,不赘述
# 用于定位文本链接
# 例如定位百度页面的新闻链接
driver.find_element_by_link_text('新闻')

ATTENTION

  • 用于定位文本链接
  • 相当于超链接文本完全匹配
# 通过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🤣🤣🤣
posted @ 2021-10-08 21:35  莫伊101  阅读(136)  评论(0)    收藏  举报