目录
Selenium 与 WebDriver 分析
HtmlUnit 功能介绍
使用 HtmlUnit 模拟一次登录
Selenium 与 WebDriver 分析
Selenium 是使用广泛的开源自动化测试工具,其中一个很重要的功能就是,可以通过各种浏览器的 Driver 模拟浏览器的操作,例如:FirfoxDriver,ChromeDriver 等。
通过对浏览器的模拟,对页面进行分析,我们可以:
这样就不需要人工分析 js 功能再执行相应的操作。可以极大的简化程序中的自动化页面操作。
但是模拟浏览器的 Driver 在运行时,都会启动一个真实浏览器进程,进行 GUI 层面的渲染和执行 js 代码,这种方式的缺点在于:
如果要更高效的执行自动化代码和简化环境依赖,HtmlUnit 是一个不错的选择。
Selenium 中可以使用基于 HtmlUnit 的 HTMLUnitDriver,实现无界面的快速运行。
HtmlUnit 功能简介
HtmlUnit 是一个用 java 编写的无界面的浏览器模拟工具,具有完整的浏览器功能,常用于自动化测试和爬虫中,具有如下优点:
系统中只需要安装 jdk 就可以运行,无需其他依赖,环境配置简单。
相对于有界面的 Driver,运行速度更快,稳定性强。
采用 java 程序编写的自动化代码,可以使用多线程实现多浏览器并发模拟。
当然,HtmlUnit 并不具备浏览器引擎中的特性,比如 chrome 或 firefox 特有的 js 处理。
HtmlUnit 主要的类有两个,掌握这两个类就可以实现大多数的模拟功能。
使用 HtmlUnit 模拟一次登录
下面我们使用 HtmlUnit,通过 5 个步骤,模拟一次对https://gitee.com
的登录。
1. 创建`WebClient`并设置配置项
WebClient webClient = new WebClient(BrowserVersion.CHROME)
复制代码
2. 从网站的初始域名开始请求
//开始请求网站
HtmlPage page = webClient.getPage("https://gitee.com");
复制代码
3.点击按钮
//点击首页上的登陆按钮,跳转到登陆页面
HtmlPage loginPage = ((DomElement) page.getByXPath("/html/body/header/div/div/div[5]/a[1]").get(0)).click();
复制代码
3.1 不了解 CSS 选择器,如何获取按钮的 Dom?
4.填充用户名和密码,并登陆
/*
* 获取登陆表单,表单如果是依赖js或css生成的,要等待加载完成,现有框架里等待方法不完善
* 这里可以采用循环等待的方案,等到全部资源加载完,获取到了要取的表单元素再继续执行
*/
while (loginPage.getByXPath("/html/body/div[2]/div[2]/div/div[1]/div[2]/div/form[1]").size() == 0) {
Thread.sleep(500);
}
//获取登陆表单元素
HtmlForm form = (HtmlForm) loginPage.getByXPath("/html/body/div[2]/div[2]/div/div[1]/div[2]/div/form[1]").get(0);
//用户名input
HtmlTextInput username = (HtmlTextInput) form.getElementsByAttribute("input", "id", "user_login").get(0);
//密码input
HtmlPasswordInput password = (HtmlPasswordInput) form.getElementsByAttribute("input", "id", "user_password").get(0);
//设置input的value
username.setValueAttribute("*****");
password.setValueAttribute("*****");
//登陆
HtmlPage home = ((DomElement) loginPage.getByXPath("/html/body/div[2]/div[2]/div/div[1]/div[2]/div/form[1]/div[2]/div/div/div[4]/input").get(0)).click();
复制代码
* 这里如果直接获取登陆表单,会出现因为 js 加载不全,导致获取不到的问题。
* 当前 HtmlUnit 自带的等待资源加载方法不完善。这里可以简单的使用一个循环,等到获取到了要取的表单元素再继续执行。
5.webClient 中的 cookies
完整代码示例
public void loginGitee() {
try (WebClient webClient = new WebClient(BrowserVersion.CHROME)) {
/******配置webClient******/
//ajax
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
//支持js
webClient.getOptions().setJavaScriptEnabled(true);
//忽略js错误
webClient.getOptions().setThrowExceptionOnScriptError(false);
//忽略css错误
webClient.setCssErrorHandler(new SilentCssErrorHandler());
//不执行CSS渲染
webClient.getOptions().setCssEnabled(false);
//超时时间
webClient.getOptions().setTimeout(3000);
//允许重定向
webClient.getOptions().setRedirectEnabled(true);
//允许cookie
webClient.getCookieManager().setCookiesEnabled(true);
//开始请求网站
HtmlPage page = webClient.getPage("https://gitee.com");
//点击首页上的登陆按钮,跳转到登陆页面
HtmlPage loginPage = ((DomElement) page.getByXPath("/html/body/header/div/div/div[5]/a[1]").get(0)).click();
/*
* 获取登陆表单,表单如果是依赖js或css生成的,要等待加载完成,现有框架里等待方法不完善
* 这里可以采用循环等待的方案,等到全部资源加载完,获取到了要取的表单元素再继续执行
*/
while (loginPage.getByXPath("/html/body/div[2]/div[2]/div/div[1]/div[2]/div/form[1]").size() == 0) {
Thread.sleep(500);
}
//获取登陆表单元素
HtmlForm form = (HtmlForm) loginPage.getByXPath("/html/body/div[2]/div[2]/div/div[1]/div[2]/div/form[1]").get(0);
//用户名input
HtmlTextInput username = (HtmlTextInput) form.getElementsByAttribute("input", "id", "user_login").get(0);
//密码input
HtmlPasswordInput password = (HtmlPasswordInput) form.getElementsByAttribute("input", "id", "user_password").get(0);
//设置input的value
username.setValueAttribute("*****");
password.setValueAttribute("*****");
//登陆
HtmlPage home = ((DomElement) loginPage.getByXPath("/html/body/div[2]/div[2]/div/div[1]/div[2]/div/form[1]/div[2]/div/div/div[4]/input").get(0)).click();
//搜索项目
HtmlPage searchPage = webClient.getPage("https://gitee.com/search?utf8=%E2%9C%93&type=&fork_filter=on&q=java");
//打印列表
HtmlElement a = (HtmlElement) searchPage.getByXPath("/html/body/div[3]/div[1]/div/div[2]").get(0);
System.out.println(searchPage.getBaseURL());
System.out.println(a.getTextContent());
} catch (Exception e) {
e.printStackTrace();
}
}
复制代码
本篇文章仅供学习交流使用
以上内容属个人学习总结,如有不当之处,欢迎在评论中指正
评论