/** * 项目名:Crawler * 文件名:NewsInfoLoad.java * 作者:zhouyh * 时间:2014-9-4 上午08:47:06 * 描述:TODO(用一句话描述该文件做什么) */package com.newsTest.infoload;import java.io.IOException;import java.io.InputStream;import java.nio.charset.Charset;import java.util.regex.Matcher;import java.util.regex.Pattern;import org.apache.commons.io.IOUtils;import org.apache.commons.lang3.StringUtils;import org.apache.http.HttpEntity;import org.apache.http.client.ClientProtocolException;import org.apache.http.client.config.RequestConfig;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpGet;import org.apache.http.entity.ContentType;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.impl.client.LaxRedirectStrategy;import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;import org.apache.http.util.EntityUtils;import org.jsoup.Jsoup;import org.jsoup.nodes.Document;import org.jsoup.nodes.Element;import org.jsoup.select.Elements;import com.newsTest.constant.NewsConstant;/** * 类名: NewsInfoLoad * 包名: com.newsTest.infoload * 作者: zhouyh * 时间: 2014-9-4 上午08:47:06 * 描述: 新闻下载类 */public class NewsInfoLoad { //创建httpclient实例 private CloseableHttpClient httpClient = null; /** * * 私有的构造函数 * 作者:zhouyh */ private NewsInfoLoad(){ initHttpClient(); } /** * * 方法名:initHttpClient * 作者:zhouyh * 创建时间:2014-9-4 上午08:53:19 * 描述:创建httpClient连接池,并初始化httpclient */ private void initHttpClient(){ //创建httpclient连接池 PoolingHttpClientConnectionManager httpClientConnectionManager = new PoolingHttpClientConnectionManager(); httpClientConnectionManager.setMaxTotal(NewsConstant.MAX_TOTAL); //设置连接池线程最大数量 httpClientConnectionManager.setDefaultMaxPerRoute(NewsConstant.MAX_ROUTE_TOTAL); //设置单个路由最大的连接线程数量 //创建http request的配置信息 RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(NewsConstant.REQUEST_TIMEOUT) .setSocketTimeout(NewsConstant.REQUEST_SOCKET_TIME).build(); //设置重定向策略 LaxRedirectStrategy redirectStrategy = new LaxRedirectStrategy(); //初始化httpclient客户端 httpClient = HttpClients.custom().setConnectionManager(httpClientConnectionManager) .setDefaultRequestConfig(requestConfig).setUserAgent(NewsConstant.USER_AGENT).setRedirectStrategy(redirectStrategy).build(); } /********单例模式声明开始********************/ //类初始化时,自行实例化,饿汉式单例模式 private static final NewsInfoLoad newsInfoLoad = new NewsInfoLoad(); /** * * 方法名:getNewsInfoLoadInstance * 作者:zhouyh * 创建时间:2014-9-4 上午08:52:19 * 描述:单例的静态方法 * @return */ public static NewsInfoLoad getNewsInfoLoadInstance(){ return newsInfoLoad; } /************************单例模式声明结束********/ /** * * 方法名:loadSrc * 作者:zhouyh * 创建时间:2014-9-4 上午09:04:40 * 描述:根据给定的url下载信息 * @param url * @return */ public String loadSrc(String url){ String src = ""; if(null==url || "".equals(url)) { return src; //如果url为空或者null,则返回src空值 } //创建httpclient请求方式 HttpGet httpGet = new HttpGet(url); CloseableHttpResponse response = null; try { //执行请求 response = httpClient.execute(httpGet); //获得响应的消息实体 HttpEntity entity = response.getEntity(); //获取响应状态码 int statusCode = response.getStatusLine().getStatusCode(); //根据响应状态码进行处理 switch (statusCode) { case NewsConstant.RESPONSE_200: //请求返回成功 /** * inputstream转换成byte数组,然后将这个byte数组转成字符串(随便哪种编码方式) * 然后解析字符串中的编码方式。再利用这种编码方式将之前的byte数组转成正确的网页字符串 */ InputStream inputStream = entity.getContent(); byte[] contentBytes = IOUtils.toByteArray(inputStream); src = new String(contentBytes, "gb2312"); //获得响应字符集编码 ContentType contentType = ContentType.getOrDefault(entity); String charSet = null; try { Charset charset = contentType.getCharset(); if(charset != null){ charSet = charset.toString(); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } //如果没有获取到字符编码则从meta标签中获取 if(charSet==null || charSet.equals("")){ //判断页面的编码方式 Document document = Jsoup.parse(src); Elements elements = document.select("meta"); for(Element metaElement : elements){ if(metaElement!=null && StringUtils.isNotBlank(metaElement.attr("http-equiv")) && metaElement.attr("http-equiv").toLowerCase().equals("content-type")){ String content = metaElement.attr("content"); charSet = getCharSet(content); break; } } } //用获取的编码对contentBytes进行重新编码 if(!charSet.equalsIgnoreCase("gb2312")){ src = new String(contentBytes, charSet); } //去除特殊标签 src = replaceStr(src); break; default: break; } //关闭httpEntity流 EntityUtils.consume(entity); } catch (ClientProtocolException e) { // TODO 这里写异常处理的代码 e.printStackTrace(); } catch (IOException e) { // TODO 这里写异常处理的代码 e.printStackTrace(); } finally{ if(null != response){ try { //关闭response response.close(); } catch (IOException e) { // TODO 这里写异常处理的代码 e.printStackTrace(); } } } return src; } /** * * 方法名:getCharSet * 作者:zhouyh * 创建时间:2014-9-4 上午09:57:58 * 描述:根据正则获取正文编码方式 * @param content * @return */ private String getCharSet(String content){ String regex = ".*charset=([^;]*).*"; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(content); if(matcher.find()) return matcher.group(1); else return null; } /** * * 方法名:replaceStr * 作者:zhouyh * 创建时间:2014-9-4 上午09:03:53 * 描述:去除源码中的特殊字符 * @param src * @return */ public String replaceStr(String src){ if (src == null || "".equals(src)) return null; src = src.replaceAll(" ", ""); src = src.replaceAll("<", "<"); src = src.replaceAll(">", ">"); src = src.replaceAll(""", "\""); src = src.replaceAll(" ", " "); src = src.replaceAll("&", "&"); return src; } /** * 方法名:main * 作者:zhouyh * 创建时间:2014-9-4 上午08:47:06 * 描述:TODO(这里用一句话描述这个方法的作用) * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub String url = "http://blog.sina.com.cn/s/blog_5dade77b0101lpu7.html"; NewsInfoLoad newsLoad = NewsInfoLoad.getNewsInfoLoadInstance(); System.out.println(newsLoad.loadSrc(url)); } }