HttpClient爬虫入门

分类: 365bet游戏 时间: 2025-07-18 01:06:38 作者: admin

文章目录

一、maven引入jar包二、HttpClient使用1.步骤2.向网页发送GET请求3.向网页发送POST请求4.使用连接池管理请求

三、Jsoup使用1.使用jsoup解析url2.使用jsoup解析字符串3.使用jsoup解析.html文件

什么是HttpClient?

顾名思义,httpclient就是http客户端的意思;在项目中前后台交互是通过HTTP/HTTPS请求、响应来进行的,而HTTP请求是由浏览器生成并发送给后台服务器的,服务器接收request请求处理过后返回前台response响应。HttpClient就是代替并模拟浏览器,由代码生成HTTPrequest请求;请求发送给各个大型网站的服务器,获取其网页内容可以实现网络爬虫的功能。

一、maven引入jar包

org.apache.httpcomponents

httpclient

4.5.13

二、HttpClient使用

1.步骤

浏览器发送HTTP请求步骤:

打开个人PC客户端浏览器输入网址按下Enter发送GET请求收到服务器返回的请求

使用HttpClient向网页发送请求本质就是用代码的方式实现了上面“浏览器发送HTTP请求步骤”,即代码代替手工(方便理解)。

2.向网页发送GET请求

查看HttpGet的源码可以发现HttpGet方法有三个构造函数,可以接受URI对象和String字符串。

代码如下(示例):

/**

* 使用httpclient发送get请求

* 并且通过URIBuilder设置带参数的请求(可以不设置,直接发送GET请求)

* @throws Exception

*/

@Test

public void test2() throws Exception{

/**

* CloseableHttpClient:

* 可以关闭的httpclient客户端,相当于打开一个浏览器

* 据说是在老版本中httpClient不能及时关闭,造成了资源的浪费,所以有了CloseableHttpClient类。

*/

CloseableHttpClient closeableHttpClient = HttpClients.createDefault();

String urlStr = "https://www.huawei.com/cn/searchresult";

/**

* 通过URIBuilder设置带参数的get请求

* 如果有多个参数可以采用链式编程的方法设置多个键值对参数。

*/

URIBuilder uriBuilder = new URIBuilder(urlStr);

/**

* 最终成型样式打印:

* "GET /cn/searchresult?keywords=p50 HTTP/1.1[\r][\n]"

*/

uriBuilder.setParameter("keywords","p50");

/**

* 构造httpGet请求对象

* 打印httpGet:GET https://www.huawei.com/ HTTP/1.1

* 其构造方法可以接受字符串或者是URI实例对象;

* 即:如果是HttpGet httpGet = new HttpGet(urlStr);

* 的话是不带参数发送GET请求

*/

HttpGet httpGet = new HttpGet(uriBuilder.build());

/**

* 设置请求头,防止多次请求后被网页服务器认定为破坏者给封了

*/

httpGet.setHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36");

// 可以关闭的httpClient客户端的响应

CloseableHttpResponse closeableHttpResponse = null;

//相当于按下Enter发送请求,然后用closeableHttpResponse 接收返回的响应。

closeableHttpResponse = closeableHttpClient.execute(httpGet);

/**

* 获取status:HTTP/1.1 200 OK 获取状态码:

* 代码实现:closeableHttpResponse.getStatusLine().getStatusCode();

*/

/**

* HttpEntity:

* 发送请求后获取响应的结果,即获取返回的结果!!!

* HttpEntity不仅可以作为结果,也可以作为请求的实体参数,他有很多实现。

* 输出entity:org.apache.http.client.entity.DecompressingEntity@dd3b207

* HttpEntity表示http的request和resposne实体,它由消息头和消息体组成。

* 从HttpEntity中可以获取http请求头和回应头,也可以获取http请求体和回应体信息。

*/

HttpEntity entity = closeableHttpResponse.getEntity();

/**

* EntityUtils是对HttpEntity操作的工具类

* responseResult就是完整的响应

*/

String responseResult = EntityUtils.toString(entity,StandardCharsets.UTF_8);

//System.out.print("测试输出请求的内容:"+entity.getContentType().getValue());

System.out.print(responseResult);

//关闭流水

EntityUtils.consume(entity);

if(closeableHttpClient != null){

closeableHttpClient.close();

}

if(closeableHttpResponse != null){

closeableHttpResponse.close();

}

}

对网页手动发出带参数的请求右击查看网页源代码,和下面的对比发现一样。 执行代码,发出请求,打印结果 补充:请求主体的设置

//请求主体的设置,可加在代码中也可不加,记录一下使用方法。

//通过RequestConfig设置,通过httpGet.setConfig将设置添加到http请求中去

HttpGet httpGet = new HttpGet(urlStr);

RequestConfig requestConfig = RequestConfig

.custom()

.setConnectTimeout(10000) //设置链接超时时间为10秒钟,单位是毫秒

.setConnectionRequestTimeout(1000) //设置获取连接的最长时间

.setSocketTimeout(10000) //设置读取超时时间为十秒钟

.build();

httpGet.setConfig(requestConfig);

3.向网页发送POST请求

可以设置带参数也可以不带参数,这里直接设置的带参数的post请求,去掉设置请求参数的代码就是不带参数的post请求了;同样可以请求成功。

/**

* 实现:发送Post请求

* 步骤:

* 1.开启客户端

* 2.找到网址

* 3.发送GET/POST请求

* 4.收到response响应

* 5.处理响应

* 6.关闭网页,释放资源

*/

@Test

public void testPost() throws Exception{

CloseableHttpClient httpClient = HttpClients.createDefault();

//创建httpPost对象,设置url访问地址

HttpPost httpPost = new HttpPost("https://www.huawei.com/cn/searchresult");

//封装表单中的额数据--->声明list集合

List paramsList = new ArrayList();

//设置请求地址是:https://www.huawei.com/cn/searchresult?keywords=p50,是post请求!

paramsList.add(new BasicNameValuePair("keywords","p50"));

//创建表单的Entitty的对象

UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(paramsList,StandardCharsets.UTF_8);

//将表单对象加入到post请求中

httpPost.setEntity(urlEncodedFormEntity);

CloseableHttpResponse closeableHttpResponse = httpClient.execute(httpPost);

//判断是否请求成功,状态码是200说明得到了正确的响应

if(closeableHttpResponse.getStatusLine().getStatusCode() == 200){

HttpEntity entity = closeableHttpResponse.getEntity();

String s = EntityUtils.toString(entity);

System.out.print(s);

}

httpClient.close();

closeableHttpResponse.close();

}

4.使用连接池管理请求

/**

* 功能:测试连接池

* 问:为什么使用连接池?

* 答:每次使用HttpClient时,需要开启一个可关闭的httpclient客户端(实际是在内存中申请地址获取硬件资源),使用完后关闭时释放内存资源;

* 单次使用未有大问题,但是频繁开启httpclient客户端会造成资源的利用不合理。使用连接池可以提前申请好资源,不用频繁开启关闭,使得硬件资源合理利用。

*

* 步骤:

* 1.创建连接池管理器

* 2.配置连接池

* 3.使用连接池管理器发起请求

*

* 使用连接池和使用HttpClient发起请求的区别:

* 1.使用连接池管理器创建http请求时不需要使用 HttpClients.createDefault()的方法创建请求

* 2.请求发起并完成后逇链接不需要关闭,因为有连接池管理器在管理链接。

*/

@Test

public void connPoolMan() throws Exception{

//1.创建连接池

PoolingHttpClientConnectionManager pool = new PoolingHttpClientConnectionManager();

//2.配置连接池

pool.setMaxTotal(100);//设置最大连接

pool.setDefaultMaxPerRoute(10);//设置每个主机的最大连接数

//3.使用连接池发起请求

conn(pool);

conn(pool);

}

public static void conn(PoolingHttpClientConnectionManager pool) throws Exception{

CloseableHttpClient closeableHttpClient = HttpClients.custom().setConnectionManager(pool).build();

/**

* 可以看到两次的请求地址是不一样的:

* HttpClient客户端地址:org.apache.http.impl.client.InternalHttpClient@19dc67c2

* HttpClient客户端地址:org.apache.http.impl.client.InternalHttpClient@1e127982

*/

System.out.println("HttpClient客户端地址:"+closeableHttpClient);

HttpGet httpGet = new HttpGet("https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=parser&fenlei=256&oq=Incompatible%2520types.%2520Found%253A%2520%2526%252339%253Bcom.minGe.SpringSecurityStudy.WeekDay%2526%252339%253B%252C%2520required&rsv_pq=89062b920009f034&rsv_t=c484X67GB9z1uE4WJcPgGer043fTPO5I83E1A7YpLoq%2Fw9NM4JZlWN94GOw&rqlang=cn&rsv_enter=1&rsv_dl=tb&rsv_btype=t&rsv_sug3=53&rsv_sug1=41&rsv_sug7=100&rsv_sug2=0&inputT=1201&rsv_sug4=2524");

CloseableHttpResponse execute = closeableHttpClient.execute(httpGet);

if(execute.getStatusLine().getStatusCode()==200){

HttpEntity string = execute.getEntity();

System.out.println("占用了多少字节:"+EntityUtils.toString(string).length());

}

/**

* 注意:

* closeableHttpClient.close()不需要,连接池管理资源,所以不需要再手动去关闭。

*/

execute.close();

}

三、Jsoup使用

1.使用jsoup解析url

从下图看到Jsoup.parse的构造函数可以接收多种类型的数据,并且其返回的结果只有一种形式,均是Document类型的结果。

@Test

/**

* 功能:使用jsoup解析url

* 注意:

* 从程序中可以看出使用jsoup可以代替HttpClient直接发起请求并且解析数据,而且简单,但是为何不用jsoup爬取数据?

* 因为在实际开发中需要使用到多线程、连接池、代理等等方式;而jsoup对这些支持不是很好,所以我们吧jsoup仅仅作为html解析工具使用。

*/

public void parseURL() throws Exception{

//直接解析url地址,返回的是一个Document对象

Document document = Jsoup.parse(new URL("https://www.huawei.com/cn/searchresult"), 10000);

//获取解析到的document对象中的第一个title标签下的文字内容

String span = document.getElementsByTag("title").first().text();

//打印结果:站内搜索 - 华为

System.out.println(span);

}

执行结果:

2.使用jsoup解析字符串

//解析字符串

String content = FileUtils.readFileToString(new File("C://Users//minge//Desktop//这就是一段简单html内容.txt"));

Document docu = Jsoup.parse(content);

System.out.println(docu.getElementsByTag("title").text());

使用FileUtils工具类要导commons-io包:

commons-io

commons-io

2.4

3.使用jsoup解析.html文件

//直接解析文件,是在Windows系统下解析的文件,Windows系统下的文件默认使用GB2312编码。

Document document = Jsoup.parse(new File("C://Users//minge//Desktop//这就是一段简单html内容.html"), "GB2312");

//打印结果对比:

我嫩爹

我嫩爹

System.out.println(document.getElementsByClass("wonendie").html());

System.out.println(document.getElementsByClass("wonendie").text());