java通过HtmlUnit⼯具和J4L实现模拟带验证码登录
1.HtmlUnit
1.1介绍
HtmlUnit是⼀个⽤java编写的⽆界⾯浏览器,建模html⽂档,通过API调⽤页⾯,填充表单,点击链接等等。如同正常浏览器⼀样操作。典型应⽤于测试以及从⽹页抓取信息。
官⽅简介翻译
HtmlUnit是⼀个⽆界⾯浏览器Java程序。它为HTML⽂档建模,提供了调⽤页⾯、填写表单、单击链接等操作的API。就跟你在浏览器⾥做的操作⼀样。
HtmlUnit不错的JavaScript⽀持(不断改进),甚⾄可以使⽤相当复杂的AJAX库,根据配置的不同模拟Chrome、Firefox或Internet Explorer等浏览器。
HtmlUnit通常⽤于测试或从web站点检索信息。
1.2使⽤场景
httpClient的局限性
对于使⽤java实现的⽹页爬⾍程序,我们⼀般可以使⽤apache的HttpClient组件进⾏HTML页⾯信息的获取,HttpClient实现的http请求返回的响应⼀般是纯⽂本的document页⾯,即最原始的html页⾯。
对于⼀个静态的html页⾯来说,使⽤httpClient⾜够将我们所需要的信息爬取出来了。但是对于现在越来越多的动态⽹页来说,更多的数据是通过异步JS代码获取并渲染到的,最开始的html页⾯是不包含这部分数据的。
上图我们所见到的⽹页,在最初的document加载完成之后,并不会看到红框中的数据列表。浏览器通过执⾏异步JS请求,将获取到的动态数据,渲染到最初的document页⾯中,才最终变成了我们看到的⽹页。⽽对于这部分需要执⾏JS代码获取的数据,httpClient就显得⽆能为⼒了。虽然我们可以通过研究拿到JS执⾏的请求路径再⽤java代码获取我们需要的这部分数据,且不说我们能不能够从JS脚本中分析到这个请求路径和请求参数,光是分析这部分源码的代价就已经很⾼了。
HtmlUnit来解决
通过上⾯的介绍,我们了解了现在很⼤⼀部分动态⽹页,展现的数据都是通过异步JS请求获取,然后再通过JS对页⾯进⾏渲染得到的。那我们是不是可以进⾏这么⼀个假设,假设我们的爬⾍程序模拟了
⼀个浏览器,在获取html页⾯之后,像浏览器⼀样执⾏异步JS代码,等到JS将html页⾯渲染完成之后,就可以愉快的获取页⾯上的节点信息了。那么有没有这样的java程序呢?
答案是有的。
HtmlUnit就是这么⼀个程序库,⽤来做出了界⾯展⽰意外所有的异步⼯作。由于没有了展⽰这⼀块耗时的⼯作,HtmlUnit加载完成⼀个完整的⽹页要⽐实际的浏览器块多了。并且根据不同配置,HtmlUnit可以模拟市⾯上常⽤的浏览器如Chrome、Firefox、IE浏览器等。
通过HtmlUnit库,加载⼀个完整的Html页⾯(图⽚视频除外),然后就可以将其转换成我们常⽤的字串格式,⽤其他⼯具如Jsoup来获取其中的元素了。当然也可以直接在HtmlUnit提供的对象中获取⽹页元素,甚⾄是操作如按钮、表单等控件。除了不能像可见浏览器⼀样⽤⿏标键盘浏览⽹页之外,我们可以⽤HtmlUnit来模拟操作其他的⼀切操作,像登录⽹站,撰写博客等等都是可以完成的。当然⽹页内容爬取是最简单的⼀个应⽤了。
2.J4L
2.1官⽅简介
The J4L OCR tools is set of components that can be used to include OCR capabilities in Java applic
ations. That means you can receive faxes, PDF files or scan documents and extract business information from the images. The main 3 components are:
a Java wrapper for the  engine. The OCR engine Tesseract itself is delivered under the Apache 2.0 license and we support a version compiled for windows only.
a PDF to text converter.
a text document parser.
关于j4l⼯具详细使⽤步骤可以参考本篇⽂章:
本篇⽂章主要介绍使⽤HtmlUnit模拟登陆
3.实际案例
3.1.场景
⼀个登陆页⾯,包含⼀个表单,需要填写⽤户名、登陆密码、验证码实现⽤户登录。
3.2操作步骤
使⽤htmlunit模拟登录,就是⼀个获取登录页⾯->到输⼊框->填⼊⽤户名密码->填写验证码->模拟点击登录的过程。
4.实现代码
4.1maven引⼊HtmlUnit依赖
<dependency>
  <groupId>net.sourceforge.htmlunit</groupId>
  <artifactId>htmlunit</artifactId>
  <version>2.18</version>
</dependency>
4.2主⽅法
Login.java
public static void main(String[] args) throws Exception {
login();
}
public static void login() throws Exception {
WebClient webClient = new WebClient(BrowserVersion.CHROME);//设置浏览器内核
//ajax
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
/
/允许重定向
//连接超时
//js执⾏超时
webClient.setJavaScriptTimeout(10000 * 3);
//允许cookie
String url = "hrportalneu.cs/HRPortalNeu/check.aspx";
HtmlPage page = Page(url);
webClient.waitForBackgroundJavaScript(5000);
HtmlPage newPage;
newPage = readyPage(page, webClient, "btnCheckIn1");
System.out.println("url----------------" + Url());
System.out.println("Login执⾏后页⾯:" + newPage.asXml());
IOUtils.write(newPage.asXml().getBytes(), new FileWriter(new File("D:/")));
if (!newPage.asXml().contains("登录成功")) {
login();
}
webClient.close();
}
public static HtmlPage readyPage(HtmlPage page, WebClient webClient, String type) throws Exception {        //封装页⾯元素
HtmlForm form = HtmlElementById("form1");
HtmlTextInput tbxUsername = InputByName("tbxUsername");
tbxUsername.setValueAttribute("⽤户名*******");
HtmlPasswordInput tbxPassword = InputByName("tbxPassword");
tbxPassword.setValueAttribute("密码*******");
//获取验证码图⽚
HtmlImage verify_img = (HtmlImage) ElementById("AuthCode1$codeText$img");
File file = new File("D:\\" + "check" + ".png");
//保存验证码图⽚
verify_img.saveAs(file);
System.out.println("验证码图⽚已保存!");
/
/保存路径
String filePath = Path();
//裁剪验证码这⾥使⽤原始的图⽚⽂件识别成功率不⾼可以先进⾏裁剪
ImageUtil.cutImage(filePath, 1, 1, 96, 34);
//⾃动识别验证码
OCRFacade facade = new OCRFacade();
//识别验证码
String code = izeFile(filePath, "eng");
//处理字符串
code = placeAll(" ", "");
code = placeAll("\\n", "");
System.out.println("验证码:" + code);
//定位验证码输⼊框
HtmlTextInput verify_code = InputByName("AuthCode1$codeText");
//填⼊⾃动识别出来的验证码
verify_code.setValueAttribute(code);
System.out.println("原始页⾯:" + page.asXml());
HtmlPage newPage = null;
//操作按钮
if (type.equals("btnCheckIn1")) {
DomElement btnCheckIn1 = ElementById("btnCheckIn1");
System.out.println("doCheckIn");
newPage = btnCheckIn1.click();
}
//等待js加载
webClient.waitForBackgroundJavaScript(5000);
return newPage;
} 
ImageUtil.java
public class ImageUtil {
public static void cutImage(String filePath, int x, int y, int w, int h)
throws Exception {
// ⾸先通过ImageIo中的⽅法,创建⼀个Image + InputStream到内存
ImageInputStream iis = ImageIO
.createImageInputStream(new FileInputStream(filePath));
// 再按照指定格式构造⼀个Reader(Reader不能new的)
Iterator it = ImageReadersByFormatName("gif");网页设计html代码翻译
ImageReader imagereader = (ImageReader) it.next();
// 再通过ImageReader绑定 InputStream
imagereader.setInput(iis);
// 设置感兴趣的源区域。
ImageReadParam par = DefaultReadParam();        par.setSourceRegion(new Rectangle(x, y, w, h));
// 从 reader得到BufferImage
BufferedImage bi = ad(0, par);
// 将BuffeerImage写出通过ImageIO
ImageIO.write(bi, "png", new File(filePath));
}
}
在控制台查看Login执⾏后的页⾯,查看是否登录成功。
以上就是本篇⽂章的全部内容,如有不正确的地⽅,欢迎讨论。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。