必威体育Betway必威体育官网
当前位置:首页 > IT技术

HttpClient

时间:2019-09-26 16:45:31来源:IT技术作者:seo实验室小编阅读:52次「手机版」
 

client

httpclient简介

HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。

官方站点:http://hc.apache.org/

最新版本4.5 http://hc.apache.org/httpcomponents-client-4.5.x/

官方文档: http://hc.apache.org/httpcomponents-client-4.5.x/tutorial/html/index.html

maven地址:

1

2

3

4

5

<dependency>

    <groupId>org.apache.httpcomponents</groupId>

    <artifactId>httpclient</artifactId>

    <version>4.5.2</version>

</dependency>

HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 java 应用程序需要直接通过 HTTP 协议来访问网络资源

虽然在 JDK 的 java net包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。

HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 

HTTP 协议最新的版本和建议。

HttpClient 已经应用在很多的项目中,比如 Apache Jakarta 上很著名的另外两个开源项目 Cactus 和 HTMLUnit 都使用了 HttpClient。

我们搞爬虫的,主要是用HttpClient模拟浏览器请求第三方站点url,然后响应,获取网页数据,然后用Jsoup来提取我们需要的信息;

HttpClient HelloWorld实现

首先建一个Maven项目,然后添加httpClient依赖,版本是4.5

1

2

3

4

5

<dependency>

    <groupId>org.apache.httpcomponents</groupId>

    <artifactId>httpclient</artifactId>

    <version>4.5.2</version>

</dependency>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

package com.open1111.httpclient;

import java.io.IOException;

import org.apache.http.HttpEntity;

import org.apache.http.ParseException;

import org.apache.http.client.ClientProtocolException;

import org.apache.http.client.methods.CloseableHttpresponse;

import org.apache.http.client.methods.HttpGet;

import org.apache.http.impl.client.CloseableHttpClient;

import org.apache.http.impl.client.HttpClients;

import org.apache.http.util.EntityUtils;

public class HelloWorld {

    public static void main(String[] args) {

        CloseableHttpClient httpClient=HttpClients.createDefault(); // 创建httpClient实例

        HttpGet httpget = new HttpGet("http://www.open1111.com/"); // 创建httpget实例

        CloseableHttpResponse response=null;

        try {

            response = httpClient.execute(httpget);

        catch (ClientProtocolException e) {  // http协议异常

            // TODO Auto-generated catch block

            e.printstacktrace();

        catch (IOException e) { // io异常

            // TODO Auto-generated catch block

            e.printStackTrace();

        // 执行get请求

        HttpEntity entity=response.getEntity(); // 获取返回实体

        try {

            System.out.println("网页内容:"+EntityUtils.toString(entity, "utf-8"));

        catch (ParseException e) {  // 解析异常

            // TODO Auto-generated catch block

            e.printStackTrace();

        catch (IOException e) { // io异常

            // TODO Auto-generated catch block

            e.printStackTrace();

        // 指定编码打印网页内容

        try {

            response.close();

        catch (IOException e) {  // io异常

            // TODO Auto-generated catch block

            e.printStackTrace();

        // 关闭流和释放系统资源

    }

}

运行输出:

这里得到了网站首页源码,当然要获得具体数据的话,要用到Jsoup

假如你对这些异常都熟悉 我们可以简化下,异常抛出,这样代码可读性好点。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

import org.apache.http.HttpEntity;

import org.apache.http.client.methods.CloseableHttpResponse;

import org.apache.http.client.methods.HttpGet;

import org.apache.http.impl.client.CloseableHttpClient;

import org.apache.http.impl.client.HttpClients;

import org.apache.http.util.EntityUtils;

public class HelloWorld2 {

    public static void main(String[] args) throws Exception{

        CloseableHttpClient httpclient = HttpClients.createDefault(); // 创建httpclient实例

        HttpGet httpget = new HttpGet("http://www.open1111.com/");    // 创建httpget实例

        CloseableHttpResponse response = httpclient.execute(httpget); // 执行get请求

        HttpEntity entity=response.getEntity(); // 获取返回实体

        System.out.println("网页内容:"+EntityUtils.toString(entity, "utf-8")); // 指定编码打印网页内容

        response.close(); // 关闭流和释放系统资源

    }

}

但是实际开发的话,我们对于每一种异常的抛出,catch里都需要做一些业务上的操作,所以以后用的话,还是第一种,

假如爬虫任务很简单,容易爬取,并且量小,那就第二种。还是要根据具体情况来。

HttpClient设置请求头消息User-Agent模拟浏览器

HttpClient设置请求头消息User-Agent模拟浏览器

比如我们请求 www.tuicool.com

用前面的代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

import org.apache.http.HttpEntity;

import org.apache.http.client.methods.CloseableHttpResponse;

import org.apache.http.client.methods.HttpGet;

import org.apache.http.impl.client.CloseableHttpClient;

import org.apache.http.impl.client.HttpClients;

import org.apache.http.util.EntityUtils;

public class Demo01 {

    public static void main(String[] args) throws Exception{

        CloseableHttpClient httpClient=HttpClients.createDefault(); // 创建httpClient实例

        HttpGet httpGet=new HttpGet("http://www.tuicool.com/");     // 创建httpget实例

        CloseableHttpResponse response=httpClient.execute(httpGet); // 执行http get请求

        HttpEntity entity=response.getEntity(); // 获取返回实体

        System.out.println("网页内容:"+EntityUtils.toString(entity, "utf-8")); // 获取网页内容

        response.close(); // response关闭

        httpClient.close(); // httpClient关闭

    }

}

返回内容:

网页内容:<!DOCTYPE html>

<html>

<head>

  <meta http-equiv="content-Type" content="text/html; charset=utf-8">

</head>

<body>

<p>系统检测亲不是真人行为,因系统资源限制,我们只能拒绝你的请求。如果你有疑问,可以通过微博 http://weibo.com/tuicool2012/ 联系我们。</p>

</body>

</html>

我们模拟下浏览器 设置下User-Agent头消息:

// 设置请求头消息User-Agent

httpGet.setHeader("User-Agent", "Mozilla/5.0 (windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0"); 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

import org.apache.http.HttpEntity;

import org.apache.http.client.methods.CloseableHttpResponse;

import org.apache.http.client.methods.HttpGet;

import org.apache.http.impl.client.CloseableHttpClient;

import org.apache.http.impl.client.HttpClients;

import org.apache.http.util.EntityUtils;

public class Demo01 {

    public static void main(String[] args) throws Exception{

        CloseableHttpClient httpClient=HttpClients.createDefault(); // 创建httpClient实例

        HttpGet httpGet=new HttpGet("http://www.tuicool.com/");     // 创建httpget实例

        httpGet.setHeader(                                          // 设置请求头消息User-Agent

        "User-Agent"

        "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0"); 

        CloseableHttpResponse response=httpClient.execute(httpGet); // 执行http get请求

        HttpEntity entity=response.getEntity(); // 获取返回实体

        System.out.println("网页内容:"+EntityUtils.toString(entity, "utf-8")); // 获取网页内容

        response.close(); // response关闭

        httpClient.close(); // httpClient关闭

    }

}

运行 :

当然通过火狐firebug,我们还可以看到其他请求头消息:

都是可以通过setHeader方法 设置key value;来得到模拟浏览器请求;

HttpClient获取响应内容类型Content-Type

HttpClient获取响应内容类型Content-Type

响应的网页内容都有类型也就是Content-Type

通过火狐firebug,我们看响应头信息:

当然我们可以通过HttpClient接口来获取;

HttpEntity的getContentType().getValue() 就能获取到响应类型;  

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

import org.apache.http.HttpEntity;

import org.apache.http.client.methods.CloseableHttpResponse;

import org.apache.http.client.methods.HttpGet;

import org.apache.http.impl.client.CloseableHttpClient;

import org.apache.http.impl.client.HttpClients;

import org.apache.http.util.EntityUtils;

public class Demo2 {

    public static void main(String[] args) throws Exception{

        CloseableHttpClient httpClient=HttpClients.createDefault(); // 创建httpClient实例

        HttpGet httpGet=new HttpGet("http://www.java1234.com");     // 创建httpget实例

        httpGet.setHeader(                                          // 设置请求头消息User-Agent

        "User-Agent"

        "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0"); 

        CloseableHttpResponse response=httpClient.execute(httpGet); // 执行http get请求

        HttpEntity entity=response.getEntity();                     // 获取返回实体

        System.out.println("Content-Type:"+entity.getContentType().getValue());

        //System.out.println("网页内容:"+EntityUtils.toString(entity, "utf-8")); // 获取网页内容

        response.close(); // response关闭

        httpClient.close(); // httpClient关闭

    }

}

运行输出:Content-Type:text/html

一般网页是text/html当然有些是带编码的,比如请求www.tuicool.com:输出:Content-Type:text/html; charset=utf-8

假如请求js文件,比如 http://www.open1111.com/static/js/jQuery.js运行输出:Content-Type:APPlication/JavaScript

假如请求的是文件,比如 http://central.maven.org/maven2/HTTPClient/HTTPClient/0.3-3/HTTPClient-0.3-3.jar

运行输出:Content-Type:application/java-archive

当然Content-Type还有一堆,那这东西对于我们爬虫有啥用的,

我们再爬取网页的时候 ,可以通过Content-Type来提取我们需要爬取的网页或者是爬取的时候,需要过滤掉的一些网页;

HttpClient获取响应状态Status

我们HttpClient向服务器请求时,

正常情况 执行成功 返回200状态码,

不一定每次都会请求成功,比如这个请求地址不存在 返回404

服务器内部报错 返回500

有些服务器有防采集,假如你频繁的采集数据,则返回403 拒绝你请求。

当然 我们是有办法的 后面会讲到用代理IP。

这个获取状态码,我们可以用 CloseableHttpResponse对象的getStatusLine().getStatusCode()

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

package com.open1111.httpclient.chap02;

import org.apache.http.HttpEntity;

import org.apache.http.client.methods.CloseableHttpResponse;

import org.apache.http.client.methods.HttpGet;

import org.apache.http.impl.client.CloseableHttpClient;

import org.apache.http.impl.client.HttpClients;

import org.apache.http.util.EntityUtils;

public class Demo3 {

    public static void main(String[] args) throws Exception{

        CloseableHttpClient httpClient=HttpClients.createDefault(); // 创建httpClient实例

        HttpGet httpGet=new HttpGet("http://www.open1111.com"); // 创建httpget实例

        httpGet.setHeader("User-Agent""Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0"); // 设置请求头消息User-Agent

        CloseableHttpResponse response=httpClient.execute(httpGet); // 执行http get请求

        System.out.println("Status:"+response.getStatusLine().getStatusCode());

        HttpEntity entity=response.getEntity(); // 获取返回实体

        System.out.println("Content-Type:"+entity.getContentType().getValue());

        //System.out.println("网页内容:"+EntityUtils.toString(entity, "utf-8")); // 获取网页内容

        response.close(); // response关闭

        httpClient.close(); // httpClient关闭

    }

}

运行输出:

Status:200

Content-Type:text/html;charset=UTF-8

假如换个页面 http://www.open1111.com/aaa.jsp

因为不存在,所以返回 404

HttpClient使用代理IP

在爬取网页的时候,有的目标站点有反爬虫机制,对于频繁访问站点以及规则性访问站点的行为,会采集屏蔽IP措施。

这时候,代理IP就派上用场了。

关于代理IP的话 也分几种 透明代理、匿名代理、混淆代理、高匿代理

1、透明代理(Transparent Proxy)

REMOTE_ADDR = Proxy IP

HTTP_VIA = Proxy IP

HTTP_X_FORWARDED_FOR = Your IP

透明代理虽然可以直接“隐藏”你的IP地址,但是还是可以从HTTP_X_FORWARDED_FOR来查到你是谁。

2、匿名代理(Anonymous Proxy)

REMOTE_ADDR = proxy IP

HTTP_VIA = proxy IP

HTTP_X_FORWARDED_FOR = proxy IP

匿名代理比透明代理进步了一点:别人只能知道你用了代理,无法知道你是谁。

还有一种比纯匿名代理更先进一点的:混淆代理,见下节。

3、混淆代理(Distorting Proxies)

REMOTE_ADDR = Proxy IP

HTTP_VIA = Proxy IP

HTTP_X_FORWARDED_FOR = Random IP address

如上,与匿名代理相同,如果使用了混淆代理,别人还是能知道你在用代理,但是会得到一个假的IP地址,伪装的更逼真:-)

4、高匿代理(Elite proxy或High Anonymity Proxy)

REMOTE_ADDR = Proxy IP

HTTP_VIA = not determined

HTTP_X_FORWARDED_FOR = not determined

可以看出来,高匿代理让别人根本无法发现你是在用代理,所以是最好的选择。

一般我们搞爬虫 用的都是 高匿的代理IP;

那代理IP 从哪里搞呢 很简单  百度一下,你就知道 一大堆代理IP站点。  一般都会给出一些免费的,但是花点钱搞收费接口更加方便;

比如 http://www.66ip.cn/

httpClient使用代理IP代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

package com.open1111.httpclient.chap04;

import org.apache.http.HttpEntity;

import org.apache.http.HttpHost;

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.impl.client.CloseableHttpClient;

import org.apache.http.impl.client.HttpClients;

import org.apache.http.util.EntityUtils;

public class Demo1 {

    public static void main(String[] args)throws Exception {

        CloseableHttpClient httpClient=HttpClients.createDefault(); // 创建httpClient实例

        HttpGet httpGet=new HttpGet("https://www.taobao.com/"); // 创建httpget实例

        HttpHost proxy=new HttpHost("116.226.217.54"9999);

        RequestConfig requestConfig=RequestConfig.custom().setProxy(proxy).build();

        httpGet.setConfig(requestConfig);

        httpGet.setHeader(

        "User-Agent""Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0");

        CloseableHttpResponse response=httpClient.execute(httpGet); // 执行http get请求

        HttpEntity entity=response.getEntity(); // 获取返回实体

        System.out.println("网页内容:"+EntityUtils.toString(entity, "utf-8")); // 获取网页内容

        response.close(); // response关闭

        httpClient.close(); // httpClient关闭

    }

}

建议大家用国内代理IP 以及主干道网络大城市的代理IP 访问速度快;

HttpClient连接超时及读取超时

HttpClient连接超时及读取超时

httpClient在执行具体http请求时候 有一个连接的时间和读取内容的时间;

HttpClient连接时间

所谓连接的时候 是HttpClient发送请求的地方开始到连接上目标url主机地址的时间,理论上是距离越短越快,线路越通畅越快,

但是由于路由复杂交错,往往连接上的时间都不固定,运气不好连不上,

HttpClient的默认连接时间,据我测试,默认是1分钟,假如超过1分钟 过一会继续尝试连接,这样会有一个问题 假如遇到一个url老是连不上,会影响其他线程的线程进去,所以我们有必要进行特殊设置,比如设置10秒钟 假如10秒钟没有连接上 我们就报错,这样我们就可以进行业务上的处理,比如我们业务上控制 过会再连接试试看。并且这个特殊url写到log4j日志里去。方便管理员查看。

HttpClient读取时间

所谓读取的时间 是HttpClient已经连接到了目标服务器,然后进行内容数据的获取,一般情况 读取数据都是很快速的,

但是假如读取的数据量大,或者是目标服务器本身的问题(比如读取数据库速度慢,并发量大等等..)也会影响读取时间。

同上,我们还是需要来特殊设置下,比如设置10秒钟 假如10秒钟还没读取完,就报错,同上,我们可以业务上处理。

比如我们这里给个地址 http://central.maven.org/maven2/这个是国外地址 连接时间比较长的,而且读取的内容多 

很容易出现连接超时和读取超时;

我们如何用代码实现呢?

HttpClient给我们提供了一个RequestConfig类 专门用于配置参数比如连接时间,读取时间以及前面讲解的代理IP等。

这里给下示例代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

import org.apache.http.HttpEntity;

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.impl.client.CloseableHttpClient;

import org.apache.http.impl.client.HttpClients;

import org.apache.http.util.EntityUtils;

public class Demo2 {

    public static void main(String[] args)throws Exception {

        CloseableHttpClient httpClient=HttpClients.createDefault();      // 创建httpClient实例

        HttpGet httpGet=new HttpGet("http://central.maven.org/maven2/"); // 创建httpget实例

        RequestConfig config=RequestConfig.custom()

                .setConnectTimeout(5000)

                .setsocketTimeout(5000)

                .build();

        httpGet.setConfig(config);

        httpGet.setHeader(

        "User-Agent""Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0");

        CloseableHttpResponse response=httpClient.execute(httpGet);             // 执行http get请求

        HttpEntity entity=response.getEntity();                                 // 获取返回实体

        System.out.println("网页内容:"+EntityUtils.toString(entity, "utf-8"));  // 获取网页内容

        response.close();                                                       // response关闭

        httpClient.close();                                                     // httpClient关闭

    }

}

相关阅读

【HTTPClient】HttpClient框架详解

【HTTPClient】HttpClient框架详解 2016年12月24日 15:42:08 阅读数:4293 HttpClient简介 HTTP 协议可能是现在 Internet 上使

分享到:

栏目导航

推荐阅读

热门阅读