创建实体类Content存储数据
7. @Data8. @AllArgsConstructor9. @NoArgsConstructor10. public class Content {11. private String title;12. private String img;13. private String price;14. //可以自己添加数据15. }
再创建一个工具类UtilOfKeyWord 并测试
@Componentpublic class HtmlParseUtil {public static List<Content> praseJD(String keywords) throws IOException {//获取请求 https://search.jd.com/Search?keyword=java//前提,需要联网,String url = "https://search.jd.com/Search?keyword="+keywords;//解析网页(jsoup返回的Document就是浏览器的Document对象)Document document = Jsoup.parse(new URL(url), 3000);//所有在js中的方法这里都可以使用Element element = document.getElementById("J_goodsList");// System.out.println(element.html());//获取所有的li元素Elements elements = element.getElementsByTag("li");ArrayList<Content> goodList = new ArrayList<>();//获取元素里面的内容for (Element el:elements){String img = el.getElementsByTag("img").eq(0).attr("data-lazy-img");String price = el.getElementsByClass("p-price").eq(0).text();String title = el.getElementsByClass("p-name").eq(0).text();Content content = new Content();content.setTitle(title);content.setPrice(price);content.setImg(img);goodList.add(content);}return goodList;}}
添加 配置文件 config/ElasticSearchConfig.java
@Configurationpublic class ElasticSearchClientConfig {@Beanpublic RestHighLevelClient restHighLevelClient(){RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));return client;}}
编写业务类
将jd 查询数据存储es中
//1.解析数据,放入es索引中public Boolean parseContent(String keywords) throws IOException {List<Content> contents = HtmlParseUtil.praseJD(keywords);//把查询到的数据放入es中BulkRequest bulkRequest = new BulkRequest();bulkRequest.timeout("2m");for (int i = 0 ;i < contents.size();i++){bulkRequest.add(new IndexRequest("kuang_index").id(""+(i+1)).source(JSON.toJSONString(contents.get(i)), XContentType.JSON));}BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);return !bulk.hasFailures();}
编写ContentController
/7. @RestController8. public class ContentController {9.10. @Autowired11. private ContentService contentService;12.13. @GetMapping("/parse/{keyword}")14. public Boolean parse(@PathVariable("keyword") String keyword) throws Exception{15. return contentService.parseContent(keyword);16. }17. }
将京东数据存储es中
访问请求http://localhost:9090/parse/java
es 中显示内容
实现搜索功能(高亮)
3.1 编写搜索业务方法
ContentService层代码
package cn.ither.esjd.service;import cn.ither.esjd.pojo.Content;import cn.ither.esjd.utils.HtmlParseUtil;import com.alibaba.fastjson.JSON;import org.elasticsearch.action.bulk.BulkRequest;import org.elasticsearch.action.bulk.BulkResponse;import org.elasticsearch.action.index.IndexRequest;import org.elasticsearch.action.search.SearchRequest;import org.elasticsearch.action.search.SearchResponse;import org.elasticsearch.client.RequestOptions;import org.elasticsearch.client.RestHighLevelClient;import org.elasticsearch.common.text.Text;import org.elasticsearch.common.unit.TimeValue;import org.elasticsearch.common.xcontent.XContentType;import org.elasticsearch.index.query.QueryBuilders;import org.elasticsearch.index.query.TermQueryBuilder;import org.elasticsearch.search.SearchHit;import org.elasticsearch.search.builder.SearchSourceBuilder;import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.io.IOException;import java.util.ArrayList;import java.util.List;import java.util.Map;import java.util.concurrent.TimeUnit;/*** @Author: zhanghuan* @date: 2020/9/28 15:54* @description:*/@Servicepublic class ContentServiceImpl implements IContentService{@Autowiredprivate RestHighLevelClient restHighLevelClient;//1.解析数据,放入es索引中public Boolean parseContent(String keywords) throws IOException {List<Content> contents = HtmlParseUtil.praseJD(keywords);//把查询到的数据放入es中BulkRequest bulkRequest = new BulkRequest();bulkRequest.timeout("2m");for (int i = 0 ;i < contents.size();i++){bulkRequest.add(new IndexRequest("kuang_index").id(""+(i+1)).source(JSON.toJSONString(contents.get(i)), XContentType.JSON));}BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);return bulk.hasFailures();}//2.获取这些数据实现搜索功能(分页查询)public List<Map<String,Object>> searchPage(String keyword, int pageNo, int pageSize) throws IOException {if (pageNo <=0){pageNo = 1;}//条件搜索SearchRequest searchRequest = new SearchRequest("kuang_index");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//分页searchSourceBuilder.from(pageNo);searchSourceBuilder.size(pageSize);//精准匹配//查询条件TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", keyword);searchSourceBuilder.query(termQueryBuilder);// searchSourceBuilder.timeout(new TimeValue(60,TimeUnit.SECONDS));//执行搜索searchRequest.source(searchSourceBuilder);SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);//解析结果ArrayList<Map<String,Object>> list = new ArrayList<>();for(SearchHit documentFields:searchResponse.getHits().getHits()){list.add( documentFields.getSourceAsMap());}return list;}//3.获取这些数据实现搜索功能(高亮)public List<Map<String,Object>> searchPageHighlightBuilder(String keyword, int pageNo, int pageSize) throws IOException {if (pageNo <=0){pageNo = 1;}//条件搜索SearchRequest searchRequest = new SearchRequest("kuang_index");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//分页searchSourceBuilder.from(pageNo);searchSourceBuilder.size(pageSize);//精准匹配//查询条件TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", keyword);searchSourceBuilder.query(termQueryBuilder);searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));//高亮// 高亮HighlightBuilder highlightBuilder = new HighlightBuilder();highlightBuilder.field("title");//设置标题高亮highlightBuilder.requireFieldMatch(false);//关闭多个高亮显示highlightBuilder.preTags("<span style ='color:red;font-weight: bold'>"); //设置标签头highlightBuilder.postTags("</span>"); //设置标签尾searchSourceBuilder.highlighter(highlightBuilder);//执行搜索searchRequest.source(searchSourceBuilder);SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);ArrayList<Map<String,Object>> list = new ArrayList<>();for (SearchHit documentFields: searchResponse.getHits().getHits()){Map<String, HighlightField> highlightFields = documentFields.getHighlightFields();HighlightField title = highlightFields.get("title");Map<String, Object> sourceAsMap = documentFields.getSourceAsMap();//获取原来的结果//解析高亮的字段,将原来的字段换为高亮字段即可if(title != null){Text[] fragments = title.fragments();String n_title="";for (Text text: fragments) {//获取高亮的字段n_title+=text;}sourceAsMap.put("title",n_title);//高亮字段替换为原来内容即可}list.add(sourceAsMap);}return list;}}
ContentController层代码
import cn.ither.esjd.service.IContentService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RestController;import java.io.IOException;import java.util.List;import java.util.Map;/*** @Author: zhanghuan* @date: 2020/9/28 15:54* @description:*/@RestControllerpublic class ContentController {@Autowiredprivate IContentService contentService;@GetMapping("/parse/{keywords}")public Boolean parse(@PathVariable("keywords") String keywords) throws IOException {return contentService.parseContent(keywords);}@GetMapping("/search/{keywords}/{pageNo}/{pageSize}")public List<Map<String,Object>> search(@PathVariable("pageNo") int pageNo,@PathVariable("pageSize")int pageSize,@PathVariable("keywords") String keywords) throws IOException {return contentService.searchPage(keywords,pageNo,pageSize);}}
前后的交互
index.html代码
<!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}"/></head><body class="pg"><div class="page" id="app"><div id="mallPage" 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" value="dd" 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>{{result.price}}</em></p><!--标题--><p class="productTitle"><a v-html="result.title"></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 src="https://unpkg.com/axios/dist/axios.min.js"></script><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>new Vue({el:"#app",data :{keyword:"",//搜索关键字results:[] //搜索结果},methods: {searchKey() {var keyword = this.keyword;console.log(keyword);//对接后端的接口axios.get('search/'+keyword+"/1/10").then(response=>{console.log(response)this.results=response.data;})}}})</script></body></html>
页面展示效果


