欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

HttpClient的爬取网页源代码

程序员文章站 2022-05-31 08:28:19
...
包UTIL;

进口java.io.BufferedReader中;
进口java.io.IOException异常;
进口的java.io.InputStream;
进口java.io.InputStreamReader中;
进口java.text.DateFormat中;
进口java.text.SimpleDateFormat的;
进口的java.util.ArrayList;
进口java.util.Date;
进口的java.util.HashMap;
进口的java.util.List;
进口的java.util.Map;
进口java.util.Set中;
进口java.util.Map.Entry;
进口java.util.zip.GZIPInputStream;

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

/ **
* @author六味
*日期:2009年12月18日
*
* TODO
* HttpClient的辅助类
* /
public类HttpClientHelper
{

/ **
* HttpClient的连接超时,读取数据超时时间设置(单位:毫秒)
* /
公共静态最终诠释HTTPCLIENT_CONNECTION_TIMEOUT = 30000;
公共静态最终诠释HTTPCLIENT_SO_TIMEOUT = 120000;
公共静态最终诠释HTTPMETHOD_SO_TIMEOUT = 5000;

//让的ConnectionManager管理httpclientconnection时是否关闭连接
私有静态布尔alwaysClose = FALSE;
私人静态字符串defaultEncode =“UTF-8”;

私有静态最后的DateFormat DATE_FORMAT =新的SimpleDateFormat(“YYYY-MM-DD HH:MM:SS”);

/ **
*获取HttpClient的连接,并设置相关参数
*
* @return
* /
公共静态HttpClient的getHttpClient()
{
HttpClient的客户端=新的HttpClient(新SimpleHttpConnectionManager(alwaysClose));
HttpConnectionManagerParams managerParams = client.getHttpConnectionManager()getParams()方法。
//设置连接超时时间(单位毫秒)
managerParams.setConnectionTimeout(HTTPCLIENT_CONNECTION_TIMEOUT);
//设置读数据超时时间(单位毫秒)
managerParams.setSoTimeout(HTTPCLIENT_SO_TIMEOUT);
返回客户端;
}

/ **
*获取HttpClient的连接,并设置相关参数
*
* @参数logonSite
* @参数logonPort
* @参数协议
* @return
* /
公共静态HttpClient的getHttpClient(最后弦乐logonSite,最终诠释logonPort,最后弦乐协议)
{
HttpClient的客户端=新的HttpClient(新SimpleHttpConnectionManager(alwaysClose));
client.getHostConfiguration()setHost(logonSite,logonPort,协议)。
HttpConnectionManagerParams managerParams = client.getHttpConnectionManager()getParams()方法。
//设置连接超时时间(单位毫秒)
managerParams.setConnectionTimeout(HTTPCLIENT_CONNECTION_TIMEOUT);
//设置读数据超时时间(单位毫秒)
managerParams.setSoTimeout(HTTPCLIENT_SO_TIMEOUT);
返回客户端;
}

私有静态列表<标题> getHeaders(地图<String,字符串>头)
{
名单<标题> =报头的ArrayList新<标题>();
布尔includeUserAgent = FALSE;
如果(空=头&&假== header.isEmpty()!)
{
集<进入<字符串,字符串>> =的entrySet header.entrySet();
对于(进入<String,字符串>项:的entrySet)
{
如果(假== includeUserAgent
&&“用户代理”.equals(entry.getKey()))
{
includeUserAgent = TRUE;
}
headers.add(新报头(entry.getKey(),entry.getValue()));
}
}

如果(假== includeUserAgent)
{
headers.add(新标题(
“用户代理”,
“Mozilla的/ 4.0(兼容; MSIE 7.0; Windows NT的5.1; GTB5; .NET CLR 1.1.4322; .NET CLR 2.0 0.50727; Alexa工具条; MAXTHON 2.0)“));
}
返回头;
}

私有静态的NameValuePair [] getPairs(地图<String,字符串> POSTDATA)
{
如果(空== || POSTDATA postData.isEmpty())
{
返回NULL;
}

设置<输入<字符串,字符串>> =的entrySet postData.entrySet();
INT DATALENGTH = entrySet.size();
的NameValuePair [] =对新的NameValuePair [DATALENGTH]
INT I = 0;
对于(进入<String,字符串>项:的entrySet)
{
双[我++] =新的NameValuePair(entry.getKey(),entry.getValue());
}
返回对;
}

/ **
*请求网页内容信息
*
* @参数的HttpClient
* @参数reqUrl
*参数标题
* @参数POSTDATA
*参数编码
* @return
* /
公共静态字符串doRequest(HttpClient的HttpClient的,字符串reqUrl,
地图<字符串, String>的头,地图<String,字符串> POSTDATA,字符串编码)
{
字符串htmlContent = NULL;
如果(空== HttpClient的)
{
返回htmlContent;
}

//请求编码设置
编码=(空==编码defaultEncode:编码);

//头部请求信息
列表<标题> =头getHeaders(头);

的System.out.println(“[”+ DATE_FORMAT.format(新的Date())+“] - doRequest - ”+ reqUrl);

//交方式
,如果(空= POSTDATA!)
{
的PostMethod的PostMethod =新EncodePostMethod(reqUrl,编码);
对于(头tempHeader:头)
{
postMethod.setRequestHeader(tempHeader);
}

//后参数设置
的NameValuePair [] = PARAMS getPairs(POSTDATA);
如果(空=参数!)
{
postMethod.setRequestBody(PARAMS);
}

//提取网页内容
htmlContent = executeMethod(HttpClient的,后方法,编码,getWebSite(reqUrl));
}
其他
{
GetMethod getMethod =新的实现getMethod(reqUrl);
对于(头tempHeader:头)
{
getMethod.setRequestHeader(tempHeader);
}

//提取网页内容
htmlContent = executeMethod(HttpClient的,getMethod,编码,NULL);
}
返回htmlContent;
}

私有静态字符串getWebSite(字符串reqUrl)
{
字符串网站= NULL;
如果(空== reqUrl || reqUrl.isEmpty())
{
返回网站;
}

字符串前缀=“HTTP://”;
如果(reqUrl.startsWith(前缀))
{
INT指数= reqUrl.substring(prefix.length())的indexOf(“/”)+ prefix.length();
网站= reqUrl.substring(0,索引);
}
返回网站;
}

/ **
*通过列举HTTPMethod获取网页内容
*
* @参数的HttpClient
* @参数requestMethod
*参数编码
*参数的网站
* @return
* /
私有静态字符串executeMethod(HttpClient的HttpClient的,列举HTTPMethod requestMethod,编码字符串,字符串网站)
{
字符串responseContent = NULL;
如果(空== HttpClient的)
{
返回responseContent;
}

//判断是否请求加密数据
的布尔dataEncrypt = FALSE;
头acceptEncoding = requestMethod.getRequestHeader(“接受编码”);
如果(!空= acceptEncoding
。&& acceptEncoding.getValue()包含(“gzip的”))
{
dataEncrypt = TRUE;
}

的InputStream responseStream = NULL;
尝试
{
INT状态= httpClient.executeMethod(requestMethod);
如果(HttpStatus.SC_OK ==状态)
{
responseStream = requestMethod.getResponseBodyAsStream();
responseContent = getContentByStream(dataEncrypt新GZIPInputStream(responseStream):responseStream,编码);
responseStream.close();
}
//返回代码为301302303307时,表示页面己经重定向,则重新请求位置的URL,这在一些登录授权取饼干时很重要
否则,如果(HttpStatus.SC_MOVED_PERMANENTLY ==状态
|| HttpStatus.SC_MOVED_TEMPORARILY ==状态
|| HttpStatus.SC_SEE_OTHER ==状态
|| HttpStatus.SC_TEMPORARY_REDIRECT ==状态)
{
//读取新的URL地址
头球冲顶= requestMethod.getResponseHeader(“位置”);
如果(!头= NULL)
{
字符串的redirectUrl = header.getValue();
如果(零=的redirectUrl!
&&假== redirectUrl.isEmpty())
{
responseContent =无效;
如果(空==的redirectUrl || redirectUrl.isEmpty())
{
的redirectUrl =“/”;
}

如果(假== redirectUrl.startsWith(“HTTP://”)
!&&空=网站)
{
如果(website.startsWith(“/”))
{
的redirectUrl =网站+的redirectUrl;
}
其他
{
的redirectUrl =网站+“/”+的redirectUrl;
}
}

GetMethod重定向=新的实现getMethod(的redirectUrl);
头引荐= requestMethod.getRequestHeader(“引荐”);
如果(空=引用者!)
{
redirect.addRequestHeader(引荐);
}
头的cookie = requestMethod.getRequestHeader(“曲奇”);
如果(空=饼干!)
{
redirect.addRequestHeader(饼干);
}
状态= httpClient.executeMethod(重定向);
如果(HttpStatus.SC_OK ==状态)
{
responseStream = redirect.getResponseBodyAsStream();
responseContent = getContentByStream(responseStream,编码);
responseStream.close();
}
}

} //端头

} //结束状态

}赶上(例外五)
{
e.printStackTrace();
}最后
{
如果(requestMethod!= NULL)
{
requestMethod.releaseConnection();
}
}
返回responseContent;
}

/ **
*按照指定编码从流中读取信息
*
* @参数inStream中
*参数编码
* @返回
*引发IOException
* /
公共静态字符串getContentByStream(的InputStream inStream中,字符串编码)抛出IOException异常
{
如果(空= =插播广告)
{
返回NULL;
}

StringBuilder的内容=新的StringBuilder();
//采用指定编码格式读取流内容
的BufferedReader读者=新的BufferedReader(新的InputStreamReader(插播广告,编码));
字符串消息= NULL;
而(空=(消息= reader.readLine())!)
{
content.append(消息);
content.append(“\ r \ n”);
}
//关闭读取器,释放资源
reader.close();
返回(content.toString());
}

/ **
*内部类,继承于的PostMethod,用来指定邮政请求编码格式
* /
公共静态类EncodePostMethod扩展的PostMethod
{
私人字符串编码= NULL;

公共EncodePostMethod(URL字符串,字符串编码)
{
超(URL);
this.encode =编码;
}

@覆盖
公共字符串getRequestCharSet()
{
// TODO自动生成方法存根
回报(this.encode);
}

}

/ **
*测试
*
* @参数ARGS
* /
公共静态无效的主要(字串[] args)
{
//System.setProperty("http.proxyHost“,”165.228.128.10“);
//System.setProperty("http.proxyPort“,”3128“);
//System.setProperty("http.proxySet“,”真“);


字符串reqUrl =“ http://news.39.net/jbyw/index.html ”;
reqUrl =“ http://news.39.net/a/2010722/1404231.html ”;
地图<String,字符串>标题=新的HashMap <String,字符串>();
headers.put(“接受编码”,“gzip的,放气”);

HttpClient的HttpClient的= getHttpClient();
字符串htmlContent = doRequest(HttpClient的,reqUrl,头,空,“GBK”);
的System.out.println(htmlContent);

}
}