Selenium_WebDriver_定位元素
版权声明:本文为博主原创文章,转载请注明出处。
定位单个元素
WebDriver提供了八种元素定位方法,Java中定位语句形如:driver.findElement(By.id());
何为元素定位?当我们使用百度进行信息搜索时,打开网址后,我们的眼睛会聚焦到搜索栏,然后在搜索栏中输入我们需要搜索的关键,然后点击“百度一下”按钮,从上面的描述中我们可以看到,要完成搜索我们必须找到“搜索栏 && 百度一下按钮”,我们有眼睛可以浏览页面去定位“搜索栏 && 百度一下按钮”的位置,那脚本怎么知道“搜索栏 && 百度一下按钮”在哪里呢,这就要用到元素定位方法,通过元素定位,相当于给浏览器驱动器安装了一双眼睛,这样就可以找到“搜索栏 && 百度一下按钮”的“位置”了;
元素定位方式 |
描述 |
示例及场景 |
id |
HTML规定id属性在HTML文档中必须是唯一的,这就类似于公民的身份证号,具有很强的唯一性。 |
示例:定位"百度一下"按钮,并点击; 语法: driver.findElement(By.id("su")).click(); 场景: <input type="submit" value="百度一下" id="su" class="btn self-btn bg s_btn"> |
name |
HTML规定name来指定元素的名称,因此它的作用更像是人的姓名。name的属性值,在当前页而中可以不唯一。 |
示例:定位"百度搜索首页”的输入框,并输入"Selenium"; 语法:driver.findElement(By.name("wd")).sendKeys("Selenium"); 场景:<input type="text" class="s_ipt" name="wd" id="kw" maxlength="100" autocomplete="off"> |
class name |
HTML规定class来指定元素的类名。 其用法与id、name类似。 |
示例:定位"百度一下"按钮,并点击; 语法:driver.findElement(By.className("btn self-btn bg s_btn")).click(); 场景: <input type="submit" value="百度一下" id="su" class="btn self-btn bg s_btn"> |
tag name |
HTML的本质就是通过tag来定义实现不同的功能,每一个元素本质上也是一个tag。因为一个tag往往用来定义一类功能,所以通过tag识别某个元素的概率很低。 |
语法1:driver.findElement(By.tagName("input")); 示例2:查找页面上有多少个input,就可以用input这个tagName来进行查找 语法2:List<WebElement> inputs = driver.findElements(By.tagName("input")); System.out.println(inputs.size()); |
link text |
专门用来定位文本链接 |
示例:定位"百度搜索主页"右上角的"新闻"文本链接,并点击; 语法:driver.findElement(By.linkText("新闻")).click(); 场景:<a href="http://news.baidu.com" target="_blank" class="mnav">新闻</a> |
partial link text [ˈpɑ:ʃl] |
parial link定位是对link定位的一种补充,有些文本链接会比较长,这个时候我们可以取文本链接的一部分定位,只要这一部分信息可以唯一地标识这个链接即可。 |
示例:定位"百度搜索主页"右上角的"更多产品"文本链接,并点击; 语法:driver.findElement(By.partialLinkText("更多产")).click(); 场景:<a href="http://www.baidu.com/more/" name="tj_briicon" class="s_bri" target="_blank"> 更多产品</a> |
xpath |
XPath是一种在XML文档中定位元素的语言。 这种方法几乎可以定位到页面上的任意元素。 还可直接使用find_element_by_xpath()方法来定位元素。 |
|
①绝对路径 |
XPath主要用标签名的层级关系来定位元素的绝对路径,最外层为html语言。有body文本内,一级一级往下查找,如果一个层级下有多个相同的标签名,那么就按上下顺序确定是第几个,例如div[2]表示当前层级下的第二个div标签。 |
|
②相对路径 (需要学习Xpath定位语法) |
示例:定位"百度一下"按钮,并点击; 语法:driver.findElement(By.xpath("//*[@id='su']")).click(); 场景:利用谷歌F12中自带的“Copy XPath”,获取到“百度一下”按钮的XPath路径; |
|
css selector |
CSS使用选择器来为页面元素绑定属性。 CSS可以较为灵活地选择控件的任意属性,一般情况下定位速度要比XPath快。 |
|
选择器(利用谷歌F12中自带的“Copy Selector”) |
||
#id id 选择器,选择id="***'的所有元素; |
示例:定位"百度一下"按钮,并点击; 语法:driver.findElement(By.cssSelector("#su")).click(); 场景:<input type="submit" value="百度一下" id="su" class="btn self-btn bg s_btn"> |
|
.class class 选择器,选择class="***"的所有元素; |
示例:定位"百度一下"按钮,并点击; 语法:driver.findElement(By.cssSelector(".btn self-btn bg s_btn")).click(); 场景:<input type="submit" value="百度一下" id="su" class="btn self-btn bg s_btn"> |
|
* |
选择所有元素 |
|
element |
选择所有<element>元素 |
|
element1 > element2 |
选择父元素为<element1 >的所有<element2>元素 |
|
element1 + element2 |
选择同一级中紧接在<element1>元素之后的所有<element2>元素 |
|
[attribute=value] |
选择target = value的所有元素 |
定位一组元素
定位一组元素的方法与定位单个元素的方法类似,唯一的区别是在单词 element 后面多了一个 s 表示复数。定位一组元素一般用于以下场景:
①批量操作元素,例如勾选页面上所有的复选框。
②先获取一组元素,再从这组对象中过滤出需要操作的元素。例如定位出页面上所有的 checkbox,然后选择其中的一个进行操作。
注:对获取到的获取到的元素进行操作时,操作页面不能有跳转,否则会出现页面失效错误“stale element reference: element is not attached to the page document”
findElements() |
原型 |
java.util.List<WebElement> findElements(By by) |
参数 |
和findElement的可取的参数是一样的; |
|
返回值 |
返回一个装有WebElement的List容器; 因此,可以使用Java中关于List相关的方法,如:size()获取webelement的个数; |
|
示例 |
示例说明:登录cnblog,并为"精华"页面的前2篇博文点击"推荐"; 关键语法: ①List<WebElement> elements = driver.findElements(By.className("diggit")); //定位所有的“推荐”按钮; ②element = elements.get(i);//获取单个博文的“推荐”按钮,用到了Java循环For语句,List的get()方法; ③element.click(); //点击“推荐”按钮; |
附上测试代码:
测试环境: ①Eclipse:jee-mars-4.5.2 ②Selenium:selenium-java-3.5.3 ③GoogleChrome:60 ④chromedriver:2.30; |
package com.SeleniumLib.jase; import java.util.List; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; public class FindElement_s{ public static void main(String[]args) throws InterruptedException{ System.out.println("start selenium"); WebDriver driver; System.setProperty("webdriver.chrome.driver","D:/selenium-java-3.5.3/chromedriver.exe"); //chromedriver驱动的本地存放路径 driver = new ChromeDriver(); driver.get("https://www.baidu.com/"); //id /*driver.findElement(By.id("kw")).sendKeys("Selenium"); driver.findElement(By.id("su")).click();*/ //name /*driver.findElement(By.name("wd")).sendKeys("Selenium"); driver.findElement(By.id("su")).click();*/ //className /*driver.findElement(By.className("s_ipt")).sendKeys("Selenium"); driver.findElement(By.className("btn self-btn bg s_btn")).click();*/ //tagName /*List<WebElement> inputs = driver.findElements(By.tagName("input")); System.out.println(inputs.size()); driver.findElement(By.tagName("input"));*/ //linkText /*driver.findElement(By.linkText("新闻")).click();*/ //partialLinkText /*driver.findElement(By.partialLinkText("更多产")).click();*/ //XPath //绝对路径 //如下的绝对路径不正确,已放弃T_T //driver.findElement(By.xpath("/html/body/div[2]/div[1]/div[5]/div[1]/div[1]/form/span/input")).sendKeys("Selenium"); //driver.findElement(By.xpath("/html/body/div[2]/div/div[5]/div/div/form/span[2]/input")).click(); //XPath //相对路径:利用谷歌F12中自带的“Copy XPath”,获取到XPath路径,需要对其中的双引号做处理:换为单引号、或者使用\对双引号进行转义; /*driver.findElement(By.xpath("//*[@id='kw']")).sendKeys("Selenium"); //获取到的XPath://*[@id="su"] 将双引号换为单引号; driver.findElement(By.xpath("//*[@id=\"su\"]")).click(); //获取到的XPath:使用\对双引号进行转义*/ //cssSelector .class /*driver.findElement(By.cssSelector(".s_ipt")).sendKeys("Selenium"); driver.findElement(By.cssSelector(".btn self-btn bg s_btn")).click();*/ //cssSelector #id /*driver.findElement(By.cssSelector("#kw")).sendKeys("Selenium"); driver.findElement(By.cssSelector("#su")).click();*/ //cssSelector * /*List<WebElement> inputs2 = driver.findElements(By.cssSelector("*")); System.out.println(inputs2.size());*/ //cssSelector element1 > element2 /*List<WebElement> inputs3 = driver.findElements(By.cssSelector("html > body")); System.out.println(inputs3.size()); */ //cssSelector element1 + element2 /*List<WebElement> inputs4 = driver.findElements(By.cssSelector("span + input")); System.out.println(inputs4.size()); */ // [attribute=value] /*List<WebElement> inputs5 = driver.findElements(By.cssSelector("[type=submit]")); System.out.println(inputs5.size()); */ //多个元素1————//登录cnblog,并为"精华"页面的前2篇博文点击"推荐"; driver.get("https://passport.cnblogs.com/user/signin?ReturnUrl=https%3A%2F%2Fwww.cnblogs.com%2F"); driver.findElement(By.id("input1")).sendKeys("天使未必在场"); driver.findElement(By.id("input2")).sendKeys("******"); //个人密码 driver.findElement(By.id("signin")).click(); Thread.sleep(2000); //需要等待几s,否则程序还未正确跳转到cnblog登录主页,元素查找的个数为0; //抛出异常InterruptedException System.out.println("CurrentUrl"+driver.getCurrentUrl()); driver.get("https://www.cnblogs.com/pick/"); //跳转到"精华"页面; List<WebElement> elements = driver.findElements(By.className("diggit")); int listsize = elements.size(); System.out.println("“精华”页首页共有【 "+ listsize +"】个className=diggit的元素"); for(int i = 0;i < 2;++i) //控制只为前两篇点赞; { WebElement element; System.out.println(i); element = elements.get(i); //本打算依次从elements列表中获取每一个element元素,但获取完第一个元素"新闻"后,因为页面跳转导致第二个元素失效; element.click(); //点击“推荐”按钮; Thread.sleep(1000); } //driver.navigate().refresh(); //多个元素2——页面元素失效测试:定位“百度搜索”首页右上角的超文本链接“新闻、hao123、地图、视频、贴吧、学术,共6个”,再模拟点击这6个元素; /*List<WebElement> elements2 = driver.findElements(By.className("mnav")); int listsize2 = elements2.size(); //使用list迭代器的方法size()获取element的个数; System.out.println("共有【 "+ listsize2 +"】个className=mnav的元素"); for(int i = 0;i < listsize2;++i) { WebElement element; System.out.println(i); //System.out.println(elements.get(i)); element = elements2.get(i); //本打算依次从elements列表中获取每一个element元素,但获取完第一个元素"新闻"后,因为页面跳转导致第二个元素失效; element.click(); }*/ System.out.println("end selenium"); ///////driver.close(); //测试时为了更直观直接注释掉了,也可使用延时 } } |