如何使用httpclient的使用

使用HttpClient组件进行网站的模拟登录 -
- ITeye技术网站
实现用程序代码来实现某个网站的模拟登录,本文介绍使用httpclient完成这个工作。获得登录后的Session的演示代码如下:
package cn.xiyang.
import java.io.BufferedR
import java.io.IOE
import java.io.InputS
import java.io.InputStreamR
import java.util.ArrayL
import java.util.L
import org.apache.http.HttpE
import org.apache.http.HttpR
import org.apache.http.NameValueP
import org.apache.http.client.ClientProtocolE
import org.apache.http.client.HttpC
import org.apache.http.client.entity.UrlEncodedFormE
import org.apache.http.client.methods.HttpP
import org.apache.http.impl.client.DefaultHttpC
import org.apache.http.message.BasicNameValueP
* 演示登录
* @author xiyang
public class Demo3 {
public static void main(String[] args) throws ClientProtocolException, IOException {
HttpClient httpclient = new DefaultHttpClient();
//设置登录参数
List&NameValuePair& formparams = new ArrayList&NameValuePair&();
formparams.add(new BasicNameValuePair("[user_label]", "sdlgxxy"));
formparams.add(new BasicNameValuePair("[pwd_label]", "*****"));
UrlEncodedFormEntity entity1 = new UrlEncodedFormEntity(formparams, "UTF-8");
//新建Http
HttpPost httppost = new HttpPost("http://*****/login");
httppost.setEntity(entity1);
//处理请求,得到响应
HttpResponse response = httpclient.execute(httppost);
String set_cookie = response.getFirstHeader("Set-Cookie").getValue();
//打印Cookie值
System.out.println(set_cookie.substring(0,set_cookie.indexOf(";")));
//打印返回的结果
HttpEntity entity = response.getEntity();
StringBuilder result = new StringBuilder();
if (entity != null) {
InputStream instream = entity.getContent();
BufferedReader br = new BufferedReader(new InputStreamReader(instream));
String temp = "";
while ((temp = br.readLine()) != null) {
String str = new String(temp.getBytes(), "utf-8");
result.append(str);
System.out.println(result);
获得Session之后,把该值保存下来。然后再访问其他受保护对象时设置头信息的Cookie字段就好了,代码片段如下
HttpClient httpclient = new DefaultHttpClient();
// 根据获得的Cookie值,设置头信息,然后发送请求,获得内容
HttpGet httpget = new HttpGet("http://***/showsource?solution_id=7263065");
httpget.setHeader("Cookie", "JSESSIONID=817CFE3DFFE59532FD02");
HttpResponse response = httpclient.execute(httpget);
这样就可以获得该网页的内容。所需的jar包可在附件中下载
下载次数: 332
下载次数: 312
浏览: 19750 次
来自: 济南
什么都没输出……咋回事?HttpClient和HtmlUnit的比较总结以及使用技巧(一)_小组_ThinkSAAS
HttpClient和HtmlUnit的比较总结以及使用技巧(一)
HttpClient和HtmlUnit的比较总结以及使用技巧(一)
大家在做爬虫、网页采集、通过网页自动写入数据时基本上都接触过这两个组件(权且称之为组件吧),网上入门资料已经很多了,我想从实际的应用角度谈谈我对于这两个组件的看法,并记录在博客中,以便日后翻阅,欢迎大家批评指正。
本文主要比较两者的优劣性以及介绍应用中的使用技巧,推荐一些入门资料以及非常实用的辅助工具,希望能对大家有所帮助。
大家有任何疑问或者建议希望留言给我,一起交流学习。
下面我们首先来看下2个组件的区别和优劣性:
HtmlUnit本来是一款自动化测试的工具,它采用了HttpClient和java自带的网络api结合来实现,它与HttpClient的不同之处在于,它比HttpClient更“人性化”。
在写HtmlUnit代码的时候,仿佛感觉到的就是在操作浏览器而非写代码,得到页面(getPage)-- 寻找到文本框(getElementByID || getElementByName || getElementByXPath 等等)-- 输入文字(type,setValue,setText等等)-- 其他一些类似操作 -- 找到提交按钮 -- 提交 -- 得到新的Page,这样就非常像一个人在后台帮你操作浏览器一样,而你要做的就是告诉他如何操作以及需要填入哪些值。
一、网页的模拟化
首先说说HtmlUnit相对于HttpClient的最明显的一个好处,HtmlUnit更好的将一个网页封装成了一个对象,如果你非要说HttpClient返回的接口HttpResponse实际上也是存储了一个对象那也可以,但是HtmlUnit不仅保存了这个网页对象,更难能可贵的是它还存有这个网页的所有基本操作甚至事件。这就是说,我们对于操作这个网页可以像在jsp中写js一样,这是非常方便的,比如:你想某个节点的上一个节点,查找所有的按钮,查找样式为“bt-style”的所有元素,对于某些元素先进行一些改造,然后再转成String,或者我直接得到这个网页之后操作这个网页,完成一次提交都是非常方便的。这意味着你如果想分析一个网页会来的非常的容易,比如我附上一段百度新闻高级搜索的代码:
// 得到浏览器对象,直接New一个就能得到,现在就好比说你得到了一个浏览器了
WebClient webclient = new WebClient();
// 这里是配置一下不加载css和javaScript,配置起来很简单,是不是
webclient.getOptions().setCssEnabled(false);
webclient.getOptions().setJavaScriptEnabled(false);
// 做的第一件事,去拿到这个网页,只需要调用getPage这个方法即可
HtmlPage htmlpage = webclient.getPage("/advanced_news.html");
// 根据名字得到一个表单,查看上面这个网页的源代码可以发现表单的名字叫“f”
final HtmlForm form = htmlpage.getFormByName("f");
// 同样道理,获取”百度一下“这个按钮
final HtmlSubmitInput button = form.getInputByValue("百度一下");
// 得到搜索框
final HtmlTextInput textField = form.getInputByName("q1");
// 最近周星驰比较火呀,我这里设置一下在搜索框内填入”周星驰“
textField.setValueAttribute("周星驰");
// 输入好了,我们点一下这个按钮
final HtmlPage nextPage = button.click();
// 我把结果转成String
String result = nextPage.asXml();
System.out.println(result);
然后你可以把得到的result结果复制到一个文本,然后用浏览器打开该文本,是不是想要的东西(如图结),很简单对吧,为什么会感觉简单,因为它完全符合我们操作浏览器的习惯,当然最终它也是用HttpClient和其它一些工具类实现的,但是这样的封装是非常人性化和令人惊叹的。
Htmlunit可以有效的分析出 dom标签,并且可以有效的运行页面上的js以便得到一些需要执行JS才能得到的值,你仅仅需要做的就是执行executeJavaScript()这个方法而已,这些都是HtmlUnit帮我们封装好,我们要做的仅仅是告诉它需要做什么。
WebClient webclient = new WebClient();
HtmlPage htmlpage = webclient.getPage("you url");
htmlpage.executeJavaScript("the function name you want to execute");
对于使用Java程序员来说,对对象的操作就再熟悉不过了,HtmlUnit所做的正是帮我们把网页封装成一个对象,一个功能丰富的,透明的对象。
二、网络响应的自动化处理
HtmlUnit拥有强大的响应处理机制,我们知道:常见的404是找不到资源,100等是继续,300等是跳转...我们在使用HttpClient的时候它会把响应结果告诉我们,当然,你可以自己来判断,比如说,你发现响应码是302的时候,你就在响应头去找到新的地址并自动再跳过去,发现是100的时候就再发一次请求,你如果使用HttpClient,你可以这么去做,也可以写的比较完善,但是,HtmlUnit已经较为完整的实现了这一功能,甚至说,他还包括了页面JS的自动跳转(响应码是200,但是响应的页面就是一个JS),天涯的登录就是这么一个情况,让我们一起来看下。
* @author CaiBo
* @date 日 上午9:16:36
* @version $Id$
public class TianyaTest {
public static void main(String[] args) throws Exception {
// 这是一个测试,也是为了让大家看的更清楚,请暂时抛开代码规范性,不要纠结于我多建了一个局部变量等
// 得到认证https的浏览器对象
HttpClient client = getSSLInsecureClient();
// 得到我们需要的post流
HttpPost post = getPost();
// 使用我们的浏览器去执行这个流,得到我们的结果
HttpResponse hr = client.execute(post);
// 在控制台输出我们想要的一些信息
showResponseInfo(hr);
private static void showResponseInfo(HttpResponse hr) throws ParseException, IOException {
System.out.println("响应状态行信息:"+ hr.getStatusLine());
System.out.println("---------------------------------------------------------------");
System.out.println("响应头信息:");
Header[] allHeaders = hr.getAllHeaders();
for (int i = 0; i & allHeaders. i++) {
System.out.println(allHeaders[i].getName() +":"+ allHeaders[i].getValue());
System.out.println("---------------------------------------------------------------");
System.out.println("响应正文:");
System.out.println(EntityUtils.toString(hr.getEntity()));
// 得到一个认证https链接的HttpClient对象(因为我们将要的天涯登录是Https的)
// 具体是如何工作的我们后面会提到的
private static HttpClient getSSLInsecureClient() throws Exception {
// 建立一个认证上下文,认可所有安全链接,当然,这是因为我们仅仅是测试,实际中认可所有安全链接是危险的
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
return HttpClients.custom().//
setSSLSocketFactory(sslsf)//
// .setProxy(new HttpHost("127.0.0.1", 8888))
// 获取我们需要的Post流,如果你是把我的代码复制过去,请记得更改为你的用户名和密码
private static HttpPost getPost() {
HttpPost post = new HttpPost("/login");
// 首先我们初始化请求头
post.addHeader("Referer","/login.jsp");
post.addHeader("Host","");
post.addHeader("Origin","");
// 然后我们填入我们想要传递的表单参数(主要也就是传递我们的用户名和密码)
// 我们可以先建立一个List,之后通过post.setEntity方法传入即可
// 写在一起主要是为了大家看起来方便,大家在正式使用的当然是要分开处理,优化代码结构的
List&NameValuePair& paramsList = new ArrayList&NameValuePair&();
* 添加我们要的参数,这些可以通过查看浏览器中的网络看到,如下面我的截图中看到的一样
* 不论你用的是firebut,httpWatch或者是谷歌自带的查看器也好,都能查看到(后面会推荐辅助工具来查看)
* 要把表单需要的参数都填齐,顺序不影响
paramsList.add(new BasicNameValuePair("Submit",""));
paramsList.add(new BasicNameValuePair("fowardURL",""));
paramsList.add(new BasicNameValuePair("from",""));
paramsList.add(new BasicNameValuePair("method","name"));
paramsList.add(new BasicNameValuePair("returnURL",""));
paramsList.add(new BasicNameValuePair("rmflag","1"));
paramsList.add(new BasicNameValuePair("__sid","1#1#1.0#a6c606d9-1efa-4e12-8ad5-3eefd12b8254"));
// 你可以申请一个天涯的账号 并在下两行代码中替换为你的用户名和密码
paramsList.add(new BasicNameValuePair("vwriter","ifugletest2014"));// 替换为你的用户名
paramsList.add(new BasicNameValuePair("vpassword","test123456"));// 你的密码
// 将这个参数list设置到post中
post.setEntity(new UrlEncodedFormEntity(paramsList, Consts.UTF_8));
执行上面这个Main函数你会得到一下的结果:
我们看到,响应码确实是200,表明成功了,其实这个响应相当于是302,它是需要跳转的,只不过它的跳转写到了body部分的js里面而已。
location.href=":80/online/loginSuccess.jsp?fowardurl=http%3A%2F%%2F&userthird=&regOrlogin=%E7%99%BB%E5%BD%95%E4%B8%AD......&t=9&k=8cd4dc5eabc054&c=6fc7ebf8d782a07bbfbbf3f";
它这是一个页面上的跳转
那这个时候如果你使用HttpClient就头疼了(当然也是可以处理的,后面讲到)。如果你使用的是HtmlUnit,整个过程显得简单轻松。
public class TianyaTestByHtmlUnit {
public static void main(String[] args) throws Exception {
WebClient webClient = new WebClient();
// 拿到这个网页
HtmlPage page = webClient.getPage("/login.jsp");
// 填入用户名和密码
HtmlInput username = (HtmlInput) page.getElementById("userName");
username.type("ifugletest2014");
HtmlInput password = (HtmlInput) page.getElementById("password");
password.type("test123456");
HtmlButton submit = (HtmlButton) page.getElementById("loginBtn");
HtmlPage nextPage = submit.click();
System.out.println(nextPage.asXml());
这样简单的几行代码就完成了。
三、并行控制 和串行控制
既然HtmlUnit封装了那么多的底层api和hHttpClient操作,那么它有没有给我们提供自定义各种响应策略和监听整个执行过程的方法呢?,答案是肯定的。由于HtmlUnit提供的监听和控制方法比较多,我说几个大家可能接触比较少,但很有用的方法。其他的类似于:设置CSS有效,设置不抛出JS异常,设置使用SSL安全链接,诸如此类,大家通过webClient.getOptions().set***,就可以设置了,这种大家都比较熟了。
(1)首先来看一下JS错误处理监听机制,我们打开HtmlUnit源码可以看到(该源码位置在JavaScriptEngine类中的handleJavaScriptException方法处)
protected void handleJavaScriptException(final ScriptException scriptException, final boolean triggerOnError) {
// Trigger window.onerror, if it has been set.
final HtmlPage page = scriptException.getPage();
if (triggerOnError && page != null) {
final WebWindow window = page.getEnclosingWindow();
if (window != null) {
final Window w = (Window) window.getScriptObject();
if (w != null) {
w.triggerOnError(scriptException);
catch (final Exception e) {
handleJavaScriptException(new ScriptException(page, e, null), false);
// 这里尝试去取我们设置的JavaScript错误处理器
final JavaScriptErrorListener javaScriptErrorListener = getWebClient().getJavaScriptErrorListener();
if (javaScriptErrorListener != null) {
javaScriptErrorListener.scriptException(page, scriptException);
// Throw a Java exception if the user wants us to.
if (getWebClient().getOptions().isThrowExceptionOnScriptError()) {
throw scriptE
// L ScriptException instances provide good debug info.
("Caught script exception", scriptException);
也就是说我们它在发现JS错误的时候会自动去寻找我们是否有处理器,有的话就会用我们设置的处理器来处理,要在webClient里加一个处理器也非常的方便。使用:
webClient.setJavaScriptErrorListener(new 你自己的JavaScriptErrorListener());即可。自己的JavaScriptErrorListener也很好实现,直接继承JavaScriptErrorListener接口即可,然后你就可以在javaScript出错时自行处理,你可以选择分析它的url、修正它的url、重新再获取或者直接忽略等等。有js错误处理器,当然也还有别的了,这一类型的我就只说一个了。为了防止有小白不明白,我还是贴出一个简单的实现好了。
* @author CaiBo
* @date 日 上午12:32:08
* @version $Id: WaiJavaScriptErrorListener.java -12 03:54:25Z CaiBo $
public class WaiJavaScriptErrorListener implements JavaScriptErrorListener {
public WaiJavaScriptErrorListener() {
public void scriptException(HtmlPage htmlPage, ScriptException scriptException) {
// TODO Auto-generated method stub
public void timeoutError(HtmlPage htmlPage, long allowedTime, long executionTime) {
// TODO Auto-generated method stub
public void malformedScriptURL(HtmlPage htmlPage, String url, MalformedURLException malformedURLException) {
// TODO Auto-generated method stub
public void loadScriptError(HtmlPage htmlPage, URL scriptUrl, Exception exception) {
// TODO Auto-generated method stub
public static void main(String[] args) {
WebClient webClient = new WebClient();
webClient.setJavaScriptErrorListener(new WaiJavaScriptErrorListener());
Main方法处实现了JS错误自定义处理的webClient
(2)链接响应监听
很多时候我们想看看HtmlUnit到底去拿了什么东西,或者说我想对它拿的东西过滤一下,再或者我想把它拿到的某些东西存起来,那这个时候响应监听就很必要了。比如说一个最简单的响应监听。
* @author CaiBo
* @date 日 上午10:59:30
* @version $Id$
public class SimpleConectionListener extends FalsifyingWebConnection {
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleConectionListener.class);
public SimpleConectionListener(WebClient webClient) throws IllegalArgumentException {
super(webClient);
public WebResponse getResponse(WebRequest request) throws IOException {
// 得到了这个响应,你想怎么处理就怎么处理了,不多写了
WebResponse response = super.getResponse(request);
String url = response.getWebRequest().getUrl().toString();
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("下载文件链接:"+ url);
if (check(url)) {
return createWebResponse(response.getWebRequest(),"","application/javascript", 200,"Ok");
private boolean check(String url) {
// TODO 加入你自己的判断什么的
这样我们就实现了一个自己的监听器,虽然比较简陋。现在我们把它设置到我们的webClient里面去。
WebClient webClient = new WebClient();
// 如果你好奇这里仅仅传进去没有返回,怎么webClient就改变了,你可以到这个实例化里面看下就明白了
new WebConnectionListener(webClient);
// 这个webClient在上一步之后,已经被监听了
webClient.getPage("someUrl");
结果就如上图所示了。
HtmlUnit还有其他许多并、串行控制方法,统一cookie,统一连接池等等,就不一一叙述了。
四、强大的缓存机制
为什么第一次获取一个网页可能会比较慢,但是第二次来拿就特别快呢?在HtmlUnit源码webClient类中的loadWebResponseFromWebConnection方法中我们可以看到。
final WebResponse fromCache = getCache().getCachedResponse(webRequest);
final WebResponse webR
if (fromCache != null) {
webResponse = new WebResponseFromCache(fromCache, webRequest);
webResponse = getWebConnection().getResponse(webRequest);
catch (final NoHttpResponseException e) {
return new WebResponse(responseDataNoHttpResponse_, webRequest, 0);
getCache().cacheIfPossible(webRequest, webResponse, null);
当然,它还有许多别的缓存机制来加快我们的访问速度,减少带宽压力。
相对于HttpClient来说,HtmlUnit的优点大致就这么多了,那相对于HttpClient来说,短程距离上(访问量小的情况下),HtmlUnit的性能是不如HttpClient的,这也很容易理解,HtmlUnit把HttpClient封装了一层嘛,在短程距离行不如HttpClient就很正常了,在具体的业务下,那就要看程序员水平了。
写太长我自己容易疏忽,大家看着也累,所以第一篇就只谈一下HtmlUnit的优势和劣势了,下一篇将讲述HttpClient的优势和劣势,之后再对他们进行详细比较以及介绍技巧。
PHP开发框架
缓存Memcache
服务器环境
ThinkSAAS商业授权:
ThinkSAAS为用户提供有偿个性定制开发服务
ThinkSAAS将为商业授权用户提供二次开发指导和技术支持
手机客户端
ThinkSAAS接收任何功能的Iphone(IOS)和Android手机的客户端定制开发服务
让ThinkSAAS更好,把建议拿来。httpClient如何利用会话继续访问
[问题点数:50分,无满意结帖,结帖人lishuiqing]
httpClient如何利用会话继续访问
[问题点数:50分,无满意结帖,结帖人lishuiqing]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2012年8月 总版技术专家分月排行榜第三2012年7月 总版技术专家分月排行榜第三
2014年8月 高性能开发大版内专家分月排行榜第一2013年11月 高性能开发大版内专家分月排行榜第一2012年12月 Java大版内专家分月排行榜第一2012年11月 Java大版内专家分月排行榜第一2012年10月 Java大版内专家分月排行榜第一2012年9月 Java大版内专家分月排行榜第一2012年8月 Java大版内专家分月排行榜第一2012年7月 Java大版内专家分月排行榜第一2012年6月 Java大版内专家分月排行榜第一2012年5月 Java大版内专家分月排行榜第一2012年4月 Java大版内专家分月排行榜第一2012年3月 Java大版内专家分月排行榜第一2012年2月 Java大版内专家分月排行榜第一2012年1月 Java大版内专家分月排行榜第一
本帖子已过去太久远了,不再提供回复功能。httpclient中使用HTTPS的方法 - jackyrong - ITeye技术网站
博客分类:
import javax.net.ssl.SSLC
import javax.net.ssl.TrustM
import javax.net.ssl.X509TrustM
import java.security.cert.CertificateE
import java.security.cert.X509C
import org.apache.http.client.ClientProtocolE
import org.apache.http.client.HttpC
import org.apache.http.client.ResponseH
import org.apache.http.client.methods.HttpG
import org.apache.http.conn.ClientConnectionM
import org.apache.http.conn.scheme.S
import org.apache.http.conn.scheme.SchemeR
import org.apache.http.conn.scheme.SchemeSocketF
import org.apache.http.conn.ssl.SSLSocketF
import org.apache.http.impl.client.BasicResponseH
import org.apache.http.impl.client.ClientParamsS
import org.apache.http.impl.client.DefaultHttpC
import org.apache.http.params.DefaultedHttpP
import org.apache.http.params.HttpP
public class HttpClientTest {
public static void main(String args[]) {
HttpClient httpclient = new DefaultHttpClient();
//Secure Protocol implementation.
SSLContext ctx = SSLContext.getInstance("SSL");
//Implementation of a trust manager for X509 certificates
X509TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] xcs,
String string) throws CertificateException {
public void checkServerTrusted(X509Certificate[] xcs,
String string) throws CertificateException {
public X509Certificate[] getAcceptedIssuers() {
ctx.init(null, new TrustManager[] { tm }, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx);
ClientConnectionManager ccm = httpclient.getConnectionManager();
//register https protocol in httpclient's scheme registry
SchemeRegistry sr = ccm.getSchemeRegistry();
sr.register(new Scheme("https", 443, ssf));
HttpGet httpget = new HttpGet("");
HttpParams params = httpclient.getParams();
params.setParameter("param1", "paramValue1");
httpget.setParams(params);
System.out.println("REQUEST:" + httpget.getURI());
ResponseHandler responseHandler = new BasicResponseHandler();
String responseB
responseBody = httpclient.execute(httpget, responseHandler);
System.out.println(responseBody);
// Create a response handler
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
浏览 20736
浏览: 3045588 次
来自: 广州
有没有一种简单的方法,对于任何JS时间插件生成的格式、任何语种 ...
胜多负少少时诵诗书是是是
as53315 写道中文报错 乱码。。DataTables导出 ...
这个是数据的多列,我想要的是控件的多列,
可以参考最新的文档:如何在eclipse jee中检出项目并转 ...

我要回帖

更多关于 httpclient使用详解 的文章

 

随机推荐