Java爬虫爬取图片壁纸
Java爬虫
以sougou
图片为例:https://pic.sogou.com/
JDK17、SpringBoot3.2.X、hutool5.8.24实现Java爬虫,爬取页面图片
项目介绍
开发工具:
IDEA2023.2.5
JDK:
Java17
SpringBoot:
3.2.x
通过 SpringBoot
快速构建开发环境,通过 Jsoup
实现对网页的解析,并获取想要的资源数据
使用 hutool
工具,将所需要的字符串转成 JSON
对象,并从 JSON
对象中获取对应的数据资源
爬取网页图片资源,并将爬取到的资源下载到本地文件夹,对于大量的资源使用多线程下载
核心Jar包
<!-- 解html析 -->
<dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.15.3</version>
</dependency>
项目依赖
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.1</version><relativePath/></parent><groupId>cn.molu</groupId><artifactId>jsoup</artifactId><version>0.0.1-SNAPSHOT</version><name>jsoup</name><description>java网络爬虫;更多技术分享地址请关注:https://blog.csdn.net/qq_51076413</description><properties><java.version>17</java.version><java.source.version>17</java.source.version><java.target.version>17</java.target.version><java.compiler.version>17</java.compiler.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding></properties><dependencies><!-- hutool工具包 --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.24</version></dependency><!-- jsoup解析包,核心 --><dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.15.3</version></dependency><!-- web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 热加载,修改代码后不需要手动重启(如果配置了JRebel可以不使用该插件) --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><!-- lombok简化实体类 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins>·</build>
</project>
爬取思路
一、解析网页:获取资源网页,从网页中解析想要的资源数据;
- 查看网页资源的位置,分析资源渲染到页面的规律;
- 根据分析到的规律,统一提取资源数据,得到列表;
- 对列表数据进行进一步解析,最终拿到想要的资源;
- 对资源数据进行处理,保存到数据库或是下载资源;
二、调用接口:直接获取想要的图片资源;
- 需要分析资源网站,获取资源数据加载的时机和请求接口;
- 分析接口的请求参数,入参是否有加密,是否有请求限制;
- 测试接口,拿到结果,查看结果是否是自己所需要的资源;
- 处理资源数据,保存到数据库或者将资源文件下载到本地;
三、缓存资源:从页面JS中直接获取资源
- 页面加载后,我们下滑或者分页时,没有请求日志;
- 页面没有重新加载,但是数据在不断更新和加载中;
- 当超过一定数量时,会有一次的请求日志显示出来;
- 最后分析得到,数据是缓存到页面中的JS变量中了;
一、解析网页
1.1、过程与思路
分析资源:
- 打开资源网站,分析和定位资源所在位置,并分析资源渲染到页面的规律;
- 如图,定位到资源位置,并发现了资源渲染的规律,使用
document.querySelectorAll('xxx')
可以得到页面中所有的资源
网站地址:https://pic.sogou.com/pic/searchList.jsp?from=homeHotSearch&rcer=&spver=0&keyword=美女壁纸#top=1395.199951171875&more=false
定位资源所在位置
使用css选择器获取资源:
- 根据分析到的规律,统一提取资源数据,得到列表;
document.querySelectorAll('div#result div.similar div.similar-item a.single-box')
得到所有的资源列表
获取资源链接和标题:
- 对列表数据进行进一步解析,最终拿到想要的资源;
document.querySelector('xxx')
提取资源标题和资源链接
示例代码如下:
let divElement = document.querySelectorAll('div#result div.similar div.similar-item a.single-box'), result = [];
for (let tag of divElement ) {let title = (tag.querySelector('h4.info-title').innerText||'').replace(/\s*/g,''); // 拿到标题,去除所有空格和特殊字符let url = tag.querySelector("div.img-height img").currentSrc||''; // 拿到资源链接result.push({title,url}); // 收集资源数据
}
console.log(result); // 打印资源列表
处理资源数据:
- 对资源数据进行处理,保存到数据库或是下载资源;
1.2、Java代码实现
按照以上思路,我们使用
Java
代码来实现以上操作;页面地址:
https://pic.sogou.com/pic/searchList.jsp?from=homeHotSearch&rcer=&spver=0&keyword=美女壁纸#top=1395.199951171875&more=false
public static void main(String[] args) {// 获取网页资源Document document = Jsoup.parse(HttpUtil.get("https://pic.sogou.com/pic/searchList.jsp?from=homeHotSearch&rcer=&spver=0&keyword=美女壁纸#top=1395.199951171875&more=false", 15000));// 只获取<body>标签中的元素Element body = document.body();// 使用css选择器提取所有资源,得到列表数据Elements aElements = Optional.of(body.select("div#result")).orElseGet(Elements::new).select("div.similar div.similar-item a.single-box");// 进一步解析,获取资源链接和标题,将资源收集成集合中Set<JSONObject> result = aElements.stream().map(tag -> {JSONObject resource = new JSONObject();String title = tag.select("div.img-info h4.info-title").text();String src = tag.select("div.img-height img").attr("src");return resource.set("title", title).set("src", src);}).filter(ObjUtil::isNotEmpty).collect(Collectors.toSet());// 打印数据集System.out.println(result);System.out.println("共获取到:" + result.size() + "条数据");
}
1.3、爬取结果展示
[{"title":"每日更新 颜值美女壁纸,男人看了都会 珍藏 颜值","src":"https://i04piccdn.sogoucdn.com/485013ec7340e4f6"},
{"title":"美女 手机壁纸","src":"https://i02piccdn.sogoucdn.com/25a5aad0f9df1e0f"},
{"title":"美女 手机壁纸","src":"https://i04piccdn.sogoucdn.com/d4fe1d8d67d92d03"},
{"title":"美女 手机壁纸","src":"https://i01piccdn.sogoucdn.com/c9363d03d43130cd"},
{"title":"亭亭玉立,美若天仙","src":"https://i04piccdn.sogoucdn.com/51ea6e33666f6e57"}]共获取到:5条数据
二、调用接口
2.1、过程与思路
分析网站资源得到资源接口:
- 需要分析资源网站,获取资源数据加载的时机和请求接口;
- 分析接口的请求参数,入参是否有加密,是否有请求限制;
- 测试接口,拿到结果,查看结果是否是自己所需要的资源;
- 处理资源数据,保存到数据库或者将资源文件下载到本地;
2.2、Java代码实现
按照上述,找到接口
https://pic.sogou.com/napi/wap/searchlist
,拿到参数,直接发起POST
请求,得到资源;
请求参数
{"initQuery": "美女手机壁纸", "queryFrom": "wap","from": "homeHotSearch","rcer": "","spver": "0","keyword": "美女壁纸","start": 48,"reqType": "client","reqFrom": "wap_result","prevIsRedis": "n","qua": "","headers": {},"pagetype": 0,"amsParams": []
}
Java代码
接口地址:
https://pic.sogou.com/napi/wap/searchlist
请求方式:
POST
public static void main(String[] args) {// 查询接口String postUrl = "https://pic.sogou.com/napi/wap/searchlist";// 查询参数String params = """{"initQuery": "美女手机壁纸","queryFrom": "wap","from": "homeHotSearch","rcer": "","spver": "0","keyword": "美女壁纸","start": 48,"reqType": "client","reqFrom": "wap_result","prevIsRedis": "n","qua": "","headers": {},"pagetype": 0,"amsParams": []}""";// 发起post请求,得到上图所述的结果数据String json = HttpUtil.post(postUrl, params, 15000);// 解析结果数据,拿到最终的资源节点JSONArray jsonArray = JSONUtil.parseObj(json).getJSONObject("data").getJSONObject("picResult").getJSONArray("items");// 进一步解析提取所需要的资源数据,排除不需要的数据,将资源收集成集合中Set<JSONObject> result = jsonArray.stream().map(item -> {JSONObject resource = new JSONObject();if (item instanceof JSONObject jsonObject) {String title = jsonObject.getStr("title"); // 资源标题String picUrl = jsonObject.getStr("picUrl"); // 图片链接String thumbUrl = jsonObject.getStr("thumbUrl"); // 缩略图链接String oriPicUrl = jsonObject.getStr("oriPicUrl"); // 原图链接String locImageLink = jsonObject.getStr("locImageLink"); // 原图链接return resource.set("title", title).set("picUrl", picUrl).set("thumbUrl", thumbUrl).set("oriPicUrl", oriPicUrl).set("locImageLink", locImageLink);}return null;}).filter(ObjUtil::isNotEmpty).collect(Collectors.toSet());// 打印数据集System.out.println(result);System.out.println("共获取到:" + result.size() + "条数据");
}
2.3、爬取结果展示
三、缓存资源
3.1、过程与思路
- 页面加载后,我们下滑或者分页时,没有请求日志;
- 页面没有重新加载,但是数据在不断更新和加载中;
- 当超过一定数量时,会有一次的请求日志显示出来;
- 最后分析得到,数据是缓存到页面中的JS变量中了;
3.2、Java代码实现
变量名:
window.__INITIAL_STATE__
缓存中有很多数据,我们以
searchlist -> groupFixedResult -> groupPic
中的数据为例,获取并解析里面的资源资源地址:
https://pic.sogou.com/pic/searchList.jsp?from=homeHotSearch&rcer=&spver=0&tagQSign=%E9%AB%98%E6%B8%85,3636d5ad&showMode=0&routeName=searchlist&keyword=美女
public static void main(String[] args) {// 请求资源地址得到页面数据Document document = Jsoup.parse(HttpUtil.get("https://pic.sogou.com/pic/searchList.jsp?from=homeHotSearch&rcer=&spver=0&tagQSign=%E9%AB%98%E6%B8%85,3636d5ad&showMode=0&routeName=searchlist&keyword=美女", 15000));String variableName = "window.__INITIAL_STATE__";// 解析得到所有的<script>Elements scriptTags = document.getElementsByTag("script");// 过滤得到包含'__INITIAL_STATE__'的<script>List<String> collects = scriptTags.stream().map(Element::data).filter(data -> data.contains(variableName)).filter(StrUtil::isNotEmpty).toList();String scriptData = CollectionUtil.isEmpty(collects) ? "" : collects.get(0);// 截取js中'__INITIAL_STATE__'变量内容int startIndex = scriptData.indexOf("{");int endIndex = scriptData.lastIndexOf("}");// 得到js中'__INITIAL_STATE__'的json数据String jsonData = scriptData.substring(startIndex, endIndex + 1);// 将JS数据转为Java的JSON对象JSONObject jsonObject = JSONUtil.parseObj(jsonData);jsonObject = jsonObject.getJSONObject("searchlist");jsonObject = jsonObject.getJSONObject("groupFixedResult");JSONArray groupPicArray = jsonObject.getJSONArray("groupPic");Set<Map<String, String>> list = new HashSet<>();// 从JSON对象中提取资源数据getSource(groupPicArray, list);// 打印数据集System.out.println(list);System.out.println("共获取到:" + list.size() + "条数据");
}/*** 解析资源,获取资源数据** @param jsonArray 资源数据集* @param list 结果数据集*/
private static void getSource(JSONArray jsonArray, Set<Map<String, String>> list) {for (Object object : jsonArray) {if (object instanceof JSONArray item) {getSource(item, list);}if (object instanceof JSONObject item) {var map = new HashMap<String, String>();map.put("thumbUrl", item.getStr("thumbUrl"));map.put("title", item.getStr("title"));map.put("pageUrl", item.getStr("pageUrl"));map.put("picUrl", item.getStr("picUrl"));list.add(map);}}
}
3.3、爬取结果展示
四、完整测试代码
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.util.*;
import java.util.stream.Collectors;/*** @author 陌路* @apiNote 解析网页资源* @date 2024/1/15 19:55* @tool Created by IntelliJ IDEA*/
public class GetWebResourceTest {/*** 通过解析网页获取资源*/public static void main(String[] args) {// 获取网页资源Document document = Jsoup.parse(HttpUtil.get("https://pic.sogou.com/pic/searchList.jsp?from=homeHotSearch&rcer=&spver=0&keyword=%E7%BE%8E%E5%A5%B3%E5%A3%81%E7%BA%B8#top=1395.199951171875&more=true", 15000));// 只获取<body>标签中的元素Element body = document.body();// 使用css选择器提取所有资源,得到列表数据Elements aElements = Optional.of(body.select("div#result")).orElseGet(Elements::new).select("div.similar div.similar-item a.single-box");// 进一步解析,获取资源链接和标题,将资源收集成集合中Set<JSONObject> result = aElements.stream().map(tag -> {JSONObject resource = new JSONObject();String title = tag.select("div.img-info h4.info-title").text();String src = tag.select("div.img-height img").attr("src");return resource.set("title", title).set("src", src);}).filter(ObjUtil::isNotEmpty).collect(Collectors.toSet());// 打印数据集System.out.println(result);System.out.println("共获取到:" + result.size() + "条数据");}/*** 通过API接口获取资源*/public static void main1(String[] args) {// 查询接口String postUrl = "https://pic.sogou.com/napi/wap/searchlist";// 查询参数String params = """{"initQuery": "美女手机壁纸","queryFrom": "wap","from": "homeHotSearch","rcer": "","spver": "0","keyword": "美女壁纸","start": 48,"reqType": "client","reqFrom": "wap_result","prevIsRedis": "n","qua": "","headers": {},"pagetype": 0,"amsParams": []}""";// 发起post请求,得到上图所述的结果数据String json = HttpUtil.post(postUrl, params, 15000);// 解析结果数据,拿到最终的资源节点JSONArray jsonArray = JSONUtil.parseObj(json).getJSONObject("data").getJSONObject("picResult").getJSONArray("items");// 进一步解析提取所需要的资源数据,排除不需要的数据,将资源收集成集合中Set<JSONObject> result = jsonArray.stream().map(item -> {JSONObject resource = new JSONObject();if (item instanceof JSONObject jsonObject) {String title = jsonObject.getStr("title"); // 标题String picUrl = jsonObject.getStr("picUrl"); // 图片链接String thumbUrl = jsonObject.getStr("thumbUrl"); // 缩略图链接String oriPicUrl = jsonObject.getStr("oriPicUrl"); // 原图链接String locImageLink = jsonObject.getStr("locImageLink"); // 原图链接return resource.set("title", title).set("picUrl", picUrl).set("thumbUrl", thumbUrl).set("oriPicUrl", oriPicUrl).set("locImageLink", locImageLink);}return null;}).filter(ObjUtil::isNotEmpty).collect(Collectors.toSet());// 打印数据集System.out.println(result);System.out.println("共获取到:" + result.size() + "条数据");}/*** 通过js获取数据资源*/public static void main2(String[] args) {// 请求资源地址得到页面数据Document document = Jsoup.parse(HttpUtil.get("https://pic.sogou.com/pic/searchList.jsp?from=homeHotSearch&rcer=&spver=0&tagQSign=%E9%AB%98%E6%B8%85,3636d5ad&showMode=0&routeName=searchlist&keyword=美女", 15000));String variableName = "window.__INITIAL_STATE__";// 解析得到所有的<script>Elements scriptTags = document.getElementsByTag("script");// 过滤得到包含'__INITIAL_STATE__'的<script>List<String> collects = scriptTags.stream().map(Element::data).filter(data -> data.contains(variableName)).filter(StrUtil::isNotEmpty).toList();String scriptData = CollectionUtil.isEmpty(collects) ? "" : collects.get(0);// 截取js中'__INITIAL_STATE__'变量内容int startIndex = scriptData.indexOf("{");int endIndex = scriptData.lastIndexOf("}");// 得到js中'__INITIAL_STATE__'的json数据String jsonData = scriptData.substring(startIndex, endIndex + 1);// 将JS数据转为Java的JSON对象JSONObject jsonObject = JSONUtil.parseObj(jsonData);jsonObject = jsonObject.getJSONObject("searchlist");jsonObject = jsonObject.getJSONObject("groupFixedResult");JSONArray groupPicArray = jsonObject.getJSONArray("groupPic");Set<Map<String, String>> list = new HashSet<>();// 从JSON对象中提取资源数据getSource(groupPicArray, list);// 打印数据集System.out.println(list);System.out.println("共获取到:" + list.size() + "条数据");}/*** 解析资源,获取资源数据** @param jsonArray 资源数据集* @param list 结果数据集*/private static void getSource(JSONArray jsonArray, Set<Map<String, String>> list) {for (Object object : jsonArray) {if (object instanceof JSONArray item) {getSource(item, list);}if (object instanceof JSONObject item) {var map = new HashMap<String, String>();map.put("thumbUrl", item.getStr("thumbUrl"));map.put("title", item.getStr("title"));map.put("pageUrl", item.getStr("pageUrl"));map.put("picUrl", item.getStr("picUrl"));list.add(map);}}}
}
五、下载资源
5.1、过程与思路
本案例仅以获取并解析JS
资源为例来下载资源
下载图片资源,并将资源列表以
json
格式写入到本地(存入到数据库也可以,这里只写入到文件)
- 根据上述代码,将获取到的数据资源下载到本地;
- 将所有收集到的资源写入到文件中,方便于查看;
5.2、操作文件工具类
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import java.io.File;
import java.io.FileWriter;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Map;/*** @author 陌路* @apiNote 操作文件工具类* @date 2024/1/16 12:10* @tool Created by IntelliJ IDEA*/
@Slf4j
public class FileUtil {/*** 文件保存路径地址(修改为自己的地址)*/public static final String FILE_PATH = "D:/Code/picture/sougou/";/*** 写入文件** @param pathName 文件路径* @param suffix 文件类型,后缀名* @param data 数据集*/public static void write(String pathName, String suffix, String data) {File file = new File(pathName + suffix);try (FileWriter writer = new FileWriter(file)) {writer.write(JSONUtil.toJsonStr(data));writer.flush();} catch (Exception e) {log.error("写入数据出错了:" + e.getMessage(), e);}}/*** 获取文件路径** @param filePath 文件路径* @return 文件路径*/public static String getFilePath(String filePath) {filePath = StrUtil.isBlank(filePath) ? "" : filePath + "/";DateTime dateTime = new DateTime();String currentDate = dateTime.toString(DatePattern.NORM_DATE_PATTERN);return FILE_PATH + filePath + currentDate + "/";}/*** 获取文件名** @param title 标题* @return 文件名*/public static String getFileName(String title) {return StrUtil.isBlank(title) ? "" : MD5.create().digestHex(title, StandardCharsets.UTF_8);}/*** 下载文件** @param url 文件地址* @param filePath 文件路径* @param fileName 文件名* @param picUrl 图片地址*/@SuppressWarnings("all")public static void downloadFile(String url, String filePath, String fileName, String picUrl, boolean isDownload) {fileName = FileUtil.getFileName(fileName);File file = new File(filePath + "/" + fileName + ".jpg");try {if (!file.exists()) {file.getParentFile().mkdirs();file.createNewFile();}HttpUtil.downloadFile(url, file, 5000);} catch (Exception e) {if (!isDownload) {downloadFile(picUrl, filePath, fileName, picUrl, true);}log.error("下载文件出错:" + e.getMessage(), e);}}/*** 下载文件** @param filePath 文件路径* @param list 数据集*/public static void downloadFile(String filePath, Collection<Map<String, String>> list) {list.forEach(item -> FileUtil.downloadFile(item.get("thumbUrl"), filePath, item.get("title") + item.get("picUrl"), item.get("picUrl"), false));}
}
5.3、资源下载实现类
本案例仅以获取
JS
中的资源实现下载
/*** 解析html* @param keyword 搜索关键字* @return 爬取结果*/
public Set<Map<String, String>> parseHtmlByKeyword(String keyword) {Document document = Jsoup.parse(HttpUtil.get(UrlConstant.APP_BASE_URL + keyword, 15000));String variableName = "window.__INITIAL_STATE__";String scriptData = getJsonByScript(document.getElementsByTag("script"), variableName);int startIndex = scriptData.indexOf("{");int endIndex = scriptData.lastIndexOf("}");String jsonData = scriptData.substring(startIndex, endIndex + 1);JSONObject jsonObject = JSONUtil.parseObj(jsonData);jsonObject = jsonObject.getJSONObject("searchlist");jsonObject = jsonObject.getJSONObject("groupFixedResult");JSONArray groupPicArray = jsonObject.getJSONArray("groupPic");Set<Map<String, String>> list = new HashSet<>();getSource(groupPicArray, list);String filePath = FileUtil.getFilePath(keyword);// 资源数量小于100,直接下载,否则使用多线程下载long start = System.currentTimeMillis();// 是否使用多线程下载,资源数量>100的时候使用多线程if (list.size() < 100) {list.forEach(item -> FileUtil.downloadFile(item.get("thumbUrl"), filePath, item.get("title") + item.get("picUrl"), item.get("picUrl"), false));} else {multiThreaded(new ArrayList<>(list), keyword); // 多线程下载}long time = System.currentTimeMillis()- start;// 打印下载资源所耗时长log.info("共耗时:{}ms、{}s、{}m", time, (time / 1000), ((time / 1000) / 60));// 将资源数据写入到source.json文件中FileUtil.write(filePath + "/source", ".json", JSONUtil.toJsonStr(list));return list;
}
5.4、下载结果展示
5.5、调用示例
/*** @author 陌路* @apiNote 解析网页资源控制器* @date 2024/1/16 15:36* @tool Created by IntelliJ IDEA*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/parseHtml")
public class ParseHtmlController {private final ParseHtmlService parseHtmlService;/*** 根据关键字爬取数据** @param keyword 搜索关键字* @return 结果集*/@GetMapping("/query/{keyword}")public ResultVo<Collection<Map<String, String>>> parseHtml(@PathVariable String keyword) {if (StrUtil.isBlank(keyword)) return ResultVo.fail("请输入搜索关键字!");return ResultVo.ok(parseHtmlService.parseHtmlByKeyword(keyword));}
}
六、完整代码
完整代码:
https://gitee.com/mmolu/open-source/tree/master/jsoup
七、说明
本实例仅学习供参考使用
请勿用来牟利或非法使用
本示例仅供学习参考,请勿用来牟利或非法使用!
本示例仅供学习参考,请勿用来牟利或非法使用!
本示例仅供学习参考,请勿用来牟利或非法使用!
更多技术分享请关注:.陌路-CSDN博客
创作不易,采集、转发请注明出处:https://blog.csdn.net/qq_51076413?type=blog
.
相关文章:

Java爬虫爬取图片壁纸
Java爬虫 以sougou图片为例:https://pic.sogou.com/ JDK17、SpringBoot3.2.X、hutool5.8.24实现Java爬虫,爬取页面图片 项目介绍 开发工具:IDEA2023.2.5 JDK:Java17 SpringBoot:3.2.x 通过 SpringBoot 快速构建开发环境…...

红队打靶练习:HOLYNIX: V1
目录 信息收集 1、arp 2、netdiscover 3、nmap 4、nikto whatweb 目录探测 1、gobuster 2、dirsearch 3、dirb 4、feroxbuster WEB sqlmap 1、爆库 2、爆表 3、爆列 4、爆字段 后台登录 1、文件上传 2、文件包含 3、越权漏洞 反弹shell 提权 总结 信息…...

elasticsearch[二]-DSL查询语法:全文检索、精准查询(term/range)、地理坐标查询(矩阵、范围)、复合查询(相关性算法)、布尔查询
ES-DSL查询语法(全文检索、精准查询、地理坐标查询) 1.DSL查询文档 elasticsearch 的查询依然是基于 JSON 风格的 DSL 来实现的。 1.1.DSL 查询分类 Elasticsearch 提供了基于 JSON 的 DSL(Domain Specific Language)来定义查…...

Microsoft Word 设置底纹
Microsoft Word 设置底纹 References 打开文档页面,选中特定段落或全部文档 在“段落”中单击“边框”下三角按钮 在列表中选择“边框和底纹”选项 在“边框和底纹”对话框中单击“底纹”选项卡 在图案样式和图案颜色列表中设置合适颜色的底纹,单击“确…...

【大数据】Flink 详解(九):SQL 篇 Ⅱ
《Flink 详解》系列(已完结),共包含以下 10 10 10 篇文章: 【大数据】Flink 详解(一):基础篇【大数据】Flink 详解(二):核心篇 Ⅰ【大数据】Flink 详解&…...

workflow源码解析:GoTask
关于go task 提供了另一种更简单的使用计算任务的方法,模仿go语言实现的go task。 使用go task来实计算任务无需定义输入与输出,所有数据通过函数参数传递。 与ThreadTask 区别 ThreadTask 是有模板,IN 和 OUT, ThreadTask 依赖…...

SpringMVC入门案例
引言 Spring MVC是一个基于MVC架构的Web框架,它的主要作用是帮助开发者构建Web应用程序。它提供了一个强大的模型驱动的开发方式,可以帮助开发者实现Web应用程序的各种功能,如请求处理、数据绑定、视图渲染、异常处理等。 开发步骤 1.创建we…...

Docker本地私有仓库搭建配置指导
一、说明 因内网主机需要拉取镜像进行Docker应用,因此需要一台带外主机作为内网私有仓库来提供内外其他docker业务主机使用。参考架构如下: 相关资源:加密、Distribution registry、Create and Configure Docker Registry、Registry部署、D…...

python 通过定时任务执行pytest case
这段Python代码使用了schedule库来安排一个任务,在每天的22:50时运行。这个任务执行一个命令来运行pytest,并生成一个报告。 代码开始时将job_done变量设为False,然后运行预定的任务。一旦任务完成,将job_done设置为True并跳出循…...

算法面试题:合并两个有序链表
描述:给定两个按非递减顺序排列的链表,合并两个链表,并将结果按非递减顺序排列。 例如: # 链表 1: 1 -> 2 -> 4 # 链表 2: 1 -> 3 -> 4合并后的链表应该是:1 -> 1 -> 2 -> 3 -> 4 -> 4 …...

LaWGPT安装和使用教程的复现版本【细节满满】
文章目录 前言一、下载和部署1.1 下载1.2 环境安装1.3 模型推理 总结 前言 LaWGPT 是一系列基于中文法律知识的开源大语言模型。该系列模型在通用中文基座模型(如 Chinese-LLaMA、ChatGLM等)的基础上扩充法律领域专有词表、大规模中文法律语料预训练&am…...

西门子博途用SCL语言写的入栈出栈
1.用户登录 #pragma code ("useadmin.dll") #include "PWRT_api.h" #pragma code() PWRTLogin(1) 2.用户退出 #pragma code ("useadmin.dll") #include "PWRT_api.h" #pragma code() PWRTLogout(); 3.画面跳转 SetPictureName("P…...

密码产品推介 | 沃通安全电子签章系统(ES-1)
产品介绍 沃通安全电子签章系统(ES-1)是一款基于密码技术、完全自主研发的商用密码产品,严格遵循国家密码管理局制定的相关标准,可为企业和个人提供安全、合规的电子签章功能服务。产品的主要用途是为各类文书、合同、表单等电子…...

蓝桥杯真题(Python)每日练Day1
说明:在CSP认证的基础上(可以看看本人CSP打卡系列的博客)备赛2024蓝桥杯(Python),本人专业:大数据与数据科学 因此对python要求熟练掌握,通过练习蓝桥杯既能熟悉语法又能锻炼算法和思…...

IDEA怎么用Devtools热部署
IDEA怎么用Devtools热部署 大家知道在项目开发过程中,有时候会改动代码逻辑或者修改数据结构,为了能使改动的代码生效,往往需要重启应用查看改变效果,这样会相当耗费时间。 重启应用其实就是重新编译生成新的Class文件࿰…...

boost.circular_buffer的使用和介绍
C 文章目录 C 很多时候,我们需要在内存中记录最近一段时间的数据,如操作记录等。由于这部分数据记录在内存中,因此并不能无限递增,一般有容量限制,超过后就将最开始的数据移除掉。在stl中并没有这样的数据结构…...

深入理解Java中的ThreadLocal
第1章:引言 大家好,我是小黑。今天咱们来聊聊ThreadLocal。首先,让咱们先搞清楚,ThreadLocal是个什么玩意儿。简单说,ThreadLocal可以让咱们在每个线程中创建一个变量的“私有副本”。这就意味着,每个线程…...

【重点】【DP】300. 最长递增子序列
题目 更好的方法是耐心排序,参见《算法小抄》的内容!!! 法1:DP 基础解法必须掌握!!! class Solution {public int lengthOfLIS(int[] nums) {if (nums null || nums.length 0) …...

使用freessl为网站获取https证书及配置详细步骤
文章目录 一、进入freessl网站二、修改域名解析记录三、创建证书四、配置证书五、服务启动 一、进入freessl网站 首先进入freessl网站,需要注册一个账号 freessl网站 进入网站后填写自己的域名 接下来要求进行DCV配置 二、修改域名解析记录 到域名管理处编辑域名…...

Java-初识正则表达式 以及 练习
目录 什么是正则表达式? 1. 正则表达式---字符类(一个大括号匹配一个字符): 2. 正则表达式---预字符类(也是匹配一个字符): 正则表达式---数量词 (可以匹配多个字符)…...

【Flutter 问题系列第 80 篇】TextField 输入框组件限制可输入的最大长度后,输入的内容中包含表情符号时,获取输入的内容数还是会超出限制的问题
这是【Flutter 问题系列第 80 篇】,如果觉得有用的话,欢迎关注专栏。 博文当前所用 Flutter SDK:3.10.5、Dart SDK:3.0.5 一:问题描述 在输入用户名称、简介等内容时,一般我们都会限制输入框内最大可输入…...

漏洞检测和评估【网站子域扫描工具02】
上一篇:爬取目标网站的域名和子域名【网站子域扫描工具01】 在Python中,有一些流行的漏洞扫描库可以对子域进行漏洞扫描和评估,比如Nmap、Sublist3r等。 1.端口扫描 以下是一个简单的示例代码,展示了如何使用Nmap进行基本的端口扫…...
压力测试+接口测试(工具jmeter)
jmeter是apache公司基于java开发的一款开源压力测试工具,体积小,功能全,使用方便,是一个比较轻量级的测试工具,使用起来非常简单。因 为jmeter是java开发的,所以运行的时候必须先要安装jdk才可以。jmeter是…...

LeetCode 46 全排列
题目描述 全排列 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1: 输入:nums [1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]示例 2: 输入…...

npm install 无反应 npm run serve 无反应
说明情况:其实最开始我就是发现我跟着黑马的苍穹外卖的前端day2的环境搭建做的时候,到这一步出现了问题,无论我怎么 npm install 和 npm run serve 都没有像黑马一样有很多东西进行加载,因此我换了一种方法 1.在这个文件夹下cmd …...

JAVAEE初阶 文件IO(二)
文件IO 一. 文件流1.1 字节流 inputStream(1) try with resources方法 1.2 read方法(1) 第一个read方法(2) 第二个read方法(3) read的第三个方法 1.3 字节流 OutoutStream1.4 字符流(1) reader(2) writer 一. 文件流 1.1 字节流 inputStream 在字节流中,我们使用inputStream和…...

Golang 三数之和+ 四数之和 leetcode15、18 双指针法
文章目录 三数之和 leetcode15map记录 失败!超出限制双指针法 四数之和 leetcode18 三数之和 leetcode15 知识补充: map的key值必须是可以比较运算的类型,不可以是函数、map、slice map记录 失败!超出限制 //得到结果后再去重 失…...

Mysql三种常用的删除方式
前言 在 MySQL 中,有三种常用的方式可以删除表中的数据或整个表,它们分别是 TRUNCATE、DROP 和 DELETE。 TRUNCATE TABLE TRUNCATE TABLE属于DDL语言,不走事务,数据不会回滚 TRUNCATE TABLE 语句会删除表中的所有数据ÿ…...

Eureka 本机集群实现
距离上次发布博客已经一年多了,主要就是因为考研,没时间学习技术的内容,现在有时间继续完成关于代码方面的心得,希望跟大家分享。 今天在做一个 Eureka 的集群实现,我是在本电脑上跑的,感觉这个挺有意思&a…...

查看神经网络中间层特征矩阵及卷积核参数
可视化feature maps以及kernel weights,使用alexnet模型进行演示。 1. 查看中间层特征矩阵 alexnet模型,修改了向前传播 import torch from torch import nn from torch.nn import functional as F# 对花图像数据进行分类 class AlexNet(nn.Module):d…...