阿里云服务器,elasticsearch,kibana,ik分词器碎碎念。

阿里云服务器,elasticsearch,kibana,ik分词器碎碎念。,第1张

阿里云服务器,elasticsearch,kibana,ik分词器碎碎念。

此处没有安装步骤,安装过程挺简单,开箱即用,只是安装过程有一些坑,此处只有碎碎念,随记。

目录

0、前述。

1、部署过程的一些问题。

2、搜索使用的技术。

3、freenom域名。

 4、部分代码。


0、前述。

趁着双11优惠,弄了一台1核2G的阿里云服务器,琢磨着部署点什么东西上去,刚好最近在学elasticsearch,就把做的一个搜索部署上去好了。

访问地址:

效果图:

1、部署过程的一些问题。

(1)elasticsearch、kibana、IK分词器,三者版本要一致,都用相同的版本。

特别是elasticsearch与IK的版本要一致,否则ES直接启动不了。

使用的elasticsearch版本:7.15.1。

使用的kibana版本:7.15.1。

使用的ik分词器版本:7.15.1。

(2)elasticsearch 7.x版本,JDK必须使用1.8以上版本,官方推荐使用jdk 11版本。

在安装ES之前,我已经在服务器上安装了一个JDK 1.8的版本,在window上jdk 1.8搭配elasticsearch7.15.0是可以运行的,在服务器上ES启动不了,最终服务器的jdk换成了jdk 11。

(3)启动ES,不要使用root用户,创建一个专门用于elasticsearch的用户,否则启动不了。

例如:创建一个名称为elastic的用户,添加到elastic组中。

groupadd elastic
useradd els -g elastic
passwd elastic
chown -R elastic:elastic /root

使用命令切换用户到elastic,然后启动ES。

su elastic

在window下不是管理员用户可以启动ES。

(4)服务器内存太小,只有2G。ES启动后不久后自动关闭,被系统kill掉了。或启动之后占满了内存,系统卡死。

修改elasticsearch的jvm内存。

vim elasticsearch-7.15.1/config/jvm.options

找到配置内容。

## -Xms4g
## -Xmx4g

去掉#号,修改配置为如下。

-Xms256m
-Xmx256m

(5)安装kibana,修改kibana的jvm内存。

vim  kibana-7.15.1-linux-x86_64/config/node.options

找到配置内容。

#--max-old-space-size=4096

去掉#号,修改配置为如下:

--max-old-space-size=400

(6)部署在服务器上的kibana,通过浏览器访问不到。

修改配置kibana.yml文件。

vim kibana-7.15.1-linux-x86_64/config/kibana.yml

找到配置内容。

#server.host: "localhost"

去掉#号,修改成服务器的内网IP地址,是内网IP地址,不是外网IP地址。默认kibana为localhost,只有安装kibana的服务器可以访问,其他访问不了。

修改配置:

server.host: "172.x.x.x"

修改完成之后,还是访问不到kibana。

修改阿里云服务器安全组规则访问,开启防火墙相关端口。

kibana.yml默认访问端口是5601。

#server.port: 5601

云服务器 ECS:
网络与安全-->安全组-->配置规则-->入方向。

(6)使用了jsoup,爬取不到数据,连接超时timeout。

jsoup端口随机生成的,。。。开启服务器出方向端口。

云服务器 ECS:
网络与安全-->安全组-->配置规则-->出方向。

2、搜索使用的技术。

(1)使用的主要技术elasticsearch、kibana、jsoup、spring boot。

次要技术:lombok、fastjson、selenium。

jsoup用来抓取解析数据,elasticsearch用来存储数据。kibana用来建ES索引,查看数据。
selenium用来配合Firefox浏览器等网页加载完成,再用jsoup解析数据,要打开浏览器,只能在有界面的系统使用,window下、带界面的Linux可以跑。

使用matchAllQuery搜索全部记录。
使用BoolQuery布尔查询组合matchQuery全文检索查询和TermQueryBuilder精准匹配查询 。
使用IK分词器ik_smart方式。
实现搜索高亮HighlightBuilder。

(2)建立ES索引。

使用默认shard,5个primary shard,5个replica shard。

title字段,使用IK分词器ik_smart解析,结合ES自带keyword分词器使用。

PUT /jd_goods
{
  "mappings": {
        "properties": {
          "img": {
            "type": "keyword"
          },
          "price": {
            "type": "double"
          },
          "shopname": {
            "type": "keyword"
          },
          "title": {
            "type": "text",
            "analyzer": "ik_smart",
            "fields": {
                "keyword": {
                  "type": "keyword"
                }
              }
          },
          "url": {
            "type": "keyword"
          }
        }
    }

}

3、freenom域名。

部署好了,绑定一个玉米,折腾了半天申请下来一个freenom免费玉米,配置好,因为没有备案,不到1分钟域名就被封了。。。。。。

 4、部分代码。

package com.xinxin.controller;

import com.xinxin.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;



    
    @GetMapping("/searchAll/{pageNo}/{pageSize}")
    public List> searchAll(@PathVariable("pageNo") int pageNo,
                                               @PathVariable("pageSize") int pageSize) throws IOException {
        return contentService.searchAllBuilder(pageNo, pageSize);
    }


    
    @GetMapping("/searchPage/{keyword}/{pageNo}/{pageSize}")
    public List> searchPage(@PathVariable("keyword") String keyword,
                                            @PathVariable("pageNo") int pageNo,
                                            @PathVariable("pageSize") int pageSize) throws IOException {
        return contentService.searchPage(keyword, pageNo, pageSize);
    }


    
    @GetMapping("/searchPageHighlight/{keyword}/{pageNo}/{pageSize}")
    public List> searchPageHighlight(@PathVariable("keyword") String keyword,
                                            @PathVariable("pageNo") int pageNo,
                                            @PathVariable("pageSize") int pageSize) throws IOException {
        return contentService.searchPageHighlightBuilder(keyword, pageNo, pageSize);
    }


    
    @GetMapping("/searchBoolQuery/{shopname}/{keyword}/{pageNo}/{pageSize}")
    public List> searchBoolQuery(@PathVariable("keyword") String keyword,
                                            @PathVariable("shopname") String shopname,
                                            @PathVariable("pageNo") int pageNo,
                                            @PathVariable("pageSize") int pageSize) throws IOException {
        //String nshopname = shopname!="" ? shopname : "机械工业出版社自营官方旗舰店";
        return contentService.searchBoolQueryBuilder(keyword, shopname, pageNo, pageSize);
    }


    
    @GetMapping("/searchBoolFilter/{keyword}/{pageNo}/{pageSize}")
    public List> searchBoolFilterQuery(@PathVariable("keyword") String keyword,
                                            @PathVariable("pageNo") int pageNo,
                                            @PathVariable("pageSize") int pageSize) throws IOException {
        return contentService.searchBoolFilterQueryBuilder(keyword, pageNo, pageSize);
    }


    
    @GetMapping("/search/{id}")
    public List> searchPageById(@PathVariable("id") String id) throws IOException {
        return contentService.searchPageById(id);
    }


    
    @GetMapping("/searchMulti/{keyword}/{pageNo}/{pageSize}")
    public List> searchMulti(@PathVariable("keyword") String keyword,
                                            @PathVariable("pageNo") int pageNo,
                                            @PathVariable("pageSize") int pageSize) throws Exception {
        return contentService.searchMultiMatchQueryBuilder(keyword, pageNo, pageSize);
    }


    
    @GetMapping("/search/{keyword}/{pageNo}/{pageSize}")
    public List> search(@PathVariable("keyword") String keyword,
                                            @PathVariable("pageNo") int pageNo,
                                            @PathVariable("pageSize") int pageSize) throws Exception {
        return contentService.search(keyword, pageNo, pageSize);
    }



    @GetMapping("/parse/{keyword}")
    public Boolean parse(@PathVariable("keyword") String keyword) throws Exception {
        return contentService.parseContent(keyword);
    }


}

package com.xinxin.service;

import com.alibaba.fastjson.JSON;
import com.xinxin.pojo.Content;
import com.xinxin.utils.ESconst;
import com.xinxin.utils.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.text.Text;
import org.elasticsearch.common.unit.Timevalue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
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.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


@Service
public class ContentService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;


    
    public Boolean parseContent(String keywords) throws Exception {
        List contents = new HtmlParseUtil().parseJD(keywords);
        //System.out.println(JSON.toJSonString(contents));

        //把从网站查询到的数据放入ES中。
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout("2m");

        for (int i = 0; i < contents.size(); i++) {
            bulkRequest.add(
                    new IndexRequest(ESconst.ES_INDEX)
                            .source(JSON.toJSonString(contents.get(i)), XContentType.JSON));
        }

        BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);

        return !bulk.hasFailures();
    }


    
    public List> searchPage(String keyword, int pageNo, int pageSize) throws IOException {
        if (pageNo <= 1) {
            pageNo = 1;
        }

        //条件搜索
        SearchRequest searchRequest = new SearchRequest(ESconst.ES_INDEX);
        //搜索源构建对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        //分页
        sourceBuilder.from(pageNo);
        sourceBuilder.size(pageSize);

        //termQuery精准匹配
        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> list = new ArrayList<>();
        for (SearchHit hit : searchResponse.getHits().getHits()) {
            //hit.getSourceAsMap() 源文档内容,就是数据中_source中的内容
            list.add(hit.getSourceAsMap());
        }

        return list;
    }


    
    public List> searchPageHighlightBuilder(String keyword, int pageNo, int pageSize) throws IOException {
        if (pageNo <= 1) {
            pageNo = 1;
        }

        //条件搜索
        SearchRequest searchRequest = new SearchRequest(ESconst.ES_INDEX);
        //搜索源构建对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        //分页
        sourceBuilder.from(pageNo);
        sourceBuilder.size(pageSize);

        //termQuery精确匹配
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", keyword);
        sourceBuilder.query(termQueryBuilder);
        sourceBuilder.timeout(new Timevalue(60, TimeUnit.SECONDS));

        //高亮,加上高亮。
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title");
        highlightBuilder.preTags("");
        highlightBuilder.postTags("");
        //是否多个高亮显示
        highlightBuilder.requireFieldMatch(false);
        sourceBuilder.highlighter(highlightBuilder);

        //执行搜索
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //解析结果
        List> list = new ArrayList<>();
        for (SearchHit hit : searchResponse.getHits().getHits()) {
            //解析出高亮,放到map中。
            Map highlightFields = hit.getHighlightFields();
            HighlightField title = highlightFields.get("title");
            //源文档内容,就是数据中_source中的内容
            //原来的结果。
            Map sourceAsMap = hit.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;
    }


    
    public List> searchAllBuilder(int pageNo, int pageSize) throws IOException {
        //搜索请求对象
        SearchRequest searchRequest = new SearchRequest(ESconst.ES_INDEX);
        //搜索源构建对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //分页查询,设置起始下标,从0开始
        searchSourceBuilder.from(pageNo);
        //每页显示个数
        searchSourceBuilder.size(pageSize);

        //搜索方式
        //matchAllQuery:搜索全部
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());

        //source源字段过虑,第一个参数结果集包括哪些字段,第二个参数表示结果集不包括哪些字段 "title", "img", "price", "url", "shopname"
        searchSourceBuilder.fetchSource(new String[]{"title", "img", "price", "url", "shopname"}, new String[]{});
        //向搜索请求对象中添加搜索源
        searchRequest.source(searchSourceBuilder);
        //执行搜索,向es发出http请求
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        //解析结果
        List> list = new ArrayList<>();
        for (SearchHit documentFields : searchResponse.getHits().getHits()) {
            list.add(documentFields.getSourceAsMap());
        }

        return list;
    }


    
    public List> searchPageById(String id) throws IOException {
        //条件搜索
        SearchRequest searchRequest = new SearchRequest(ESconst.ES_INDEX);
        //搜索源构建对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        //termsQuery精准匹配,根据id查询。
        //String[] split = new String[]{"1","2"};
        //List idList = Arrays.asList(split);
        TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery("_id", id);
        sourceBuilder.query(termsQueryBuilder);
        sourceBuilder.timeout(new Timevalue(60, TimeUnit.SECONDS));

        //执行搜索
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //解析结果
        List> list = new ArrayList<>();
        for (SearchHit hit : searchResponse.getHits().getHits()) {
            //hit.getSourceAsMap() 源文档内容,就是数据中_source中的内容
            list.add(hit.getSourceAsMap());
        }

        return list;
    }


    
    public List> searchMatchQueryHighlight(String keyword, int pageNo, int pageSize) throws IOException {
        if (pageNo <= 1) {
            pageNo = 1;
        }

        //条件搜索
        SearchRequest searchRequest = new SearchRequest(ESconst.ES_INDEX);
        //搜索源构建对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        //分页
        sourceBuilder.from(pageNo);
        sourceBuilder.size(pageSize);

        //matchQuery即全文检索。它的搜索方式是先将搜索字符串分词,再使用各各词条从索引中搜索。
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", keyword).minimumShouldMatch("80%"); //80%相似度就能匹配到
        sourceBuilder.query(matchQueryBuilder);
        sourceBuilder.timeout(new Timevalue(60, TimeUnit.SECONDS));

        //高亮,加上高亮。
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title");
        highlightBuilder.preTags("");
        highlightBuilder.postTags("");
        //是否多个高亮显示
        highlightBuilder.requireFieldMatch(false);
        sourceBuilder.highlighter(highlightBuilder);

        //执行搜索
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //解析结果
        List> list = new ArrayList<>();
        for (SearchHit hit : searchResponse.getHits().getHits()) {
            //解析出高亮,放到map中。
            Map highlightFields = hit.getHighlightFields();
            HighlightField title = highlightFields.get("title");
            //源文档内容,就是数据中_source中的内容
            //原来的结果。
            Map sourceAsMap = hit.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;
    }


    
    public List> searchMultiMatchQueryBuilder(String keyword, int pageNo, int pageSize) throws IOException {
        if (pageNo <= 1) {
            pageNo = 1;
        }

        //条件搜索
        SearchRequest searchRequest = new SearchRequest(ESconst.ES_INDEX);
        //搜索源构建对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        //分页
        sourceBuilder.from(pageNo);
        sourceBuilder.size(pageSize);

        //multiQuery多字段匹配查询,一次可以匹配多个字段。单项匹配是在一个field中去匹配,多项匹配是拿关键字去多个Field中匹配。
        //keyword(注:xxx yyy中间需要有空格不然不分词)在title或者shopname中任何一个有就可以。
        MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(keyword, "title", "shopname")
                .minimumShouldMatch("50%")   //50%相似度就能匹配到
                .field("title", 10);//提升boost:给name字段的权重提高10倍

        sourceBuilder.query(multiMatchQueryBuilder);
        sourceBuilder.timeout(new Timevalue(60, TimeUnit.SECONDS));


        //高亮,加上高亮。
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title");
        highlightBuilder.preTags("");
        highlightBuilder.postTags("");
        //是否多个高亮显示
        highlightBuilder.requireFieldMatch(false);
        sourceBuilder.highlighter(highlightBuilder);

        //执行搜索
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //解析结果
        List> list = new ArrayList<>();
        for (SearchHit hit : searchResponse.getHits().getHits()) {
            //解析出高亮,放到map中。
            Map highlightFields = hit.getHighlightFields();
            HighlightField title = highlightFields.get("title");
            //源文档内容,就是数据中_source中的内容
            //原来的结果。
            Map sourceAsMap = hit.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;
    }



    
    public List> searchBoolQueryBuilder(String keyword, String shopname, int pageNo, int pageSize) throws IOException {
        if (pageNo <= 1) {
            pageNo = 1;
        }

        //条件搜索
        SearchRequest searchRequest = new SearchRequest(ESconst.ES_INDEX);
        //搜索源构建对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        //分页
        sourceBuilder.from(pageNo);
        sourceBuilder.size(pageSize);

        //BoolQuery布尔查询,搜索方式。
        //1.先定义一个MultiMatchQuery,多字段匹配查询。
        //      multiQuery多字段匹配查询,一次可以匹配多个字段。单项匹配是在一个field中去匹配,多项匹配是拿关键字去多个Field中匹配。
        //      keyword(注:xxx yyy中间需要有空格不然不分词)在title或者shopname中任何一个有就可以。
        MultiMatchQueryBuilder field = QueryBuilders.multiMatchQuery(keyword, "title", "price")
                .minimumShouldMatch("50%")   //50%相似度就能匹配到
                .field("title", 10);//提升boost:给name字段的权重提高10倍

        //2.再定义一个termQuery,精准匹配查询。
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title.keyword", keyword);

        //3.再定义一个BooleanQuery布尔查询,把上面两个查询结合在一起。
        //BoolQuery布尔查询。
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.should(field);
        boolQueryBuilder.should(termQueryBuilder);

        sourceBuilder.query(boolQueryBuilder);
        sourceBuilder.timeout(new Timevalue(60, TimeUnit.SECONDS));

        //高亮,加上高亮。
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title");
        highlightBuilder.preTags("");
        highlightBuilder.postTags("");
        //是否多个高亮显示
        highlightBuilder.requireFieldMatch(false);
        sourceBuilder.highlighter(highlightBuilder);

        //执行搜索
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //解析结果
        List> list = new ArrayList<>();
        for (SearchHit hit : searchResponse.getHits().getHits()) {
            //解析出高亮,放到map中。
            Map highlightFields = hit.getHighlightFields();
            HighlightField title = highlightFields.get("title");
            //源文档内容,就是数据中_source中的内容
            //原来的结果。
            Map sourceAsMap = hit.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;
    }



    
    public List> searchBoolQueryBuilder2(String keyword, int pageNo, int pageSize) throws IOException {
        if (pageNo <= 1) {
            pageNo = 1;
        }

        //条件搜索
        SearchRequest searchRequest = new SearchRequest(ESconst.ES_INDEX);
        //搜索源构建对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        //分页
        sourceBuilder.from(pageNo);
        sourceBuilder.size(pageSize);

        //BoolQuery布尔查询,搜索方式。
        //1.先定义一个MultiMatchQuery,多字段匹配查询。
        //      multiQuery多字段匹配查询,一次可以匹配多个字段。单项匹配是在一个field中去匹配,多项匹配是拿关键字去多个Field中匹配。
        //      keyword(注:spring css中间需要有空格不然不分词)在title或者shopname中任何一个有就可以。
        
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", keyword).minimumShouldMatch("80%"); //80%相似度就能匹配到
        matchQueryBuilder.analyzer("ik_smart");
        //matchQueryBuilder.analyzer("comma");


        //2.再定义一个termQuery,精准匹配查询。
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title.keyword", keyword);
        //MatchQueryBuilder matchQueryBuilder1 = QueryBuilders.matchQuery("title", keyword);
        //matchQueryBuilder1.analyzer("keyword");

        //3.再定义一个BooleanQuery布尔查询,把上面两个查询结合在一起。
        //BoolQuery布尔查询。
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.should(termQueryBuilder);
        boolQueryBuilder.should(matchQueryBuilder);

        sourceBuilder.query(boolQueryBuilder);
        sourceBuilder.timeout(new Timevalue(60, TimeUnit.SECONDS));

        //高亮,加上高亮。
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title");
        highlightBuilder.preTags("");
        highlightBuilder.postTags("");
        //是否多个高亮显示
        highlightBuilder.requireFieldMatch(false);
        sourceBuilder.highlighter(highlightBuilder);

        //执行搜索
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //解析结果
        List> list = new ArrayList<>();
        for (SearchHit hit : searchResponse.getHits().getHits()) {
            //解析出高亮,放到map中。
            Map highlightFields = hit.getHighlightFields();
            HighlightField title = highlightFields.get("title");
            //源文档内容,就是数据中_source中的内容
            //原来的结果。
            Map sourceAsMap = hit.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;
    }



    
    public List> searchBoolFilterQueryBuilder(String keyword, int pageNo, int pageSize) throws IOException {
        if (pageNo <= 1) {
            pageNo = 1;
        }

        //条件搜索
        SearchRequest searchRequest = new SearchRequest(ESconst.ES_INDEX);
        //搜索源构建对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        //分页
        sourceBuilder.from(pageNo);
        sourceBuilder.size(pageSize);

        //BoolQuery布尔查询,搜索方式。
        //1.先定义一个MultiMatchQuery,多字段匹配查询。
        //      multiQuery多字段匹配查询,一次可以匹配多个字段。单项匹配是在一个field中去匹配,多项匹配是拿关键字去多个Field中匹配。
        //      keyword(注:spring css中间需要有空格不然不分词)在title或者shopname中任何一个有就可以。
        MultiMatchQueryBuilder field = QueryBuilders.multiMatchQuery(keyword, "title", "shopname")
                .minimumShouldMatch("50%")   //50%相似度就能匹配到
                .field("title", 10);//提升boost:给name字段的权重提高10倍

        //2.再定义一个BooleanQuery布尔查询。
        //BoolQuery布尔查询。
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(field);

        //过虑是针对搜索的结果进行过虑,过虑器主要判断的是文档是否匹配,不去计算和判断文档的匹配度得分,
        // 所以过虑器性能比查询要高,且方便缓存,推荐尽量使用过虑器去实现查询或者过虑器和查询共同使用。
        //过滤器,过滤条件。
        //boolQueryBuilder.filter(QueryBuilders.termQuery("publish", "201001"));//在publish里过滤201001
        boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(60).lte(100));  //价格区间
        sourceBuilder.query(boolQueryBuilder);


        sourceBuilder.timeout(new Timevalue(60, TimeUnit.SECONDS));

        //高亮,加上高亮。
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title");
        highlightBuilder.preTags("");
        highlightBuilder.postTags("");
        //是否多个高亮显示
        highlightBuilder.requireFieldMatch(false);
        sourceBuilder.highlighter(highlightBuilder);

        //执行搜索
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //解析结果
        List> list = new ArrayList<>();
        for (SearchHit hit : searchResponse.getHits().getHits()) {
            //解析出高亮,放到map中。
            Map highlightFields = hit.getHighlightFields();
            HighlightField title = highlightFields.get("title");
            //源文档内容,就是数据中_source中的内容
            //原来的结果。
            Map sourceAsMap = hit.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;
    }


    
    public List> search(String keyword, int pageNo, int pageSize) throws Exception {
        List> list = searchBoolQueryBuilder2(keyword, pageNo, pageSize);
        if (list.size()==0 || list.isEmpty()) {
            Boolean bool = parseContent(keyword);
            if (bool) {
                while (list.size()==0) {
                    list = searchBoolQueryBuilder2(keyword, pageNo, pageSize);
                }
            }
        }
        return list;
    }


}

package com.xinxin.utils;

import com.xinxin.pojo.Content;
import org.jsoup.Jsoup;
import org.jsoup.nodes.document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.openqa.selenium.Platform;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxBinary;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxProfile;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;


public class HtmlParseUtil {


    public static void main(String[] args) throws Exception {
        new HtmlParseUtil().parseJD("java").forEach(System.out::println);
    }


    public List parseJD(String keywords) throws IOException, InterruptedException {
        //获取请求  https://search.jd.com/Search?keyword=java&enc=utf-8
        String requestURL = "https://search.jd.com/Search?enc=utf-8&keyword=" + keywords;

        
        //方式一:等待网页加载完成解析。
        //版本:firefox浏览器:91.3.0esr (64 位)。geckodriver.exe:v0.30.0。
        //1、安装firefox浏览器。
        //2、下载geckodriver.exe驱动。下载地址:https://github.com/mozilla/geckodriver/releases,根据系统情况下载对于的驱动。例如:下window的驱动geckodriver-v0.30.0-win64.zip。
        //3、解压geckodriver-v0.30.0-win64.zip,将geckodriver.exe放到firefox安装目录,例如:D:Program FilesMozilla Firefox
        
        


        //方式二:不等网页加载完成就解析,解析网页,jsoup返回document就是浏览器document对象。
        document document = Jsoup.parse(new URL(requestURL), 30000);
        //System.out.println(document.html());
        Element element = document.getElementById("J_goodsList");
        //System.out.println(element.html());

        //获取所有的li元素
        Elements elements = element.getElementsByTag("li");

        List goodsList = new ArrayList<>();


        Content content = null;
        //获取元素中的内容。
        for (Element el : elements) {
            //获取图片,第1个img标签的src属性。
            String img = el.getElementsByTag("img").eq(0).attr("data-lazy-img");
            if ("done".equals(img) || StringUtils.isEmpty(img)) {
                img = el.getElementsByTag("img").eq(0).attr("src");
            }
            if ("done".equals(img) || StringUtils.isEmpty(img)) {
                img = el.getElementsByTag("img").eq(0).attr("source-data-lazy-img");
            }

            //获取价格,获取p-price样式的div的文本。
            //System.out.println(el.getElementsByClass("p-price").eq(0).select("strong").text());
            String price = el.getElementsByClass("p-price").eq(0).select("strong").text();
            price = price.replaceFirst("¥", "");
            //获取标题,获取p-name样式的div的文本。
            String title = el.getElementsByClass("p-name").eq(0).select("em").text();
            //获取详情页地址
            String url = el.getElementsByTag("a").eq(0).attr("href");
            //店铺名称
            String shopname = el.getElementsByClass("hd-shopname").eq(0).text();

            System.out.println("=====================================");
            System.out.println(img);
            System.out.println(price);
            System.out.println(title);
            System.out.println(url);
            System.out.println(shopname);

            content = new Content();
            content.setTitle(title);
            Double price1 = StringUtils.isEmpty(price) ? 6.66d : Double.parseDouble(price);
            content.setPrice(price1);
            content.setImg(img);
            content.setUrl(url);
            content.setShopname(shopname);
            goodsList.add(content);
        }

        return goodsList;
    }

}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5117452.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-17
下一篇 2022-11-17

发表评论

登录后才能评论

评论列表(0条)

保存