httpclient 模拟浏览器动作需注意的cookie和HTTP头等信息

转自:http://resolute.javaeye.com/blog/491701

 

commons-httpclient是apache下的一个开源项目,提供了一个纯java实现的http客户端,使用它可以很方便发送HTTP请求,接受HTTP应答,自动管理Cookie等等。 

对于contact-list类库来说,需要使用的功能有,自动管理Cookie,设置HTTP头,发送HTTP请求,接受HTTP应答,转发HTTP重定向,还有输出HTTP请求/应答日志,下面对这些功能的实现进行解释: 

1. 自动管理Cookie 
view source 
print? 
1.public EmailImporter(String email, String password, String encoding) { 
2.    ...... 
3.    client = new HttpClient(); 
4.    client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY); 
5.    client.getParams().setParameter("http.protocol.single-cookie-header", true); 
6.} 

其中将HttpClient的Cookie策略设置为CookiePolicy.BROWSER_COMPATIBILITY,即表示java client将按照浏览器的方式来自动处理Cookie。当然你也可以在运行过程中手动调整cookie,比如: 

hotmail登录之前需要设置当前时间的Cookie: 
view source 
print? 
1.client.getState().addCookie(new Cookie("login.live.com", "CkTst", "G" + new Date().getTime())); 

不过,httpclient似乎没有提供删除cookie的功能,于是我增加了两个cookie管理的接口,一个是保留指定的cookies,一个是删除指定的cookies: 
view source 
print? 
01.protected void retainCookies(String[] cookieNames) { 
02.    Cookie[] cookies = client.getState().getCookies(); 
03.    ArrayList<Cookie> retainCookies = new ArrayList<Cookie>(); 
04.    for (Cookie cookie : cookies) { 
05.        if (Arrays.binarySearch(cookieNames, cookie.getName()) >= 0) { 
06.            retainCookies.add(cookie); 
07.        } 
08.    } 
09.    client.getState().clearCookies(); 
10.    client.getState().addCookies(retainCookies.toArray(new Cookie[0])); 
11.} 
12. 
13.protected void removeCookies(String[] cookieNames) { 
14.    Cookie[] cookies = client.getState().getCookies(); 
15.    ArrayList<Cookie> retainCookies = new ArrayList<Cookie>(); 
16.    for (Cookie cookie : cookies) { 
17.        if (Arrays.binarySearch(cookieNames, cookie.getName()) < 0) { 
18.            retainCookies.add(cookie); 
19.        } 
20.    } 
21.    client.getState().clearCookies(); 
22.    client.getState().addCookies(retainCookies.toArray(new Cookie[0])); 
23.} 

2. 设置HTTP头: 

http头的设置,可以让邮件服务器认为是在和浏览器打交道,而避免被refuse的可能: 
view source 
print? 
01.private void setHeaders(HttpMethod method) { 
02.    method.setRequestHeader("Accept", "text/html,application/xhtml+xml,application/xml;"); 
03.    method.setRequestHeader("Accept-Language", "zh-cn"); 
04.    method.setRequestHeader("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3"); 
05.    method.setRequestHeader("Accept-Charset", encoding); 
06.    method.setRequestHeader("Keep-Alive", "300"); 
07.    method.setRequestHeader("Connection", "Keep-Alive"); 
08.    method.setRequestHeader("Cache-Control", "no-cache"); 
09.} 

另外,在GET和POST的时候设置referer值,以及在POST的时候设置Content-Type: 
view source 
print? 
1.protected String doPost(String actionUrl, NameValuePair[] params, String referer) throws HttpException, IOException { 
2.    ...... 
3.    method.setRequestHeader("Referer", referer); 
4.    method.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 
5.    ...... 
6.} 

3. 发送HTTP请求,接收HTTP应答。在contact-list中只使用了GET和POST请求,我也做了简单的封装: 
view source 
print? 
01.protected String doGet(String url, String referer) throws HttpException, IOException { 
02.    GetMethod method = new GetMethod(url); 
03.    setHeaders(method); 
04.    method.setRequestHeader("Referer", referer); 
05.    // log request 
06.    client.executeMethod(method); 
07.    String responseStr = readInputStream(method.getResponseBodyAsStream()); 
08.    // log response 
09.    method.releaseConnection(); 
10.    lastUrl = method.getURI().toString(); 
11.    return responseStr; 
12.} 
13. 
14.protected String doPost(String actionUrl, NameValuePair[] params, String referer) throws HttpException, IOException { 
15.    PostMethod method = new PostMethod(actionUrl); 
16.    setHeaders(method); 
17.    method.setRequestHeader("Referer", referer); 
18.    method.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 
19.    method.setRequestBody(params); 
20.    // log request 
21.    client.executeMethod(method); 
22.    String responseStr = readInputStream(method.getResponseBodyAsStream()); 
23.    // log response 
24.    method.releaseConnection(); 
25.    if (method.getResponseHeader("Location") != null) { 
26.        // do redirect 
27.    } else { 
28.        lastUrl = method.getURI().toString(); 
29.        return responseStr; 
30.    } 
31.} 

4. HTTP重定向,主要是两种,一种是根据HTTP头的Location 
view source 
print? 
1.if (method.getResponseHeader("Location").getValue().startsWith("http")) { 
2.    return doGet(method.getResponseHeader("Location").getValue()); 
3.} else { 
4.    return doGet("http://" + getResponseHost(method) + method.getResponseHeader("Location").getValue()); 
5.} 

另一种是根据javascript中的window.location.replace。 

5. 输出请求/应答日志,这个对调试非常重要: 
view source 
print? 
01.private void logGetRequest(GetMethod method) throws URIException { 
02.    logger.debug("do get request: " + method.getURI().toString()); 
03.    logger.debug("header:/n" + getHeadersStr(method.getRequestHeaders())); 
04.    logger.debug("cookie:/n" + getCookieStr()); 
05.} 
06. 
07.private void logGetResponse(GetMethod method, String responseStr) throws URIException { 
08.    logger.debug("do get response: " + method.getURI().toString()); 
09.    logger.debug("header: /n" + getHeadersStr(method.getResponseHeaders())); 
10.    logger.debug("body: /n" + responseStr); 
11.} 
12. 
13.private void logPostRequest(PostMethod method) throws URIException { 
14.    logger.debug("do post request: " + method.getURI().toString()); 
15.    logger.debug("header:/n" + getHeadersStr(method.getRequestHeaders())); 
16.    logger.debug("body:/n" + getPostBody(method.getParameters())); 
17.    logger.debug("cookie:/n" + getCookieStr()); 
18.} 
19. 
20.private void logPostResponse(PostMethod method, String responseStr) throws URIException { 
21.    logger.debug("do post response:" + method.getURI().toString()); 
22.    logger.debug("header:/n" + getHeadersStr(method.getResponseHeaders())); 
23.    logger.debug("body:/n" + responseStr); 
24.} 
25. 
26.private String getHeadersStr(Header[] headers) { 
27.    StringBuilder builder = new StringBuilder(); 
28.    for (Header header : headers) { 
29.        builder.append(header.getName()).append(": ").append(header.getValue()).append("/n"); 
30.    } 
31.    return builder.toString(); 
32.} 
33. 
34.private String getPostBody(NameValuePair[] postValues) { 
35.    StringBuilder builder = new StringBuilder(); 
36.    for (NameValuePair pair : postValues) { 
37.        builder.append(pair.getName()).append(":").append(pair.getValue()).append("/n"); 
38.    } 
39.    return builder.toString(); 
40.} 
41. 
42.private String getCookieStr() { 
43.    Cookie[] cookies = client.getState().getCookies(); 
44.    StringBuilder builder = new StringBuilder(); 
45.    for (Cookie cookie : cookies) { 
46.        builder.append(cookie.getDomain()).append(":") 
47.               .append(cookie.getName()).append("=").append(cookie.getValue()).append(";") 
48.               .append(cookie.getPath()).append(";") 
49.               .append(cookie.getExpiryDate()).append(";") 
50.               .append(cookie.getSecure()).append(";/n"); 
51.    } 
52.    return builder.toString(); 
53.}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值