ElasticSearchの包括的な実践

ElasticSearchの包括的な実践

一、爬虫

JDでJavaコピーリンクを検索https://search.jd.com/Search?keyword=java&enc=utf-8
ここに画像の説明を挿入します

そのdivの下で本を表示するにはF12
ここに画像の説明を挿入します

各本の次の情報
ここに画像の説明を挿入します

jsoupの依存関係をインポートする

<!--解析网页jsoup-->
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.13.1</version>
        </dependency>

<!--引入阿里巴巴的fastjson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.75</version>
        </dependency>

utilsパッケージを作成し、HtmlParseUtil.javaクロールテストをビルドします

//测试数据
public static void main(String[] args) throws IOException, InterruptedException {
    
    
	//获取请求
    String url = "https://search.jd.com/Search?keyword=java";
	// 解析网页 (Jsou返回的Document就是浏览器的Docuement对象)
    Document document = Jsoup.parse(new URL(url), 30000);
    //获取id,所有在js里面使用的方法在这里都可以使用
    Element element = document.getElementById("J_goodsList");
    //获取所有的li元素
    Elements elements = element.getElementsByTag("li");
    //用来计数
    int c = 0;
    //获取元素中的内容  ,这里的el就是每一个li标签
    for (Element el : elements) {
    
    
        c++;
        //这里有一点要注意,直接attr使用src是爬不出来的,因为京东使用了img懒加载
        String img = el.getElementsByTag("img").eq(0).attr("data-lazy-img");
        //获取商品的价格,并且只获取第一个text文本内容
        String price = el.getElementsByClass("p-price").eq(0).text();
        String title = el.getElementsByClass("p-name").eq(0).text();
        String shopName = el.getElementsByClass("p-shop").eq(0).text();

        System.out.println("========================================");
        System.out.println(img);
        System.out.println(price);
        System.out.println(title);
        System.out.println(shopName);
    }
    System.out.println(c);
}

テスト結果
ここに画像の説明を挿入します
問題なく結果が得られたら、このメソッドを使用するツールクラスとしてカプセル化します。

pojoエンティティクラスを作成します

Content.java

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Content {
    
    
    private String title;
    private String img;
    private String price;
    //可以自行添加属性
}

パッケージングツール

HtmlParseUtils.java

@Component
public class HtmlParseUtil {
    
    
//    public static void main(String[] args) throws IOException {
    
    
//        new HtmlParseUtil().parseJD("Java").forEach(System.out::println);
//    }

    public List<Content> parseJD(String keywords) throws IOException {
    
    
        //获取请求 https://search.jd.com/Search?keyword=java&enc=utf-8
        //前提需要连网
        String url = "https://search.jd.com/Search?keyword=" + keywords + "&enc=utf-8";
        //解析网页 (Jsoup返回Document就是浏览器Document对象)
        Document document = Jsoup.parse(new URL(url), 30000);
        //所有在js中能使用的方法,这里都能用
        Element element = document.getElementById("J_goodsList");
        //获取所有li元素
        Elements elements = element.getElementsByTag("li");

        ArrayList<Content> goodList = new ArrayList<>();

        //通过元素中的内容,这里el就是每一个li标签了
        for (Element el : elements) {
    
    
            //加if判断是为了 过滤空标签
            if (el.attr("class").equalsIgnoreCase("gl-item")) {
    
    
                //关于这种图片特别多的网页,所有的图片都是延迟加载的
                //在jd搜索后f12可以看到存放在data-lazy-img中
                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.setImg(img);
                content.setPrice(price);
                content.setTitle(title);
                goodList.add(content);
            }

        }
        return goodList;
 }
}

ビジネスレイヤコードを記述し、インターフェイスを削除します

ContentService.java

まず、クロールされたデータをESに保存する方法を完了します

//业务编写
@Service
public class ContentService {
    
    
	
	//将客户端注入
    @Autowired
    @Qualifier("restHighLevelClient")
    private RestHighLevelClient client;

    //1、解析数据放到 es 中
    public boolean parseContent(String keyword) throws IOException {
    
    
        List<Content> contents = new HtmlParseUtil().parseJD(keyword);
        //把查询的数据放入 es 中
        BulkRequest request = new BulkRequest();
        request.timeout("2m");

        for (int i = 0; i < contents.size(); i++) {
    
    
            request.add(
                    new IndexRequest("jd_goods")
                            .source(JSON.toJSONString(contents.get(i)), XContentType.JSON));

        }
        BulkResponse bulk = client.bulk(request, RequestOptions.DEFAULT);
        return !bulk.hasFailures();
    }
}

コントローラパッケージの下でビルドする

ContentController.java

//请求编写
@RestController
public class ContentController {
    
    

    @Autowired
    private ContentService contentService;

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

Springbootプロジェクトを開始して、データをESにクロールし
ここに画像の説明を挿入します
ここに画像の説明を挿入します
て検索機能実現できるかどうかにアクセスします
。ContentService.javaに追加します

//2、获取这些数据实现基本的搜索功能
public List<Map<String, Object>> searchPage(String keyword, int pageNo, int pageSize) throws IOException {
    
    
    if (pageNo <= 1) {
    
    
        pageNo = 1;
    }
    if (pageSize <= 1) {
    
    
        pageSize = 1;
    }

    //条件搜索
    SearchRequest searchRequest = new SearchRequest("jd_goods");
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

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

    //精准匹配
    TermQueryBuilder termQuery = QueryBuilders.termQuery("title", keyword);

    sourceBuilder.query(termQuery);
    sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
    //执行搜索
    SearchRequest source = searchRequest.source(sourceBuilder);
    SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
    //解析结果

    List<Map<String, Object>> list = new ArrayList<>();
    for (SearchHit documentFields : searchResponse.getHits().getHits()) {
    
    
        list.add(documentFields.getSourceAsMap());
    }
    return list;
}

ContentController.javaに検索リクエストを追加し、RestFulを使用します

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

http:// localhost:9090 / search / java / 1/20にアクセスします(Javaをクエリし、最初から20番目まで表示します)
ここに画像の説明を挿入します
。このデータのクロールと検索に問題はありません。ここで、の分離の前後から開始します。終わりは働いています

2、フロントとリアの分離

最初に準備されたリソースをインポートし、axios、jquery、vueのjsパッケージをインポートします。
ここに画像の説明を挿入します
フロントエンドはデータを受け入れる必要があります

vueでデータを受信する
ここに画像の説明を挿入します

<!--前端使用vue完成前后端分离-->
    <script th:src="@{/js/axios.min.js}"></script>
    <script th:src="@{/js/vue.min.js}"></script>
<script>
    new Vue({
     
     
        el: '#app',
        data: {
     
     
            keyword: '',  //搜索的关键字
            result: []  //搜索的结果
        },
        methods: {
     
     
            searchKey() {
     
     
                var keyword = this.keyword
                axios.get('search/' + keyword + '/1/210').then(response => {
     
     
                    //console.log(response);
                    this.result = response.data;//绑定数据!
            })
            }
        }
    })
</script>

次に、ボタンクリックイベントと検索バインディングをバインドし、
ここに画像の説明を挿入します
vueを使用してデータをフロントエンドに渡し、
ここに画像の説明を挿入します
localhost:9090にアクセスし、Javaを検索して試してください
ここに画像の説明を挿入します

3、検索のハイライト

ContentService.javaの検索機能を変更します

//3、获取这些数据实现基本的搜索高亮功能
public List<Map<String, Object>> searchPagehighlighter(String keyword, int pageNo, int pageSize) throws IOException {
    
    
    if (pageNo <= 1) {
    
    
        pageNo = 1;
    }
    if (pageSize <= 1) {
    
    
        pageSize = 1;
    }

    //条件搜索
    SearchRequest searchRequest = new SearchRequest("jd_goods");
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

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

    //精准匹配
    TermQueryBuilder termQuery = QueryBuilders.termQuery("title", keyword);

    //====================================   高   亮   ==========================================
    HighlightBuilder highlightBuilder = new HighlightBuilder(); //获取高亮构造器
    highlightBuilder.field("title"); //需要高亮的字段
    highlightBuilder.requireFieldMatch(false);//不需要多个字段高亮
    highlightBuilder.preTags("<span style='color:red'>"); //前缀
    highlightBuilder.postTags("</span>"); //后缀
    sourceBuilder.highlighter(highlightBuilder); //把高亮构造器放入sourceBuilder中
    sourceBuilder.query(termQuery);
    sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
    //执行搜索
    SearchRequest source = searchRequest.source(sourceBuilder);
    SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
    
    //解析结果
    List<Map<String, Object>> list = new ArrayList<>();
    for (SearchHit hit : searchResponse.getHits().getHits()) {
    
    

        Map<String, HighlightField> highlightFields = hit.getHighlightFields();//获取高亮字段
        HighlightField title = highlightFields.get("title"); //得到我们需要高亮的字段
        Map<String, Object> sourceAsMap = hit.getSourceAsMap();//原来的返回的结果

        //解析高亮的字段
        if (title != null) {
    
    
            Text[] fragments = title.fragments();
            String new_title = "";
            for (Text text : fragments) {
    
    
                new_title += text;
            }
            sourceAsMap.put("title", new_title);  //高亮字段替换掉原来的内容即可
        }
        list.add(sourceAsMap);
    }
    return list;
}

コントローラで検索リクエストを変更してみてください

@GetMapping("/search/{keyword}/{pageNo}/{pageSize}")
public List<Map<String, Object>> search(@PathVariable("keyword") String keyword,
                                        @PathVariable("pageNo") int pageNo,
                                        @PathVariable("pageSize") int pageSize) throws IOException {
    
    
    List<Map<String, Object>> list = contentService.searchPagehighlighter(keyword, pageNo, pageSize);
    return list;
}

アクセスの試み
ここに画像の説明を挿入します

完了しました
ここに画像の説明を挿入します

おすすめ

転載: blog.csdn.net/qq_43803285/article/details/114806210