Selenium元素定位八种常用方法
http://www.cnblogs.com/qingchunjun/p/4208159.html
1)By.name()
WebElement comfirm = driver.findElement(By.name(“OK”));
2)By.id()
WebElement comfirm = driver.findElement(By.id(“su”));
3)By.tagName()
例:<button type=”button” class=”JS-trigger-click-sure”>确 定</button>
List<WebElement> buttons = driver.findElements(By.tagName(“button”));
System.out.println(buttons.size()); //打印出有多少个button
WebElement confirm = buttons.get(1); //取第2个button
另外在使用tagName方法进行定位时,通常有些HTML元素的tagName是相同的。例如下表中单选框、复选框、文本框和密码框的元素标签都是input,单靠tagName无法准确定位,要结合type属性才能过滤出来。
public class SearchElementsByTagName{
public static void main(String[] args){
WebDriver driver = new FirefoxDriver();
driver.get("http://www.forexample.com");
List<WebElement> allInputs = driver.findElements(By.tagName("input"));
//只打印所有文本框的值
for(WebElement e: allInputs){
if (e.getAttribute(“type”).equals(“text”)){
System.out.println(e.getText().toString()); //打印出每个文本框里的值
}
}
}
}
4)By.className()
className属性是利用元素的css样式表所引用的伪类名称来进行元素查找的方法。对于任何HTML页面的元素来说,一般程序员或页面设计师会给元素直接赋予一个样式属性或者利用css文件里的伪类来定义元素样式,使元素在页面上显示时能够更加美观。一般css样式表可能会长成下面这个样子:
.buttonStyle{
width: 50px;
height: 50px;
border-radius: 50%;
margin: 0% 2%;
}
定义好后,就可以在页面元素中引用上述定义好的样式,如下:
<button name="sampleBtnName" id="sampleBtnId" class="buttonStyle">I'm Button</button>
如果此时我们要通过className属性来查找该button并操作它的话,代码如下:
public class SearchElementsByClassName{
public static void main(String[] args){
WebDriver driver = new FirefoxDriver();
driver.get("http://www.forexample.com");
WebElement searchBox = driver.findElement(By.className("buttonStyle"));
searchBox.sendKeys("Hello, world");
}
}
注意:使用className来进行元素定位时,有时会碰到一个元素指定了若干个class属性值的“复合样式”的情况,如下面这个button:
<button id="J_sidebar_login" class="btn btn_big btn_submit" type="submit">登录</button>
这个button元素指定了三个不同的css伪类名作为它的样式属性值,此时就必须结合后面要介绍的cssSelector方法来定位了,稍后会有详细例子。
5)By.linkText()
通过超文本链接上的文字信息来定位元素,这种方式一般专门用于定位页面上的超文本链接。
<a href="/intl/en/about.html">About Google</a>
public class SearchElementsByLinkText{
public static void main(String[] args){
WebDriver driver = new FirefoxDriver();
driver.get("http://www.forexample.com");
WebElement aboutLink = driver.findElement(By.linkText("About Google"));
aboutLink.click();
}
}
6)By.partialLinkText()
这个方法是By.linkText()的扩展。当不能准确知道超链接上的文本信息或者只想通过一些关键字进行匹配时,可以使用这个方法来通过部分链接文字进行匹配。代码如下:
public class SearchElementsByPartialLinkText{
public static void main(String[] args){
WebDriver driver = new FirefoxDriver();
driver.get("http://www.forexample.com");
WebElement aboutLink = driver.findElement(By.partialLinkText("About"));
aboutLink.click();
}
}
注意:使用这种方法进行定位时,可能会引起的问题是,当你的页面中不止一个超链接包含About时,findElement方法只会返回第一个查找到的元素,而不会返回所有符合条件的元素。如果你要想获得所有符合条件的元素,还是只能使用findElements方法。
7)By.xpath()
XPath是XML Path的简称,由于HTML文档本身就是一个标准的XML页面,所以我们可以使用XPath的语法来定位页面元素。
------------------------------------------------------------------------------------------------------------------------------------------
以下图所示HTML代码为例,要引用对应的对象,XPath语法如下:
绝对路径写法(只有一种),引用页面上的form元素(即源码中的第3行):/html/body/form[1]
-----------------------------------------------------------------------------------------------------------------------------------------
注意:
1. 元素的xpath绝对路径可通过firebug直接查询。
2. 一般不推荐使用绝对路径的写法,因为一旦页面结构发生变化,该路径也随之失效,必须重新写。
3. 绝对路径以单/号表示,而下面要讲的相对路径则以//表示,这个区别非常重要。
4. 当xpath的路径以/开头时,表示让Xpath解析引擎从文档的根节点开始解析;
5. 当xpath路径以//开头时,则表示让xpath引擎从文档的任意符合的元素节点开始进行解析;
6. 当/出现在xpath路径中时,则表示寻找父节点的直接子节点;
7. 当//出现在xpath路径中时,表示寻找父节点下任意符合条件的子节点;
-------------------------------------------------------------------------------------------------------------------------------------------
下面是相对路径的引用写法:
1.查找根元素://
2.查找所有的input元素://input
3.查找第一个form元素内的直接子input元素://form[1]/input
4.查找第一个form元素内的所有子input元素://form[1]//input
5.查找第一个form元素://form[1]
6.查找id为loginForm的form元素://form[@id='loginForm']
7.查找具有name属性为username的input元素://input[@name='username']
8.查找页面上id为loginForm的form元素下的第一个input元素://form[@id='loginForm']/input[1]
9.查找页面具有name属性为contiune并且type属性为button的input元素://input[@name='continue'][@type='button']
10.查找页面上id为loginForm的form元素下第4个input元素://form[@id='loginForm']/input[4]
--------------------------------------------------------------------------------------------------------------------------------------------------
Xpath功能很强大,也可以更复杂的写法,如下图中HTML源码:
图3
要引用id为“J_password”的input元素:
WebElement password = driver.findElement(By.xpath("//*[@id='J_login_form']/dl/dt/input[@id='J_password']"));
也可写成:
WebElement password = driver.findElement(By.xpath("//*[@id='J_login_form']/*/*/input[@id='J_password']"));
-----------------------------------------------------------------------------------------------------------------------------------------------------
前面讲的是xpath中基于准确元素属性的定位, xpath作为定位神器也可以用于模糊匹配:
图4
代码中的“退出”这个超链接,没有标准id元素,只有rel和href,用xpath的3种模糊匹配模式来定位:
A. 用contains关键字定位:
driver.findElement(By.xpath(“//a[contains(@href, ‘logout’)]”));
【寻找页面中href属性值包含有logout这个单词的所有a元素,其中@后面可以跟该元素任意的属性名】
B. 用start-with定位:
driver.findElement(By.xpath(“//a[starts-with(@rel, ‘nofo’)]”));
【寻找rel属性以nofo开头的a元素。其中@后面的rel可以替换成元素的任意其他属性】
C. 用Text关键字定位:
driver.findElement(By.xpath(“//*[text()=’退出’]”));
【查找页面当中所有的退出二字,根本就不用知道它是个a元素了。这种方法也经常用于纯文字的查找。】
D. 另外,如果知道超链接元素的文本内容,也可以用:
driver.findElement(By.xpath(“//a[contains(text(), ‘退出’)”]));
【这种方式一般用于知道超链接上显示的部分或全部文本信息时,可以使用】
------------------------------------------------------------------------------------------------------------------------------------------------
注意:关于xpath这种定位方式,webdriver会将整个页面的所有元素进行扫描以定位我们所需要的元素,所以这是一个非常费时的操作,如果你的脚本中大量使用xpath做元素定位的话,将导致你的脚本执行速度大大降低,所以请慎用。
8)By.cssSelector()
cssSelector这种元素定位方式跟xpath比较类似,但执行速度较快,而且各种浏览器对它的支持都相当到位,所以功能也是蛮强大的。
------------------------------------------------------------------------------------------------------------------------------------------------
常见的cssSelector的定位方式:
1. 定位id为flrs的div元素:#flrs 相当于xpath语法的//div[@id=’flrs’]
2. 定位id为flrs下的a元素:#flrs > a 相当于xpath语法的//div[@id=’flrs’]/a
3. 定位id为flrs下的href属性值为/forexample/about.html的元素: #flrs > a[href=”/forexample/about.html”]
如果需要指定多个属性值时,可以逐一加在后面,如#flrs > input[name=”username”][type=”text”]
------------------------------------------------------------------------------------------------------------------------------------------------
用cssSelector方式来引用图(3)中选中的那个input对象:
WebElement password = driver.findElement(By.cssSelector("#J_login_form>dl>dt>input[id=’ J_password’]"));
-------------------------------------------------------------------------------------------------------------------------------------------------
用cssSelector定位使用复合样式表的元素,button代码如下:
<button id="J_sidebar_login" class="btn btn_big btn_submit" type="submit">登录</button>
cssSelector引用元素代码如下:
driver.findElement(By.cssSelector("button.btn.btn_big.btn_submit"));
这样就可以顺利引用到使用了复合样式的元素了。
----------------------------------------------------------------------------------------------------------------------------------------------
此外,cssSelector还有一些高级用法,如:^用于匹配一个前缀,$用于匹配一个后缀,*用于匹配任意字符
匹配一个有id属性,并且id属性是以”id_prefix_”开头的超链接元素:a[id^='id_prefix_']
匹配一个有id属性,并且id属性是以”_id_sufix”结尾的超链接元素:a[id$='_id_sufix']
匹配一个有id属性,并且id属性中包含”id_pattern”字符的超链接元素:a[id*='id_pattern']
-------------------------------------------------------------------------------------------------------------------------------------------
最后再总结一下,各种方式在选择的时候应该怎么选择:
1. 当页面元素有id属性时,最好尽量用id来定位。但由于现实项目中很多程序员其实写的代码并不规范,会缺少很多标准属性,这时就只有选择其他定位方法。
2. xpath很强悍,但定位性能不是很好,所以还是尽量少用。如果确实少数元素不好定位,可以选择xpath或cssSelector。
3. 当要定位一组元素相同元素时,可以考虑用tagName或name。
4. 当有链接需要定位时,可以考虑linkText或partialLinkText方式。
参考资料:
《Selenium Webdriver Practical Guide》
https://saucelabs.com/resources/selenium/css-selectors