平时一些软件需要用到背景图片,但是一直用一张背景图片时间长了又会觉得腻,所以一直使用的都是随机图片来作为背景,之前用的那个接口最近一段时间晚高峰的时候总会响应很慢,所以自建了一个图库,这样可以更好的留存自己喜欢的图片
实现思路
- 批量爬取一部分图片
- 把图片放置到自定义的web静态文件路径下
- 获取所有图片的路径、拼接url路径并上传到数据库
- 写一个接口实现获取数据库中所有数据的数量,并使用random方法随机返回一个值作为ID从数据库中查询出对应的url重定向
使用依赖
<!--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/
-
通过浏览器打开https://mm.tvv.tw/category/Innocent_girl/1/
发现每一组图片都有一个对应的class属性blog-image
-
我们可以根据class属性获取到所有的套图集合
-
同时每一个套图都有一个对应的<a>
标签,标签中的href
属性就是我们需要的套图的url
打开获取到的套图url
- 通过浏览器审查元素可以看到所有的图片都在一个class属性为
blog-details-text
的下面
- 但是又发现
blog-details-text
下面还有<p>
标签环绕
- 此时我们可以用select来获取
p:nth-child(2) > img
所有的img集合
- 通过获取到的图片url集合遍历请求并保存到本地
实现代码
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)
}
}
}
创建数据库
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工具类
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到数据库
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接口
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方法请自行实现..