创建一个项目
代码语言:javascript复制<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com</groupId>
<artifactId>demojd</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demojd</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<elasticsearch.version>7.6.1</elasticsearch.version>
</properties>
<dependencies>
<!-- 这个就是解析网页的-->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.10.2</version>
</dependency>
es
<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.60</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.60</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
yml里面配置
代码语言:javascript复制server.port=9090
#关闭页面缓存
spring.thymeleaf.cache=false
引入前端的页面
访问前端页面的controller层
代码语言:javascript复制@Controller
public class IndexCintroller {
@RequestMapping("/index")
public String index(){
return "index";
}
}
启动项目
以上就是静态的页面
爬虫爬取数据,保存在es里面
导入依赖
代码语言:javascript复制<!-- 这个就是解析网页的-->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.10.2</version>
</dependency>
创建实体类
代码语言:javascript复制@NoArgsConstructor
@AllArgsConstructor
@Data
public class Content {
private String name;
private String img;
private String price;
}
以上的实体类就是存放 爬取下的数据
工具类
这个工具类就是解析网站
业务代码的书写
将爬取下的数据放到es里面
controller层书写
代码语言:javascript复制 @Autowired
private ContentService contentService;
// 将爬取的数据保存在es里面的代码
@RequestMapping("/parse/{keyword}")
public Boolean parse(@PathVariable("keyword") String keyword) throws IOException {
return contentService.parseConent(keyword);
}
service 书写
代码语言:javascript复制// 将爬取下来的数据放到es里面
public Boolean parseConent(String keywords ) throws IOException {
根据关键字查询数据
List<Content> contents = new HtmlParseUtil().parseID(keywords);
// 批量将list数据插入到索引库里面
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.timeout("10s");
// 批处理请求
for (int i = 0; i < contents.size(); i ) {
// 批量更新和批量删除,就在这里修改对应的请求就可以了
bulkRequest.add(
new IndexRequest("jd").id("" (i 1))
.source(JSON.toJSONString(contents.get(i)),
XContentType.JSON));
}
BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
System.out.println(bulkResponse.hasFailures());
// 是否失败,返回 false 代表 成功!
return !bulkResponse.hasFailures();
}
访问链接
以上返回true ,意思是 已经将爬下来的数据放到es里面了。我们看看
以上是已经创建的索引
以上是爬取的数据,只是没有将图片爬取下来,这个有待解决
将es里面的数据取出来给前段的接口
controller
代码语言:javascript复制// 将es里面的数据取出来给前段的接口
@RequestMapping("/search/{keyword}/{pageNo}/{pageSize}")
public List<Map<String,Object>> search(@PathVariable("keyword") String keyword,
@PathVariable("pageNo")int pageNo,@PathVariable("pageSize")int pageSize) throws IOException {
return contentService.searchPage(keyword,pageNo,pageSize);
}
service
就是从es数据库里面获取数据返回给前段就可以了,就是一个根据关键字查询
代码语言:javascript复制 //实现从es里面获取高亮
public List<Map<String,Object>> searchPage(String keyword,int pageNo,int pageSize) throws IOException {
if (pageNo<=1){
pageNo=1;
}
从哪个索引,也就是哪个数据库查询数据
SearchRequest searchRequest = new SearchRequest("jd");
// 构建搜索条件
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 高亮 ,以哪个字段里面构建高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("name");
// 不需要多有的都高亮
highlightBuilder.requireFieldMatch(false);
highlightBuilder.preTags("<span style='color:red'>");
highlightBuilder.postTags("</span>");
将高亮的条件放到 搜索条件对象里面
sourceBuilder.highlighter(highlightBuilder);
// 分页查询
sourceBuilder.from(pageNo);
sourceBuilder.size(pageSize);
// 查询条件,我们可以使用 QueryBuilders 工具来实现
// QueryBuilders.termQuery 精确
//QueryBuilders.matchAllQuery() 匹配所有
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", keyword);
MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
将精确查询的对象放到 搜索对象里面
sourceBuilder.query(termQueryBuilder);
添加延迟时间
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
放到数据库对象里面
searchRequest.source(sourceBuilder);
执行
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
// System.out.println(JSON.toJSONString(searchResponse.getHits()));
// System.out.println("=================================");
// 解析搜索出来的数据,变为前端的格式,
ArrayList<Map<String,Object>> list = new ArrayList<>();
for(SearchHit documentFields :searchResponse.getHits().getHits()){
// 解析高亮的字段
Map<String, HighlightField> highlightFields = documentFields.getHighlightFields();
HighlightField title = highlightFields.get("name");
// 得到原来的字段
Map<String, Object> sourceAsMap = documentFields.getSourceAsMap();
if(title !=null){
Text[] fragments = title.fragments(); 得到高亮字段的值
String n_title = "";
for (Text text:fragments){
n_title =text;
}
sourceAsMap.put("name",n_title);//替换原来的字段
}
list.add(sourceAsMap);
}
return list;
}
解释查询es的service的代码
我们要根据关键字查询es数据库。并且要在显示的时候,要将我们查询的关键字高亮显示。这个咋实现呢?
在查询的时候,我们要设置高亮的代码
代码语言:javascript复制// 高亮 ,以哪个字段里面构建高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("name");
// 不需要多有的都高亮
highlightBuilder.requireFieldMatch(false);
highlightBuilder.preTags("<span style='color:red'>");
highlightBuilder.postTags("</span>");
将高亮的条件放到 搜索条件对象里面
sourceBuilder.highlighter(highlightBuilder);
并且这个高亮的字段 和 后面查询的字段名字要一样。 查询语句是
代码语言:javascript复制 SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
查询的条件是:
代码语言:javascript复制TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", keyword);
最后查询的结果searchResponse是一个集合,我们需要遍历
代码语言:javascript复制 for(SearchHit documentFields :searchResponse.getHits().getHits()){
System.out.println(documentFields);
输出的每一个documentFields是
以上和在kibana里面查询出的数据是一样的,因为在查询之前我们设置了高亮字段,并且设置了查询的条件,所以现在我们看到的每一个的结果中
根据查询的关键字中,已经将高亮的字段值中,将关键字用前端代码标注了,也就是已经高亮了。
既然已经查询出的数据已经高亮了,那么从这个结果里面将数据拿出来,整合为前端要的格式返回给前段就可以了。
将高亮里面name的字段放到原来数据里面,替换了,之后返回给前段的name字段里面就是显示高亮了。
关键的一点就是 替换