webdriver元素定位的八种常用方法
id、name、class name、tag、link text、partial link text、xpath、css selector
一、id,name,class name
HTML示例1:
<input id="search" type="text" name="q" value="" class="input-text" maxlength="128" />
定位方法:
find_element_by_id(‘search’)
find_element_by_name(‘q’)
find_element_by_class_name(‘input-text’)
二、tag_name
HTML示例2:
<ul class="promos">
<li>
<a href="http://demo.magentocommerce.com/home-decor.html">
<img src="/media/wysiwyg/homepage-three-column-promo-
01B.png" alt="Physical & Virtual Gift Cards">
</a>
</li>
<li>
<a href="http://demo.magentocommerce.com/vip.html">
<img src="/media/wysiwyg/homepage-three-column-promo-
02.png" alt="Shop Private Sales - Members Only">
</a>
</li>
<li>
<a href="http://demo.magentocommerce.com/accessories/
bags-luggage.html">
<img src="/media/wysiwyg/homepage-three-columnpromo-
03.png" alt="Travel Gear for Every Occasion">
</a>
</li>
</ul>
定位方法:
该方法可以通过元素的标签名称来查找元素。
这个方法搜索到的元素通常不止一个,所以一般建议结合使用findElements方法来使用。
banner_list = self.driver.find_element_by_class_name(“promos”)
banners = banner_list.find_elements_by_tag_name(“img”)
先找到父类,即ul标签,再找到子类所有含有img标签的元素
方法二:
banner_list = self.driver.find_element_by_class_name(“promos”)
banners = banner_list.find_elements_by_tag_name(“img”)[1]
先找到父类,即ul标签,再找到子类所有含有img标签的元素,并且定位到第二个img标签
三、link_text,partial_link_text
HTML示例3:
<a href="#header-account" class="skip-link skip-account">
<span class="icon"></span>
<span class="label">Account</span>
</a>
定位方法:
通过超文本链接上的文字信息来定位元素,这种方式一般专门用于定位页面上的超文本链接
account_link = self.driver.find_element_by_link_text(“Account”)
partial_link_text是link_text的扩展。当你不能准确知道超链接上的文本信息或者只想通过一些关键字进行匹配时,可以使用这个方法来通过部分链接文字进行匹配。
四、Xpath
XPath是XML Path的简称,由于HTML文档本身就是一个标准的XML页面,所以我们可以使用XPath的语法来定位页面元素。
HTML示例4:
<html>
<body>
<form id="loginForm">
<input name="username" type="text" />
<input name="password" type="password" />
<input name="continue" type="submit" value="Login" />
<input name="continue" type="button" value="Clear" />
</form>
</body>
<html>
绝对路径的引用写法:
引用页面上的form元素(即源码中的第3行):/html/body/form[1]
注意:
1)元素的xpath绝对路径可通过firebug直接查询。
2)一般不推荐使用绝对路径的写法,因为一旦页面结构发生变化,该路径也随之失效,必须重新写。
3)绝对路径以单/号表示
相对路径的引用写法:
- 查找页面根元素://
- 查找页面上所有的input元素://input
- 查找页面上第一个form元素内的直接子input元素(即只包括form元素的下一级input元素,使用绝 对路径表示,单/号)://form[1]/input
- 查找页面上第一个form元素内的所有子input元素(只要在form元素内的input都算,不管还嵌套了多少个其他标签,使用相对路径表示,双//号)://form[1]//input
- 查找页面上第一个form元素://form[1]
- 查找页面上id为loginForm的form元素://form[@id=‘loginForm’]
- 查找页面上具有name属性为username的input元素://input[@name=‘username’]
- 查找页面上id为loginForm的form元素下的第一个input元素://form[@id=‘loginForm’]/input[1]
- 查找页面具有name属性为contiune并且type属性为button的input元素://input[@name=‘continue’][@type=‘button’]
- 查找页面上id为loginForm的form元素下第4个input元素://form[@id=‘loginForm’]/input[4]
ps:
当xpath的路径以/开头时,表示让Xpath解析引擎从文档的根节点开始解析。
当xpath路径以//开头时,则表示让xpath引擎从文档的任意符合的元素节点开始进行解析。
当/出现在xpath路径中时,则表示寻找父节点的直接子节点,
当//出现在xpath路径中时,表示寻找父节点下任意符合条件的子节点,不管嵌套了多少层级。
前面讲的都是xpath中基于准确元素属性的定位,其实xpath作为定位神器也可以用于模糊匹配。比如下面图所示代码:
<a rel="nofollow" href="http://localhost/phpwind/index.php?m=u&c=login&a=logput">
<em class="icon_quit"></em>
退出
</a>
a. 用contains关键字,定位代码如下:
1 driver.findElement(By.xpath(“//a[contains(@href, ‘logout’)]”));
这句话的意思是寻找页面中href属性值包含有logout这个单词的所有a元素,由于这个退出按钮的href属性里肯定会包含logout,所以这种方式是可行的,也会经常用到。其中@后面可以跟该元素任意的属性名。
b. 用start-with关键字,定位代码如下:
1 driver.findElement(By.xpath(“//a[starts-with(@rel, ‘nofo’)]));
这句的意思是寻找rel属性以nofo开头的a元素。其中@后面的rel可以替换成元素的任意其他属性。
c. 用Text关键字,定位代码如下:
1 driver.findElement(By.xpath(“//*[text()=’退出’]));
这个方法可谓相当霸气啊。直接查找页面当中所有的退出二字,根本就不用知道它是个a元素了。这种方法也经常用于纯文字的查找。
最后,关于xpath这种定位方式,webdriver会将整个页面的所有元素进行扫描以定位我们所需要的元素,所以这是一个非常费时的操作,如果你的脚本中大量使用xpath做元素定位的话,将导致你的脚本执行速度大大降低,所以请慎用。
五、css_selector
常见符号:
"#"表示 id选择器
"."表示 class选择器
">"表示子元素,层级
一个空格也表示子元素,但是是所有的后代子元素,相当于 xpath 中的相对路径
1、css:属性定位
1)css可以通过元素的id、class、标签这三个常规属性直接定位到
2)如下是百度输入框的的html代码:
<input id="kw" class="s_ipt" type="text" autocomplete="off" maxlength="100" name="wd"/>
3)css用#号表示id属性,如:#kw
4)css用.表示class属性,如:.s_ipt
5)css直接用标签名称,无任何标示符,如:input
2、css:其它属性
1)css除了可以通过tag、class、id这三个常规属性定位外,也可以通过其它属性定位
2)以下是定位其它属性的格式
[class=“bv-no-focus-ring”] [name=“example-input-1”]
ps:中间带空格表示层级,子元素;说白了其他属性可以用[property=value]的方式来定位,当然id和class同样可以用[property=value]定位
3、css:标签
css页可以通过标签与属性的组合来定位元素
input.s_ipt
input#kw
input[id=‘kw’]
4、css:层级关系
div.el-table__body-wrapper > table.el-table__body > tbody > tr:nth-child(1) > td:nth-child(2)
上述exp也可以写成:
div.el-table__body-wrapper table.el-table__body tbody tr:nth-child(1) td:nth-child(2)
5、css:索引
css也可以通过索引nth-child(1)来定位子元素,直接翻译过来就是第几个小孩
总结:选择标签后,找第几个小孩即可
第四点中,tr:nth-child(1)表示选择第一个tr标签
nth-child和nth-of-type的区别:
nth-of-type是取当前元素的兄弟元素的第n个,
nth-child取的是当前元素的第n个节点的当前元素
ele:nth-of-type(n)是指父元素下第n个ele元素,
而ele:nth-child(n)是指父元素下第n个元素且这个元素为ele,若不是,则选择失败。
6、css:逻辑运算
css同样也可以实现逻辑运算,同时匹配两个属性,这里跟xpath不一样,无需写and关键字
[type=‘checkbox’][name=‘checkbox1’]
六、xpath和css定位比较
- Xpath能通过子元素搜索父元素, Css无法实现,Css只能从父级往下级搜索
- Xpath能按文本搜索元素,Css不能
- Css比Xpath更简单易读,执行速度更快
定位方式 | xpath | CSS | |
---|---|---|---|
常规属性 | id | //*[@id=‘kw’] | #kw |
class | //input[@class=‘s_ipt’] | .s_ipt | |
name | //input[@name=‘wd’] | [name=‘wd’] | |
其他属性 | 其他属性 | ||
多个属性组合(逻辑运算) | //input[@autocomplete=‘off’] | [autocomplete=‘off’] | |
//input[@type='text’and @name=‘wd’] | [type=‘text’][name=‘wd’] | ||
文本属性 | //*[text()=‘文本内容’] | ||
层级关系 | 相对路径 | //form[@id='form]/span/input | form#form>span>input |
索引 | //select[@id=‘nr’]/option[3] | select#nr>option:nth-child(3) | |
select#nr>option:eq(2) | |||
select#nr>option:first | |||
select#nr>option:last | |||
通过儿子找父亲 | 两个点代表父级 | //*[@id=’’]/…/… | |
模糊匹配 | 模糊匹配text | //*[contains(text(),‘糯米’)] | |
模糊匹配某个属性 | //*[contains(@class,‘s_ip’)] | ||
模糊匹配以xx开头 | //*[starts-with(@id,‘xx’)] |
最后再总结一下,各种方式在选择的时候应该怎么选择:
- 当页面元素有id属性时,最好尽量用id来定位。但由于现实项目中很多程序员其实写的代码并不规范,会缺少很多标准属性,这时就只有选择其他定位方法
- xpath很强悍,但定位性能不是很好,所以还是尽量少用。如果确实少数元素不好定位,可以选择xpath或cssSelector
- 当要定位一组元素相同元素时,可以考虑用tagName或name
- 当有链接需要定位时,可以考虑linkText或partialLinkText方式