Java常用技术:Httpclient 实现网络请求 + Jsoup 解析网页(案例实战)

zyqok 2020-11-13 10:12:58
java 技术 实现 HttpClient 常用


【前言】

你是否也曾羡慕过有些 phython 大神有着如下的神操作:

他们就轻轻的执行一串代码,就能循环的抓取很多自己想要的数据。

其实不用太羡慕他们,因为不光 phython 能实现,我们用 Java 同样也能够轻松实现。

闲话不多说,下面我们直接开始实战:

【1】创建项目

(1.1)我们用 IDEA(Eclipse同理) 创建一个全新的maven工程,我这里取名工程名 zyqok,各位随意。

(1.2)在 pom.xml 里面加上 <dependencies>

(1.3)创建 Test 类,好了工程就已经搭好了。

【2】Httpclient 实现网络请求

(2.1)什么是 httpclient ?

Httpclient 是 Apache 的一个子项目,它是一个为 Java 可以实现网络请求的客户端工具包。

简单的说,他是一个 Jar 包,有了他,我们通过 Java 程序就可以实现网络请求。

  (2.2) 复制下面的 httpclient 依赖,加入到 pom.xml 文件中。

<!-- httpclient 核心包 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>

 (2.3)创建一个 HttpTool 的类,这个类我们专门用来实现网络请求相关方法。

(2.4) 为了避免其他网站侵权问题,下面以我个人网站一个页面为例(http://www.zyqok.cn/material/index),我们来抓取这个页面上的所有图片。

(2.5) 可以看得出,这是一个 get 请求,并且返回的是一个 Html 页面。所以我们在 HttpTool 类中加入一个如下方法体:

 /**
* 实现Get请求
* @param url 请求地址
* @return 页面内容
*/
public static String doGet(String url) {
return null;
}

(2.6)复制代码,添加 get 实现方法:

 // 构建get请求
HttpGet get = new HttpGet(url);
// 创建客户端
CloseableHttpClient client = HttpClients.createDefault();
try {
// 客户端执行请求,获取响应
HttpResponse response = client.execute(get);
// 获取响应的页面内容
InputStream in = response.getEntity().getContent();
StringBuilder sb = new StringBuilder();
byte[]b = new byte[102400];
int length;
while ((length = in.read(b)) != -1) {
sb.append(new String(b, 0, length, "utf-8"));
}
// 返回页面内容
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
}

(2.7)OK,网络请求相关实现类我们已经写好了,我们接下来测试下,我们在 Test 类的 main 方法里加入如下代码:

 String html = HttpTool.doGet("http://www.zyqok.cn/material/index");
System.out.println(html);

(2.8)执行程序,查看结果。可以看到我们确实已经通过请求,获取到网页的返回内容了。

【3】Jsoup 解析网页

在整个【2】的实现过程中,我们已经拿到网页返回的数据,但我们要的是整个网页中的图片,并不是这种杂乱无章的网页页面数据,那么我们该怎么办呢?简单,接下来我们需要用到另外一种技术了 ---- Jsoup。

(3.1)什么是 Jsoup 技术?

下面是度娘给出的一个官方解释:Jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据(摘自百度)。

下面再用我个人语言简单的总结下:Jsoup 技术就是用来处理各种 html 页面 和 xml 数据。我们这里可以通过 Jsoup 来处理【2】中返回的 html 页面。

(3.2)加入 Jsoup 依赖

 我们在 pom.xml 加入如下依赖:

<!-- Jsoup 核心包 -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency>

(3.3)当然,使用 Jsoup 之前,我们需要对响应的 HTML 页面进行分析,分析主要作用是:如何定位筛选出我们需要的数据?

我们把【2】中获取到的页面响应拷贝到 txt 文本中,然后可以发现:每个图片它都包含在一个 div 中,且该div 有一个名为 material-div 的 class。

(3.4)按照上面分析:首先我们要获取到包含图片的所有 div,于是我们修改main方法中代码为如下:

 String html = HttpTool.doGet("http://www.zyqok.cn/material/index");
// 将 html 页面解析为 Document 对象
Document doc = Jsoup.parse(html);
// 获取所有包含 class = material-div 的 div 元素
Elements elements = doc.select("div.material-div");
for(Element div: elements){
System.out.println(div.toString());
}

注意:doc.select() 括号中的参数为过滤条件,基本等同于 Jquery 的过滤条件,所以会Jquery的同学,如何筛选条件基本就得心应手的,当然不会写筛选条件的也不要怕,这里有一份 Jsoup 使用指南,阁下不妨收下(传送门:Jsoup 官方使用指南)。

(3.5)我们执行代码,将输出结果继续拷贝到文本中。

可以看到,本次确实只有图片相关的div元素了,但这并不是我们想要的最终结果,我们最终的结果是获取到所有图片。

所以我们还需要继续分析:如何获取所有图片的链接和名字。

(3.6)由于每个图片所在的div元素结构都一样,所以我们可以取随机取一个div元素进行分析,于是我们可以取第一个div来进行分析,结构如下:

<div align="center" style="padding: 10px;" class="material-div">
<div style="width: 80px; height: 80px; margin-bottom: 3px; display: flex; align-items: center; justify-content: center">
<img class="fangda image" src="https://zyqok.oss-cn-chengdu.aliyuncs.com/20200414220946131_大树夕阳.jpg">
<input type="hidden" class="materialId" value="121">
</div>
<font style="font-size: 5px">大树夕阳.jpg</font><br>
<font style="font-size: 5px">2020-04-14 22:09:46</font>
</div>

(3.7)我们可以看到,整个结构内,就一个 img 元素标签,于是我们可以取第1个img标签的 src 属性为图片链接;同理,我们取第1个 font 元素的文本内容为图片名称。

(3.8)于是我们可以修改循环中的代码内容如下:

// 获取第1个 img 元素
Element img = div.selectFirst("img");
// 获取第1个 font 元素
Element font = div.selectFirst("font");
// 获取img元素src属性,即为图片链接
String url = img.attr("src");
// 获取name元素文本,即为图片名称
String name = font.text();
System.out.println(name + ": " + url);

(3.9)我们执行上面代码,可以得出如下结果。

可以看到,这个页面上的所有图片地址和名称已经被我们成功抓下来了。

【4】获取图片到本地

在第【3】步中,我们获取到的只是所有图片的链接,并没有将所有图片下载到我们本地,那么接下来,我们要将这个图片下载到我们本地才算完成。

(4.1)既然要下载到本地,我们首先在本地找个地方,用于存放这些图片。

比如:我将这图片全部下载到 D:\imgs(D 盘的 imgs 文件夹)中。

(4.2)我们在 HttpTool 类中增加保存图片到本地的方法,代码如下:

 /**
* 保存图片到本地
* @param src 图片地址
* @param name 图片名称
*/
public static void saveImg(String src, String name) {
// 构建get请求
HttpGet get = new HttpGet(src);
// 创建客户端
CloseableHttpClient client = HttpClients.createDefault();
try {
// 客户端执行请求,获取响应
HttpResponse response = client.execute(get);
// 获取响应的页面内容
InputStream in = response.getEntity().getContent();
int length;
byte[] bytes = new byte[1024];
FileOutputStream fos = new FileOutputStream("D:\\imgs\\" + name);
while ((length = in.read(bytes)) != -1) {
fos.write(bytes, 0, length);
fos.flush();
}
in.close();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}

(4.3)修改 Test 类 main 方法最终代码如下:

 public static void main(String args[]) throws Exception {
String html = HttpTool.doGet("http://www.zyqok.cn/material/index");
// 将 html 页面解析为 Document 对象
Document doc = Jsoup.parse(html);
// 获取所有包含 class = material-div 的 div 元素
Elements elements = doc.select("div.material-div");
for (int i = 0; i<elements.size(); i++) {
Element div = elements.get(i);
// 获取第1个 img 元素
Element img = div.selectFirst("img");
// 获取第1个 font 元素
Element font = div.selectFirst("font");
// 获取img元素src属性,即为图片链接
String src = img.attr("src");
// 获取name元素文本,即为图片名称
String name = font.text();
if (!name.contains(".")) {
name += ".jpg";
}
HttpTool.saveImg(src, i + name);
System.out.println("抓取第 " + i + " 张图片成功! 图片名称 : " + name);
}
System.out.println("所有图片抓取完成 !!");
}

  

(4.4)执行代码,打印如下图,看到这个结果,是不是感觉有点文章开头的展示味道了。

最后,我们只需要去本地文件夹下看看,所有图片是否成功保存到了本地?如果有图片,则我们就成功了。

(4.5)我们打开D盘imgs文件夹,可以看到网站上的图片确实已经全部保存到本地了。

【5】结尾语

通过我们 [批量抓取网络图片] 这一实战案例,我们可以感受到:通过 Httopclient 和 Jsoup 这两种技术,不仅仅可以批量抓取数据,其实还可以实现很多功能。

比如:网站登录,分布式服务器之间的数据传递,三方平台的API对接,有效数据的筛选和保存,数据的二次加工等等。

最后,附上一个作者写的 HttpTool 工具类:Java工具类:HttpTool(实现http的请求,获取响应)

版权声明
本文为[zyqok]所创,转载请带上原文链接,感谢
https://zyqok.blog.csdn.net/article/details/107859609

  1. [front end -- JavaScript] knowledge point (IV) -- memory leakage in the project (I)
  2. This mechanism in JS
  3. Vue 3.0 source code learning 1 --- rendering process of components
  4. Learning the realization of canvas and simple drawing
  5. gin里获取http请求过来的参数
  6. vue3的新特性
  7. Get the parameters from HTTP request in gin
  8. New features of vue3
  9. vue-cli 引入腾讯地图(最新 api,rocketmq原理面试
  10. Vue 学习笔记(3,免费Java高级工程师学习资源
  11. Vue 学习笔记(2,Java编程视频教程
  12. Vue cli introduces Tencent maps (the latest API, rocketmq)
  13. Vue learning notes (3, free Java senior engineer learning resources)
  14. Vue learning notes (2, Java programming video tutorial)
  15. 【Vue】—props属性
  16. 【Vue】—创建组件
  17. [Vue] - props attribute
  18. [Vue] - create component
  19. 浅谈vue响应式原理及发布订阅模式和观察者模式
  20. On Vue responsive principle, publish subscribe mode and observer mode
  21. 浅谈vue响应式原理及发布订阅模式和观察者模式
  22. On Vue responsive principle, publish subscribe mode and observer mode
  23. Xiaobai can understand it. It only takes 4 steps to solve the problem of Vue keep alive cache component
  24. Publish, subscribe and observer of design patterns
  25. Summary of common content added in ES6 + (II)
  26. No.8 Vue element admin learning (III) vuex learning and login method analysis
  27. Write a mini webpack project construction tool
  28. Shopping cart (front-end static page preparation)
  29. Introduction to the fluent platform
  30. Webpack5 cache
  31. The difference between drop-down box select option and datalist
  32. CSS review (III)
  33. Node.js学习笔记【七】
  34. Node.js learning notes [VII]
  35. Vue Router根据后台数据加载不同的组件(思考-&gt;实现-&gt;不止于实现)
  36. Vue router loads different components according to background data (thinking - & gt; Implementation - & gt; (more than implementation)
  37. 【JQuery框架,Java编程教程视频下载
  38. [jQuery framework, Java programming tutorial video download
  39. Vue Router根据后台数据加载不同的组件(思考-&gt;实现-&gt;不止于实现)
  40. Vue router loads different components according to background data (thinking - & gt; Implementation - & gt; (more than implementation)
  41. 【Vue,阿里P8大佬亲自教你
  42. 【Vue基础知识总结 5,字节跳动算法工程师面试经验
  43. [Vue, Ali P8 teaches you personally
  44. [Vue basic knowledge summary 5. Interview experience of byte beating Algorithm Engineer
  45. 【问题记录】- 谷歌浏览器 Html生成PDF
  46. [problem record] - PDF generated by Google browser HTML
  47. 【问题记录】- 谷歌浏览器 Html生成PDF
  48. [problem record] - PDF generated by Google browser HTML
  49. 【JavaScript】查漏补缺 —数组中reduce()方法
  50. [JavaScript] leak checking and defect filling - reduce() method in array
  51. 【重识 HTML (3),350道Java面试真题分享
  52. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  53. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  54. [re recognize HTML (3) and share 350 real Java interview questions
  55. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  56. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  57. 【重识 HTML ,nginx面试题阿里
  58. 【重识 HTML (4),ELK原来这么简单
  59. [re recognize HTML, nginx interview questions]
  60. [re recognize HTML (4). Elk is so simple