httpclient使用详解(爬虫)

一、简介

HttpClient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。HttpClient已经应用在很多的项目中,比如Apache Jakarta上很著名的另外两个开源项目Cactus和HTMLUnit都使用了HttpClient。

下载地址: http://hc.apache.org/downloads.cgi

二、特性

1. 基于标准、纯净的java语言。实现了Http1.0和Http1.1

2. 以可扩展的面向对象的结构实现了Http全部的方法(GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE)。

3. 支持HTTPS协议。

4. 通过Http代理建立透明的连接。

5. 利用CONNECT方法通过Http代理建立隧道的https连接。

6. Basic, Digest, NTLMv1, NTLMv2, NTLM2 Session, SNPNEGO/Kerberos认证方案。

7. 插件式的自定义认证方案。

8. 便携可靠的套接字工厂使它更容易的使用第三方解决方案。

9. 连接管理器支持多线程应用。支持设置最大连接数,同时支持设置每个主机的最大连接数,发现并关闭过期的连接。

10. 自动处理Set-Cookie中的Cookie。

11. 插件式的自定义Cookie策略。

12. Request的输出流可以避免流中内容直接缓冲socket服务器。

13. Response的输入流可以有效的从socket服务器直接读取相应内容。

14. 在http1.0和http1.1中利用KeepAlive保持持久连接。

15. 直接获取服务器发送的response code和 headers。

16. 设置连接超时的能力。

17. 实验性的支持http1.1 response caching。

18. 源代码基于Apache License 可免费获取。

三、使用方法

使用HttpClient发送请求、接收响应很简单,一般需要如下几步即可。

1. 创建HttpClient对象。

2. 创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。

3. 如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HetpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。

4. 调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。

5. 调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。

6. 释放连接。无论执行方法是否成功,都必须释放连接

四、样例

HttpClientRequestHandler类

[java]  view plain  copy
  1. package com.xiaojiang.httpclient;  
  2.   
  3. import java.io.ByteArrayInputStream;  
  4. import java.io.ByteArrayOutputStream;  
  5. import java.io.IOException;  
  6. import java.net.MalformedURLException;  
  7. import java.util.ArrayList;  
  8. import java.util.List;  
  9. import java.util.Map;  
  10. import java.util.zip.GZIPInputStream;  
  11.   
  12. import org.apache.commons.io.IOUtils;  
  13. import org.apache.http.Header;  
  14. import org.apache.http.HttpResponse;  
  15. import org.apache.http.NameValuePair;  
  16. import org.apache.http.client.HttpClient;  
  17. import org.apache.http.client.entity.UrlEncodedFormEntity;  
  18. import org.apache.http.client.methods.HttpGet;  
  19. import org.apache.http.client.methods.HttpPost;  
  20. import org.apache.http.message.BasicNameValuePair;  
  21. import org.apache.http.util.EntityUtils;  
  22. import org.jsoup.Jsoup;  
  23. import org.jsoup.nodes.Document;  
  24. import com.xiaojiang.exception.DataTaskException;  
  25.   
  26.   
  27. public class HttpClientRequestHandler {  
  28.   
  29.     private static final int ERROR_CODE = 1;  
  30.   
  31.       
  32.     /** 
  33.      * get方式提交数据 
  34.      */  
  35.     public static Document doGet(String url, String proxyIp, Integer proxyPort) throws DataTaskException{  
  36.           
  37.         //System.out.println("doGet中使用代理:"+proxyIp+":"+proxyPort);  
  38.           
  39.         HttpClient client = HttpConnectionManager.getHttpClient(proxyIp, proxyPort);  
  40.           
  41.         HttpGet httpGet = new HttpGet(url);  
  42.         httpGet.setHeader("Accept-Language""zh-cn,zh;q=0.5");  
  43.         httpGet.setHeader("Accept-Charset""GB2312,utf-8;q=0.7,*;q=0.7");  
  44.         httpGet.setHeader("Accept""text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");  
  45.         httpGet.setHeader("Accept-Encoding""gzip, deflate");  
  46.         httpGet.setHeader("User-Agent", HttpUserAgent.get());  
  47.           
  48.         try{  
  49.             //执行  
  50.             HttpResponse response = client.execute(httpGet);  
  51.             int statuCode = response.getStatusLine().getStatusCode();  
  52.             if(statuCode == 200){  
  53.                 String html = formatResponse(response);  
  54.                   
  55.                 if(html != null){  
  56.                     return Jsoup.parse(html);  
  57.                 }  
  58.                 return null;  
  59.                   
  60.             } else {  
  61.                 throw new DataTaskException(statuCode, "请求URL【"+url+"】,"+statuCode+"错误"null);  
  62.             }  
  63.         } catch (Exception e){  
  64.             throw new DataTaskException(ERROR_CODE, e.getMessage(), e);  
  65.         } finally {  
  66.             if(httpGet != null){  
  67.                 httpGet.abort();  
  68.             }  
  69.         }  
  70.     }  
  71.       
  72.   
  73.     /**  
  74.      * post方式提交  
  75.      * @throws DataTaskException   
  76.      */  
  77.     public static Document doPost(String url, Map<String,String> paramaters, String proxyIp, Integer proxyPort) throws DataTaskException{  
  78.           
  79.         HttpClient client = HttpConnectionManager.getHttpClient(proxyIp, proxyPort);  
  80.           
  81.         HttpPost request = new HttpPost(url);  
  82.           
  83.         request.setHeader("Accept""application/json, text/javascript, */*; q=0.01");  
  84.         request.setHeader("Accept-Encoding""gzip, deflate");  
  85.         request.setHeader("Accept-Language""zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");  
  86.         request.setHeader("Cache-Control""no-cache");  
  87.         request.setHeader("Connection""keep-alive");  
  88.         request.setHeader("Content-Type""application/x-www-form-urlencoded; charset=UTF-8");  
  89.   
  90.         // 创建名/值组列表  
  91.         List<NameValuePair> parameters = new ArrayList<NameValuePair>();  
  92.         for(String key : paramaters.keySet()){  
  93.             parameters.add(new BasicNameValuePair(key, paramaters.get(key)));  
  94.         }  
  95.           
  96.         try {  
  97.             // 创建UrlEncodedFormEntity对象  
  98.             UrlEncodedFormEntity formEntiry = new UrlEncodedFormEntity(parameters);  
  99.             request.setEntity(formEntiry);  
  100.               
  101.             // 执行请求  
  102.             HttpResponse response = client.execute(request);  
  103.             int statuCode = response.getStatusLine().getStatusCode();  
  104.               
  105.             if (statuCode == 200) {  
  106.                 String html = formatResponse(response);  
  107.                   
  108.                 if(html != null){  
  109.                     return Jsoup.parse(html);  
  110.                 }  
  111.                           
  112.                 return null;  
  113.   
  114.             } else if (statuCode == 404) {  
  115.                   
  116.                 throw new DataTaskException(ERROR_CODE, "请求URL【"+url+"】,404错误"null);  
  117.             }  
  118.         } catch (Exception e) {  
  119.               
  120.             throw new DataTaskException(ERROR_CODE, e.getMessage(), e);  
  121.           
  122.         } finally {  
  123.             if(request != null){  
  124.                 request.abort();  
  125.             }  
  126.         }  
  127.         return null;  
  128.     }  
  129.       
  130.     /**  
  131.      * 格式化请求结果  
  132.      * @throws DataTaskException   
  133.      */  
  134.     private static String formatResponse(HttpResponse response) throws DataTaskException {  
  135.           
  136.         ByteArrayInputStream bis = null;  
  137.         try{  
  138.             Header contentEncoding = response.getFirstHeader("Content-Encoding");  
  139.               
  140.             if(contentEncoding == null){  
  141.                 return EntityUtils.toString(response.getEntity(),"UTF-8");  
  142.             } else {  
  143.                   
  144.                 String charset = "utf-8";  
  145.                 Header contentType = response.getFirstHeader("Content-Type");  
  146.                   
  147.                 if(contentType != null){  
  148.                     String contentTypeStr = contentType.getValue();  
  149.                     if(contentTypeStr != null && !"".equals(contentTypeStr)){  
  150.                         charset = contentTypeStr.substring(contentTypeStr.indexOf("=") + 1,contentTypeStr.length());  
  151.                           
  152.                     }  
  153.                 }  
  154.                   
  155.                 String contentEncodingType = contentEncoding.getValue();  
  156.                 if(contentEncodingType.equalsIgnoreCase("gzip")){  
  157.                     if(response.toString().contains("soufun"))  
  158.                         charset = "gb2312";  
  159.                       
  160.                     byte[] bytes = IOUtils.toByteArray(response.getEntity().getContent());  
  161.                     bis = new ByteArrayInputStream(bytes);  
  162.                       
  163.                     return uncompress(bis ,charset);  
  164.                 }  
  165.                   
  166.             }  
  167.               
  168.         } catch(Exception e) {  
  169.             throw new DataTaskException(ERROR_CODE, "格式化HttpResponse出错", e);  
  170.         } finally {  
  171.             if(bis != null){  
  172.                 try {  
  173.                     bis.close();  
  174.                 } catch (IOException e) {  
  175.                     throw new DataTaskException(ERROR_CODE, "格式化HttpResponse出错", e);  
  176.                 }  
  177.             }  
  178.         }  
  179.           
  180.         return null;  
  181.     }  
  182.   
  183.       
  184.     /** 
  185.      * GZIP解压 
  186.      */  
  187.     private static String uncompress(ByteArrayInputStream in, String charset) {  
  188.   
  189.         ByteArrayOutputStream out = new ByteArrayOutputStream();  
  190.           
  191.         try {  
  192.             GZIPInputStream gunzip = new GZIPInputStream(in);  
  193.             byte[] buffer = new byte[256];  
  194.             int n;  
  195.             while((n = gunzip.read(buffer)) >=0 ){  
  196.                 out.write(buffer, 0, n);  
  197.             }  
  198.             return out.toString(charset);  
  199.               
  200.         } catch (IOException e) {  
  201.             e.printStackTrace();  
  202.         }  
  203.         return null;  
  204.     }  
  205.       
  206.       
  207. }  

HttpConnectionManager类

[java]  view plain  copy
  1. package com.xiaojiang.httpclient;  
  2.   
  3. import org.apache.http.HttpHost;  
  4. import org.apache.http.client.HttpClient;  
  5. import org.apache.http.conn.ClientConnectionManager;  
  6. import org.apache.http.conn.params.ConnManagerParams;  
  7. import org.apache.http.conn.params.ConnPerRouteBean;  
  8. import org.apache.http.conn.params.ConnRouteParams;  
  9. import org.apache.http.conn.scheme.PlainSocketFactory;  
  10. import org.apache.http.conn.scheme.Scheme;  
  11. import org.apache.http.conn.scheme.SchemeRegistry;  
  12. import org.apache.http.conn.ssl.SSLSocketFactory;  
  13. import org.apache.http.impl.client.DefaultHttpClient;  
  14. import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;  
  15. import org.apache.http.params.BasicHttpParams;  
  16. import org.apache.http.params.HttpConnectionParams;  
  17. import org.apache.http.params.HttpParams;  
  18.   
  19. public class HttpConnectionManager {  
  20.   
  21.     private static HttpParams httpParams;  
  22.     private static ClientConnectionManager connectionManager;  
  23.       
  24.     //最大连接数  
  25.     public final static int MAX_TOTAL_CONNECTIONS = 800;  
  26.       
  27.     //获取连接的最大等待时间  
  28.     public final static int WAIT_TIMEOUT = 60000;  
  29.       
  30.     //每个路由最大连接数  
  31.     public final static int MAX_ROUTE_CONNECTIONS = 400;  
  32.       
  33.     //连接超时时间  
  34.     public final static int CONNECT_TIMEOUT = 60000;  
  35.       
  36.     //读取超时时间  
  37.     public final static int READ_TIMEOUT = 60000;  
  38.       
  39.     static {  
  40.         httpParams = new BasicHttpParams();  
  41.         // 设置最大连接数  
  42.         ConnManagerParams.setMaxTotalConnections(httpParams, MAX_TOTAL_CONNECTIONS);  
  43.         // 设置获取连接的最大等待时间  
  44.         ConnManagerParams.setTimeout(httpParams, WAIT_TIMEOUT);  
  45.         // 设置每个路由最大连接数  
  46.         ConnPerRouteBean connPerRoute = new ConnPerRouteBean(MAX_ROUTE_CONNECTIONS);  
  47.         ConnManagerParams.setMaxConnectionsPerRoute(httpParams,connPerRoute);  
  48.           
  49.         // 设置连接超时时间  
  50.         HttpConnectionParams.setConnectionTimeout(httpParams, CONNECT_TIMEOUT);  
  51.         // 设置读取超时时间  
  52.         HttpConnectionParams.setSoTimeout(httpParams, READ_TIMEOUT);  
  53.       
  54.         SchemeRegistry registry = new SchemeRegistry();  
  55.         registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));  
  56.         registry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));  
  57.   
  58.         connectionManager = new ThreadSafeClientConnManager(httpParams, registry);  
  59.     }  
  60.       
  61.       
  62.     public static HttpClient getHttpClient(String proxyIp, Integer proxyPort){  
  63.         DefaultHttpClient client = new DefaultHttpClient(connectionManager, httpParams);  
  64.           
  65.         if(proxyIp !=null && proxyPort !=null){  
  66.             HttpHost proxy = new HttpHost(proxyIp, proxyPort);  
  67.             client.getParams().setParameter(ConnRouteParams.DEFAULT_PROXY, proxy);  
  68.         }  
  69.         return client;  
  70.     }  
  71.       
  72.       
  73.       
  74.       
  75.       
  76.       
  77.       
  78. }  

HttpUserAgent类package com.xiaojiang.httpclient;

[java]  view plain  copy
  1. package com.xiaojiang.httpclient;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5. import java.util.Random;  
  6.   
  7. public class HttpUserAgent {  
  8.   
  9.       
  10. private static List<String> agents;  
  11.       
  12.     static{  
  13.         agents = new ArrayList<String>();  
  14.           
  15.         //IE  
  16.         agents.add("Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)");  
  17.         agents.add("Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2)");  
  18.         agents.add("Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");  
  19.         agents.add("Mozilla/4.0 (compatible; MSIE 5.0; Windows NT)");  
  20.           
  21.         //Firefox   
  22.         agents.add("Mozilla/5.0 (Windows; U; Windows NT 5.2) Gecko/2008070208 Firefox/3.0.1 ");  
  23.         agents.add("Mozilla/5.0 (Windows; U; Windows NT 5.1) Gecko/20070309 Firefox/2.0.0.3 ");  
  24.         agents.add("Mozilla/5.0 (Windows; U; Windows NT 5.1) Gecko/20070803 Firefox/1.5.0.12");  
  25.         agents.add("Mozilla/5.0 (Windows NT 6.3; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0)");  
  26.         agents.add("Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0");  
  27.           
  28.         //Opera   
  29.         agents.add("Opera/9.27 (Windows NT 5.2; U; zh-cn)");  
  30.         agents.add("Opera/8.0 (Macintosh; PPC Mac OS X; U; en)");  
  31.         agents.add("Mozilla/5.0 (Macintosh; PPC Mac OS X; U; en) Opera 8.0");  
  32.           
  33.         //Safari    
  34.         agents.add("Mozilla/5.0 (Windows; U; Windows NT 5.2) AppleWebKit/525.13 (KHTML, like Gecko) Version/3.1 Safari/525.13");  
  35.         agents.add("Mozilla/5.0 (iPhone; U; CPU like Mac OS X) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/4A93 Safari/419.3");  
  36.   
  37.         //Chrome    
  38.         agents.add("Mozilla/5.0 (Windows; U; Windows NT 5.2) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13");  
  39.         agents.add("Mozilla/5.0 (Windows NT 5.2) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.122 Safari/534.30");  
  40.           
  41.         //Navigator     
  42.         agents.add("Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.12) Gecko/20080219 Firefox/2.0.0.12 Navigator/9.0.0.6");  
  43.           
  44.         //360极速浏览器     
  45.         agents.add("Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ;  QIHU 360EE)");  
  46.           
  47.     }  
  48.       
  49.       
  50.     public static String get(){  
  51.         return agents.get(new Random().nextInt(agents.size()-1));  
  52.     }  
  53. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值