编写不易,转载请注明(http://shihlei.iteye.com/blog/2067707)!
一 概述
HttpClient适合处理静态资源,网络爬虫等类似应用很大程度需要处理动态网页(内容有js填充,如百度图片,body里基本没有数据,碰到最麻烦的是新浪微博列表页)。将网页下载后,结合JS和Dom模型还原网页,我目前还未攻破,但在下载层还原网页,HtmlUnit是一种解决方案,虽然对JS的支持还是不完美。
HtmlUnit其实是自动化测试工具,集成了下载(HttpClient),Dom(NekoHtml),驱动JS(Rhino)。有一定的网页渲染能力,由于会驱动Dom,会消耗些CPU,内存。
本文描述HTMLUnit请求响应,设置cookies,设置代理,驱动JS等方法。
二 版本
<dependency> <groupId>net.sourceforge.htmlunit</groupId> <artifactId>htmlunit</artifactId> <version>2.14</version> </dependency>
三 典型功能
1) 打开google搜索百度
/** * 打开google 搜索百度 * * @param args * @throws Exception */ public static void main(String[] args) throws Exception { String url = "http://www.google.com.hk"; final WebClient webClient = new WebClient(); HtmlPage htmlPage = webClient.getPage(url); // HtmlUnit dom模型 // 获取表单 ,获得form标签name属性=f HtmlForm form = htmlPage.getFormByName("f"); // 获取输入框, 获取 input标签 ,name属性=q HtmlTextInput text = form.getInputByName("q"); // 搜索百度 text.setText("baidu"); // 获取提交按钮 HtmlSubmitInput button = form.getInputByName("btnG"); // 提交表单 HtmlPage listPage = button.click(); System.out.println(listPage.asXml()); webClient.closeAllWindows(); }
2)获取动态页面
/** * 获取百度图片js后的内容 * * @throws Exception */ public void demo2() throws Exception { String url = "http://image.baidu.com/i?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=result&fr=&sf=1&fmq=1400328281672_R&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&word=html"; final WebClient webClient = new WebClient(); // 1 启动JS webClient.getOptions().setJavaScriptEnabled(true); // 2 禁用Css,可避免自动二次请求CSS进行渲染 webClient.getOptions().setCssEnabled(false); // 3 启动客户端重定向 webClient.getOptions().setRedirectEnabled(true); // 4 js运行错误时,是否抛出异常 webClient.getOptions().setThrowExceptionOnScriptError(false); // 5 设置超时 webClient.getOptions().setTimeout(50000); HtmlPage htmlPage = webClient.getPage(url); // 等待JS驱动dom完成获得还原后的网页 webClient.waitForBackgroundJavaScript(10000); // 网页内容 System.out.println(htmlPage.asXml()); webClient.closeAllWindows(); }
四 样例
(1)请求响应
/** * Get请求 * @param url * @return * @throws Exception */ public static byte[] sendGetRequest(String url) throws Exception{ WebClient webClient = new WebClient(); WebRequest webRequest = new WebRequest(new URL(url)); webRequest.setHttpMethod(HttpMethod.GET); return sendRequest(webClient,webRequest); } /** * Post 请求 * * @param url * @param params * @return * @throws Exception */ public static byte[] sendPostRequest(String url,Map<String,String> params) throws Exception{ WebClient webClient = new WebClient(); WebRequest webRequest = new WebRequest(new URL(url)); webRequest.setHttpMethod(HttpMethod.POST); if (params != null && params.size() > 0) { for (Entry<String, String> param : params.entrySet()) { webRequest.getRequestParameters().add(new NameValuePair(param.getKey(), param.getValue())); } } return sendRequest(webClient,webRequest); } //底层请求 private static byte[] sendRequest(WebClient webClient,WebRequest webRequest) throws Exception{ byte[] responseContent = null; Page page = webClient.getPage(webRequest); WebResponse webResponse = page.getWebResponse(); int status = webResponse.getStatusCode(); System.out.println("Charset : " + webResponse.getContentCharset()); System.out.println("ContentType : " + webResponse.getContentType()); // 读取数据内容 if (status==200) { if (page.isHtmlPage()) { // 等待JS执行完成,包括远程JS文件请求,Dom处理 webClient.waitForBackgroundJavaScript(10000); // 使用JS还原网页 responseContent = ((HtmlPage) page).asXml().getBytes(); } else { InputStream bodyStream = webResponse.getContentAsStream(); responseContent = ByteStreams.toByteArray(bodyStream); bodyStream.close(); } } // 关闭响应流 webResponse.cleanUp(); return responseContent; }
(2)配置JS,CSS,超时,重定向
private void configWebClient(WebClient webClient) { // 设置webClient的相关参数 // 1 启动JS webClient.getOptions().setJavaScriptEnabled(true); // 2 禁用Css,可避免自动二次请求CSS进行渲染 webClient.getOptions().setCssEnabled(false); // 3 启动客户端重定向 webClient.getOptions().setRedirectEnabled(true); // 4 js运行错误时,是否抛出异常 webClient.getOptions().setThrowExceptionOnScriptError(false); // 5 设置超时 webClient.getOptions().setTimeout(timeout); }
(3)代理
private void setProxy(WebClient webClient,HttpProxy proxy) { ProxyConfig proxyConfig = webClient.getOptions().getProxyConfig(); proxyConfig.setProxyHost(proxy.getHost()); proxyConfig.setProxyPort(proxy.getPort()); DefaultCredentialsProvider credentialsProvider = (DefaultCredentialsProvider) webClient .getCredentialsProvider(); credentialsProvider.addCredentials(proxy.getUser(), proxy.getPassword()); }
辅助类:
package x.http.core; /** * Http代理 * * @author shilei * */ public class HttpProxy { private String proxy = "http"; private String host; private int port; private String user; private String password; public String getProxy() { return proxy; } public void setProxy(String proxy) { this.proxy = proxy; } public String getHost() { return host; } public void setHost(String host) { this.host = host; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public String getUser() { return user; } public void setUser(String user) { this.user = user; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
(4)Cookies:可以用于认证数据设置
1)设置Cookies
private void setCookies(WebClient webClient,String domain, Map<String, String> cookies) { if (cookies != null && cookies.size() > 0) { webClient.getCookieManager().setCookiesEnabled(true);// enable // cookies for (Entry<String, String> c : cookies.entrySet()) { Cookie cookie = new Cookie(domain, c.getKey(), c.getValue()); webClient.getCookieManager().addCookie(cookie); } } }
2)获取响应Cookies
private Map<String, String> getResponseCookies(WebClient webClient) { Set<Cookie> cookies = webClient.getCookieManager().getCookies(); Map<String, String> responseCookies = Maps.newHashMap(); for (Cookie c : cookies) { responseCookies.put(c.getName(), c.getValue()); } return responseCookies; }
3)删除所有Cookies
/** * 清除所有cookie */ public void clearCookies(WebClient webClient) { webClient.getCookieManager().clearCookies(); }
(5)驱动JS:
可实现自动化流程,如驱动表单提交,获取表单提交后的页面
如登录后页面:
public void doWeb(Page page) { if (page instanceof HtmlPage) { StringBuilder js = new StringBuilder(); js.append("document.getElementsByName('username')[1].value='").append(WeiboAccount.USERNAME) .append("';"); js.append("document.getElementsByName('password')[1].value='").append(WeiboAccount.PASSWORD) .append("';"); js.append("document.getElementsByClassName('W_btn_g')[1].click();"); HtmlPage htmlPage = (HtmlPage) page; htmlPage.executeJavaScript(js.toString()); } }
附录:完整代码
package x.http.simple.htmlunit; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import x.http.core.HttpProxy; import com.gargoylesoftware.htmlunit.DefaultCredentialsProvider; import com.gargoylesoftware.htmlunit.HttpMethod; import com.gargoylesoftware.htmlunit.Page; import com.gargoylesoftware.htmlunit.ProxyConfig; import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.WebRequest; import com.gargoylesoftware.htmlunit.WebResponse; import com.gargoylesoftware.htmlunit.html.HtmlForm; import com.gargoylesoftware.htmlunit.html.HtmlPage; import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput; import com.gargoylesoftware.htmlunit.html.HtmlTextInput; import com.gargoylesoftware.htmlunit.util.Cookie; import com.gargoylesoftware.htmlunit.util.NameValuePair; import com.google.common.collect.Maps; import com.google.common.io.ByteStreams; public class HtmlUnitDemo { private WebClient webClient = null; private int timeout = 50000; public HtmlUnitDemo() { this(null); } /** * Get请求 * * @param url * @return * @throws Exception */ public byte[] sendGetRequest(String url) throws Exception { WebRequest webRequest = new WebRequest(new URL(url)); webRequest.setHttpMethod(HttpMethod.GET); return sendRequest(webRequest); } /** * Post 请求 * * @param url * @param params * @return * @throws Exception */ public byte[] sendPostRequest(String url, Map<String, String> params) throws Exception { WebRequest webRequest = new WebRequest(new URL(url)); webRequest.setHttpMethod(HttpMethod.POST); if (params != null && params.size() > 0) { for (Entry<String, String> param : params.entrySet()) { webRequest.getRequestParameters().add(new NameValuePair(param.getKey(), param.getValue())); } } return sendRequest(webRequest); } // 底层请求 private byte[] sendRequest(WebRequest webRequest) throws Exception { byte[] responseContent = null; Page page = webClient.getPage(webRequest); WebResponse webResponse = page.getWebResponse(); int status = webResponse.getStatusCode(); System.out.println("Charset : " + webResponse.getContentCharset()); System.out.println("ContentType : " + webResponse.getContentType()); // 读取数据内容 if (status == 200) { if (page.isHtmlPage()) { // 等待JS执行完成 webClient.waitForBackgroundJavaScript(100000); responseContent = ((HtmlPage) page).asXml().getBytes(); } else { InputStream bodyStream = webResponse.getContentAsStream(); responseContent = ByteStreams.toByteArray(bodyStream); bodyStream.close(); } } // 关闭响应流 webResponse.cleanUp(); return responseContent; } public HtmlUnitDemo(HttpProxy proxy) { webClient = new WebClient(); configWebClient(); // 设置代理 if (proxy != null) { setProxy(proxy); } } private void configWebClient() { // 设置webClient的相关参数 // 1 启动JS webClient.getOptions().setJavaScriptEnabled(true); // 2 禁用Css,可避免自动二次请求CSS进行渲染 webClient.getOptions().setCssEnabled(false); // 3 启动客户端重定向 webClient.getOptions().setRedirectEnabled(true); // 4 js运行错误时,是否抛出异常 webClient.getOptions().setThrowExceptionOnScriptError(false); // 5 设置超时 webClient.getOptions().setTimeout(timeout); } private void setProxy(HttpProxy proxy) { ProxyConfig proxyConfig = webClient.getOptions().getProxyConfig(); proxyConfig.setProxyHost(proxy.getHost()); proxyConfig.setProxyPort(proxy.getPort()); DefaultCredentialsProvider credentialsProvider = (DefaultCredentialsProvider) webClient .getCredentialsProvider(); credentialsProvider.addCredentials(proxy.getUser(), proxy.getPassword()); } @SuppressWarnings("unused") private Map<String, String> getResponseCookies() { Set<Cookie> cookies = webClient.getCookieManager().getCookies(); Map<String, String> responseCookies = Maps.newHashMap(); for (Cookie c : cookies) { responseCookies.put(c.getName(), c.getValue()); } return responseCookies; } @SuppressWarnings("unused") private void setCookies(String domain, Map<String, String> cookies) { if (cookies != null && cookies.size() > 0) { webClient.getCookieManager().setCookiesEnabled(true);// enable // cookies for (Entry<String, String> c : cookies.entrySet()) { Cookie cookie = new Cookie(domain, c.getKey(), c.getValue()); webClient.getCookieManager().addCookie(cookie); System.out.println("Set Cookies : " + c.getKey() + " | " + c.getValue()); } } } /** * 清除所有cookie */ public void clearCookies() { webClient.getCookieManager().clearCookies(); } public void shutdown() throws IOException { webClient.closeAllWindows(); } /** * 打开google 搜索百度 * * @param args * @throws Exception */ public void demo() throws Exception{ String url = "http://www.google.com.hk"; final WebClient webClient = new WebClient(); HtmlPage htmlPage = webClient.getPage(url); // HtmlUnit dom模型 // 获取表单 ,获得form标签name属性=f HtmlForm form = htmlPage.getFormByName("f"); // 获取输入框, 获取 input标签 ,name属性=q HtmlTextInput text = form.getInputByName("q"); // 搜索百度 text.setText("baidu"); // 获取提交按钮 HtmlSubmitInput button = form.getInputByName("btnG"); // 提交表单 HtmlPage listPage = button.click(); System.out.println(listPage.asXml()); webClient.closeAllWindows(); } /** * 打开google 搜索百度 * * @param args * @throws Exception */ public static void main(String[] args) throws Exception { String url = "http://www.google.com.hk"; HtmlUnitDemo htmlUnit = new HtmlUnitDemo(); byte[] getResponse = htmlUnit.sendGetRequest(url); System.out.println("Get Body : " + new String(getResponse, "utf-8")); byte[] postResponse = htmlUnit.sendPostRequest(url, null); System.out.println("Get Body : " + new String(postResponse, "utf-8")); htmlUnit.shutdown(); } }
相关推荐
在标题中提到的"htmlunit2.14包",指的是HTMLUnit的2.14版本,这是一个特定的发行版,包含了该版本的所有源代码、类库和其他必要的组件。 在描述中提到的“爬虫技术htmlunit可屏蔽javascript”,指的是HTMLUnit的一...
在HTMLUnit-2.14中,可能使用了这些模块来提供基本的数据操作和功能支持。 2. **cssparser**:这是一个用于解析CSS(层叠样式表)的库,允许HTMLUnit解析并应用网页的样式规则,这对于准确地呈现页面的视觉效果至关...
htmlunit-2.14 jar包htmlunit爬去js加载后的页面特表好用
通过编程方式模拟用户行为,它可以获取动态生成的内容,从而帮助开发者获取和分析网页数据。 10. **兼容性**:HTMLUnit致力于保持与最新HTML、CSS和JavaScript标准的兼容性。`htmlunit-2.14`版本可能支持当时的大...
使用HTMLUnit获取执行JavaScript后的HTML文档,首先需要理解HTMLUnit的工作原理。HTMLUnit内建了一个基于WebClient的组件,它能够加载网页、执行JavaScript和处理DOM(文档对象模型)。以下是使用HTMLUnit进行此类...
在使用HTMLUnit进行爬虫开发时,你需要了解如何创建`HtmlUnit WebClient`实例,设置网络代理,处理异常,以及如何使用`HtmlPage`对象来获取和操作网页元素。同时,你也需要掌握JavaScript引擎的相关知识,因为...
在HTMLUnit 2.23中,开发者可以利用其JavaScript引擎执行网页上的脚本,这意味着它可以处理动态加载的内容,如AJAX请求和JavaScript事件。这使得HTMLUnit成为一个功能强大的工具,不仅能够获取静态HTML,还能处理...
htmlunit java版无界面浏览器 实现网页自动登录利器 官方最新下载 htmlunit 是一款开源的java 页面分析工具,读取页面后,可以有效的使用htmlunit分析页面上的内容。项目可以模拟浏览器运行,被誉为java浏览器的开源...
通过分析这些请求,开发者可以找到数据接口,并使用HttpClient来模拟这些请求,获取到动态加载的数据。 在本例中,我们通过Jsoup获取到了京东商品页面的静态HTML代码,但价格信息并未包含在内。通过分析页面源码...
使用HTMLUnit,开发者可以编写代码来浏览网页、填写表单、点击链接,甚至执行JavaScript,而无需真正打开一个浏览器。这对于自动化测试、数据抓取和无头爬虫来说非常有用。由于其无头特性,HTMLUnit在服务器端或...
本主题主要关注如何使用`httpclient4.*`库来绕过验证码获取公司信息,以及结合`jsoup`解析静态网页信息和`htmlUnit`处理动态网站的抓取。以下是对这些知识点的详细说明: 1. **httpclient4.***: Apache HttpClient...
HTMLUnit是一个Java库,模拟浏览器行为,用于自动化网页交互和数据抓取。它是一个无头浏览器,意味着它没有图形用户界面,而是通过程序接口(API)进行操作。这个压缩包包含21个jar文件,这些文件是实现HTMLUnit功能...
HTMLUnit是一款功能强大的Java库,它模拟了一个无头Web浏览器,...它简化了网页爬虫的编写,尤其是在处理需要JavaScript渲染的动态网页时。通过理解并正确配置其依赖,你可以有效地利用HTMLUnit进行各种自动化任务。
HTMLUnit是一个强大的无头浏览器库,它允许程序员模拟浏览器行为,...综上所述,HTMLUnit结合Apache POI库可以实现高效且灵活的网页数据抓取和整理,将动态网页内容转化为结构化的Excel表格,方便后续的分析和处理。
htmlunit 模拟cookie 存取 cookie值登录 如: wsyyuser.xywy.com Cookie c = new Cookie("wsyyuser.xywy.com", "PHPSESSID", Common.getValue("session_id") );
接着,如果有JavaScript存在,HTMLUnit会使用内置的Rhino JavaScript引擎执行这些脚本,更新DOM树以反映动态变化的网页状态。这样,开发者可以通过HTMLUnit提供的API来访问和操作这个虚拟DOM,就像在实际浏览器中...
5. **HtmlunitTest.java**:这看起来是一个测试类,可能包含了使用HTMLUnit进行网页测试或爬虫的示例代码。通过这个文件,你可以学习如何初始化`WebClient`,加载网页,执行JavaScript,以及如何提取和处理网页上的...
3. **错误处理**:在使用HTMLUnit时,由于JavaScript执行和网络请求的复杂性,需要处理可能出现的各种异常。 4. **性能优化**:虽然HTMLUnit是为了快速和自动化测试设计的,但在大规模使用时,仍需考虑性能优化,...
2. **JavaScript支持**:HTMLUnit能够执行JavaScript代码,这意味着它能够解析和处理那些依赖JavaScript动态加载内容的网页。 3. **AJAX支持**:HTMLUnit可以处理AJAX异步请求,使得开发者能够测试那些通过AJAX技术...