Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页
zhezhongyun 2024-12-15 17:54 29 浏览
【前言】
你是否也曾羡慕过有些 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对接,有效数据的筛选和保存,数据的二次加工等等。
相关推荐
- JPA实体类注解,看这篇就全会了
-
基本注解@Entity标注于实体类声明语句之前,指出该Java类为实体类,将映射到指定的数据库表。name(可选):实体名称。缺省为实体类的非限定名称。该名称用于引用查询中的实体。不与@Tab...
- Dify教程02 - Dify+Deepseek零代码赋能,普通人也能开发AI应用
-
开始今天的教程之前,先解决昨天遇到的一个问题,docker安装Dify的时候有个报错,进入Dify面板的时候会出现“InternalServerError”的提示,log日志报错:S3_USE_A...
- 用离散标记重塑人体姿态:VQ-VAE实现关键点组合关系编码
-
在人体姿态估计领域,传统方法通常将关键点作为基本处理单元,这些关键点在人体骨架结构上代表关节位置(如肘部、膝盖和头部)的空间坐标。现有模型对这些关键点的预测主要采用两种范式:直接通过坐标回归或间接通过...
- B 客户端流RPC (clientstream Client Stream)
-
客户端编写一系列消息并将其发送到服务器,同样使用提供的流。一旦客户端写完消息,它就等待服务器读取消息并返回响应gRPC再次保证了单个RPC调用中的消息排序在客户端流RPC模式中,客户端会发送多个请...
- 我的模型我做主02——训练自己的大模型:简易入门指南
-
模型训练往往需要较高的配置,为了满足友友们的好奇心,这里我们不要内存,不要gpu,用最简单的方式,让大家感受一下什么是模型训练。基于你的硬件配置,我们可以设计一个完全在CPU上运行的简易模型训练方案。...
- 开源项目MessageNest打造个性化消息推送平台多种通知方式
-
今天介绍一个开源项目,MessageNest-可以打造个性化消息推送平台,整合邮件、钉钉、企业微信等多种通知方式。定制你的消息,让通知方式更灵活多样。开源地址:https://github.c...
- 使用投机规则API加快页面加载速度
-
当今的网络用户要求快速导航,从一个页面移动到另一个页面时应尽量减少延迟。投机规则应用程序接口(SpeculationRulesAPI)的出现改变了网络应用程序接口(WebAPI)领域的游戏规则。...
- JSONP安全攻防技术
-
关于JSONPJSONP全称是JSONwithPadding,是基于JSON格式的为解决跨域请求资源而产生的解决方案。它的基本原理是利用HTML的元素标签,远程调用JSON文件来实现数据传递。如果...
- 大数据Doris(六):编译 Doris遇到的问题
-
编译Doris遇到的问题一、js_generator.cc:(.text+0xfc3c):undefinedreferenceto`well_known_types_js’查找Doris...
- 网页内嵌PDF获取的办法
-
最近女王大人为了通过某认证考试,交了2000RMB,官方居然没有给线下教材资料,直接给的是在线教材,教材是PDF的但是是内嵌在网页内,可惜却没有给具体的PDF地址,无法下载,看到女王大人一点点的截图保...
- 印度女孩被邻居家客人性骚扰,父亲上门警告,反被围殴致死
-
微信的规则进行了调整希望大家看完故事多点“在看”,喜欢的话也点个分享和赞这样事儿君的推送才能继续出现在你的订阅列表里才能继续跟大家分享每个开怀大笑或拍案惊奇的好故事啦~话说只要稍微关注新闻的人,应该...
- 下周重要财经数据日程一览 (1229-0103)
-
下周焦点全球制造业PMI美国消费者信心指数美国首申失业救济人数值得注意的是,下周一希腊还将举行第三轮总统选举需要谷歌日历同步及部分智能手机(安卓,iPhone)同步日历功能的朋友请点击此链接,数据公布...
- PyTorch 深度学习实战(38):注意力机制全面解析
-
在上一篇文章中,我们探讨了分布式训练实战。本文将深入解析注意力机制的完整发展历程,从最初的Seq2Seq模型到革命性的Transformer架构。我们将使用PyTorch实现2个关键阶段的注意力机制变...
- 聊聊Spring AI的EmbeddingModel
-
序本文主要研究一下SpringAI的EmbeddingModelEmbeddingModelspring-ai-core/src/main/java/org/springframework/ai/e...
- 前端分享-少年了解过iframe么
-
iframe就像是HTML的「内嵌画布」,允许在页面中加载独立网页,如同在画布上叠加另一幅动态画卷。核心特性包括:独立上下文:每个iframe都拥有独立的DOM/CSS/JS环境(类似浏...
- 一周热门
- 最近发表
- 标签列表
-
- HTML 教程 (33)
- HTML 简介 (35)
- HTML 实例/测验 (32)
- HTML 测验 (32)
- HTML 参考手册 (28)
- JavaScript 和 HTML DOM 参考手册 (32)
- HTML 拓展阅读 (30)
- HTML中如何键入空格 (27)
- HTML常用标签 (29)
- HTML文本框样式 (31)
- HTML滚动条样式 (34)
- HTML5 浏览器支持 (33)
- HTML5 新元素 (33)
- HTML5 WebSocket (30)
- HTML5 代码规范 (32)
- HTML5 标签 (717)
- HTML5 标签 (已废弃) (75)
- HTML5电子书 (32)
- HTML5开发工具 (34)
- HTML5小游戏源码 (34)
- HTML5模板下载 (30)
- HTTP 状态消息 (33)
- HTTP 方法:GET 对比 POST (33)
- 键盘快捷键 (35)
- 标签 (226)