最近在做收索引擎,需要对网页进行爬虫,课程建议使用python写爬虫,但是因为没学过python,所以尝试使用java来写爬虫。为了高效的爬取网页,使用HttpClient爬取网页,下面就来展示怎样使用HttpClient进行爬虫。
一、HttpClient
HttpClient 是 Apache 下的一个开源项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。下载地址:http://hc.apache.org/downloads.cgi,
这里下载4.53.zip版本,可以通过自己的系统下载不同压缩包,一般windows下载zip包,linux下载tar.gz包。完成下载后解压。第三方jar包在lib文件夹下可以根据自己的需要导入相应的jar包,如果担心报错可以全部导入。
二、爬取网页过程
使用 HttpClient 需要以下 6 个步骤:
1. 创建 HttpClient 的实例
2. 创建某种连接方法的实例,选择get或post请求
3. 确定是否有参数
4. 执行请求,并获得 response响应,然后获得HttpEntity对象
5. 释放连接。无论执行方法是否成功,都必须释放连接
6. 对得到后的内容进行处理
下面对这6个步骤详细说明。
1. 创建 HttpClient 的实例
//1.创建httpclient对象
CloseableHttpClient httpclient=HttpClients.createDefault();
2.
创建某种连接方法的实例,
选择get或post请求。创建的参数是一个访问URI,这个URI可以直接以String的形式指定,也可以通过URI类来动态生成。
//2.选择get请求
//创建一个URI
URI uri=null;
try {
uri=new URIBuilder()
.setScheme("http")//协议
.setHost("www.baidu.com")//地址
.setPath("index.php")//文件
//.setParameter("ip", "0")//参数,可以为若干个
.build();//创建
} catch (Exception e) {
e.printStackTrace();
}
HttpGet httpget=null;
if(uri!=null){
//get请求
httpget=new HttpGet(uri);
//post请求
//HttpPost httppost=new HttpPost(uri);
}
//直接指定URI
//get请求
//httpget=new HttpGet("http://www.baidu.com/index.php");
//post请求
//HttpPost httppost=new HttpPost("http://www.baidu.com/index.php");
3. 确定是否有参数。创建的连接方法需要进行配置,如设置超时时间。另外对于防护较好的网站禁止机器爬取内容,因此可以设置连接为模仿人工从浏览器访问。
// 3.确定是否有参数
// 设置为人工访问
httpget.setHeader("User-Agent",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36");
// 设置超时
RequestConfig request = RequestConfig.custom()
.setConnectTimeout(5000)//连接超时
.setConnectionRequestTimeout(5000)//请求超时
.setSocketTimeout(5000).build();//Socket协议超时
// 设置连接
httpget.setConfig(request);
4.
执行请求,并获得
response响应,然后获得HttpEntity对象。通过以上步骤一个连接并没有真正的建立,因此需要创建请求连接,并获得响应对象response。
另外可以查看response的一些内容如状态、长度和版本等内容来判断Http请求是否成功和分析获取的内容。获取HttpEntity对象,该对象就是请求获得的Html文档。
//4.执行请求
CloseableHttpResponse respose=null;//为了关闭respose提前声明
try {
//执行请求
respose=httpclient.execute(httpget);
System.out.println("版本信息"+respose.getProtocolVersion());
//状态码:200正常,402禁止,404未找到,500服务器错误,更多状态码可以通过百度百科查看
System.out.println("状态码:"+respose.getStatusLine().toString());
//获得httpentity对象
HttpEntity entity=respose.getEntity();
System.out.println("================================");
if(entity!=null){//可能为空
//长度
System.out.println("长度"+entity.getContentLength());
//以UTF-8字符编码打印网页的内容,字符编码是个很重要的问题,爬取网页时一定要
//通过浏览器确定网页使用的字符编码,否则爬的内容可能出现乱码。
System.out.println("内容:"+EntityUtils.toString(entity,"UTF-8"));
//关闭应该关闭的资源(不包括连接),适当的释放资源 ,关闭底层的流。
EntityUtils.consume(entity);
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
5. 释放连接。无论执行方法是否成功,都必须释放连接。
try {
//关闭链接
respose.close();
} catch (IOException e) {
e.printStackTrace();
}
6. 对得到后的内容进行处理,处理这篇文章不进行分析,下一篇文章java 网页解析使用第三方分析工具Jsoup对网页进行分析。
三、java实现
以下使用一个类来展示上述过程,爬取的网页是http协议下的百度首页,这个页面的javascript内容太多了,整个控制台都没有显示完。所以输出的内容仅仅输出请求的状态。
package httpget;
import java.io.IOException;
import java.net.URI;
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.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
/*
* @vamesary
* 使用httpclient访问抓取百度首页
*/
public class DoHttpGet{
/*
* HttpClient4.5实例,
*/
public static void HttpGet45(){
String GETURI="www.baidu.com";
String CHARACTER="UTF-8";
String HTTP="http";
//1.创建httpclient对象
CloseableHttpClient httpclient=HttpClients.createDefault();
//2.选择get请求
//创建一个URI
URI uri=null;
try {
uri=new URIBuilder()
.setScheme(HTTP)//协议
.setHost(GETURI)//地址
//.setPath("index.php")//文件
//.setParameter("ip", "0")//参数,可以为若干个
.build();//创建
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(uri);
HttpGet httpget=null;
if(uri!=null){
//get请求
httpget=new HttpGet(uri);
//post请求
//HttpPost httppost=new HttpPost(uri);
}
//直接指定URI
//get请求
//httpget=new HttpGet("http://www.baidu.com");
//post请求
//HttpPost httppost=new HttpPost("http://www.baidu.com");
// 3.确定是否有参数
// 设置为人工访问
httpget.setHeader("User-Agent",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36");
// 设置超时
RequestConfig request = RequestConfig.custom()
.setConnectTimeout(5000)//连接超时
.setConnectionRequestTimeout(5000)//请求超时
.setSocketTimeout(5000).build();//Socket协议超时
// 设置连接
httpget.setConfig(request);
//4.执行请求
CloseableHttpResponse respose=null;//为了关闭respose提前声明
try {
//执行请求
respose=httpclient.execute(httpget);
System.out.println("版本信息"+respose.getProtocolVersion());
//状态码:200正常,402禁止,404未找到
System.out.println("状态码:"+respose.getStatusLine().toString());
//获得httpentity对象
HttpEntity entity=respose.getEntity();
if(entity!=null){//可能为空
//以UTF-8字符编码打印网页的内容,字符编码是个很重要的问题,爬取网页时一定要
//通过浏览器确定网页使用的字符编码,否则爬的内容可能出现乱码。
//System.out.println("内容:"+EntityUtils.toString(entity,"UTF-8"));
//关闭应该关闭的资源(不包括连接),适当的释放资源 ,关闭底层的流。
EntityUtils.consume(entity);
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
//关闭链接
respose.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main (String args[] ){
HttpGet45();
}
}
输出:
http://www.baidu.com
版本信息HTTP/1.1
状态码:HTTP/1.1 200 OK
版本信息HTTP/1.1
状态码:HTTP/1.1 200 OK
需要对网页进行分析的可以查看下一篇文章:
java 网页解析