`

HttpClient爬取网页源代码

    博客分类:
  • java
 
阅读更多

package util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.zip.GZIPInputStream;

import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.SimpleHttpConnectionManager;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.params.HttpMethodParams;

/**
* @author liuwei
* date:Dec 18, 2009
*
* TODO 
* HttpClient辅助类
*/
public class HttpClientHelper
{

/**
* HttpClient 连接超时、读取数据超时时间设置(单位:毫秒)
*/
public static final int HTTPCLIENT_CONNECTION_TIMEOUT = 30000;
public static final int HTTPCLIENT_SO_TIMEOUT = 120000;
public static final int HTTPMETHOD_SO_TIMEOUT = 5000;

// 让connectionmanager管理httpclientconnection时是否关闭连接
private static boolean alwaysClose = false;
private static String defaultEncode = "UTF-8";

private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

/**
* 获取HttpClient连接,并设置相关参数

* @return
*/
public static HttpClient getHttpClient()
{
HttpClient client = new HttpClient(new SimpleHttpConnectionManager(alwaysClose));
HttpConnectionManagerParams managerParams = client.getHttpConnectionManager().getParams();
// 设置连接超时时间(单位毫秒) 
managerParams.setConnectionTimeout(HTTPCLIENT_CONNECTION_TIMEOUT); 
// 设置读数据超时时间(单位毫秒) 
managerParams.setSoTimeout(HTTPCLIENT_SO_TIMEOUT); 
return client;
}

/**
* 获取HttpClient连接,并设置相关参数

* @param logonSite
* @param logonPort
* @param protocol
* @return
*/
public static HttpClient getHttpClient(final String logonSite, final int logonPort, final String protocol)
{
HttpClient client = new HttpClient(new SimpleHttpConnectionManager(alwaysClose));
client.getHostConfiguration().setHost(logonSite, logonPort, protocol);
HttpConnectionManagerParams managerParams = client.getHttpConnectionManager().getParams();
// 设置连接超时时间(单位毫秒) 
managerParams.setConnectionTimeout(HTTPCLIENT_CONNECTION_TIMEOUT); 
// 设置读数据超时时间(单位毫秒) 
managerParams.setSoTimeout(HTTPCLIENT_SO_TIMEOUT); 
return client;
}

private static List<Header> getHeaders(Map<String, String> header)
{
List<Header> headers = new ArrayList<Header>();
boolean includeUserAgent = false;
if (null != header && false == header.isEmpty())
{
Set<Entry<String, String>> entrySet = header.entrySet();
for (Entry<String, String> entry : entrySet)
{
if (false == includeUserAgent 
&& "User-Agent".equals(entry.getKey())) 
{
includeUserAgent = true;
}
headers.add(new Header(entry.getKey(), entry.getValue()));
}
}

if (false == includeUserAgent)
{
headers.add(new Header(
"User-Agent", 
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; GTB5; .NET CLR 1.1.4322; .NET CLR 2.0.50727; Alexa Toolbar; MAXTHON 2.0)"));
}
return headers;
}

private static NameValuePair[] getPairs(Map<String, String> postData) 
{
if (null == postData || postData.isEmpty())
{
return null;
}

Set<Entry<String, String>> entrySet = postData.entrySet();
int dataLength = entrySet.size();
NameValuePair[] pairs = new NameValuePair[dataLength];
int i = 0;
for (Entry<String, String> entry : entrySet)
{
pairs[i++] = new NameValuePair(entry.getKey(), entry.getValue());
}
return pairs;
}

/**
* 请求网页内容信息

* @param httpClient
* @param reqUrl
* @param header
* @param postData
* @param encode
* @return
*/
public static String doRequest(HttpClient httpClient, String reqUrl, 
Map<String, String> header, Map<String, String> postData, String encode) 
{
String htmlContent = null;
if (null == httpClient)
{
return htmlContent;
}

// 请求编码设置
encode = (null == encode ? defaultEncode : encode);

// 头部请求信息
List<Header> headers = getHeaders(header);

System.out.println("[ " + DATE_FORMAT.format(new Date()) + " ] -- doRequest -- "+reqUrl);

// post方式
if (null != postData)
{
PostMethod postMethod = new EncodePostMethod(reqUrl, encode);
for (Header tempHeader : headers)
{
postMethod.setRequestHeader(tempHeader);
}

// post参数设置
NameValuePair[] params = getPairs(postData);
if (null != params)
{
postMethod.setRequestBody(params);
}

// 提取网页内容
htmlContent = executeMethod(httpClient, postMethod, encode, getWebSite(reqUrl));
}
else
{
GetMethod getMethod = new GetMethod(reqUrl);
for (Header tempHeader : headers)
{
getMethod.setRequestHeader(tempHeader);
}

// 提取网页内容
htmlContent = executeMethod(httpClient, getMethod, encode, null);
}
return htmlContent;
}

private static String getWebSite(String reqUrl)
{
String website = null;
if (null == reqUrl || reqUrl.isEmpty())
{
return website;
}

String prefix = "http://";
if (reqUrl.startsWith(prefix)) 
{
int index = reqUrl.substring(prefix.length()).indexOf("/") + prefix.length();
website = reqUrl.substring(0, index);
}
return website;
}

/**
* 通过HttpMethod 获取网页内容

* @param httpClient
* @param requestMethod
* @param encode
* @param website
* @return
*/
private static String executeMethod(HttpClient httpClient, HttpMethod requestMethod, String encode, String website)
{
String responseContent = null;
if (null == httpClient)
{
return responseContent;
}

// 判断是否请求加密数据
boolean dataEncrypt = false;
Header acceptEncoding = requestMethod.getRequestHeader("accept-encoding");
if (null != acceptEncoding
&& acceptEncoding.getValue().contains("gzip"))
{
dataEncrypt = true;
}

InputStream responseStream = null;
try
{
int status = httpClient.executeMethod(requestMethod);
if (HttpStatus.SC_OK == status)
{
responseStream = requestMethod.getResponseBodyAsStream();
responseContent = getContentByStream(dataEncrypt ? new GZIPInputStream(responseStream) : responseStream, encode);
responseStream.close();

// 返回代码为301,302,303,307时,表示页面己经重定向,则重新请求location的url,这在一些登录授权取cookie时很重要
else if (HttpStatus.SC_MOVED_PERMANENTLY == status 
|| HttpStatus.SC_MOVED_TEMPORARILY == status
|| HttpStatus.SC_SEE_OTHER == status
|| HttpStatus.SC_TEMPORARY_REDIRECT == status)
{
//读取新的URL地址
Header header = requestMethod.getResponseHeader("location");
if (header != null)
{
String redirectUrl = header.getValue();
if (null != redirectUrl 
&& false == redirectUrl.isEmpty())
{
responseContent = null;
if (null == redirectUrl || redirectUrl.isEmpty())
{
redirectUrl = "/";
}

if (false == redirectUrl.startsWith("http://") 
&& null != website) 
{
if (website.startsWith("/")) 
{
redirectUrl = website + redirectUrl;
}
else
{
redirectUrl = website + "/" + redirectUrl;
}
}

GetMethod redirect = new GetMethod(redirectUrl);
Header referer = requestMethod.getRequestHeader("Referer");
if (null != referer)
{
redirect.addRequestHeader(referer);
}
Header cookie = requestMethod.getRequestHeader("Cookie");
if (null != cookie)
{
redirect.addRequestHeader(cookie);
}
status = httpClient.executeMethod(redirect);
if (HttpStatus.SC_OK == status)
{
responseStream = redirect.getResponseBodyAsStream();
responseContent = getContentByStream(responseStream, encode);
responseStream.close();
}
}

} // end-headers

} // end-status

} catch (Exception e)
{
e.printStackTrace();
} finally
{
if (requestMethod != null)
{
requestMethod.releaseConnection();
}
}
return responseContent;
}

/**
* 按照指定编码从流中读取信息

* @param inStream
* @param encode
* @return
* @throws IOException
*/
public static String getContentByStream(InputStream inStream, String encode) throws IOException
{
if (null == inStream)
{
return null;
}

StringBuilder content = new StringBuilder();
// 采用指定编码格式读取流内容
BufferedReader reader = new BufferedReader(new InputStreamReader(inStream, encode));
String message = null;
while (null != (message = reader.readLine()))
{
content.append(message);
content.append("\r\n");
}
// 关闭读取器,释放资源
reader.close();
return (content.toString());
}

/**
* 内部类,继承于PostMethod,用来指定Post请求编码格式
*/
public static class EncodePostMethod extends PostMethod
{
private String encode = null;

public EncodePostMethod(String url, String encode)
{
super(url);
this.encode = encode;
}

@Override
public String getRequestCharSet()
{
// TODO Auto-generated method stub
return (this.encode);
}

}

/**
* 测试

* @param args
*/
public static void main(String[] args)
{
//System.setProperty("http.proxyHost", "165.228.128.10");
//System.setProperty("http.proxyPort", "3128");
//System.setProperty("http.proxySet", "true");


String reqUrl = "http://news.39.net/jbyw/index.html";
reqUrl = "http://news.39.net/a/2010722/1404231.html";
Map<String, String> headers = new HashMap<String, String>();
headers.put("Accept-Encoding", "gzip,deflate");

HttpClient httpClient = getHttpClient();
String htmlContent = doRequest(httpClient, reqUrl, headers, null, "gbk");
System.out.println(htmlContent);

}
}

分享到:
评论

相关推荐

    基于微信小程序的在线办公小程序答辩PPT.pptx

    基于微信小程序的在线办公小程序答辩PPT.pptx

    机器学习(预测模型):2000年至2015年期间193个国家的预期寿命和相关健康因素的数据

    这个数据集来自世界卫生组织(WHO),包含了2000年至2015年期间193个国家的预期寿命和相关健康因素的数据。它提供了一个全面的视角,用于分析影响全球人口预期寿命的多种因素。数据集涵盖了从婴儿死亡率、GDP、BMI到免疫接种覆盖率等多个维度,为研究者提供了丰富的信息来探索和预测预期寿命。 该数据集的特点在于其跨国家的比较性,使得研究者能够识别出不同国家之间预期寿命的差异,并分析这些差异背后的原因。数据集包含22个特征列和2938行数据,涉及的变量被分为几个大类:免疫相关因素、死亡因素、经济因素和社会因素。这些数据不仅有助于了解全球健康趋势,还可以辅助制定公共卫生政策和社会福利计划。 数据集的处理包括对缺失值的处理、数据类型转换以及去重等步骤,以确保数据的准确性和可靠性。研究者可以使用这个数据集来探索如教育、健康习惯、生活方式等因素如何影响人们的寿命,以及不同国家的经济发展水平如何与预期寿命相关联。此外,数据集还可以用于预测模型的构建,通过回归分析等统计方法来预测预期寿命。 总的来说,这个数据集是研究全球健康和预期寿命变化的宝贵资源,它不仅提供了历史数据,还为未来的研究和政策制

    基于微信小程序的“健康早知道”微信小程序答辩PPT.pptx

    基于微信小程序的“健康早知道”微信小程序答辩PPT.pptx

    基于微信小程序的电影交流平台答辩PPT.pptx

    基于微信小程序的电影交流平台答辩PPT.pptx

    计算机字符编码GB18030.PDF

    计算机字符编码GB18030

    Hive 操作基础(进阶版)多级分区数据文件2

    Hive 操作基础(进阶版)多级分区数据文件2

    基于java的贫困生管理系统答辩PPT.pptx

    基于java的贫困生管理系统答辩PPT.pptx

    pandas-2.1.4-cp312-cp312-win_amd64.zip

    pandas whl安装包,对应各个python版本和系统(具体看资源名字),找准自己对应的下载即可! 下载后解压出来是已.whl为后缀的安装包,进入终端,直接pip install pandas-xxx.whl即可,非常方便。 再也不用担心pip联网下载网络超时,各种安装不成功的问题。

    TA_Lib轮子无需编译-TA_Lib-0.4.18-cp38-cp38-win32.whl.zip

    TA_lib库(whl轮子),直接pip install安装即可,下载即用,非常方便,各个python版本对应的都有。 使用方法: 1、下载下来解压; 2、确保有python环境,命令行进入终端,cd到whl存放的目录,直接输入pip install TA_lib-xxxx.whl就可以安装,等待安装成功,即可使用! 优点:无需C++环境编译,下载即用,方便

    课设毕设基于SpringBoot+Vue的瑜伽体验课预约系统源码可运行.zip

    本压缩包资源说明,你现在往下拉可以看到压缩包内容目录 我是批量上传的基于SpringBoot+Vue的项目,所以描述都一样;有源码有数据库脚本,系统都是测试过可运行的,看文件名即可区分项目~ |Java|SpringBoot|Vue|前后端分离| 开发语言:Java 框架:SpringBoot,Vue JDK版本:JDK1.8 数据库:MySQL 5.7+(推荐5.7,8.0也可以) 数据库工具:Navicat 开发软件: idea/eclipse(推荐idea) Maven包:Maven3.3.9+ 系统环境:Windows/Mac

    tornado-6.2b2.tar.gz

    tornado-6.2b2.tar.gz

    javawe论坛项目 原生技术

    javawe论坛项目 原生技术

    tornado-6.2b1-cp310-cp310-macosx_10_9_universal2.whl

    tornado-6.2b1-cp310-cp310-macosx_10_9_universal2.whl

    基于司机信用评价的货运管理系统(springboot+vue+mysql+说明文档).zip

    随着物流行业的快速发展,货运管理变得愈发重要。为了提高货运效率,确保货物安全,我们开发了这款基于司机信用评价的货运管理系统。 该系统主要包含了货物信息管理、订单评价管理、货主管理等多个功能模块。在货物信息管理模块中,用户可以查看和管理货物的详细信息,包括货物名称、规格、装车状态、运输状态以及卸货状态等,方便用户随时掌握货物的动态。 订单评价管理模块是该系统的核心之一,它允许货主对司机的服务进行评价,系统会根据评价数据对司机进行信用评分。这一功能不仅有助于提升司机的服务质量,还能为货主提供更加可靠的货运选择。 此外,货主管理模块提供了货主信息的录入、修改和查询等功能,方便用户管理自己的货主资料。系统界面简洁明了,以蓝色为主色调,设计现代且专业,为用户提供了良好的使用体验。 通过该系统,用户可以轻松实现货物信息的查看和管理,对司机的服务进行评价,提高货运效率和服务质量。同时,系统也为司机提供了一个展示自我、提升信用的平台,有助于推动物流行业的健康发展。

    毕业生交流学习平台 SSM毕业设计 附带论文.zip

    毕业生交流学习平台 SSM毕业设计 附带论文 启动教程:https://www.bilibili.com/video/BV1GK1iYyE2B

    基于java的广场舞团答辩PPT.pptx

    基于java的广场舞团答辩PPT.pptx

    基于java的基于SSM的校园音乐平台答辩PPT.pptx

    基于java的基于SSM的校园音乐平台答辩PPT.pptx

    安装包JIRATimeSLA

    Jira插件安装包

    【java毕业设计】基于图像识别与分类的中国蛇类识别系统源码(springboot+vue+mysql+说明文档).zip

    项目经过测试均可完美运行! 环境说明: 开发语言:java jdk:jdk1.8 数据库:mysql 5.7+ 数据库工具:Navicat11+ 管理工具:maven 开发工具:idea/eclipse

    tornado-6.2b2-cp37-abi3-win_amd64.whl

    tornado-6.2b2-cp37-abi3-win_amd64.whl

Global site tag (gtag.js) - Google Analytics