ElasticSearch目录
文章目录
七、ElasticSearch实战(仿京东商城搜索)
7.1、项目整体概况7.2、项目初始化7.3、爬虫数据7.4、业务编写
1、编写ESConfig2、编写service3、编写controller4、测试 7.5、前后端分离(简单使用Vue)
1、下载并引入Vue.min.js和axios.min.js2、修改静态页面index.html 7.6、搜索高亮
1、ContentService 增加方法2、ContentController增加入口3、测试 7.7、问题:
1、使用term(精确查询)时,我发现三个问题,问题如下:
七、ElasticSearch实战(仿京东商城搜索) 7.1、项目整体概况目录结构
项目:wlw/ESDemo (gitee.com)
7.2、项目初始化1、导入依赖
1.8 7.6.1 org.jsoup jsoup1.10.2 com.alibaba fastjson1.2.70 org.springframework.boot spring-boot-starter-data-elasticsearchorg.springframework.boot spring-boot-starter-thymeleaforg.springframework.boot spring-boot-starter-weborg.springframework.boot spring-boot-devtoolsruntime true org.springframework.boot spring-boot-configuration-processortrue org.projectlombok lomboktrue org.springframework.boot spring-boot-starter-testtest
2、导入前端素材
3、编写 application.preperties配置文件
# 更改端口,防止冲突 server.port=9999 # 关闭thymeleaf缓存 spring.thymeleaf.cache=false
4、测试controller和view
@Controller public class IndexController { @GetMapping({"/","/index"}) public String index(){ return "index"; } }
访问 localhost:9999
7.3、爬虫数据那我们的数据怎么处理?通常可以选择数据库获取、消息队列中获取、都可以成为数据源,这里我们用爬虫
爬取数据: (获取请求返回的页面信息,筛选出我们想要的数据就可以了! )
路径:http://search.jd.com/Search?keyword=java
jsoup包。做爬虫用的
导入包:
org.jsoup jsoup1.10.2
工具类:
package com.wlw.util; import org.jsoup.Jsoup; import org.jsoup.nodes.document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import java.io.IOException; import java.net.URL; public class HtmlParseUtil { public static void main(String[] args) throws IOException { /// 使用前需要联网 // 请求url String url = "http://search.jd.com/search?keyword=java"; //1.解析网页(jsoup 解析返回的document对象 就是 浏览器document对象) document document = Jsoup.parse(new URL(url), 30000); //使用document可以使用在js对document的所有 *** 作 //2.获取元素(通过id) J_goodsList是通过F12 审查该页面源代码得到的 Element j_goodsList = document.getElementById("J_goodsList"); //3.获取J_goodsList 中的 ul里的 每一个 li 标签 Elements lis = j_goodsList.getElementsByTag("li"); System.out.println(lis); //4.获取li下的 img、price、name 标签 for (Element li : lis) { // 获取li下 第一张图片 String img = li.getElementsByTag("img").eq(0).attr("src"); 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、price、name
运行结果发现没有图片的信息
原因是啥?
一般图片特别多的网站,所有的图片都是通过延迟加载的
// 打印标签内容 Elements lis = j_goodsList.getElementsByTag("li"); System.out.println(lis);
打印所有li标签,发现img标签中并没有属性src的设置,只是data-lazy-img设置图片加载的地址
HtmlParseUtil的改写
更改图片获取属性为 data-lazy-img与实体类结合,实体类如下
package com.wlw.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; @Data @AllArgsConstructor @NoArgsConstructor public class Content implements Serializable { private static final long serialVersionUID = -8049497962627482693L; private String name; private String price; private String img; }
package com.wlw.util; import com.wlw.pojo.Content; import org.jsoup.Jsoup; import org.jsoup.nodes.document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import org.springframework.stereotype.Component; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; @Component public class HtmlParseUtil { public static void main(String[] args) throws Exception { parseJD("java").forEach(System.out::println); } public static List7.4、业务编写 1、编写ESConfigparseJD(String keywords) throws Exception { /// 使用前需要联网 // 请求url String url = "http://search.jd.com/search?keyword=" + keywords; //1.解析网页(jsoup 解析返回的document对象 就是 浏览器document对象) document document = Jsoup.parse(new URL(url), 30000); //使用document可以使用在js对document的所有 *** 作 //2.获取元素(通过id) J_goodsList是通过F12 审查该页面源代码得到的 Element j_goodsList = document.getElementById("J_goodsList"); //3.获取J_goodsList 中的 ul里的 每一个 li 标签 Elements lis = j_goodsList.getElementsByTag("li"); List contents = new ArrayList (); //4.获取li下的 img、price、name 标签 for (Element li : lis) { // 获取li下 第一张图片 // 一般图片特别多的网站,所有的图片都是通过延迟加载的 // 所以我们要获得的图片节点属性是: data-lazy-img String img = li.getElementsByTag("img").eq(0).attr("data-lazy-img"); String name = li.getElementsByClass("p-name").eq(0).text(); String price = li.getElementsByClass("p-price").eq(0).text(); //封装为对象 contents.add(new Content(name, price, img)); } return contents; } }
package com.wlw.config; import org.apache.http.HttpHost; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class ElasticSearchConfig { // 注册 rest高级客户端 @Bean public RestHighLevelClient restHighLevelClient(){ RestHighLevelClient client = new RestHighLevelClient( //如果是集群就构建多个 RestClient.builder(new HttpHost("127.0.0.1",9200,"http")) ); return client; } }2、编写service
因为是爬取的数据,那么就不走Dao,以下编写都不会编写接口,开发中必须严格要求编写
ContentService
package com.wlw.service; import com.alibaba.fastjson.JSON; import com.wlw.pojo.Content; import com.wlw.util.HtmlParseUtil; 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.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.SearchHits; import org.elasticsearch.search.builder.SearchSourceBuilder; 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; @Service public class ContentService { @Autowired private RestHighLevelClient restHighLevelClient; //把数据放入 es 索引中 public Boolean parseContent(String keywords) throws Exception { //1、获取内容 List3、编写controllercontents = HtmlParseUtil.parseJD(keywords); //2、内容放入 es 中 (批量存入到ES中) BulkRequest bulkRequest = new BulkRequest(); bulkRequest.timeout("2m"); //超时时间,可根据实际业务来设置 for (int i = 0; i < contents.size(); i++) { //jd_goods 为索引库名,所以需要事先创建好 bulkRequest.add(new IndexRequest("jd_goods") //.id(""+(i+1)) //不写就是随机id .source(JSON.toJSONString(contents.get(i)), XContentType.JSON) ); } BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT); //restHighLevelClient.close(); return !bulk.hasFailures(); } //根据keywords分页查询结果 public List
package com.wlw.controller; import com.wlw.service.ContentService; 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; @RestController public class ContentController { @Autowired private ContentService contentService; //把数据放入 es 索引中 @GetMapping("/parse/{keywords}") public Boolean parse(@PathVariable("keywords") String keywords) throws Exception { return contentService.parseContent(keywords); } //分页查询 @GetMapping("/search/{keywords}/{pageIndex}/{pageSize}") public List4、测试> parse(@PathVariable("keywords") String keywords, @PathVariable("pageIndex") Integer pageIndex, @PathVariable("pageSize") Integer pageSize) throws IOException { return contentService.search(keywords,pageIndex,pageSize); } }
http://localhost:9999/parse/java 测试插入,页面返回true,然后通过es可视化工具查询数据情况
http://localhost:9999/search/java/1/10 分页查询,页面直接返回数据
7.5、前后端分离(简单使用Vue) 1、下载并引入Vue.min.js和axios.min.js如果安装了nodejs,可以按如下步骤,没有可以到后面素材处下载
npm install vue npm install axios2、修改静态页面index.html
引入js
修改后的index.html
WLW-ES仿京东实战
评论列表(0条)