pinked

导航

es-jd

es-jd

依赖

<properties>
    <java.version>1.8</java.version>
    <elasticsearch.version>7.8.0</elasticsearch.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.62</version>
    </dependency>
    <dependency>
        <groupId>org.jsoup</groupId>
        <artifactId>jsoup</artifactId>
        <version>1.13.1</version>
    </dependency>
</dependencies>

实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Goods {
    private String name;
    private String price;
    private String img;
}

工具类方法

public List<Goods> getGoods(String keyword) throws IOException {
    String url = "https://search.jd.com/Search?keyword=" + keyword;
    Document document = Jsoup.parse(new URL(url), 30000);
    Element element = document.getElementById("J_goodsList");
    Elements elements = element.getElementsByTag("li");
    List<Goods> List = new ArrayList<>();
    for (Element li : elements) {
        Elements el = li.getElementsByTag("img").eq(0);
        String img = el.attr("src").equals("") ? el.attr("source-data-lazy-img") : el.attr("src");
        String price = li.getElementsByClass("p-price").eq(0).text();
        String name = li.getElementsByClass("p-name").eq(0).text();
        Goods goods = new Goods(name, price, img);
        List.add(goods);
    }
    return List;
}

配置config

@Configuration
public class ElasticSearchClientConfig {
    @Bean
    public RestHighLevelClient restHighLevelClient() {
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("localhost", 9200, "http")));
        return client;
    }
}

service层

@Service
public class GoodsService {

    @Autowired
    private HttpParseUtil httpParseUtil;

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    public boolean parseJD(String keyword) throws IOException {
        List<Goods> list = httpParseUtil.parseJD(keyword);
        BulkRequest request = new BulkRequest();
        request.timeout("2m");

        for (int i = 0; i < list.size(); i++) {
            request.add(
                    new IndexRequest("jd_goods")
                            .source(JSON.toJSONString(list.get(i)), XContentType.JSON)
            );
        }
        BulkResponse response = restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
        return !response.hasFailures();
    }


    public List<Map<String, Object>> searchJD(String keyword, int pageNo, int pageSize) throws IOException {
        if (pageNo <= 1) {
            pageNo = 1;
        }
        SearchRequest request = new SearchRequest("jd_goods");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //分页
        sourceBuilder.from(pageNo);
        sourceBuilder.size(pageSize);
        //精准匹配
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", keyword);
        sourceBuilder.query(termQueryBuilder);
        sourceBuilder.timeout(TimeValue.timeValueSeconds(60));

        request.source(sourceBuilder);
        SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);

        List<Map<String, Object>> list = new ArrayList<>();

        for (SearchHit documentFields : response.getHits().getHits()) {
            list.add(documentFields.getSourceAsMap());
        }
        return list;
    }

    //高亮搜索
    public List<Map<String, Object>> searchJDHighLight(String keyword, int pageNo, int pageSize) throws IOException {
        if (pageNo <= 1) {
            pageNo = 1;
        }
        SearchRequest request = new SearchRequest("jd_goods");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //分页
        sourceBuilder.from(pageNo);
        sourceBuilder.size(pageSize);
        //精准匹配
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", keyword);
        sourceBuilder.query(termQueryBuilder);
        sourceBuilder.timeout(TimeValue.timeValueSeconds(60));

        //高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("name");
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");
        sourceBuilder.highlighter(highlightBuilder);

        request.source(sourceBuilder);
        SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);

        List<Map<String, Object>> list = new ArrayList<>();

        for (SearchHit hit : response.getHits().getHits()) {
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField name = highlightFields.get("name");
            System.out.println("name->" + name);
            Map<String, Object> map = hit.getSourceAsMap();
            if (name != null) {
                Text[] fragments = name.fragments();
                String _name = "";
                for (Text fragment : fragments) {
                    _name += fragment;
                }
                map.put("name", _name);
            }
            list.add(map);
        }
        return list;
    }
}

controller层

@RestController
public class GoodsController {

    @Autowired
    GoodsService goodsService;

    @GetMapping("/parse/{keyword}")
    public boolean parseJD(@PathVariable("keyword") String keyword) throws IOException {
        return goodsService.parseJD(keyword);
    }

    @GetMapping("/search/{keyword}/{pageNo}/{pageSize}")
    public List<Map<String, Object>> searchJD(@PathVariable("keyword") String keyword,@PathVariable("pageNo")  int pageNo,@PathVariable("pageSize")  int pageSize) throws IOException {
        return goodsService.searchJDHighLight(keyword, pageNo, pageSize);
    }
}

前端页面

...

<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="search" id="searchbtn">搜索</button>
        </div>
    </fieldset>
</form>

,,,

<!-- 商品详情 -->
<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><b>¥</b>{{result.price}}</em>
            </p>
            <!--标题-->
            <p class="productTitle">
                    <a> {{result.name}} </a>-->
                <a  v-html="result.name"></a>
            </p>
            <!-- 店铺名 -->
            <div class="productShop">
                <span>店铺名</span>
            </div>
            <!-- 成交信息 -->
            <p class="productStatus">
                <span>月成交<em>999笔</em></span>
                <span>评价 <a>3</a></span>
            </p>
        </div>
    </div>
</div>

...

<script>
    new Vue({
        el: '#app',
        data: {
            keyword: '',
            results: []
        },
        methods: {
            search() {
                var keyword = this.keyword
                axios.get('/search/' + keyword + '/1' + '/20').then(res=>{
                    this.results = res.data;
                })
            }
        }
    })
</script>

posted on 2020-09-08 16:09  pinked  阅读(171)  评论(0编辑  收藏  举报