无缺i 发表于 2022-2-10 14:00

使用Java实现自建背景图库并随机返回一张图片api

> 平时一些软件需要用到背景图片,但是一直用一张背景图片时间长了又会觉得腻,所以一直使用的都是随机图片来作为背景,之前用的那个接口最近一段时间晚高峰的时候总会响应很慢,所以自建了一个图库,这样可以更好的留存自己喜欢的图片



## 实现思路

1. 批量爬取一部分图片
2. 把图片放置到自定义的web静态文件路径下
3. 获取所有图片的路径、拼接url路径并上传到数据库
4. 写一个接口实现获取数据库中所有数据的数量,并使用random方法随机返回一个值作为ID从数据库中查询出对应的url重定向

## 使用依赖

```xml
<!--mysql数据库驱动-->
      <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
      </dependency>
      <!--hutool工具类-->
      <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.15</version>
      </dependency>
      <dependency>
            <!-- jsoup HTML parser library @ https://jsoup.org/ -->
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.14.3</version>
      </dependency>
```



## 爬取图片

> 图片地址:`https://mm.tvv.tw/category/Innocent_girl/1/`

### DOM分析

#### 打开`https://mm.tvv.tw/category/Innocent_girl/1/`

1. 通过浏览器打开`https://mm.tvv.tw/category/Innocent_girl/1/`发现每一组图片都有一个对应的class属性`blog-image`

   !(https://ftp.25wz.cn/images/icehw5oedn.jpg)

2. 我们可以根据class属性获取到所有的套图集合

3. 同时每一个套图都有一个对应的`<a>`标签,标签中的`href`属性就是我们需要的套图的url

#### 打开获取到的套图url

1. 通过浏览器审查元素可以看到所有的图片都在一个class属性为`blog-details-text`的下面
2. 但是又发现`blog-details-text`下面还有`<p>`标签环绕
3. 此时我们可以用select来获取`p:nth-child(2) > img`所有的img集合
4. 通过获取到的图片url集合遍历请求并保存到本地

!(https://ftp.25wz.cn/images/tbsspxty04.jpg)

### 实现代码

```java
package cc.wuque.tool.reptile;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Objects;

/**
* @AuThor 无缺
* @ClassName mm_tvv_twReptile
* @date 2022/2/9 18:29
* @Description https://mm.tvv.tw/category/Innocent_girl网站图片爬取
*/
public class mm_tvv_twReptile {

    private static final Log log = LogFactory.get();
    private static final String FILE_PATH = "./file/";

    public static void main(String[] args) {
      ArrayList<String> list = new ArrayList<>();
      for (int i = 1; i < 15; i++) {
            String body = HttpRequest.get("https://mm.tvv.tw/category/Innocent_girl/" + i + "/").execute().body();
            Elements elements = Jsoup.parse(body).getElementsByClass("blog-image");
            log.info("当前链接:https://mm.tvv.tw/category/Innocent_girl/{}/共获取到{}个元素", i, elements.size());
            for (Element element : elements) {
                //"#features > div > div.row.blog-masonry.blog-masonry-4col.no-transition > div:nth-child(" + j + ") > div.blog-image > a"
                String href = element.select("a").attr("href");
                log.info("当前获取到的链接:{}", href);
                list.add(href);
            }
      }
      log.info("共获取到:{}个图片主题链接", list.size());
      for (String s : list) {
            String body = HttpRequest.get(s).execute().body();
            Document parse = Jsoup.parse(body);
            Elements elements = parse.getElementsByClass("blog-details-text").select("p:nth-child(2)").select("img");
            String title = Objects.requireNonNull(parse.getElementsByClass("blog-details-headline text-black").first()).text();

            log.info("当前链接:{},共获取到{}张图片", s, elements.size());
            for (Element element : elements) {
                String src = element.attr("src");
                log.info("当前图片链接:{}", src);
                InputStream inputStream = HttpRequest.get(src).execute().bodyStream();
                FileUtil.writeFromStream(inputStream, FILE_PATH + title + "/" + RandomUtil.randomString(12) + ".jpg");
            }
            //body > section > div > div > div.col-md-8.col-sm-8 > div.blog-details-text > p:nth-child(2) > img:nth-child(1)
      }
    }

}

```

### 创建数据库

```mysql
CREATE TABLE `wuqueapi_random_image` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`url` varchar(255) NOT NULL,
`path` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1723 DEFAULT CHARSET=utf8;
```



#### DBUtil工具类

```java
package cc.wuque.tool.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ResourceBundle;


public class DBUtil {

    //数据库驱动
    private static final String driverClass = "com.mysql.jdbc.Driver";
    //数据库地址
    private static final String url = "jdbc:mysql://127.0.0.1:3306";
    //数据库用户名
    private static final String username = "root";
    //数据库密码
    private static final String password = "123456";


    static {
      try {
            //注册驱动
            Class.forName(driverClass);
      } catch (ClassNotFoundException e) {
            e.printStackTrace();
      }
    }

    public static Connection getConnection() throws SQLException {
      return DriverManager.getConnection(url, username, password);
    }
}
```

**这里的数据库地址、用户名、密码请修改成自己的**

### 上传图片的路径和url到数据库

```java
package cc.wuque.tool.file;

import cc.wuque.tool.util.DBUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;

import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

/**
* @author 无缺
* @ClassName FileInfo
* @date 2022/2/9 20:16
* @Description 遍历当前目录下的所有文件地址,并上传到数据库
*/
public class FileInfo {
    private static Connection conn = null;
    private static PreparedStatement ps = null;
    private static final Log log = LogFactory.get();

    public static void main(String[] args) {
      //获取所有图片的路径并保存到list集合
      List<File> files = FileUtil.loopFiles("E:\\Java\\IdeaProject\\tool\\target\\classes\\file");
      //遍历集合
      for (File file : files) {
            //获取文件路径
            String path = file.getAbsolutePath();
            //截取并拼接路径
            path = "random/images" + path.substring(path.indexOf("file\\") + 4);
            log.info(path);
            //替换路径中的\为/
            path = path.replaceAll("\\\\", "/");
            //拼接url
            String url = "https://img.wuque.cc/" + path;
            try {
                //上传到数据库
                conn = DBUtil.getConnection();
                ps = conn.prepareStatement("insert into wuqueapi.wuqueapi_random_image(url,path) values(?,?)");
                ps.setString(1, url);
                ps.setString(2, path);
                ps.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
                log.error("数据库链接错误,请排查错误....");
            } finally {
                try {
                  //关闭驱动
                  conn.close();
                  ps.close();
                } catch (SQLException e) {
                  e.printStackTrace();
                }

            }
      }
    }
}

```

### 实现随机返回图片api接口

```java
package cc.wuque.api.controller;

import cc.wuque.api.bean.RandomImages;
import cc.wuque.api.service.RandomImagesService;
import cn.hutool.core.net.url.UrlBuilder;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
* @author 无缺
* @date 2022/2/9 21:09
*/
@Controller
public class randomImagesController {

    private static final Log log = LogFactory.get();
    private static int count;

    @Autowired
    private RandomImagesService randomImages;

    /**
   * 随机重定向返回一张图片
   *
   * @Param response
   */
    @GetMapping(value = "/random/images")
    public void randomImagesRedirect(HttpServletResponse response) {
      if (count == 0) {
            getRandomImagesCount();
      }
      int i = RandomUtil.randomInt(0, count);
      String url = randomImages.queryRandomImagesById(i).getUrl();
      log.info("{}", url);
      try {

            response.sendRedirect(UrlBuilder.ofHttp(url).build());
      } catch (IOException e) {
            e.printStackTrace();
      }
    }

    /**
   * 获取数据库中所有图片的集合
   */
    private void getRandomImagesCount() {
      List<RandomImages> imagesList = randomImages.queryAllRandomImages();
      log.info("执行了获取所有数据的方法....");
      count = imagesList.size();
    }

}

```

**api接口中的service和mapper方法请自行实现..**
![随机返回图片](https://api.wuque.cc/random/images)

username11 发表于 2022-2-11 09:31

活到老学到老,感谢分享
页: [1]
查看完整版本: 使用Java实现自建背景图库并随机返回一张图片api