Selenium学习记录2
WebDriver API
元素定位
WebDriver 提供了八种元素定位方法
- id :通过元素的id属性来定位元素——id是唯一标识
- name:通过元素的name属性值来定位元素,name属性值不是绝对唯一的
- class name:通过元素的class属性值来定位元素,class属性值不是绝对唯一的
- tag name:通过元素的tag属性值来定位元素,tag属性值不是绝对唯一的
- link text:通过元素的链接文本来定位元素,不是绝对唯一
- parial link:parial link定位是对 link 定位的一种补充,有些文本链接会比较长,可以取文本链接的一部分定位,只要这一部分信息可以唯一地标识这个链接
- XPath:通过Xpath定位
- CSS:通过CssSelector定位
在 Java 语言中对应的定位方法如下:
import org.openqa.selenium.By;
...
findElement(By.id())
findElement(By.name())
findElement(By.className())
findElement(By.tagName())
findElement(By.linkText())
findElement(By.partialLinkText())
findElement(By.xpath())
findElement(By.cssSelector())
这些方法都比较简单,这里就省略具体代码案例。需要注意的一点是,若通过任意定位方法定位元素时,多个元素符合定位条件,这时返回的是第一个满足条件的元素。
根据不同的前端项目,定位策略可能会有所不同。但大多数的定位策略都是首要考虑唯一标识id,若无法通过id定位,则要在保证元素唯一性的前提下,尽可能让检索条件简单,检索速度更快。
若想返回所有满足条件的元素,将findElement
换成findElements
即可。定位一组元素一般用于需要批量操作元素的场景。用例代码如下:
WebDriver driver = new ChromeDriver();
/** 定位一组元素 **/
driver.get("http://www.newegg.com");
List<WebElement> test2 = driver.findElements(By.xpath("//section[@class='page-section']"));
System.out.println(test2.size());
for (WebElement webElement : test2) {
System.out.println(webElement.getText());
System.out.println("------------------");
}
driver.quit();
控制浏览器
WebDriver 主要提供的是操作页面上各种元素的方法,但它也提供了操作浏览器的一些方法,例如控制浏览器的大小、操作浏览器前进和后退等。
控制浏览器窗口大小
有时候我们会希望能以某种尺寸打开浏览器,访问的页面也是在这种尺寸下运行。例如可以将浏览器设置成移动端大小(480* 800),然后访问移动站点,对其样式进行评估;WebDriver 提供了 manage().window().setSize()方法来设置浏览器的大小。如下所示
import org.openqa.selenium.Dimension;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class BrowserSize {
public static void main(String[] args) throws InterruptedException {
WebDriver driver = new ChromeDriver();
driver.get("http://www.baidu.com");
// 将浏览器窗口设置为最大值
driver.manage().window().maximize();
Thread.sleep(3000);
driver.get("http://www.baidu.com");
//将浏览器窗口设置为指定大小(480*800)
driver.manage().window().setSize(new Dimension(480,800));
Thread.sleep(3000);
driver.quit();
}
}
控制浏览器后退、前进和刷新
在使用浏览器浏览网页时,浏览器提供了后退、前进和刷新按钮,可以方便地在浏览过的网页之间切换,WebDriver也提供了对应的 back()、 forward()和refresh()方法来模拟后退、前进和刷新按钮。下面通过例子来演示这三个方法的使用:
/** 控制浏览器前进、后退 **/
// 进入到newegg首页
driver.get("http://www.newegg.com");
System.out.printf("现在的Url链接 %s",driver.getCurrentUrl());
System.out.printf("%n");
Thread.sleep(3000);
//点击“Today's Best Deals”
driver.findElement(By.linkText("Today's Best Deals")).click();
System.out.printf("现在的Url链接 %s",driver.getCurrentUrl());
System.out.printf("%n");
Thread.sleep(3000);
//执行浏览器后退
driver.navigate().back();
System.out.printf("现在的Url链接 %s",driver.getCurrentUrl());
System.out.printf("%n");
Thread.sleep(3000);
//执行浏览器前进
driver.navigate().forward();
System.out.printf("现在的Url链接 %s",driver.getCurrentUrl());
System.out.printf("%n");
Thread.sleep(3000);
//刷新当前页面
driver.navigate().refresh();
Thread.sleep(3000);
浏览器Cookie操作
WebDriver提供了一些对于Cookie的常规操作,在Java版本的WebDriver,这些Cookie操作都是封装在manage()里面,Python版本则直接调用就行。WebDriver操作cookie的方法有如下:
- getCookies():获得所有 cookie 信息
- getCookieNamed(String name):返回字典的 key 为“name”的 cookie 信息
- addCookie(cookie dict):添加 cookie。“cookie_dict”指字典对象,必须有 name 和 value 值
- deleteCookieNamed(String name) 删除 cookie 信息。“name”是要删除的 cookie 的名称;“optionsString”是该 cookie 的选项,目前支持的选项包括“路径”,“域”
- deleteAllCookies():删除所有 cookie 信息
部分方法的实例代码如下:
/** 浏览器Cookie操作 **/
driver.get("http://www.newegg.com");
System.out.println("第一次所有的Cookie:");
//获取当前浏览器Cookies
System.out.println(driver.manage().getCookies());
Thread.sleep(3000);
// 删除浏览器所有Cookies
driver.manage().deleteAllCookies();
Thread.sleep(3000);
System.out.println("删除所有Cookies:");
System.out.println(driver.manage().getCookies());
//向浏览器添加Cookie
//Cookie mycookie = new Cookie("mytest","clouds_yyds");
driver.manage().addCookie(new Cookie("test","111"));
System.out.println("添加test Cookie:");
System.out.println(driver.manage().getCookies());
Thread.sleep(3000);
多窗口切换
在页面操作过程中有时候点击某个链接会弹出新的窗口,这时就需要主机切换到新打开的窗口上进行操作。WebDriver 提供了 switchTo().window()方法可以实现在不同的窗口之间切换。但是由于WebDriver原生方法不能直接定位到新窗口,所有需要自己写逻辑判断来切换窗口,可以将其封装为公共方法,方便随时使用。实例代码如下:
/** 多窗口切换操作 **/
driver.get("http://www.baidu.com");
//获得当前窗口句柄
String first_handle = driver.getWindowHandle();
System.out.println(first_handle);
//点击”新闻“,进入新窗口
driver.findElement(By.linkText("新闻")).click();
//定位到新窗口,先通过getWindowHandles()获得所有的窗口的handle集合,再通过遍历集合,与第一个窗口的handle比对校验,看是否有新的handle。若有则定位到该新窗口
Set<String> handles = driver.getWindowHandles();
for(String handle: handles){
if(handle.equals(first_handle)==false){
//切换到新窗口
driver.switchTo().window(handle);
System.out.println("当前窗口的handle");
System.out.println(handle);
}
}
Thread.sleep(3000);
//切换到第一个窗口
driver.switchTo().window(first_handle);
Thread.sleep(3000);
元素简单操作
定位到元素后,WebDriver也提过了系列不同的元素操作方法,这里主要记录一下常用的方法。
WebDriver 常用方法
- click() :点击元素
- clear():清除文本内容
- sendKeys(*value):模拟键盘输入
- submit():用于提交表单,类似键盘“回车”操作。有时候 submit()可以与 click()方法互换来使用,submit()同样可以提交一个按钮,但 submit()的应用范围远不及 click()广泛。
- getText:获取元素文本内容
- getAttribute(name):获取属性值
- isDisplayed:判断元素受否可见
部分实例代码如下:
driver.get("https://www.baidu.com/");
WebElement search_text = driver.findElement(By.id("kw"));
WebElement search_button = driver.findElement(By.id("su"));
search_text.sendKeys("奥运");
search_text.clear();
search_text.sendKeys("Selenium");
search_button.click();
这些方法都比较简单,更多的方法,可以去Selenium的官方看WebDriver API的文档介绍。
鼠标事件
除了之前提到的Click()方法是模拟鼠标点击,WebDriver还提过其他丰富的的鼠标交互方式,例如鼠标右击、双击、悬停、甚至是鼠标拖动等功能。在 WebDriver 中,将这些关于鼠标操作的方法封装在 ActionChains 类提供。
Actions 类提供了鼠标操作的常用方法:
- contextClick():右击
- clickAndHold():鼠标点击并控制
- doubleClick():双击
- dragAndDrop():拖动
- release():释放鼠标
- perform():执行所有 Actions
模拟鼠标悬停的用例代码如下:
driver.get("https://www.baidu.com/");
WebElement search_setting = driver.findElement(By.linkText("设置"));
Actions action = new Actions(driver);
action.clickAndHold(search_setting).perform();
键盘事件
Keys()类提供了键盘上几乎所有按键的方法。前面了解到,sendKeys()方法可以用来模拟键盘输入,除此之外,还可以用它来输入键盘上的按键,甚至是组合键,如 Ctrl+A、Ctrl+C 等。常用的键盘如下:
- sendKeys(Keys.BACK_SPACE):回格键(BackSpace)
- sendKeys(Keys.SPACE):空格键(Space)
- sendKeys(Keys.TAB):制表键(Tab)
- sendKeys(Keys.ESCAPE):回退键(Esc)
- sendKeys(Keys.ENTER):回车键(Enter)
- sendKeys(Keys.CONTROL,‘a’):全选(Ctrl+A)
- sendKeys(Keys.CONTROL,‘c’):复制(Ctrl+C)
- sendKeys(Keys.CONTROL,‘x’):剪切(Ctrl+X)
- sendKeys(Keys.CONTROL,‘v’):粘贴(Ctrl+V
设置元素等待
当浏览器在加载页面时,页面上的元素可能并不是同时被加载完成的,可能会导致由于元素加载延迟而发生的定位失败。这种情况可以通过设置元素等待提高这种问题而造成的不稳定。
显示等待方法
WebDriver 提供了显式等待方法WebDriverWait,专门针对某个元素进行等待判断。实例代码如下:
WebDriver driver = new ChromeDriver();
driver.get("https://www.baidu.com");
//显式等待,针对某个元素等待
WebDriverWait wait = new WebDriverWait(driver,10,1);
wait.until(new ExpectedCondition<WebElement>(){
@Override
public WebElement apply(WebDriver text) {
return text.findElement(By.id("kw"));
}
}).sendKeys("selenium");
driver.findElement(By.id("su")).click();
Thread.sleep(2000);
driver.quit()
在设置时间内,默认每隔一段时间检测一次当前页面元素是否存在,如果超过设置时间检测不到则抛出异常。WebDriverWait的格式如下:
WebDriverWait(driver, 10, 1)
其中:driver :浏览器驱动。第二个参数表示最长超时时间,默认以秒为单位。第三个参数表示检测的的间隔(步长)时间,默认为 0.5s
隐式等待方法
WebDriver 提供了几种方法来等待元素
- implicitlyWait。识别对象时的超时时间。过了这个时间如果对象还没找到的话就会抛出NoSuchElement 异常
- setScriptTimeout。异步脚本的超时时间。WebDriver 可以异步执行脚本,这个是设置异步执行脚本脚本返回结果的超时时间
- pageLoadTimeout。页面加载时的超时时间。因为 WebDriver 会等页面加载完毕再进行后面的操作,所以如果页面超过设置时间依然没有加载完成,那么 WebDriver 就会抛出异常
//页面加载超时时间设置为 5s
driver.manage().timeouts().pageLoadTimeout(5, TimeUnit.SECONDS);
driver.get("https://www.baidu.com/");
//定位对象时给 10s 的时间, 如果 10s 内还定位不到则抛出异常
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.findElement(By.id("kw")).sendKeys("selenium");
//异步脚本的超时时间设置成 3s
driver.manage().timeouts().setScriptTimeout(3, TimeUnit.SECONDS)
其他操作
多表单切换
在 Web 应用中经常会遇到 frame/iframe 表单嵌套页面的应用,WebDriver 只能在一个页面上对元素识别与定位,对于 frame/iframe 表单内嵌页面上的元素无法直接定位。WebDriver提供了switchTo().frame()方法将当前定位的主体切换为 frame/iframe 表单的内嵌页面。
下拉框处理
Selenium 专门提供了Select类来处理下拉框的操作。例如selectByValue()方法符用于选取标签的 value 值。
警告框处理
在 WebDriver 中处理JavaScript所生成的alert、confirm以及prompt十分简单,具体做法是使用switch_to_alert()方法定位到 alert/confirm/prompt,然后使用text/accept/dismiss/sendKeys等方法进行操作。
- getText():返回 alert/confirm/prompt 中的文字信息
- accept(): 接受现有警告框
- dismiss():解散现有警告框
- sendKeys(keysToSend):发送文本至警告框
- keysToSend:将文本发送至警告框