您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > JAVA

Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

时间:2020-08-13 17:51:16  来源:  作者:

【前言】

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

Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

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

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

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

【1】创建项目

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

Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

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

Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

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

Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

【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>
Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

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

Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

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

Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

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

  /**
   * 实现Get请求
   * @param url 请求地址
   * @return 页面内容
   */
  public static String doGet(String url) {
    
    return null;
  }
Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

(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;
    }
Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

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

    String html = HttpTool.doGet("http://www.zyqok.cn/material/index");
    System.out.println(html);
Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

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

Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

【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>
Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

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

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

Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

(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 官方使用指南)。

Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

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

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

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

Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

(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 元素的文本内容为图片名称。

Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

(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);
Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

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

Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

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

【4】获取图片到本地

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

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

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

Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

(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();
    }
  }
Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

(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("所有图片抓取完成 !!");
  }
Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

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

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

Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

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

Java案例实战:Httpclient 实现网络请求 + Jsoup 解析网页

 

【5】结尾语

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

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



Tags:Httpclient   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
httpClient 请求接口失败要重试,一般人想到的可能是 做try catch 然后循环请求,但是这种方法写起来很麻烦,而且不优雅。今天就说下另外一种重试的方法,就是引入Microsoft.Extens...【详细内容】
2020-09-07  Tags: Httpclient  点击:(331)  评论:(0)  加入收藏
【前言】你是否也曾羡慕过有些 phython 大神有着如下的神操作: 他们就轻轻的执行一串代码,就能循环的抓取很多自己想要的数据。其实不用太羡慕他们,因为不光 phython 能实现,我...【详细内容】
2020-08-13  Tags: Httpclient  点击:(55)  评论:(0)  加入收藏
▌简易百科推荐
一、Redis使用过程中一些小的注意点1、不要把Redis当成数据库来使用二、Arrays.asList常见失误需求:把数组转成list集合去处理。方法:Arrays.asList 或者 Java8的stream流式处...【详细内容】
2021-12-27  CF07    Tags:Java   点击:(3)  评论:(0)  加入收藏
文章目录 如何理解面向对象编程? JDK 和 JRE 有什么区别? 如何理解Java中封装,继承、多态特性? 如何理解Java中的字节码对象? 你是如何理解Java中的泛型的? 说说泛型应用...【详细内容】
2021-12-24  Java架构师之路    Tags:JAVA   点击:(5)  评论:(0)  加入收藏
大家好!我是老码农,一个喜欢技术、爱分享的同学,从今天开始和大家持续分享JVM调优方面的经验。JVM调优是个大话题,涉及的知识点很庞大 Java内存模型 垃圾回收机制 各种工具使用 ...【详细内容】
2021-12-23  小码匠和老码农    Tags:JVM调优   点击:(11)  评论:(0)  加入收藏
前言JDBC访问Postgresql的jsonb类型字段当然可以使用Postgresql jdbc驱动中提供的PGobject,但是这样在需要兼容多种数据库的系统开发中显得不那么通用,需要特殊处理。本文介绍...【详细内容】
2021-12-23  dingle    Tags:JDBC   点击:(12)  评论:(0)  加入收藏
Java与Lua相互调用案例比较少,因此项目使用需要做详细的性能测试,本内容只做粗略测试。目前已完成初版Lua-Java调用框架开发,后期有时间准备把框架进行抽象,并开源出来,感兴趣的...【详细内容】
2021-12-23  JAVA小白    Tags:Java   点击:(10)  评论:(0)  加入收藏
Java从版本5开始,在 java.util.concurrent.locks包内给我们提供了除了synchronized关键字以外的几个新的锁功能的实现,ReentrantLock就是其中的一个。但是这并不意味着我们可...【详细内容】
2021-12-17  小西学JAVA    Tags:JAVA并发   点击:(10)  评论:(0)  加入收藏
一、概述final是Java关键字中最常见之一,表示“最终的,不可更改”之意,在Java中也正是这个意思。有final修饰的内容,就会变得与众不同,它们会变成终极存在,其内容成为固定的存在。...【详细内容】
2021-12-15  唯一浩哥    Tags:Java基础   点击:(14)  评论:(0)  加入收藏
1、问题描述关于java中的日志管理logback,去年写过关于logback介绍的文章,这次项目中又优化了下,记录下,希望能帮到需要的朋友。2、解决方案这次其实是碰到了一个问题,一般的情况...【详细内容】
2021-12-15  软件老王    Tags:logback   点击:(17)  评论:(0)  加入收藏
本篇文章我们以AtomicInteger为例子,主要讲解下CAS(Compare And Swap)功能是如何在AtomicInteger中使用的,以及提供CAS功能的Unsafe对象。我们先从一个例子开始吧。假设现在我们...【详细内容】
2021-12-14  小西学JAVA    Tags:JAVA   点击:(21)  评论:(0)  加入收藏
一、概述观察者模式,又可以称之为发布-订阅模式,观察者,顾名思义,就是一个监听者,类似监听器的存在,一旦被观察/监听的目标发生的情况,就会被监听者发现,这么想来目标发生情况到观察...【详细内容】
2021-12-13  唯一浩哥    Tags:Java   点击:(16)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条