定位页面元素
id 定位
标签的 id 具有唯一性,就像人的身份证,假设有个 input 标签如下。
<input autocorrect="off" autocomplete="off" name="j_username" id="j_username" placeholder="用户名" type="text" class="normal" autocapitalize="off" aria-label="用户名">
我们可以通过 id 定位到它,由于 id 的唯一性,我们可以不用管其他的标签的内容。
import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; public class SeleniumDemo { private final static String webDriver = "webdriver.chrome.driver"; private final static String webDriverPath ="E:\\chromedriver\\chromedriver.exe"; public static void main(String[] args) { System.setProperty(webDriver, webDriverPath); WebDriver driver= new ChromeDriver(); //Jenkins 登录界面 driver.get("http://119.167.159.214:8080/login"); //根据用户名输入框id定位 driver.findElement(By.id("j_username")); } }
name 定位
name
指定标签的名称,在页面中可以不唯一。以Jenkins登录页的用户名输入框input为例
<input autocorrect="off" autocomplete="off" name="j_username" id="j_username" placeholder="用户名" type="text" class="normal" autocapitalize="off" aria-label="用户名">
我们可以使用 findElement(By.name("j_username")) 定位到 input 标签。
//根据用户名输入框name定位 driver.findElement(By.name("j_username"));
class 定位
class
指定标签的类名,在页面中可以不唯一。以Jenkins登录页的登录按钮为例
<input name="Submit" type="submit" value="登录" class="submit-button primary ">
我们可以使用 findElement(By.className("submit-button primary")) 定位到 input
标签(登录按钮)。
//根据class定位 driver.findElement(By.className("submit-button primary"));
tag 定位
每个 tag
往往用来定义一类功能,所以通过 tag
来识别某个元素的成功率很低,每个页面一般都用很多相同的 tag
,比如:<span>、<a>、<img>、<div>、<input>、<form>等。这里还是用Jenkins登录页面的 form作为例子。
<form method="post" name="login" action="j_spring_security_check"><div class="formRow"><input autocorrect="off" autocomplete="off" name="j_username" id="j_username" placeholder="用户名" type="text" class="normal" autocapitalize="off" aria-label="用户名"></div><div class="formRow"><input name="j_password" placeholder="密码" type="password" class="normal" aria-label="密码"></div><input name="from" type="hidden"><div class="submit formRow"><input name="Submit" type="submit" value="登录" class="submit-button primary "></div><script type="text/javascript"> document.getElementById('j_username').focus(); var checkBoxClick = function(event) { document.getElementById('remember_me').click(); } </script><div class="Checkbox Checkbox-medium"><label class="Checkbox-wrapper"><input type="checkbox" id="remember_me" name="remember_me"><div class="Checkbox-indicator"><svg xmlns="http://www.w3.org/2000/svg" height="25" class="svg-icon check" focusable="false" viewBox="0 0 24 24" width="25"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"></path></svg></div><div class="Checkbox-text">保持登录状态</div></label></div></form>
我们可以使用 findElement(By.tagName("form"))
定位到 form 标签。
//根据tag定位 driver.findElement(By.tagName("form"));
link 定位
link
专门用来定位文本链接,假如要定位下面这一标签。
<a class="value" href="https://blog.csdn.net/weixin_40986713" target="_blank">洛阳泰山博客</a>
我们使用 findElement(By.linkText("洛阳泰山博客"))
并指明标签内全部文本即可定位。
driver.findElement(By.linkText("洛阳泰山博客"));
partialLinkText 定位
partial_link
翻译过来就是“部分链接”,对于有些文本很长,这时候就可以只指定部分文本即可定位,同样使用刚才的例子。
<a class="value" href="https://blog.csdn.net/weixin_40986713" target="_blank">洛阳泰山博客</a>
我们使用 findElement(By.partialLinkText("博客"))
并指明标签内全部文本即可定位。
driver.findElement(By.partialLinkText("博客"));
xpath定位
xpath
是一种在 XML
文档中定位元素的语言,它拥有多种定位方式,下面通过实例我们看一下它的几种使用方式。下面是Jenkins整个登录页的html代码。
<html lang="zh-CN"><head resurl="/static/70ecc1c9" data-rooturl="" data-resurl="/static/70ecc1c9" data-imagesurl="/static/70ecc1c9/images"><title>登录 [Jenkins]</title><meta name="ROBOTS" content="NOFOLLOW"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/static/70ecc1c9/css/simple-page.css" type="text/css"><link rel="stylesheet" href="/static/70ecc1c9/css/simple-page.theme.css" type="text/css"><link rel="stylesheet" href="/static/70ecc1c9/css/simple-page-forms.css" type="text/css"></head><body><div class="simple-page" role="main"><div class="modal login"><div id="loginIntroDefault"><div class="logo"></div><h1>欢迎来到 Jenkins!</h1></div><form method="post" name="login" action="j_spring_security_check"><div class="formRow"><input autocorrect="off" autocomplete="off" name="j_username" id="j_username" placeholder="用户名" type="text" class="normal" autocapitalize="off" aria-label="用户名"></div><div class="formRow"><input name="j_password" placeholder="密码" type="password" class="normal" aria-label="密码"></div><input name="from" type="hidden"><div class="submit formRow"><input name="Submit" type="submit" value="登录" class="submit-button primary "></div><script type="text/javascript"> document.getElementById('j_username').focus(); var checkBoxClick = function(event) { document.getElementById('remember_me').click(); } </script><div class="Checkbox Checkbox-medium"><label class="Checkbox-wrapper"><input type="checkbox" id="remember_me" name="remember_me"><div class="Checkbox-indicator"><svg xmlns="http://www.w3.org/2000/svg" height="25" class="svg-icon check" focusable="false" viewBox="0 0 24 24" width="25"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"></path></svg></div><div class="Checkbox-text">保持登录状态</div></label></div></form><div class="footer"></div></div></div></body></html>
根据上面的标签需要定位 到登录按钮的 input
标签,以下列出了四种方式,xpath
定位的方式多样并不唯一,使用时根据情况进行解析即可。
绝对路径(层级关系)定位
driver.findElement(By.xpath("/html/body/div/div/form/div[2]//input"));
相对路径(层级关系)定位
driver.findElement(By.xpath("//form/div[2]//input"));
利用元素属性定位
// 利用元素属性定位(有空格的保留空格) driver.findElement(By.xpath("//*[@class='submit-button primary ']"));
注:* 是通配符
层级+元素属性定位
driver.findElement(By.xpath("//div[@class='simple-page']/div/form/div[2]/input"));
注:/form/div[2] 代表 form元素下第二个div元素,这个不是数组的下标,第一个元素的下标是1不是0。
逻辑运算符定位
driver.findElement(By.xpath("//*[@class='submit-button primary ' and @type='submit']"));
通过文字定位
WebElement login=driver.findElement(By.xpath("//*[text()='登录']"));
通过部分文字定位
WebElement login=driver.findElement(By.xpath("//*[contains(text(),''登录)]"));
通过部分属性值定位
driver.findElement(By.xpath("//div[contains(@class,'captcha_verify_img--wrapper')]"));
css 定位
1.通过class属性定位
driver.findElement(By.cssSelector(".modal login"));
2.通过id属性定位
driver.findElement(By.cssSelector("#loginIntroDefault"));
3.通过标签名定位
driver.findElements(By.cssSelector("input"));
4.通过父子关系定位
driver.findElements(By.cssSelector("form>div>input"));
5.通过属性定位
driver.findElement(By.cssSelector("*[id=loginIntroDefault]"));
6.通配符
//选择每一个class属性的值以”_ipt"结尾的元素 driver.findElement(By.cssSelector("[class$=login]"));
7.组合定位
driver.findElement(By.cssSelector("form>div>input.submit-button primary "));
- findElement()方法定位元素时,会查询整个DOM,然后返回第一个匹配的元素
- findElements()方法,可以得到指定规则的集合,适用于需要在一组相似的元素上进行操作的情况。
定位一组元素
上 面讲述了定位一个元素的 8 种方法,定位一组元素使用的方法只需要将 findElement 改为 findElements即可,它的使用场景一般是为了批量操作元素。
这里以 CSDN 首页的一个 作者推荐栏 为例。
编辑
下面用findElements(By.xpath())来定位所有推荐作者的名称。
<div class="recommendation" data-v-282f7478="" data-v-c95253ce=""><a target="_blank" data-report-click="{"spm":"1001.2100.3001.7371"}" href="https://blog.csdn.net/ityouknow" class="portrait-box" data-v-282f7478=""><img src="https://profile.csdnimg.cn/1/9/4/1_ityouknow" alt="" class="portrait" data-v-282f7478=""> <img src="https://csdnimg.cn/release/cmsfe/public/img/blog-expert.b9c32f92.png" alt="" class="tag" data-v-282f7478=""> <!----> <!----> <!----></a> <dl data-v-282f7478=""><dt data-v-282f7478=""><a target="_blank" data-report-click="{"spm":"1001.2100.3001.7371"}" href="https://blog.csdn.net/ityouknow" data-v-282f7478="">微笑很纯洁</a></dt> <dd data-v-282f7478="">一个有故事的程序员,公号:纯洁的微笑,博客:www.ityouknow.com</dd></dl> <div data-report-click="{"spm":"1001.2100.3001.7372"}" class="recommendation-btn " data-v-282f7478="">关注</div></div>
代码实现如下:
import org.openqa.selenium.*; import org.openqa.selenium.chrome.ChromeDriver; import java.io.IOException; import java.util.List; public class SeleniumDemo { private final static String webDriver = "webdriver.chrome.driver"; private final static String webDriverPath ="E:\\chromedriver\\chromedriver.exe"; public static void main(String[] args) throws InterruptedException, IOException { System.setProperty(webDriver, webDriverPath); WebDriver driver= new ChromeDriver(); //进入csdn首页 driver.get("https://blog.csdn.net/"); Thread.sleep(1000); //定位元素 List<WebElement> elements=driver.findElements(By.xpath("//div[@class='template'][1]/div[2]/div/dl/dt/a")); //输入所有作者名 elements.forEach(e-> System.out.println(e.getText())); } }
小结:实际开发过程中,精准的定位到网页元素重中之重,实际开发中,定位元素可能回会不少时间,尤其是设置反爬的网站,定位元素花费的时间可能需要更多时间,比开发的时间还长!!!