htmlunit 抓取网页(的java程序是什么?答案是有哪些?? )
优采云 发布时间: 2022-03-30 21:29htmlunit 抓取网页(的java程序是什么?答案是有哪些??
)
1.HtmlUnit1.1 简介
HtmlUnit 是一个用 java 编写的无界面浏览器,它可以对 html 文档进行建模、通过 API 调用页面、填写表单、单击链接等等。像普通浏览器一样运行。通常用于测试和从网页中抓取信息。
官方简介翻译:<br />
HtmlUnit是一个无界面浏览器Java程序。它为HTML文档建模,提供了调用页面、填写表单、单击链接等操作的API。就跟你在浏览器里做的操作一样。
HtmlUnit不错的JavaScript支持(不断改进),甚至可以使用相当复杂的AJAX库,根据配置的不同模拟Chrome、Firefox或Internet Explorer等浏览器。
HtmlUnit通常用于测试或从web站点检索信息。
1.2 使用场景
对于java实现的网络爬虫程序,我们一般可以使用apache的HttpClient组件来获取HTML页面信息。HttpClient实现的http请求返回的响应一般是纯文本文档页面,也就是最原创的html页面。
对于一个静态的html页面,使用httpClient就足够爬出我们需要的信息了。但是对于越来越多的动态网页,更多的数据是通过异步JS代码获取和渲染的,而初始的html页面是不收录这部分数据的。
上图中我们看到的网页在初始文档加载后并没有看到红框中的数据列表。浏览器通过执行异步JS请求,将获取到的动态数据渲染到原创文档页面中,最终变成我们看到的网页。对于这部分需要JS代码执行的数据,httpClient是无能为力的。虽然我们可以通过研究得到JS执行的请求路径,然后用java代码来获取我们需要的部分数据,不说能不能从JS脚本中分析请求路径和请求参数,只分析这部分数据源码成本已经很高了。
通过上面的介绍,我们了解到现在很大一部分动态网页都是通过异步JS请求获得的数据,然后通过JS渲染页面。那么我们能不能做这样的假设,假设我们的爬虫程序模拟一个浏览器,拿到html页面后,像浏览器一样执行异步JS代码,JS渲染好html页面后,就可以愉快的获取到节点信息了这页纸。那么有没有这样的java程序呢?
答案是肯定的。
HtmlUnit就是这样一个库,用来做界面显示的所有异步工作。没有耗时的显示工作,HtmlUnit 加载的完整网页比实际的浏览器块更多。并且根据不同的配置,HtmlUnit可以模拟市面上常见的Chrome、Firefox、IE浏览器等浏览器。
通过HtmlUnit库,加载一个完整的Html页面(图片和视频除外),然后将其转换成我们常用的字符串格式,使用Jsoup等其他工具获取元素。当然,你也可以直接从HtmlUnit提供的对象中获取网页元素,甚至可以操作按钮、表单等控件。除了不能像可见浏览器那样用鼠标和键盘浏览网页之外,我们可以使用HtmlUnit来模拟所有其他的操作,比如登录网站、写博客等都可以完成。当然,网页内容抓取是最简单的应用。
2.J4L2.1官方简介
J4L OCR 工具是一组组件,可用于在 Java 应用程序中收录 OCR 功能。这意味着您可以接收传真、PDF 文件或扫描文档并从图像中提取商业信息。主要的3个组件是:
详细使用步骤请参考这篇文章文章:Java使用J4L识别验证码
本文文章主要介绍使用HtmlUnit模拟登录
3.实际案例3.1.场景
登录页面,包括表单,需要填写用户名、登录密码、验证码,实现用户登录。
3.2操作步骤
使用htmlunit模拟登录是一个获取登录页面->找到输入框->填写用户名和密码->填写验证码->模拟点击登录的过程。
4.实现代码4.1maven引入HtmlUnit依赖
net.sourceforge.htmlunit
htmlunit
2.18
4.2 主要方法
登录类
public static void main(String[] args) throws Exception {
DoCheck();
}
public static void DoCheck() throws Exception {
WebClient webClient = new WebClient(BrowserVersion.CHROME);//设置浏览器内核
webClient.getOptions().setJavaScriptEnabled(true);// js是否可用
webClient.getOptions().setCssEnabled(true);//css 一般设置false因为影响运行速度
webClient.getOptions().setThrowExceptionOnScriptError(false);//设置js抛出异常:false
webClient.getOptions().setActiveXNative(false);
//ajax
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
webClient.getOptions().setUseInsecureSSL(false);
//允许重定向
webClient.getOptions().setRedirectEnabled(true);
//连接超时
webClient.getOptions().setTimeout(5000);
//js执行超时
webClient.setJavaScriptTimeout(10000 * 3);
//允许cookie
webClient.getCookieManager().setCookiesEnabled(true);
String url = "http://hrportalneu.cs/HRPortalNeu/check.aspx";
HtmlPage page = webClient.getPage(url);
webClient.waitForBackgroundJavaScript(5000);
HtmlPage newPage;
newPage = readyPage(page, webClient, "btnCheckIn1");
System.out.println("url----------------" + newPage.getUrl());
System.out.println("checkIn执行后页面:" + newPage.asXml());
IOUtils.write(newPage.asXml().getBytes(), new FileWriter(new File("D:/checkIn.txt")));
if (!newPage.asXml().contains("登录成功")) {
DoCheck();
}
webClient.close();
}
public static HtmlPage readyPage(HtmlPage page, WebClient webClient, String type) throws Exception {
//封装页面元素
HtmlForm form = page.getHtmlElementById("form1");
HtmlTextInput tbxUsername = form.getInputByName("tbxUsername");
tbxUsername.setValueAttribute("用户名*******");
HtmlPasswordInput tbxPassword = form.getInputByName("tbxPassword");
tbxPassword.setValueAttribute("密码*******");
//获取验证码图片
HtmlImage verify_img = (HtmlImage) page.getElementById("AuthCode1$codeText$img");
File file = new File("D:\\" + "check" + ".png");
//保存验证码图片
verify_img.saveAs(file);
System.out.println("验证码图片已保存!");
//保存路径
String filePath = file.getPath();
//裁剪验证码
ImageUtil.cutImage(filePath, 1, 1, 96, 34);
//自动识别验证码
OCRFacade facade = new OCRFacade();
//识别验证码
String code = facade.recognizeFile(filePath, "eng");
//处理字符串
code = code.replaceAll(" ", "");
code = code.replaceAll("\\n", "");
System.out.println("验证码:" + code);
//定位验证码输入框
HtmlTextInput verify_code = form.getInputByName("AuthCode1$codeText");
//填入自动识别出来的验证码
verify_code.setValueAttribute(code);
System.out.println("原始页面:" + page.asXml());
HtmlPage newPage = null;
//操作按钮
if (type.equals("btnCheckIn1")) {
DomElement btnCheckIn1 = page.getElementById("btnCheckIn1");
System.out.println("doCheckIn");
newPage = btnCheckIn1.click();
}
//等待js加载
webClient.waitForBackgroundJavaScript(5000);
return newPage;
}
ImageUtil.class
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 = ImageIO.getImageReadersByFormatName("gif");
ImageReader imagereader = (ImageReader) it.next();
// 再通过ImageReader绑定 InputStream
imagereader.setInput(iis);
// 设置感兴趣的源区域。
ImageReadParam par = imagereader.getDefaultReadParam();
par.setSourceRegion(new Rectangle(x, y, w, h));
// 从 reader得到BufferImage
BufferedImage bi = imagereader.read(0, par);
// 将BuffeerImage写出通过ImageIO
ImageIO.write(bi, "png", new File(filePath));
}
}