Selenium的元素八大定位详解
老鸟有兴趣可以移步Selenium元素定位神器工具谷歌浏览器插件-SelectorsHub介绍、安装和使用
目录
- Selenium的元素八大定位详解
- 1.id定位
- 2.name定位
- 3.tagname定位
- 4.css定位,目前用的不多,建议直接浏览器鼠标右键copy
- 5.classname定位
- 6.linkText定位,即使用超链接的文本内容定位
- 7.partialLinkText定位,即使用超链接的部分文本内容定位
- 8.xpath定位,即路径定位.可以定位到99%的元素
- 提高元素定位复用率/降低定位维护率的办法.
1.id定位
例如
java写法是
driver.findElement(By.id("su")});
浏览器中的定位写法是#开头直接输入id值,一般而言id值是唯一的.
#header_index
2.name定位
java写法是
driver.findElement(By.name("loginnum"))
浏览器中的定位写法同下面的xpath写法
3.tagname定位
例如
java写法是
driver.findElement(By.tagName("s_top_wrap"));
浏览器中的定位写法同下面的xpath写法
4.css定位,目前用的不多,建议直接浏览器鼠标右键copy
5.classname定位
例如
java的写法是
driver.findElement(By.className("btn self-btn bg s_btn"));
浏览器中的定位写法同下面的xpath写法
6.linkText定位,即使用超链接的文本内容定位
例如
java的写法是
driver.findElement(By.linkText("设为首页"));
浏览器中的定位写法同下面的xpath写法
7.partialLinkText定位,即使用超链接的部分文本内容定位
例如
driver.findElement(By.partialLinkText("为首页"));
8.xpath定位,即路径定位.可以定位到99%的元素
所有的定位的写法也支持单引号,比如 //*[text()='基础信息'and@class='text']
方法一:直接copy相对路径
这种简单省事但是有时候定位不准,因为有的路径的属性是动态的…
例如
driver.findElement(By.xpath("//*[@id=\"su\"]"));
方法二:copy绝对路径
省事,但是路径很长,且容易受前端页面改动影响
例如
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[5]/div/div/form/span[2]/input"));
方法三:根据文本信息定位
写法是
//*[text()="设置"]
*代表模糊匹配; //代表相对定位
也可以这样写
//span[text()="设置"]
例如
driver.findElement(By.xpath("//span[text()=\"设置\"]"));
方法四:部分信息匹配
contains写法-匹配包含xxx信息的元素
//a[contains(text(),"123")]
或者
//*[contains(text(),"o123")]
关于contains的用法这里多写几个例子供参考
//div[contains(@class,'s_form_wrapper soutu-env-nomac')]
//form[contains(@id,'for')]
//a[contains(text(),'使用百度前')]
方法五:元素属性定位
//*[@id="su"]
或者
//input[@id="su"]
方法六:根据元素的多个属性定位.
//input[@id="su" and @value="百度一下"]
或者这样写,这种写法较为通用;
//并且关系
//input[@id="su"][@value="百度一下"]
一些其他的写法
//或者关系
//input[@id="su" or @value="百度一下"]
//模糊和或者关系
//*[@id="su" or @value="百度一下"]
//input[@*="su" or @*="百度一下"]
//取反关系
//input[@id="su"][not(@value="百度三下")]
引用属性值
//引用属性值
//div[@id='order_BomVersionmain']//ul[@class='pagination em-pagination']//a[@pagenum][text()=@pagenum]
方法七:根据父子/相邻节点定位(在同一大层级下)
此方法适合解决难定位的元素;
<<<<<<<<<<<<<<<<<<<<<2020-12-18-更新-开始<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
也是实际项目中常用的,建议优先找到唯一的父亲分区然后在通过父子定位;唯一的父亲分区是指例如下图所示;所以在开始写定位时最好先熟悉下当前被测项目的前端页面的dom结构;这点之前没有提及现在补充
这种定位是比较可靠的定位方式;不易受前端改动的影响;
<<<<<<<<<<<<<<<<<<<<<2020-12-18-更新-结束<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
存在路径的层级关系的可以使用相邻节点定位
父子定位
//*[@class="bg s_btn_wr"]/input
或者
//span[@class="bg s_btn_wr"]/input
或者
//span[@class="bg s_btn_wr"]/input[@class="bg s_btn"]
- 如何有儿子元素定位到父亲元素
//div[@class='tbody-body']/../../..
或者
通过儿子tr匹配到父亲tr在匹配到孙子th,使用父子定位仍然可以加属性.
相邻定位
//div[@class="s-bottom-layer-left"]//a[text()="使用百度前必读"]
或者
//div[@class="s-bottom-layer-left"]//a[contains(text(),"度前必读")]
或者
//*[@class="s-bottom-layer-left"]//*[contains(text(),"度前必读")]
或者
//form[@id='signin-N']//button[@class='btn']
或者多个元素组合,下图演示的是三个元素相邻定位
//div//p//a[contains(text(),'使用百度前')]
xpath轴定位写法
轴定位写法有以下关键字:
parent,child,ancestor,descendant,following,following-sibling,preceding,preceding-sibling
parent:选取当前节点的父节点
//div[@id='header_index']/parent::div
child:选取当前节点的所有子元素
//div[@id='wrapper']/child::div
拓展写法
//div[@id='wrapper']/child::div[@id='sidebar']
ancestor:选取当前节点的所有先辈(父、祖父等)
//a[@title="HTML 参考手册"]/ancestor::div
拓展写法
//a[@title="HTML 参考手册"]/ancestor::div[@id='wrapper']
descendant:选取当前节点的所有后代元素(子、孙等)
//div[@id='wrapper']/descendant::div
等同于 xpath中的//
following:选取文档中当前节点的结束标签之后的所有节点
//div[@id='header_index']/following::a
following-sibling:选取文档中当前节点的结束标签之后的所有同级节点
//meta[@name='author']/following-sibling::link
拓展写法
//meta[@name='author']/following-sibling::link[@rel='apple-touch-icon-precomposed']
preceding:选取文档中当前节点的开始标签之前的所有节点
//meta[@name='author']/preceding::script
拓展写法
//meta[@name='author']/preceding::script[@type="text/javascript"]
preceding-sibling:选取当前节点之前的所有同级节点
//input[@value='Go']/preceding-sibling::input
拓展写法
//input[@value='Go']/preceding-sibling::input[@type="hidden"]
Xpath函数
contains()-包含关系
//input[contains(@value,'百度')]
text()-获取元素文本值
//a[contains(text(),'hao1')]
starts-with()-匹配xxx内容开头的元素
//a[starts-with(text(),'hao1')]
//a[starts-with(@title,'w3sch')]
ends-with()-匹配xxx内容结尾的元素
//a[ends-with(@title, '在线教程')]
但是由于这个写法是xpath2.0写法,有些浏览器不支持.截止到2021年9月2日 edge和chrome不支持
substring()-截取部分内容来匹配
索引是从0开始索引长度-3即可;
//a[substring(@title, string-length(@title) - 3) = '在线教程']
高级一点的写法,条件是:截取部分内容包含xxx
//td[contains(substring(@class, string-length(@class) - 7) ,'mwnums') ]
not()-否定关系
//div[@class='hgbeOc']//span[not(text()='文档')]
or()-或者关系
//div[@class='hgbeOc']//span[not(text()='文档') or @jsname='j' ]
normalize-space() 去掉前后的空格
这里清除文本的前后的空格也可以清楚其他属性的值的前后空格
//div[@class='hgbeOc']//span[normalize-space(text())='文字']
position() 返回当前节点在其兄弟节点中的位置
position() 函数用于返回当前节点在其兄弟节点中的位置(从 1 开始计数)
not(self::input) 用于选择所有非 input 元素
//*[not(self::input)] 是 XPath 表达式,用于选择所有非 input 元素。
//*:选择所有元素。
[not(self::input)]:条件筛选,排除 input 元素。当然也可排除其他类型的元素。
这在需要排除特定类型元素时非常有用。
示例
local-name 会返回所有属性的名称
要匹配属性名称以特定字符串开头(例如 xx
)的元素,你可以使用 XPath 选择器结合一些逻辑。虽然 XPath 1.0 并没有直接支持匹配属性名称的能力,但通过使用 local-name()
函数,我们可以间接实现这一点。
下面是一个匹配具有以 xx
开头的属性名称的 <font>
元素的 XPath 示例:
//font[count(@*) > 0 and starts-with(local-name(@*), 'xx')]
这段 XPath 的意思是选取所有 <font>
元素,这些元素至少有一个属性,并且至少有一个属性名称是以 xx
开头的。
注意
count(@*) > 0
确保<font>
元素有属性。local-name(@*)
会返回所有属性的名称,与starts-with
结合使用可以检查属性名称是否以xx
开头。
更多Xpath教程(函数,轴…)信息看这里
提高元素定位复用率/降低定位维护率的办法.
以下图为例:
如图所示,直接用name貌似就可以了,但是如果稍作修改例如此时增加一个元素和此元素的name相同.或者其他的一些情况导致同一网页下有多个此同name的元素.
为了提前防止此类事件的影响,我们在写定位的时候建议优先使用xpath定位,并且使用相对路径定位这样的元素组合定位.比如此时稍作更改上图的定位.
这里使用父节点和子节点的相对路径定位,就能较大程度的避免元素定位被重复进而提高其可靠性.