ElasticSearch-ElasticSearch实战-仿京东商城搜索(高亮)
注:此为笔者学习狂神说ElasticSearch的实战笔记,其中包含个人的笔记和理解,仅做学习笔记之用,更多详细资讯请出门左拐B站:狂神说!!!
七、ElasticSearch实战
仿京东商城搜索(高亮)

1、工程创建(springboot)

目录结构
2、基本编码
①导入依赖


<properties><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>2.3.7.RELEASE</spring-boot.version></properties><dependencies><!-- jsoup解析页面 --><!-- 解析网页 爬视频可 研究tiko --><dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.10.2</version></dependency><!-- fastjson --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.70</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<!-- <version>7.6.1</version>--></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>
②导入前端素材
③编写 application.preperties配置文件
# 更改端口,防止冲突
server.port=9999
# 关闭thymeleaf缓存
spring.thymeleaf.cache=false
④测试controller和view

@Controller
public class IndexController {@GetMapping({"/","index"})public String index(){return "index";}
}

到这里可以先去编写爬虫,编写之后,回到这里
⑤编写Config
@Configuration
public class ElasticSearchConfig {@Beanpublic RestHighLevelClient restHighLevelClient(){RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("127.0.0.1",9200,"http")));return client;}
}
⑥编写service
因为是爬取的数据,那么就不走Dao,以下编写都不会编写接口,开发中必须严格要求编写
ContentService




@Service
public class ContentService {@Autowiredprivate RestHighLevelClient restHighLevelClient;// 1、解析数据放入 es 索引中public Boolean parseContent(String keyword) throws IOException {// 获取内容List<Content> contents = HtmlParseUtil.parseJD(keyword);// 内容放入 es 中BulkRequest bulkRequest = new BulkRequest();bulkRequest.timeout("2m"); // 可更具实际业务是指for (int i = 0; i < contents.size(); i++) {bulkRequest.add(new IndexRequest("jd_goods").id(""+(i+1)).source(JSON.toJSONString(contents.get(i)), XContentType.JSON));}BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);restHighLevelClient.close();return !bulk.hasFailures();}// 2、根据keyword分页查询结果public List<Map<String, Object>> search(String keyword, Integer pageIndex, Integer pageSize) throws IOException {if (pageIndex < 0){pageIndex = 0;}SearchRequest jd_goods = new SearchRequest("jd_goods");// 创建搜索源建造者对象SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();// 条件采用:精确查询 通过keyword查字段nameTermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", keyword);searchSourceBuilder.query(termQueryBuilder);searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));// 60s// 分页searchSourceBuilder.from(pageIndex);searchSourceBuilder.size(pageSize);// 高亮// ....// 搜索源放入搜索请求中jd_goods.source(searchSourceBuilder);// 执行查询,返回结果SearchResponse searchResponse = restHighLevelClient.search(jd_goods, RequestOptions.DEFAULT);restHighLevelClient.close();// 解析结果SearchHits hits = searchResponse.getHits();List<Map<String,Object>> results = new ArrayList<>();for (SearchHit documentFields : hits.getHits()) {Map<String, Object> sourceAsMap = documentFields.getSourceAsMap();results.add(sourceAsMap);}// 返回查询的结果return results;}
}
⑦编写controller

⑧测试结果
1、解析数据放入 es 索引中

2、根据keyword分页查询结果

报错
java.lang.IllegalStateException: Request cannot be executed; I/O reactor status: STOPPED
一般是因为OTSClient被调用了shutDown,其内部的I/O reactor均已被关闭。如果此时再调用OTSClient进行读写,则会抛出这个错误。 此处是:restHighLevelClient
3、爬虫(jsoup)
数据获取:数据库、消息队列、爬虫、…
①搜索京东搜索页面,并分析页面
http://search.jd.com/search?keyword=java
页面如下

审查页面元素
页面列表id:J_goodsList

目标元素:img、price、name

②爬取数据(获取请求返回的页面信息,筛选出可用的)
创建HtmlParseUtil,并简单编写

public class HtmlParseUtil {public static void main(String[] args) throws IOException {/// 使用前需要联网// 请求urlString url = "http://search.jd.com/search?keyword=java";// 1.解析网页(jsoup 解析返回的对象是浏览器Document对象)Document document = Jsoup.parse(new URL(url), 30000);// 使用document可以使用在js对document的所有操作// 2.获取元素(通过id)Element j_goodsList = document.getElementById("J_goodsList");// 3.获取J_goodsList ul 每一个 liElements lis = j_goodsList.getElementsByTag("li");// 4.获取li下的 img、price、namefor (Element li : lis) {String img = li.getElementsByTag("img").eq(0).attr("src");// 获取li下 第一张图片String name = li.getElementsByClass("p-name").eq(0).text();String price = li.getElementsByClass("p-price").eq(0).text();System.out.println("=======================");System.out.println("img : " + img);System.out.println("name : " + name);System.out.println("price : " + price);}}
}
运行结果

原因是啥?
一般图片特别多的网站,所有的图片都是通过延迟加载的
发现img标签中并没有属性src的设置,只是data-lazy-img设置图片加载的地址




创建HtmlParseUtil、改写
- 更改图片获取属性为
data-lazy-img - 与实体类结合,实体类如下
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Content implements Serializable {private static final long serialVersionUID = -8049497962627482693L;private String name;private String img;private String price;
}
- 封装为方法
public class HtmlParseUtil {public static void main(String[] args) throws IOException {System.out.println(parseJD("java"));}public static List<Content> parseJD(String keyword) throws IOException {/// 使用前需要联网// 请求urlString url = "http://search.jd.com/search?keyword=" + keyword;// 1.解析网页(jsoup 解析返回的对象是浏览器Document对象)Document document = Jsoup.parse(new URL(url), 30000);// 使用document可以使用在js对document的所有操作// 2.获取元素(通过id)Element j_goodsList = document.getElementById("J_goodsList");// 3.获取J_goodsList ul 每一个 liElements lis = j_goodsList.getElementsByTag("li");
// System.out.println(lis);// 4.获取li下的 img、price、name// list存储所有li下的内容List<Content> contents = new ArrayList<Content>();for (Element li : lis) {// 由于网站图片使用懒加载,将src属性替换为data-lazy-imgString img = li.getElementsByTag("img").eq(0).attr("data-lazy-img");// 获取li下 第一张图片String name = li.getElementsByClass("p-name").eq(0).text();String price = li.getElementsByClass("p-price").eq(0).text();// 封装为对象Content content = new Content(name,img,price);// 添加到list中contents.add(content);}
// System.out.println(contents);// 5.返回 listreturn contents;}
}
结果展示

4、搜索高亮
在3、的基础上添加内容

①ContentService


// 3、 在2的基础上进行高亮查询
public List<Map<String, Object>> highlightSearch(String keyword, Integer pageIndex, Integer pageSize) throws IOException {SearchRequest searchRequest = new SearchRequest("jd_goods");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();// 精确查询,添加查询条件TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", keyword);searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));searchSourceBuilder.query(termQueryBuilder);// 分页searchSourceBuilder.from(pageIndex);searchSourceBuilder.size(pageSize);// 高亮 =========HighlightBuilder highlightBuilder = new HighlightBuilder();highlightBuilder.field("name");highlightBuilder.preTags("<span style='color:red'>");highlightBuilder.postTags("</span>");searchSourceBuilder.highlighter(highlightBuilder);// 执行查询searchRequest.source(searchSourceBuilder);SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);// 解析结果 ==========SearchHits hits = searchResponse.getHits();List<Map<String, Object>> results = new ArrayList<>();for (SearchHit documentFields : hits.getHits()) {// 使用新的字段值(高亮),覆盖旧的字段值Map<String, Object> sourceAsMap = documentFields.getSourceAsMap();// 高亮字段Map<String, HighlightField> highlightFields = documentFields.getHighlightFields();HighlightField name = highlightFields.get("name");// 替换if (name != null){Text[] fragments = name.fragments();StringBuilder new_name = new StringBuilder();for (Text text : fragments) {new_name.append(text);}sourceAsMap.put("name",new_name.toString());}results.add(sourceAsMap);}return results;
}
②ContentController
替换高亮的方法

@ResponseBody
@GetMapping("/h_search/{keyword}/{pageIndex}/{pageSize}")
public List<Map<String, Object>> highlightParse(@PathVariable("keyword") String keyword,@PathVariable("pageIndex") Integer pageIndex,@PathVariable("pageSize") Integer pageSize) throws IOException {return contentService.highlightSearch(keyword,pageIndex,pageSize);
}
③结果展示




最终页面

5、前后端分离(简单使用Vue)
①下载并引入Vue.min.js和axios.js
下载失败报错,试试初始化一下npm

npm install vue
npm install axios

导入vue.min.js和axios.min.js



②修改静态页面
引入js
<script th:src="@{/js/vue.min.js}"></script>
<script th:src="@{/js/axios.min.js}"></script>
实现数据的双向绑定

绑定点击事件,去掉事件冒泡



遍历数据


<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><meta charset="utf-8"/><title>狂神说Java-ES仿京东实战</title><link rel="stylesheet" th:href="@{/css/style.css}"/><script th:src="@{/js/jquery.min.js}"></script>
</head>
<body class="pg">
<div class="page"><div id="app" class=" mallist tmall- page-not-market "><!-- 头部搜索 --><div id="header" class=" header-list-app"><div class="headerLayout"><div class="headerCon "><!-- Logo--><h1 id="mallLogo"><img th:src="@{/images/jdlogo.png}" alt=""></h1><div class="header-extra"><!--搜索--><div id="mallSearch" class="mall-search"><form name="searchTop" class="mallSearch-form clearfix"><fieldset><legend>天猫搜索</legend><div class="mallSearch-input clearfix"><div class="s-combobox" id="s-combobox-685"><div class="s-combobox-input-wrap"><input v-model="keyword" type="text" autocomplete="off" id="mq"class="s-combobox-input" aria-haspopup="true"></div></div><button type="submit" @click.prevent="searchKey" id="searchbtn">搜索</button></div></fieldset></form><ul class="relKeyTop"><li><a>狂神说Java</a></li><li><a>狂神说前端</a></li><li><a>狂神说Linux</a></li><li><a>狂神说大数据</a></li><li><a>狂神聊理财</a></li></ul></div></div></div></div></div><!-- 商品详情页面 --><div id="content"><div class="main"><!-- 品牌分类 --><form class="navAttrsForm"><div class="attrs j_NavAttrs" style="display:block"><div class="brandAttr j_nav_brand"><div class="j_Brand attr"><div class="attrKey">品牌</div><div class="attrValues"><ul class="av-collapse row-2"><li><a href="#"> 狂神说 </a></li><li><a href="#"> Java </a></li></ul></div></div></div></div></form><!-- 排序规则 --><div class="filter clearfix"><a class="fSort fSort-cur">综合<i class="f-ico-arrow-d"></i></a><a class="fSort">人气<i class="f-ico-arrow-d"></i></a><a class="fSort">新品<i class="f-ico-arrow-d"></i></a><a class="fSort">销量<i class="f-ico-arrow-d"></i></a><a class="fSort">价格<i class="f-ico-triangle-mt"></i><i class="f-ico-triangle-mb"></i></a></div><!-- 商品详情 --><div class="view grid-nosku" ><div class="product" v-for="result in results"><div class="product-iWrap"><!--商品封面--><div class="productImg-wrap"><a class="productImg"><img :src="result.img"></a></div><!--价格--><p class="productPrice"><em v-text="result.price"></em></p><!--标题--><p class="productTitle"><a v-html="result.name"></a></p><!-- 店铺名 --><div class="productShop"><span>店铺: 狂神说Java </span></div><!-- 成交信息 --><p class="productStatus"><span>月成交<em>999笔</em></span><span>评价 <a>3</a></span></p></div></div></div></div></div></div>
</div>
<script th:src="@{/js/vue.min.js}"></script>
<script th:src="@{/js/axios.min.js}"></script>
<script>new Vue({el:"#app",data:{"keyword": '', // 搜索的关键字"results":[] // 后端返回的结果},methods:{searchKey(){var keyword = this.keyword;console.log(keyword);axios.get('h_search/'+keyword+'/0/20').then(response=>{console.log(response.data);this.results=response.data;})}}});
</script>
</body>
</html>
测试

ElasticSearch-ElasticSearch实战-仿京东商城搜索(高亮) 到此完结,笔者归纳、创作不易,大佬们给个3连再起飞吧
相关文章:
ElasticSearch-ElasticSearch实战-仿京东商城搜索(高亮)
注:此为笔者学习狂神说ElasticSearch的实战笔记,其中包含个人的笔记和理解,仅做学习笔记之用,更多详细资讯请出门左拐B站:狂神说!!! 七、ElasticSearch实战 仿京东商城搜索(高亮) 1、工程创建…...
解释 Python 中的描述符(Descriptor)是什么?如何在 Python 中实现一个简单的 ORM(对象关系映射)?
解释 Python 中的描述符(Descriptor)是什么?举例说明其用法。 在 Python 中,描述符(Descriptor)是一种对象属性的扩展机制,它允许你在访问或修改属性时执行自定义的操作。描述符是实现了特定协…...
IP数据云识别真实IP与虚假流量案例
随着互联网的普及,企业在数字领域面临着越来越复杂的网络威胁。为了保护网站免受虚假流量和恶意攻击的影响,许多企业正在采用IP数据云。本文将结合一个真实案例,深入探讨IP数据云如何成功准确地识别真实用户IP和虚假流量IP,提高网…...
signalR+websocket:实现消息实时通讯——技能提升
signalR 解决步骤1:npm install microsoft/signalr6.0.6 安装指定版本的microsoft/signalr,我这边安装的版本是6.0.6 解决步骤2:引入import * as signalR from microsoft/signalr; import * as signalR from microsoft/signalr; 下面第三…...
机器学习入门-----sklearn
机器学习基础了解 概念 机器学习是人工智能的一个实现途径 深度学习是机器学习的一个方法发展而来 定义:从数据中自动分析获得模型,并利用模型对特征数据【数据集:特征值+目标值构成】进行预测 算法 数据集的目标值是类别的话叫做分类问题;目标值是连续的数值的话叫做回…...
双非本科准备秋招(15.3)—— 力扣二叉树
今天学了二叉树结点表示法,建树代码如下。 public class TreeNode {public int val;public TreeNode left;public TreeNode right;public TreeNode(int val) {this.val val;}public TreeNode(int val, TreeNode left, TreeNode right) {this.val val;this.left …...
20240203在WIN10下使用GTX1080配置stable-diffusion-webui.git不支持float16精度出错的处理
20240203在WIN10下使用GTX1080配置stable-diffusion-webui.git不支持float16精度出错的处理 2024/2/3 21:23 缘起:最近学习stable-diffusion-webui.git,在Ubuntu20.04.6下配置SD成功。 不搞精简版本:Miniconda了。直接上Anacoda! …...
京东微前端框架MicroApp简介
一、MicroApp 1.1 MicroApp简介 MicroApp是由京东前端团队推出的一款微前端框架,它从组件化的思维,基于类WebComponent进行微前端的渲染,旨在降低上手难度、提升工作效率。MicroApp无关技术栈,也不和业务绑定,可以用于任何前端框架。 官网链接:https://micro-zoe.gith…...
SpringBoot 使用定时任务(SpringTask)
Spring3.0以后自带的task,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多。 使用步骤: 1.导入坐标 在spring-boot-starter-web坐标中,就包含了SpringTask,所以一般的Web项目都包含了。 <depende…...
国标GB/T 28181详解:设备视音频文件检索消息流程
目 录 一、设备视音频文件检索 二、设备视音频文件检索的基本要求 三、命令流程 1、流程图 2、流程描述 四、协议接口 五、产品说明 六、设备视音频文件检索的作用 七、参考 在国标GBT28181中,定义了设备视音频文件检索消息的流程,主…...
openssl自签名CA根证书、服务端和客户端证书生成并模拟单向/双向证书验证
1. 生成根证书 1.1 生成CA证书私钥 openssl genrsa -aes256 -out ca.key 2048 1.2 取消密钥的密码保护 openssl rsa -in ca.key -out ca.key 1.3 生成根证书签发申请文件(csr文件) openssl req -new -sha256 -key ca.key -out ca.csr -subj "/CCN/STFJ/LXM/ONONE/OU…...
NIO Selector简介
1.Selector和Channel关系 Selector一般称为选择器,也叫多路复用器,NIO的核心组件,用于检查一个或多个Channel的状态是否处于可读、可写的状态。 2.可选择通道 (1)不是所有的channel都能被selector复用,…...
2023-12蓝桥杯STEMA考试 C++ 中高级试卷解析
蓝桥杯STEMA考试 C++ 中高级试卷(12月) 一、选择题 第一题 定义字符串 string a = "Hello C++",下列选项可以获取到字符 C 的是(B)。 A、a[7] B、a[6] C、a[5] D、a[4] 第二题 下列选项中数值与其它项不同的是( C)。 A、 B、 C、 D、 第三题 定义变量 int i =…...
设计模式——2_1 命令(Command)
文章目录 定义图纸一个例子:空调和他的遥控器只有控制面板的空调遥控器可以撤销的操作 碎碎念命令和Runnable命令和事务 定义 把请求封装成一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持…...
HP数组面试题
PHP数组面试题 问题: 如何创建一个空数组和一个带有初始值的数组? 答案: 创建空数组:可以使用array()函数或空数组语法[]来创建一个空数组,例如$arr array();或$arr [];。创建带有初始值的数组:可以在创建…...
机器学习5-线性回归之损失函数
在线性回归中,我们通常使用最小二乘法(Ordinary Least Squares, OLS)来求解损失函数。线性回归的目标是找到一条直线,使得预测值与实际值的平方差最小化。 假设有数据集 其中 是输入特征, 是对应的输出。 线性回归的…...
vulhub中Adminer ElasticSearch 和 ClickHouse 错误页面SSRF漏洞复现(CVE-2021-21311)
Adminer是一个PHP编写的开源数据库管理工具,支持MySQL、MariaDB、PostgreSQL、SQLite、MS SQL、Oracle、Elasticsearch、MongoDB等数据库。 在其4.0.0到4.7.9版本之间,连接 ElasticSearch 和 ClickHouse 数据库时存在一处服务端请求伪造漏洞(…...
浅谈Zookeeper及windows下详细安装步骤
1. Zookeeper介绍 1.1 分布式系统面临的问题 分布式系统是一个硬件或软件组件分布在不同的网络计算机上,彼此之间仅仅通过消息传递进行通信和协调的系统。 面临的问题:系统每个节点之间信息同步及共享 以一个小团队为例,面临的问题 通过网络进行信息…...
vite, vue3, vue-router, vuex, ES6学习日记
学习使用vitevue3的所遇问题总结(2024年2月1日) 组件中使用<script>标签忘记加 setup 这会导致Navbar 没有暴露出来,导致使用不了,出现以下报错 这是因为,如果不用setup,就得使用 export default…...
25考研|660/880/1000/1800全年带刷计划
作为一个参加过两次研究生考试的老学姐,我觉得考研数学的难度完全取决于你自己 我自己就是一个很好的例子 21年数学题目是公认的简单,那一年考130的很多,但是我那一年只考了87分。但是22年又都说是有史以来最难的一年,和20年的难度…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...
宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...
Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...
LOOI机器人的技术实现解析:从手势识别到边缘检测
LOOI机器人作为一款创新的AI硬件产品,通过将智能手机转变为具有情感交互能力的桌面机器人,展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家,我将全面解析LOOI的技术实现架构,特别是其手势识别、物体识别和环境…...
五子棋测试用例
一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏,有着深厚的文化底蕴。通过将五子棋制作成网页游戏,可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家,都可以通过网页五子棋感受到东方棋类…...
企业大模型服务合规指南:深度解析备案与登记制度
伴随AI技术的爆炸式发展,尤其是大模型(LLM)在各行各业的深度应用和整合,企业利用AI技术提升效率、创新服务的步伐不断加快。无论是像DeepSeek这样的前沿技术提供者,还是积极拥抱AI转型的传统企业,在面向公众…...
