目录标题
技术介绍
HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、功能丰富的、支持 HTTP 协议的客户端编程工具包。相比于 java.net
包中提供的 URLConnection 与HttpURLConnection,HttpClient 增加了易用性和灵活性。在 Java 网络爬虫实战中,经常使用 HttpClient 向服务器发送请求,获取响应资源。
网络爬虫就是用程序帮助我们访问网络上的资源,我们一直以来都是使用HTTP协议访问互联网的网页,网络爬虫需要编写程序,在这里使用同样的HTTP协议访问网页。 这里我们使用Java的HTTP协议客户端 HttpClient这个技术,来实现抓取网页数据。
有什么优点?
- 易用性和灵活性: HttpClient 提供了更简洁、易读的 API,使得发送 HTTP 请求和处理响应变得更加直观和容易。其面向对象的设计和灵活的配置选项使得开发者能够更容易地进行定制和扩展。
- 功能丰富: HttpClient 提供了丰富的功能和扩展,包括但不限于请求和响应拦截器、连接池管理、Cookie 管理、身份验证、代理支持等。这些功能大大简化了复杂任务的处理,例如处理会话、保持持久连接等。
- 性能优越: HttpClient 的设计注重性能和效率,内部采用了连接池等机制,减少了连接的建立和关闭次数,提高了系统的整体性能。同时,HttpClient 采用了并发处理机制,允许多个请求并行执行,提高了系统的吞吐量。
- 协议支持: HttpClient 支持多种协议,不仅仅局限于 HTTP 和 HTTPS,还包括 FTP、HTTP/2 等。这使得 HttpClient 成为一个通用的网络编程工具,适用于各种场景。
- 错误处理和异常管理: HttpClient 提供了详细的错误处理和异常管理机制,使得开发者能够更容易地诊断和处理网络请求中可能出现的问题。这对于构建健壮的爬虫系统非常重要。
怎么在项目中引入?
环境准备:会使用Maven新建项目,在pom.xml中导入依赖:
xml
<!-- HttpClient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
请求URL
HttpClient 的重要功能是执行 HTTP 请求方法,获取响应资源。在执行具体的请求方法之前,需要实例化 HttpClient
HttpClient 的重要功能是执行 HTTP 请求方法,获取响应资源。在执行具体的请求方法之前,需要实例化 HttpClient。
基本步骤
-
创建 HttpClient 实例
CloseableHttpClient httpClient4 = HttpClients.createDefault();
-
创建请求方法实例
在网络爬虫中,常用的类是 HttpGet 与 HttpPost。
-
执行请求
基于实例化的 HttpClient,可以调用 execute(HttpUriRequest request)方法执行数据请求,返回 HttpResponse
-
获取响应信息
java
//获取具体响应信息
System.out.println("response:" + httpResponse);
//响应状态
String status = httpResponse.getStatusLine().toString();
System.out.println("status:" + status);
//获取响应状态码
int StatusCode = httpResponse.getStatusLine().getStatusCode();
System.out.println("StatusCode:" + StatusCode);
ProtocolVersion protocolVersion = httpResponse.
getProtocolVersion(); //协议的版本号
System.out.println("protocolVersion:" + protocolVersion);
//是否OK
String phrase = httpResponse.getStatusLine().getReasonPhrase();
System.out.println("phrase:" + phrase);
Header[] headers = httpResponse.getAllHeaders();
System.out.println("输出头信息为:");
EntityUtils 类
EntityUtils 类的作用是操作响应实体
java
//可以设置编码
public static String toString(final HttpEntity entity, final String
defaultCharset)
//可以设置编码
public static String toString(final HttpEntity entity, final
Charset defaultCharset)
//使用默认编码ISO-8859-1
public static String toString(final HttpEntity entity)
另外,EntityUtils 类还提供了将响应实体转化成字节数组的方法,如下:
针对图片、PDF 和压缩包等文件,可以先将响应实体转化成字节数组,之后,利用缓冲流的方式写入指定文件,
java
public static byte[] toByteArray(final HttpEntity entity)
GET请求
java
public class GetTest {
public static void main(String[] args) throws Exception {
// 创建HttpClient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
// 声明访问地址
HttpGet httpGet = new HttpGet("https://www.autohome.com.cn/bestauto/");
CloseableHttpResponse response = null;
try {
// 发起请求
response = httpClient.execute(httpGet);
// 判断状态码是否是200
if (response.getStatusLine().getStatusCode() == 200) {
// 解析数据
String content = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println(content.length());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 释放连接
if (response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
httpClient.close();
}
}
}
}
使用Apache HttpClient库进行HTTP GET请求的Java程序。下面是代码的详细解释:
- 创建HttpClient对象 :使用
HttpClients.createDefault()
方法来创建一个CloseableHttpClient
实例,这个实例可以用来发送HTTP请求和处理HTTP响应。 - 声明访问地址 :通过
HttpGet
对象,指定要请求的URL地址("https://www.autohome.com.cn/bestauto/"
)。 - 发起请求 :使用
httpClient.execute(httpGet)
来发送HTTP GET请求。这个方法会返回一个CloseableHttpResponse
对象来表示服务器的响应。 - 判断状态码 :通过
response.getStatusLine().getStatusCode()
获取HTTP响应的状态码,并判断是否等于200,即HTTP OK状态。状态码200表示请求已成功被服务器接收、理解,并接受。 - 解析数据 :如果状态码为200,则使用
EntityUtils.toString(response.getEntity(), "UTF-8")
将响应实体转换为字符串。这里指定了字符集为UTF-8,以确保正确处理字符。 - 输出内容长度 :输出解析后的内容长度,通过
content.length()
获取。 - 异常处理:如果在请求过程中发生异常,异常会被捕获并打印堆栈跟踪。
- 释放资源 :在
finally
块中,确保关闭响应和HttpClient实例,以释放系统资源。 - 异常处理:如果关闭响应或HttpClient时发生IOException异常,异常同样会被捕获并打印堆栈跟踪。
带参数的GET请求
java
public static void main(String[] args) throws Exception {
// 创建HttpClient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
// 声明访问地址
// https://www.baidu.com/s?wd=汽车之家
URI uri = new URIBuilder("https://www.baidu.com/s").setParameter("wd", "汽车之家").build();
// 创建HttpGet请求对象
HttpGet httpGet = new HttpGet(uri);
CloseableHttpResponse response = null;
try {
// 发起请求
response = httpClient.execute(httpGet);
// 判断状态码是否是200
if (response.getStatusLine().getStatusCode() == 200) {
// 解析数据
String content = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println(content.length());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 释放连接
if (response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
httpClient.close();
}
}
}
在构造HTTP GET请求时使用了URIBuilder
来构建请求的URI。主要区别在于如何构造和设置请求的URL,以及如何传递查询参数:
- 使用URIBuilder :在这段代码中,
URIBuilder
类被用来构造带有查询参数的URI。new URIBuilder("https://www.baidu.com/s")
创建了一个指向百度搜索的URIBuilder实例,然后通过.setParameter("wd", "汽车之家")
方法设置了一个查询参数wd
,其值为"汽车之家"
。这个参数是用于百度搜索的关键词参数。build()
方法用来生成最终的URI对象。 - 创建HttpGet对象时使用URI :在创建
HttpGet
对象时,直接使用uri
对象,而不是之前的代码中直接传递URL字符串。这种方式更加灵活,因为可以在不改变基础URL的情况下动态地添加或修改查询参数。 - 其他部分相同:除了构建请求的URL部分以外,其他的代码逻辑和处理方式与上一段代码基本一致。都是创建HttpClient对象,发起请求,检查响应状态码,解析响应内容,并在最后释放资源。
POST请求
java
public static void main(String[] args) throws Exception {
// 创建HttpClient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
// 声明访问地址
HttpPost httpPost = new HttpPost("https://www.oschina.net");
// 设置User-Agent属性,解决开源中国限制的问题
httpPost.setHeader("User-Agent", "");
CloseableHttpResponse response = null;
try {
// 发起请求
response = httpClient.execute(httpPost);
// 判断状态码是否是200
if (response.getStatusLine().getStatusCode() == 200) {
// 解析数据
String content = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println(content.length());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 释放连接
if (response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
httpClient.close();
}
}
}
response.getEntity()
是Apache HttpClient库中HttpResponse对象的一个方法,用于获取HTTP响应中的实体部分
服务器可能会根据User-Agent判断请求是否来自真正的用户还是爬虫。例如,一些网站可能会限制爬虫的访问,只允许真正的用户访问。此时,爬虫需要设置一个可以被服务器接受的User-Agent,才能成功获取数据。在实际应用中,应该根据目标服务器的要求设置合适的User-Agent。
总结
HttpClient是Apache Common下的子项目,提供了高效、功能丰富的HTTP客户端编程工具包。相比于java.net中的URLConnection和HttpURLConnection ,HttpClient增加了易用性和灵活性 。它具有以下优点:易用性和灵活性、功能丰富、性能优越、协议支持、错误处理和异常管理。在使用HttpClient进行网络爬虫时,首先需要创建HttpClient实例,然后执行请求,获取响应信息。
HttpClient提供了详细的错误处理和异常管理机制,方便构建健壮的爬虫系统。在使用HttpClient进行HTTP请求时,可以使用HttpGet和HttpPost方法,并在发起请求之前设置请求方法和参数。还可以使用EntityUtils类来操作响应实体,并将响应实体转化为字节数组或写入指定文件。
在发起GET请求时,可以使用URIBuilder类构建带参数的URI,并使用HttpGet对象发送请求。在发起POST请求时,可以使用HttpPost对象发送请求,并设置User-Agent属性来解决限制问题。