WebDriver is an open source tool for automated testing of webapps across many browsers. It provides capabilities for navigating to web pages, user input, JavaScript execution, and more. ChromeDriver is a standalone server that implements the W3C WebDriver standard. ChromeDriver is available for Chrome on Android and Chrome on Desktop (Mac, Linux, Windows and ChromeOS).
通过官方的介绍可以知道ChromeDriver是用于网络应用在浏览器自动化测试的开源工具。 通过ChromeDriver可以在桌面模拟人在Chrome上的操作。
需求:需要在一个星期内满足客户在线浏览pdf的需求。已知现在有一款前端开源控件能实现pdf转化swf,并可用于前端在线浏览pdf,但是该控件暂无后端版本。
思路:Chromedriver可以模拟人工操作,通过模拟人工导入pdf到控件并且在转换后通过控件的回调函数向API请求,并记录转换后的相关结果,只要每次上传把附件信息加入队列,异步触发模拟就可以满足需求,并且是自动执行。
在目前大多数的系统中请求用来鉴权的元素无外乎只有2种headers或者cookie,所以通过观测我们可以区别的到这类元素,只要有了这些元素,无论是使用httpclient请求还是进行爬虫都可以通过添加鉴权元素直接访问,下面是一个简单的demo实现分析。
需要访问外网才能访问:http://chromedriver.chromium.org/downloads
下载驱动可以直接使用: http://chromedriver.storage.googleapis.com/index.html
pom依赖
org.seleniumhq.selenium
selenium-api
3.141.0
org.seleniumhq.selenium
selenium-chrome-driver
3.141.0
org.seleniumhq.selenium
selenium-remote-driver
3.141.0
org.seleniumhq.selenium
selenium-support
3.141.0
代码分析
通过加载驱动及初始化设置实例化ChromeDriver对象
ChromeDriverService service = new ChromeDriverService.Builder().usingDriverExecutable(new File(driver))
.usingAnyFreePort().build();
try {
service.start();
} catch (IOException e) {
e.printStackTrace();
}
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.addArguments("--window-size=1280,960");//制定打开chrome大少,值随意
ChromeDriver chromeDriver = new ChromeDriver(service, chromeOptions);//生成实例
chromeDriver.navigate().to("http://127.0.0.1:8080/loginpage");
这次使用的是Spring Security从单体应用到分布式(三)-引入Spring Security Oauth2所使用的登录页面,从html文件可知道登录窗口使用的两个输入框是user和pwd,而提交窗口则为submitbtn
在后端代码中需要模拟登录操作就需要这样写
//模拟输入密码
chromeDriver.findElement(By.name("user")).sendKeys("stephanie");
chromeDriver.findElement(By.name("pwd")).sendKeys("12345678");
//获取登录元素
WebElement btn = chromeDriver.findElement(By.name("submitbtn"));
//提交表单
btn.submit();
在最简单的Spring Security登录中只要登录成功后登录信息就被记录下来,通过访问API的请求分析,我们可以分析出demo中的Cookie:JSESSIONID就是请求通过Spring Security应用过滤器的关键,在代码中指需要把前一次访问Cookie保存下载,再在实际操作中就可以多次使用,下面的代码就是保存了Cookie,如果访问目标API被拦截后把前只一次访问保留下来的cookie给予这次请求那么在cookie有效期内都可以多次访问。
Set cookies = chromeDriver.manage().getCookies();//当前访问浏览器的cookies
chromeDriver.close();//关闭第一次登录成功的浏览器
chromeDriver = new ChromeDriver(service, chromeOptions);//再一次生成实例
chromeDriver.navigate().to("http://127.0.0.1:8080/helloworld");//从新打开浏览器之后访问helloworld会被过滤器器拦截跳转回登录页面
Thread.sleep(6000);
if(!"http://127.0.0.1:8080/helloworld".equals(chromeDriver.getCurrentUrl()))
{
chromeDriver.manage().addCookie(cookies.iterator().next());
chromeDriver.navigate().to("http://127.0.0.1:8080/helloworld");
Thread.sleep(6000);
chromeDriver.close();
}
else
chromeDriver.close();
再实际使用有种比较常见的错误就是chrome不能再没有进行访问之前就设置cookie,在实际写代码的时候不能出现下面的代码,会出现org.openqa.selenium.UnableToSetCookieException: unable to set cookie,应当先访问一次地址之后再设置cookie
chromeDriver = new ChromeDriver(service, chromeOptions);
chromeDriver.manage().addCookie(cookies.iterator().next());
chromeDriver.navigate().to("http://127.0.0.1:8080/helloworld");
Thread.sleep(6000);
chromeDriver.close();
爬虫实际就是通过访问目标地址抓取需要的信息,但是往往会被登录中会有各种拦截控件,下面会介绍如何通过chromedriver来获取验证码图片
当我们访问某个网页的时候出现这样的提示
通过分析网页的html代码可以发现这个校验码虽然他通过功能限制了不能多次请求来下载该校验码,但是此次校验码我们却可以通过img标签来进行定位。
通过chromeDriver访问网页,可以获取到该页面的全屏截图,通过标签标签我们可以知道验证码实际的坐标位置和大小,然后在文件流中实现裁剪就可以得到验证码的图片。
chromeDriver.navigate().to("http://www.ourradio.hk/");
WebElement clickCaptcha = chromeDriver.findElement(By.tagName("img"));
Point codeLocation = clickCaptcha.getLocation();
File screen = chromeDriver.getScreenshotAs(OutputType.FILE);//全屏截图
String filePath = imgurl+File.separator+"code.png";
try{
try {
BufferedImage read = ImageIO.read(screen);//读取全屏截图
BufferedImage subimage = read.getSubimage(codeLocation.getX(),
codeLocation.getY(),
clickCaptcha.getSize().width,
clickCaptcha.getSize().height);//定制截图位置还有图片大少一般这设置就是获取验证码
ByteArrayOutputStream bs = new ByteArrayOutputStream();
ImageOutputStream imOut = ImageIO.createImageOutputStream(bs);
ImageIO.write(subimage, "png", imOut);
InputStream inputStream = new ByteArrayInputStream(bs.toByteArray());
OutputStream outStream = new FileOutputStream(filePath);
IOUtils.copy(inputStream, outStream);
inputStream.close();
outStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}catch (Exception ex)
{
}
ChromeDriver虽然从介绍中可以知道他是为自动化测试而设计的,但是在一些自动化业务和爬虫我们都可以通过使用ChromeDriver模拟操作实现开发语言本身不能实现或者很难实现的需求。