Selenium是一个自动化测试框架。它可以通过操作一个驱动程序,模拟用户在浏览器上浏览网页的行为。一般是用来做自动化测试的。其实也可以用它来做网络爬虫(速度贼慢,也容易出现莫名其妙的错误)。
Selenium是通过驱动来操作控制浏览器的的。所以在使用前需要针对不同的浏览器平台下载对应的浏览器驱动。
所以除了代码外,还需要准备两个东西:1、是安装浏览器(如火狐、chrome等);2、下载浏览器对应的驱动。
各类浏览器平台下载地址
火狐浏览器驱动下载地址:
geckodriver
谷歌浏览器驱动下载地址:
ChromeDriver
、
淘宝镜像
注意浏览器跟驱动的版本哦。有时候会因为版本不匹配而出现莫名其妙的错误。
如果谷歌浏览器驱动下载太慢,可以考虑去淘宝镜像下载。
其他浏览器(比如IE、Edge)也有对应的驱动,但是我不提供下载链接。哈哈问度娘吧。因为,我不怎么用。
Quick Start
一个小程序就能快速的入门并且使用Selenium进行玩耍了。
新建Maven项目导入Selenium包
<dependencies>
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-chrome-driver -->
<!--谷歌浏览器-->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-chrome-driver</artifactId>
<version>3.141.59</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
<!--测试用-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
</dependencies>
安装谷歌浏览器。(本次测试使用的是:81.0.4044.138正式版)
下载谷歌浏览器驱动。把下载好的chromedriver.exe放在D盘。(测试使用的是83.0.4103.39版本)
写代码(JDK版本1.8)import org.junit.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class MyTest {
@Test
public void run(){
//设置驱动的路径
System.setProperty("webdriver.chrome.driver", "D:\\chromedriver.exe");
WebDriver driver=new ChromeDriver();
//打开百度
driver.get("https://www.baidu.com");
运行上面的程序你会看到你的谷歌浏览器自动打开了,还莫名其妙的进入了百度这个莫名其妙的主页。
接下来你就会用Selenium了,我们来介绍一下工作中常用到的API。( ^ _ ^ )....
浏览器控制
//访问https://www.baidu.com这个网址
driver.get("https://www.baidu.com");
这就相当于你打开浏览器,在输入框中输入https://www.baidu.com然后回车。
设置浏览器的大小
等于手动放大缩小浏览器到指定大小
//将打开的浏览器设置成100*100大小
driver.manage().window().setSize(new Dimension(100,100));
浏览器最大化
driver.manage().window().maximize();
driver.manage().window().fullscreen();
全屏显示和浏览器最大化的区别,就是。最大化相当于点击浏览器右上方的“口”最大化浏览器。而全屏显示相当于按了键盘上的F11(不知道效果的可以打开个浏览器,然后按F11试试看)。
设置浏览器的位置
//设置浏览器的位置坐标为(0,50)
driver.manage().window().setPosition(new Point(0,50));
这个坐标指的是浏览器左上角的那个点。在整个屏幕中的位置。
//你懂得。相当于点右上角的:x
driver.quit();
除了设置浏览器的大小和位置,还可以通过getSize()
、getPosition()
来获取浏览的的大小和位置。用法类似。
上面介绍了浏览器的操作,下面用介绍一下页面的操作。
后退操作//后退操作:<-
driver.navigate().back();
前进操作//前进操作:->
driver.navigate().forward();
刷新操作//等于按F5刷新
driver.navigate().refresh();
跳转到某一页//首先打开本地的一个html文件,然后跳转到百度页面。
driver.get("file:///C:/Users/czx/Desktop/File/Test/test.html");
driver.navigate().to("https://www.baidu.com");
其实这两个方法看上去功能相似,具体的区别我还没发现。
获取页面信息
获取页面标题
driver.get("https://www.baidu.com");
driver.getTitle();
//getTitle()返回的结果是:百度一下,你就知道
获取当前页面的url
driver.getCurrentUrl();
//获取url地址
获取整个页面的HTML内容
driver.getPageSource()
会把整个页面的数据都返回。
页面元素选择器
id选择器
//java
driver.findElement(By.id("divId"));
<!--html-->
<div id="divId"></div>
name选择器
//java
driver.findElement(By.name("divName"));
<!--html-->
<div name="divName"></div>
linkText选择器
//java
driver.findElement(By.linkText("百度a"));
<!--html-->
<a href="https://www.baidu.com">百度a</a>
partialLink选择器
跟上面的linkText
很相似,不过partialLink
可以匹配部分链接文字
//java
driver.findElement(By.linkText("百"));
driver.findElement(By.linkText("度"));
driver.findElement(By.linkText("度a"));
//三个返回的结果是一样的
<!--html-->
<a href="https://www.baidu.com">百度a</a>
tag选择器
//java
driver.findElement(By.TagName("div"));
<!--html-->
<div></div>
class选择器
//java
driver.findElement(By.className("class1"));
driver.findElement(By.className("class2"));
//注意这里是findElements多个s
//此方法可以将所有class1都查询出来,返回一个List<WebElement>,会将下面两个div都返回。
driver.findElements(By.className("class1"));
<!--html-->
<div class="class1"></div>
<div class="class1 class2"></div>
css选择器
有好几种写法
//java
driver.findElement(By.cssSelector("#divId"));
driver.findElement(By.cssSelector(".class1"));
driver.findElement(By.cssSelector("[name=divName]"));
driver.findElement(By.cssSelector("div"));
driver.findElement(By.cssSelector("html > body > div > a"));
如果你熟悉css样式的写法的话,会对上面的内容比较清楚。
xpath选择器
这个比较复杂,但是贼灵活
//java
driver.findElement(By.xpath("//*[@id='divId']"))
driver.findElement(By.xpath("//*[@name='divName']"))
driver.findElement(By.xpath("//input[@class='class1']"))
driver.findElement(By.xpath("/html/body/form/span/input"))
driver.findElement(By.xpath("//span[@class='class1']/input"))
driver.findElement(By.xpath("//form[@id='form']/span/input"))
driver.findElement(By.xpath("//input[@id='divId' and @name='divName']"))
以上api返回的都是一个元素,即:WebElement
。如果匹配到多个元素那么默认返回第一个。想要获取多个元素,需要使用:driver.findElements(By....);
此方法返回的是List<WebElement>
。
对DOM元素的操作
上面的选择器方法可以在页面上获取一DOM元素,也就是WebElement
对象。下面是对这些对象进行操作的API。
获取文本内容
WebElement element=driver.findElement(By.id("divId"));
String text = element.getText();
//text的值是:dbwos
<!--html-->
<div id="divId">dbwos</div>
清空文本输入框的内容
WebElement element=driver.findElement(By.id("inputId"));
element.clear();
//会将下面的TEST清除掉。
<!--html-->
<input id="inputId" value="TEST"/>
模拟键盘输入值
登录的时候需要输入用户名或者密码或则验证码吧,这个就是模拟这个操作的。
element.sendKeys("zhangsan");
模拟鼠标点击
//打开一个本地html文件
driver.get("file:///D:/test.html");
WebElement element=driver.findElement(By.tagName("button"));
element.click();
<!--html-->
<button onclick="alert('我被点击了')">click me</button>
上面的例子会弹出:我被点击了。
在登录的时候,大多数都有个登录的按钮。一般这个按钮不是submit提交表单,就是监听单机click事件
element.submit();
执行Javascript代码
无论使用Selenimu进行自动化测试还是爬虫实验,都经常会需要执行js代码来做一些页面操作。
执行异步js代码
//使用JS在控制台输出了一句:Hello Selenium!
String javascriptCode="console.log('Hello Selenium!');";
((JavascriptExecutor)driver).executeScript(javascriptCode);
同样可以使用jQuery等js库来操作。但是注意:一定要等网页把jQuery.js加载完成再调用才可以。要不会报错。(这个跟直接写js原理一样,需要加载完成才能使用)
执行同步JS代码
String javascriptCode="console.log('Hello Selenium!');";
((JavascriptExecutor)driver).executeAsyncScript(javascriptCode);
同步执行脚本会阻塞当前线程,什么时候脚本执行完了才继续主线程的下面代码。
保证JS库(如:jquery)加载完成
有是有需要调用网页的js库,这时候为了避免报错,需要等待一会,让网页加载完成,js库下载完成。
//进入这个莫名其妙的网站
driver.get("https://www.dbwos.com");
//将当前线程休眠3秒,让网站加载3秒。看看是否能加载完成。
Threan.sleep(3000L);
String javascriptCode="$('#divId').html('Hello!Selenium.');";
((JavascriptExecutor)driver).executeScript(javascriptCode);
这种方法比较暴力,直接把执行线程休眠,来等待网页加载完成。
有时候打开一个网页不能立即操作,要不会报错。比如找不到元素之类的。需要等待网页加载完成后再操作才可以。Selenium提供了两种加载等待方式-显式等待、隐式等待。
通过WebDriverWait
对象实现显示的加载等待
public class MyTest {
@Test
public void run()throws InterruptedException{
System.setProperty("webdriver.chrome.driver", "D:\\chromedriver.exe");
WebDriver driver=new ChromeDriver();
driver.get("https://www.baidu.com");
WebDriverWait wait=new WebDriverWait(driver,3000);
wait.until(new ExpectedCondition<WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.id("kw"));
}).sendKeys("dbwos");
//上面的例子实现了再3秒内等待百度加载,如果再3秒内能找到id是“kw”的元素那么输入“dbows”这几个字母。
上面的例子每隔0.5秒回查找这个kw元素是否存在。如果存在就返回。如果3秒后还没找到,集抛出异常。
其实WebDriverWait
还有一个构造方法new WebDriverWait(driver,3000,500);
,其实上面的构造方法也是调用的这个,不过把第三个参数设置成默认的500毫秒。
页面加载超时时间
//3秒页面加载不完成就报异常
driver.manage().timeouts().pageLoadTimeout(3,TimeUnit.SECONDS);
driver.get("https://www.baidu.com");
查找元素超时时间
//三分钟内找不到id是kw的元素就报异常
driver.manage().timeouts().pageLoadTimeout(3,TimeUnit.MINUTES);
driver.findElement(By.id("kw"));
异步脚本执行超时
//3分钟这个脚本还没执行完就报异常
driver.manage().timeouts().setScriptTimeout(3,TimeUnit.MINUTES);
String javascriptCode="$('#divId').html('Hello!Selenium.');";
((JavascriptExecutor)driver).executeScript(javascriptCode);
为什么是异步脚本?因为执行的要是同步脚本,回阻塞当前线程。什么时候脚本执行完什么时候继续。就不存在这个超时的问题。
JAVA线程等待
除了上面两种,我们还可以使用Java的线程操作来实现等待网页加载完成。
public class MyTest {
@Test
public void run()throws InterruptedException{
System.setProperty("webdriver.chrome.driver", "D:\\chromedriver.exe");
WebDriver driver=new ChromeDriver();
driver.get("https://www.dbwos.com");
Thread.sleep(3000L);
driver.findElement(By.tagName("input"));
driver.quit();
有是有需要对浏览器的页面截图。Selenium提供了屏幕截图的API。
浏览器屏幕截图//将百度页面截图保存到d盘下的screenSnapshot.jpg文件。
driver.get("https://www.baidu.com");
File srcFile =((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileCopyUtils.copy(srcFile,new File("d:\\screenSnapshot.jpg"));
}catch (IOException e){
e.printStackTrace();
如果用java+selenium写爬虫程序,就可能会需要设置代理。String httpProxy="<HOST:PORT>";//代理的地址和端口号
String sslProxy="";
String ftpProxy="";
proxy.setHttpProxy(httpProxy);
proxy.setSslProxy(sslProxy);
proxy.setFtpProxy(ftpProxy);
options.setCapability("proxy",proxy);
WebDriver driver = new FirefoxDriver(options)