了解完基本的索引以及文档的增删改查,接下来该实战搞一搞了,老样子,打开该打开的
想要实现搜索,必须先有数据,第一步,通过网络爬虫获取京东的一些书籍数据:
通过下面代码,获取到书籍网站的 img 信息,price 信息,title 信息,网站如下:https://search.jd.com/Search
@Component
public class HtmlParseUtil {
// public static void main(String[] args) throws IOException {
// new HtmlParseUtil().parseJd("vue").forEach(System.out::println);
// }
public List<Content> parseJd(String keyswords) throws IOException {
// 获取请求
String url = "https://search.jd.com/Search?keyword=" + keyswords;
// 解析网页
Document document = Jsoup.parse(new URL(url), 30000);
Element element = document.getElementById("J_goodsList");
// System.out.println(element);
// 获取所有的 li 元素
Elements elements = element.getElementsByTag("li");
List<Content> list = 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();
list.add(new Content(title, img, price));
}
return list;
}
}
别忘了定义实体类
/**
* @Classname Content
* @Description
* @Date 2021/10/7 16:14
* @Created by thx
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Content {
private String title;
private String img;
private String price;
}
获取到数据以后,需要通过之前添加文档的方式,添加到 elasticSearch:
// 1、解析数据,放入 es 中
public Boolean parseContent(String keywords) throws IOException {
List<Content> contentList = new HtmlParseUtil().parseJd(keywords);
// 把查询的数据插入 es 中
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.timeout("2m");
for (int i = 0; i < contentList.size(); i++) {
bulkRequest.add(new IndexRequest("js_good")
.source(JSON.toJSONString(contentList.get(i)), XContentType.JSON));
}
BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
return bulk.hasFailures();
}
添加完以后,打开 elasticSearch 查看数据库信息:如下表示能够爬取到数据,并且能够添加到数据库
然后就进入正文,结合前端界面,实现数据的搜索
首先整合前端 vue
`
<!-- 头部搜索 -->
<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> {{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>
后端的代码:
controller 层,有分页信息,还有关键字
@GetMapping("/search/{keyword}/{pageNo}/{pageSize}")
public List<Map<String, Object>> search(@PathVariable("keyword") String keywords,
@PathVariable("pageNo")int pageNo,
@PathVariable("pageSize")int pageSize) throws IOException {
return contentService.searchPage(keywords, pageNo, pageSize);
}
service 层:
// 获取数据实现搜索
public List<Map<String, Object>> searchPage(String keyword, int pageNo, int pageSize) throws IOException {
if (pageNo <= 1) {
pageNo = 1;
}
// 条件搜索
SearchRequest searchRequest = new SearchRequest("js_good");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 分页
sourceBuilder.from(pageNo);
sourceBuilder.size(pageSize);
// 1、精准匹配
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", keyword);
sourceBuilder.query(termQueryBuilder);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
// 执行搜索
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
// 解析结果
List<Map<String, Object>> list = new ArrayList<>();
for (SearchHit documentFields : searchResponse.getHits().getHits()) {
list.add(documentFields.getSourceAsMap());
}
return list;
}
完成代码看结果:
需要注意,搜索的结果必须数据库里存在才行,就是是说,想要搜什么内容,都需要先去爬虫爬取数据,然后再搜索,如下 elasticsearch 里面只有 java 和 vue 的一些数据,所以只能收到这两个