HttpClient在java中的使用

本文介绍了一次从 HttpClient 3.6 到 4.3 的升级过程,详细展示了如何处理获取网页原始编码的问题。通过 Java 代码示例,包括使用 Jsoup 解析 HTML 和正则表达式来确定网页编码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目中一直在使用HttpClient,版本是3.6的,负责维护的同事离职后,就没有更新过,在这次项目改版中决定对这块进行升级到4.3版本,查阅了一些资料写了部分出来,还不是很完善,后期有时间在更新

这里对httpclient如何获取原页面编码进行了一些处理,感觉还不是很完善,后期想到在处理吧

具体的理论东西就不说了,代码中注释都有一些说明。

直接上代码

[java]  view plain copy
  1. /** 
  2.   * 项目名:Crawler 
  3.   * 文件名:NewsInfoLoad.java 
  4.   * 作者:zhouyh 
  5.   * 时间:2014-9-4 上午08:47:06 
  6.   * 描述:TODO(用一句话描述该文件做什么)  
  7.   */  
  8. package com.newsTest.infoload;  
  9.   
  10. import java.io.IOException;  
  11. import java.io.InputStream;  
  12. import java.nio.charset.Charset;  
  13. import java.util.regex.Matcher;  
  14. import java.util.regex.Pattern;  
  15.   
  16. import org.apache.commons.io.IOUtils;  
  17. import org.apache.commons.lang3.StringUtils;  
  18. import org.apache.http.HttpEntity;  
  19. import org.apache.http.client.ClientProtocolException;  
  20. import org.apache.http.client.config.RequestConfig;  
  21. import org.apache.http.client.methods.CloseableHttpResponse;  
  22. import org.apache.http.client.methods.HttpGet;  
  23. import org.apache.http.entity.ContentType;  
  24. import org.apache.http.impl.client.CloseableHttpClient;  
  25. import org.apache.http.impl.client.HttpClients;  
  26. import org.apache.http.impl.client.LaxRedirectStrategy;  
  27. import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;  
  28. import org.apache.http.util.EntityUtils;  
  29. import org.jsoup.Jsoup;  
  30. import org.jsoup.nodes.Document;  
  31. import org.jsoup.nodes.Element;  
  32. import org.jsoup.select.Elements;  
  33.   
  34. import com.newsTest.constant.NewsConstant;  
  35.   
  36. /** 
  37.  * 类名: NewsInfoLoad 
  38.  * 包名: com.newsTest.infoload 
  39.  * 作者: zhouyh 
  40.  * 时间: 2014-9-4 上午08:47:06 
  41.  * 描述: 新闻下载类 
  42.  */  
  43. public class NewsInfoLoad {  
  44.     //创建httpclient实例  
  45.     private CloseableHttpClient httpClient = null;  
  46.     /** 
  47.      *  
  48.      * 私有的构造函数 
  49.      * 作者:zhouyh 
  50.      */  
  51.     private NewsInfoLoad(){  
  52.         initHttpClient();  
  53.     }  
  54.       
  55.     /** 
  56.      *  
  57.      * 方法名:initHttpClient 
  58.      * 作者:zhouyh 
  59.      * 创建时间:2014-9-4 上午08:53:19 
  60.      * 描述:创建httpClient连接池,并初始化httpclient 
  61.      */  
  62.     private void initHttpClient(){  
  63.         //创建httpclient连接池  
  64.         PoolingHttpClientConnectionManager httpClientConnectionManager = new PoolingHttpClientConnectionManager();  
  65.         httpClientConnectionManager.setMaxTotal(NewsConstant.MAX_TOTAL);    //设置连接池线程最大数量  
  66.         httpClientConnectionManager.setDefaultMaxPerRoute(NewsConstant.MAX_ROUTE_TOTAL);    //设置单个路由最大的连接线程数量  
  67.         //创建http request的配置信息  
  68.         RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(NewsConstant.REQUEST_TIMEOUT)  
  69.                                         .setSocketTimeout(NewsConstant.REQUEST_SOCKET_TIME).build();  
  70.         //设置重定向策略  
  71.         LaxRedirectStrategy redirectStrategy = new LaxRedirectStrategy();  
  72.         //初始化httpclient客户端  
  73.         httpClient = HttpClients.custom().setConnectionManager(httpClientConnectionManager)  
  74.                         .setDefaultRequestConfig(requestConfig).setUserAgent(NewsConstant.USER_AGENT).setRedirectStrategy(redirectStrategy).build();  
  75.     }  
  76.       
  77.     /********单例模式声明开始********************/  
  78.     //类初始化时,自行实例化,饿汉式单例模式  
  79.     private static final NewsInfoLoad newsInfoLoad = new NewsInfoLoad();  
  80.     /** 
  81.      *  
  82.      * 方法名:getNewsInfoLoadInstance 
  83.      * 作者:zhouyh 
  84.      * 创建时间:2014-9-4 上午08:52:19 
  85.      * 描述:单例的静态方法 
  86.      * @return 
  87.      */  
  88.     public static NewsInfoLoad getNewsInfoLoadInstance(){  
  89.         return newsInfoLoad;  
  90.     }  
  91.       
  92.     /************************单例模式声明结束********/  
  93.       
  94.     /** 
  95.      *  
  96.      * 方法名:loadSrc 
  97.      * 作者:zhouyh 
  98.      * 创建时间:2014-9-4 上午09:04:40 
  99.      * 描述:根据给定的url下载信息 
  100.      * @param url 
  101.      * @return 
  102.      */  
  103.     public String loadSrc(String url){  
  104.         String src = "";  
  105.         if(null==url || "".equals(url)) {  
  106.             return src; //如果url为空或者null,则返回src空值  
  107.         }  
  108.         //创建httpclient请求方式  
  109.         HttpGet httpGet = new HttpGet(url);  
  110.         CloseableHttpResponse response = null;  
  111.           
  112.         try {  
  113.             //执行请求  
  114.             response = httpClient.execute(httpGet);  
  115.             //获得响应的消息实体  
  116.             HttpEntity entity = response.getEntity();  
  117.             //获取响应状态码  
  118.             int statusCode = response.getStatusLine().getStatusCode();  
  119.             //根据响应状态码进行处理  
  120.             switch (statusCode) {  
  121.             case NewsConstant.RESPONSE_200:  
  122.                 //请求返回成功  
  123.                 /** 
  124.                  * inputstream转换成byte数组,然后将这个byte数组转成字符串(随便哪种编码方式) 
  125.                  * 然后解析字符串中的编码方式。再利用这种编码方式将之前的byte数组转成正确的网页字符串 
  126.                  */  
  127.                 InputStream inputStream = entity.getContent();  
  128.                 byte[] contentBytes = IOUtils.toByteArray(inputStream);  
  129.                 src = new String(contentBytes, "gb2312");  
  130.                 //获得响应字符集编码  
  131.                 ContentType contentType = ContentType.getOrDefault(entity);  
  132.                 String charSet = null;  
  133.                 try {  
  134.                     Charset charset = contentType.getCharset();  
  135.                     if(charset != null){  
  136.                          charSet = charset.toString();  
  137.                     }  
  138.                 } catch (Exception e) {  
  139.                     // TODO: handle exception  
  140.                     e.printStackTrace();  
  141.                 }               
  142.                 //如果没有获取到字符编码则从meta标签中获取  
  143.                 if(charSet==null || charSet.equals("")){  
  144.                     //判断页面的编码方式  
  145.                     Document document = Jsoup.parse(src);  
  146.                       
  147.                     Elements elements = document.select("meta");    
  148.                     for(Element metaElement : elements){    
  149.                         if(metaElement!=null && StringUtils.isNotBlank(metaElement.attr("http-equiv")) && metaElement.attr("http-equiv").toLowerCase().equals("content-type")){    
  150.                             String content = metaElement.attr("content");    
  151.                             charSet = getCharSet(content);                            
  152.                             break;    
  153.                         }    
  154.                     }    
  155.                 }  
  156.                 //用获取的编码对contentBytes进行重新编码  
  157.                 if(!charSet.equalsIgnoreCase("gb2312")){  
  158.                     src = new String(contentBytes, charSet);  
  159.                 }                 
  160.                 //去除特殊标签  
  161.                 src = replaceStr(src);  
  162.                                   
  163.                 break;  
  164.   
  165.             default:  
  166.                 break;  
  167.             }  
  168.               
  169.             //关闭httpEntity流  
  170.             EntityUtils.consume(entity);  
  171.               
  172.         } catch (ClientProtocolException e) {  
  173.             // TODO 这里写异常处理的代码  
  174.             e.printStackTrace();  
  175.         } catch (IOException e) {  
  176.             // TODO 这里写异常处理的代码  
  177.             e.printStackTrace();  
  178.         } finally{  
  179.             if(null != response){  
  180.                 try {  
  181.                     //关闭response  
  182.                     response.close();  
  183.                 } catch (IOException e) {  
  184.                     // TODO 这里写异常处理的代码  
  185.                     e.printStackTrace();  
  186.                 }  
  187.             }  
  188.         }  
  189.           
  190.         return src;  
  191.     }  
  192.       
  193.       
  194.       
  195.     /** 
  196.      *  
  197.      * 方法名:getCharSet 
  198.      * 作者:zhouyh 
  199.      * 创建时间:2014-9-4 上午09:57:58 
  200.      * 描述:根据正则获取正文编码方式 
  201.      * @param content 
  202.      * @return 
  203.      */  
  204.     private String getCharSet(String content){    
  205.         String regex = ".*charset=([^;]*).*";    
  206.         Pattern pattern = Pattern.compile(regex);    
  207.         Matcher matcher = pattern.matcher(content);    
  208.         if(matcher.find())    
  209.             return matcher.group(1);    
  210.         else    
  211.             return null;    
  212.     }  
  213.       
  214.       
  215.     /** 
  216.      *  
  217.      * 方法名:replaceStr 
  218.      * 作者:zhouyh 
  219.      * 创建时间:2014-9-4 上午09:03:53 
  220.      * 描述:去除源码中的特殊字符 
  221.      * @param src 
  222.      * @return 
  223.      */  
  224.     public String replaceStr(String src){  
  225.         if (src == null || "".equals(src)) return null;  
  226.         src = src.replaceAll("<!--""");  
  227.         src = src.replaceAll("-->""");  
  228.         src = src.replaceAll("<""<");  
  229.         src = src.replaceAll(">"">");  
  230.         src = src.replaceAll(""", "\"");  
  231.         src = src.replaceAll(" "" ");  
  232.         src = src.replaceAll("&""&");  
  233.         return src;  
  234.     }  
  235.       
  236.     /** 
  237.      * 方法名:main 
  238.      * 作者:zhouyh 
  239.      * 创建时间:2014-9-4 上午08:47:06 
  240.      * 描述:TODO(这里用一句话描述这个方法的作用) 
  241.      * @param args 
  242.      */  
  243.     public static void main(String[] args) {  
  244.         // TODO Auto-generated method stub  
  245.         String url = "http://blog.sina.com.cn/s/blog_5dade77b0101lpu7.html";  
  246.           
  247.         NewsInfoLoad newsLoad = NewsInfoLoad.getNewsInfoLoadInstance();  
  248.           
  249.         System.out.println(newsLoad.loadSrc(url));  
  250.     }  
  251.       
  252. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值