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);
}
}
相关推荐
在C#中,我们可以使用HttpClient类来发起HTTP请求,获取网页源代码。例如: ```csharp using System.Net.Http; using System.Threading.Tasks; public async Task<string> GetHtmlAsync(string url) { using (var...
在描述中提到的“完整爬取数据源码及jar”,意味着这个压缩包可能包含了一个已经编译好的Java应用和相关的源代码。源码可能包含了以下组件: 1. HTTP请求库:如Apache HttpClient或者OkHttp,用于向目标网站发送GET...
【标题】"企查查信息爬取代码.zip"所涉及的知识点主要...实际学习时,应结合源代码深入理解每个部分的功能和作用,逐步掌握企查查信息爬取的全过程。同时,注意不断更新和优化代码,以适应网站的变化和提高爬取效率。
本压缩包文件包含的"搜索网页采集网络爬虫java源代码"为开发者提供了一个实现这一功能的实例。 首先,让我们深入了解一下Java网络爬虫的基础知识: 1. **HTTP协议**:网络爬虫的基础是HTTP(超文本传输协议),它...
这个压缩包可能包含源代码、教程或示例,帮助用户理解如何实现网页数据的自动化获取。 【描述】中的关键词“基于读取网页的数据”表明此项目的核心是Web抓取,这是通过编程方式从互联网上自动收集信息的一种技术。...
本教程将详细讲解如何使用ESP8266通过HTTP协议获取网页内容。 首先,我们需要了解HTTP协议的基本概念。HTTP(超文本传输协议)是一种用于分布式、协作式和超媒体信息系统的应用层协议。它是互联网上应用最广泛的一...
2. **限制爬取速度**:避免对目标网站造成过大压力,可以通过设置延时或限制并发数量来控制爬取速度。 3. **错误处理**:处理可能出现的HTTP错误、网络异常、文件I/O错误等。 4. **cookies和session**:如果网站需要...
通过理解这个工具的源代码,开发者可以学习到网页爬虫技术在实际项目中的应用,以及如何根据需求调整和扩展爬虫功能。 首先,我们需要了解C#网页爬虫的基本概念。C#作为.NET框架下的主要编程语言,具有丰富的库和...
在IT行业中,网络爬虫是一种常见的技术,用于自动地抓取网页内容,为数据分析、信息检索等任务提供数据源。本项目"BlogJava博客文章爬取代码"专注于使用Java编程语言来实现对BlogJava博客平台的文章内容进行爬取。...
标题中的“C#蜘蛛、网络爬虫源代码”是指使用C#编程语言编写的网络爬虫程序的源代码。网络爬虫,也称为网页抓取器或数据抓取工具,是一种自动化程序,它能遍历互联网上的网页,收集所需信息。在C#中实现爬虫,通常会...
1. **发起HTTP请求**:首先,源代码会使用System.Net命名空间中的HttpWebRequest或HttpClient类来向目标URL发送请求,获取网页的HTML内容。 2. **解析HTML**:获取到HTML后,代码会使用HTML解析库(如...
根据压缩包子文件的文件名称列表(1、5、2、3、4),我们可以推测这些可能是项目中的源代码文件,按照通常的命名习惯,可能分别代表了不同的功能模块或步骤,例如: 1. 可能是网络请求和响应处理的模块,如发送GET...
在这个"简易的网页爬虫java源代码"中,我们可以深入理解如何使用Java实现一个基本的网络爬虫,特别是在使用广度优先搜索(BFS)策略时的关键概念和技术。 首先,广度优先搜索是一种在图或树中遍历节点的算法,常...
5. **使用Eclipse打开**:Eclipse是一个广泛使用的Java集成开发环境(IDE),项目文件夹`BlogCrawler`包含了源代码、配置文件和可能的依赖库。用户需要在Eclipse中导入该项目,然后编译并运行代码。 此外,值得注意...
在提供的“DownMap_tianditu.java”源代码中,可以看到具体的实现细节,如URL构造、网络请求逻辑、文件保存策略等。而“image.png”可能是爬取过程中的示例瓦片或者爬虫工作原理的示意图。通过阅读和分析这个代码,...
【标题】"C#整站爬虫源代码"是一个关于使用C#编程语言构建网络爬虫的项目。这个源代码的目的是抓取指定网站上的所有超链接,进而下载该网站的全部资源。开发者在此基础上对原有的代码进行了改进,使之更加完善。 在...
1. **Python爬虫源代码**: - Python爬虫源代码通常涉及到requests库用于发送HTTP请求,BeautifulSoup或lxml库解析HTML或XML文档,可能还会使用到re正则表达式处理文本,以及如pandas和numpy库进行数据清洗和分析。...
压缩包中的"com"文件可能包含了项目的源代码组织结构,通常在Java项目中,"com"是顶级包名,下面可能有多个子包,分别存放不同模块的代码,如"util"用于存放工具类,"model"用于定义数据模型,"controller"或...
同时,将爬取成功的网页源代码和错误信息分别保存到本地文件,便于后期分析和调试。 在实际应用中,网页爬虫还需要考虑反爬策略。许多网站会设置cookies、session或User-Agent来识别和限制爬虫。因此,我们可能需要...
Java爬虫源代码是用于自动化抓取网页信息的程序,主要应用于数据分析、信息提取和搜索引擎优化等领域。在Java中开发爬虫,可以利用其强大的类库和跨平台特性,实现高效稳定的数据抓取。本项目包含以下几个核心知识点...