官方笔记:

京东搜索案例

1) 搭建环境

WX 狂神说回复 “ElasticSearch” 获得 网页模板.
06-京东商城搜索项目 - 图1image.png

配置 IndexController, 启动, 查看效果

2) 爬取数据

使用 jsoup 依赖, 爬取网页.

补充 tika 依赖, 用来下载内容, 比如音乐, 视频

  1. <!-- jsoup 解析网页 -->
  2. <dependency>
  3. <groupId>org.jsoup</groupId>
  4. <artifactId>jsoup</artifactId>
  5. <version>1.14.3</version>
  6. </dependency>

爬取数据通用方法:

  1. public static List<Goods> parseJDGoods(String keyword) {
  2. String url = "https://search.jd.com/Search?keyword=";
  3. List<Goods> goodsList = new LinkedList<>();
  4. try {
  5. // 支持中文搜索
  6. url += URLEncoder.encode(keyword, "utf-8");
  7. // 解析的页面, 类似 js 中的 document
  8. Document document = Jsoup.parse(new URL(url), 1000 * 10); // 10s
  9. Element element = document.getElementById("J_goodsList");
  10. assert element != null;
  11. Elements liSet = element.getElementsByTag("li");
  12. for (Element ele : liSet) {
  13. String img = ele.getElementsByTag("img").eq(0).attr("data-lazy-img");
  14. String price = ele.getElementsByClass("p-price").eq(0).text();
  15. String title = ele.getElementsByClass("p-name").eq(0).text();
  16. String shop = ele.getElementsByClass("curr-shop hd-shopname").eq(0).text();
  17. goodsList.add(new Goods(title, price, img, shop));
  18. }
  19. } catch (Exception ex) {
  20. throw new RuntimeException("解析 jd 购物页失败: " + ex.getMessage());
  21. }
  22. return goodsList;
  23. }

3) 搜索接口

两个接口:

  • 解析 JD 网页, 收集数据
  • 提供给用户搜索商品的接口

06-京东商城搜索项目 - 图3image.png

  1. @Override
  2. public List<Map<String, Object>> searchGoods(String keyword, int pageNo, int pageSize) {
  3. // 存放搜索结果
  4. List<Map<String, Object>> goodsList = new LinkedList<>();
  5. if (!StringUtils.hasLength(keyword)) return goodsList;
  6. if (pageNo <= 0) pageNo = 1;
  7. if (pageSize < 0) pageSize = 0;
  8. try {
  9. SearchRequest searchRequest = new SearchRequest(ESConstant.JD_ES_GOODS_LIST);
  10. // 构建搜索条件
  11. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  12. // 搜索超时
  13. searchSourceBuilder.timeout(TimeValue.timeValueSeconds(10));
  14. // // 精确匹配 --> title字段拆分时有时无
  15. // TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", keyword);
  16. // searchSourceBuilder.query(termQueryBuilder);
  17. // match 匹配
  18. MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", keyword);
  19. searchSourceBuilder.query(matchQueryBuilder);
  20. // 分页数据
  21. searchSourceBuilder.from(pageNo);
  22. searchSourceBuilder.size(pageSize);
  23. // 使用搜索条件
  24. searchRequest.source(searchSourceBuilder);
  25. SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
  26. SearchHit[] hits = searchResponse.getHits().getHits();
  27. for (SearchHit hit : hits) {
  28. Map<String, Object> map = hit.getSourceAsMap();
  29. goodsList.add(map);
  30. }
  31. } catch (Exception ex) {
  32. // TODO
  33. }
  34. return goodsList;
  35. }

4) 前后端分离

06-京东商城搜索项目 - 图5
image.png
前端使用 Vue 和 Axios, 请求后端接口渲染页面
image.png
06-京东商城搜索项目 - 图8
06-京东商城搜索项目 - 图9image.png

  1. new Vue({
  2. el: '#app',
  3. data: {
  4. keyword: '', // 搜索关键字
  5. goodsList: [] // 搜索结果
  6. },
  7. methods: {
  8. searchGoods() {
  9. console.log(this.keyword)
  10. // 请求数据
  11. axios.get('search/' + this.keyword + "/1/15").then(response => {
  12. console.log(response)
  13. this.goodsList = response.data
  14. })
  15. }
  16. }
  17. })

5) 高亮

06-京东商城搜索项目 - 图11
image.png
06-京东商城搜索项目 - 图13image.png
06-京东商城搜索项目 - 图15
image.png