【Elasticsearch学习之三】Elasticsearch 搜索引擎案例
环境
虚拟机:VMware 10
Linux版本:CentOS-6.5-x86_64
客户端:Xshell4
FTP:Xftp4
jdk8
elasticsearch-2.2.0
第一步:获取数据
主流搜索引擎,会使用爬虫,来获取网站的html数据,常用的工具有nutch,Python(主流),wget(c语言)
这里使用wget模拟
#安装wget
yum install wget
#使用wget从文件wget.log爬取数据
#参数:
#-o 指定爬取内容输出日志名
#-P 爬取生成文件目录父目录
#-m 拷贝
#-D 列举爬取域名清单
#-N 不重新检索文件, 除非更新文件时间晚于本地时间
#--convert-links 根据路径转换成目录
#--random-wait 随机等待 间隔性爬取 以防止被禁止访问
#-A 指定文档类型
#最后指定爬取网站地址
[cluster@PCS101 /] wget -o /tmp/wget.log -P /root/data --no-parent --no-verbose -m -D news.cctv.com -N --convert-links --random-wait -A html,HTML,shtml,SHTML http://news.cctv.com
第二步:ES集群安装分词器IK
注意:必选选择与ES对应的IK版本 https://github.com/medcl/elasticsearch-analysis-ik
#将ik目录直接ftp上传到目录下/opt/cluster/es/elasticsearch-2.2.1/plugins
#更改目录所有者
[cluster@PCS101 plugins]$ chown -R cluster:cluster ik
修改配置 plugin-descriptor.properties
elasticsearch.version=2.2.1
分发至102、103:
[cluster@PCS101 plugins]$ scp -r ik/ cluster@PCS102:`pwd`
[cluster@PCS101 plugins]$ scp -r ik/ cluster@PCS103:`pwd`
第三步:数据抽取:从网页中抽取数据
HtmlTool.java
package com.sxt.util; import java.io.File; import com.sxt.es.HtmlBean;
import com.sxt.es.IndexService; import net.htmlparser.jericho.CharacterReference;
import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.HTMLElementName;
import net.htmlparser.jericho.Source; public class HtmlTool { /**
* 数据过滤清洗 将网页转换成javabean
* @param path html 文件路径
*/
public static HtmlBean parserHtml(String path)throws Throwable{
HtmlBean bean =new HtmlBean();
Source source=new Source(new File(path));
source.fullSequentialParse();
Element titleElement=source.getFirstElement(HTMLElementName.TITLE);
if(titleElement==null){
return null;
}else{
String title=CharacterReference.decodeCollapseWhiteSpace(titleElement.getContent());
bean.setTitle(title);
}
String content =source.getTextExtractor().setIncludeAttributes(true).toString(); String url =path.substring(IndexService.DATA_DIR.length());
bean.setContent(content);
bean.setUrl(url);
return bean;
} /**
* @param args
*/
public static void main(String[] args) {
try {
System.out.println(parserHtml("e:\\data\\news.cctv.com\\2017\\05\\01\\ARTI0k5MFLx2cvzQZffwQcUp170501.shtml").getContent());
} catch (Throwable e) {
e.printStackTrace();
}
}
}
HtmlBean.java
package com.sxt.es; public class HtmlBean { private int id;
private String title;
private String content;
private String url;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
} }
第四步:把抽取出来的数据同ES建立索引
#创建索引库
IndexService.java::createIndex
#数据同ES建立索引
IndexService.java::addHtmlToES
package com.sxt.es; import java.io.File;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map; import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.Requests;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryParser;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.junit.Test;
import org.springframework.stereotype.Service; import com.sxt.util.HtmlTool; @Service
public class IndexService { //存放html文件的目录
public static String DATA_DIR="e:\\data\\";
//定义客户端
public static Client client; static {
//设置连接集群名
Settings settings = Settings.settingsBuilder().put("cluster.name", "wjy-es").build();
try {
//创建连接集群客户端
client = TransportClient
.builder()
.settings(settings)
.build()
.addTransportAddress(
new InetSocketTransportAddress(InetAddress
.getByName("134.32.123.101"), 9300))
.addTransportAddress(
new InetSocketTransportAddress(InetAddress
.getByName("134.32.123.102"), 9300))
.addTransportAddress(
new InetSocketTransportAddress(InetAddress
.getByName("134.32.123.103"), 9300));
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 创建索引库
* admin():管理索引库的。client.admin().indices()
* 索引数据的管理:client.prepare
*/
@Test
public void createIndex() throws Exception {
IndicesExistsResponse resp = client.admin().indices().prepareExists("testes").execute().actionGet();
//存在删除旧的
if(resp.isExists()){
client.admin().indices().prepareDelete("testes").execute().actionGet();
}
//创建
client.admin().indices().prepareCreate("testes").execute().actionGet(); new XContentFactory(); XContentBuilder builder = XContentFactory.jsonBuilder()
.startObject()
.startObject("htmlbean")
.startObject("properties")//type
.startObject("title")
.field("type", "string")//字符串类型
.field("store", "yes")//是否保存
.field("analyzer", "ik_max_word")//指定分词器
.field("search_analyzer", "ik_max_word")//指定搜索依赖的分词器
.endObject()
.startObject("content")
.field("type", "string")
.field("store", "yes")
.field("analyzer", "ik_max_word")
.field("search_analyzer", "ik_max_word")
.endObject()
.startObject("url")
.field("type", "string")
.field("store", "yes")
.field("analyzer", "ik_max_word")
.field("search_analyzer", "ik_max_word")
.endObject()
.endObject()
.endObject()
.endObject();
//创建type
PutMappingRequest mapping = Requests.putMappingRequest("testes").type("htmlbean").source(builder);
client.admin().indices().putMapping(mapping).actionGet(); } /**
* 把源数据html文件添加到索引库中(构建索引文件)
*/
@Test
public void addHtmlToES(){
readHtml(new File(DATA_DIR));
} /**
* 遍历数据文件目录d:/data ,递归方法
* @param file
*/
public void readHtml(File file){
if(file.isDirectory()){
File[] fs =file.listFiles();
for (int i = 0; i < fs.length; i++) {
File f = fs[i];
readHtml(f);
}
}else{
HtmlBean bean;
try {
bean = HtmlTool.parserHtml(file.getPath());
if(bean!=null){
Map<String, String> dataMap =new HashMap<String, String>();
dataMap.put("title", bean.getTitle());
dataMap.put("content", bean.getContent());
dataMap.put("url", bean.getUrl());
//写索引
client.prepareIndex("testes", "htmlbean").setSource(dataMap).execute().actionGet();
}
} catch (Throwable e) {
e.printStackTrace();
} }
} /**
* 搜索
* @param kw
* @param num
* @return
*/
public PageBean<HtmlBean> search(String kw,int num,int count){
PageBean<HtmlBean> wr =new PageBean<HtmlBean>();
wr.setIndex(num);
// //构建查询条件
// MatchQueryBuilder q1 =new MatchQueryBuilder("title", kw);
// MatchQueryBuilder q2 =new MatchQueryBuilder("content", kw);
//
// //构建一个多条件查询对象
// BoolQueryBuilder q =new BoolQueryBuilder(); //组合查询条件对象
// q.should(q1);
// q.should(q2); // RangeQueryBuilder q1 =new RangeQueryBuilder("age");
// q1.from(18);
// q1.to(40); MultiMatchQueryBuilder q =new MultiMatchQueryBuilder(kw, new String[]{"title","content"});
SearchResponse resp=null;
if(wr.getIndex()==1){//第一页
resp = client.prepareSearch("testes")
.setTypes("htmlbean")
.setQuery(q)
.addHighlightedField("title")
.addHighlightedField("content")
.setHighlighterPreTags("<font color=\"red\">")
.setHighlighterPostTags("</font>")
.setHighlighterFragmentSize(40)//设置显示结果中一个碎片段的长度
.setHighlighterNumOfFragments(5)//设置显示结果中每个结果最多显示碎片段,每个碎片段之间用...隔开
.setFrom(0)//从第几个开始
.setSize(10)//第一页数量
.execute()
.actionGet(); }else{
wr.setTotalCount(count);
resp = client.prepareSearch("testes")
.setTypes("htmlbean")
.setQuery(q)
.addHighlightedField("title")//高亮显示
.addHighlightedField("content")
.setHighlighterPreTags("<font color=\"red\">")//红色显示
.setHighlighterPostTags("</font>")
.setHighlighterFragmentSize(40)
.setHighlighterNumOfFragments(5)
.setFrom(wr.getStartRow())
.setSize(10)
.execute()
.actionGet();
}
SearchHits hits= resp.getHits();
wr.setTotalCount((int)hits.getTotalHits()); for(SearchHit hit : hits.getHits())
{
HtmlBean bean =new HtmlBean();
if(hit.getHighlightFields().get("title")==null)
{//title中没有包含关键字
bean.setTitle(hit.getSource().get("title").toString());//获取原来的title(没有高亮的title)
}
else
{
bean.setTitle(hit.getHighlightFields().get("title").getFragments()[0].toString());
} if(hit.getHighlightFields().get("content")==null)
{//content中没有包含关键字
bean.setContent(hit.getSource().get("content").toString());//获取原来的content(没有高亮的content)
}
else
{
StringBuilder sb =new StringBuilder();
for(Text text: hit.getHighlightFields().get("content").getFragments())
{
sb.append(text.toString()+"...");
}
bean.setContent(sb.toString());
} bean.setUrl("http://"+hit.getSource().get("url").toString());
wr.setBean(bean);
} return wr;
} // @Test
// public void del(){
//// client.admin().indices().prepareDelete("testes").execute().actionGet();
// client.admin().indices().prepareDelete("testes").execute().actionGet();
// }
}
第五步:搜索数据
IndexService.java::search 见上面代码
PageBean.java
package com.sxt.es; import java.util.ArrayList;
import java.util.List; public class PageBean<T> {
private int size = 10;//每页显示记录
private int index = 1;// 当前页号
private int totalCount = 0;// 记录总数 private int totalPageCount = 1;// 总页 private int[] numbers;//展示页数集合
protected List<T> list;//要显示到页面的数据集 /**
* 得到
* @return
*/
public int getStartRow() { return (index - 1) * size;
} /**
* 得到结束记录
* @return
*/
public int getEndRow() { return index * size;
} /**
* @return Returns the size.
*/
public int getSize() {
return size;
} /**
* @param size
* The size to set.
*/
public void setSize(int size) {
if (size > 0) {
this.size = size;
}
}
/**
* @return Returns the currentPageNo.
*/
public int getIndex() {
if (totalPageCount == 0) { return 0;
} return index;
} /**
* @param currentPageNo
* The currentPageNo to set.
*/
public void setIndex(int index) {
if (index > 0) {
this.index = index;
}
} /**
* @return Returns the totalCount.
*/
public int getTotalCount() {
return totalCount;
} /**
* @param totalCount
* The totalCount to set.
*/
public void setTotalCount(int totalCount) {
if (totalCount >= 0) {
this.totalCount = totalCount;
setTotalPageCountByRs();//根据总记录数计算总页
}
} public int getTotalPageCount() {
return this.totalPageCount;
} /**
* 根据总记录数计算总页
*/
private void setTotalPageCountByRs() {
if (this.size > 0 && this.totalCount > 0 && this.totalCount % this.size == 0) {
this.totalPageCount = this.totalCount / this.size;
} else if (this.size > 0 && this.totalCount > 0 && this.totalCount % this.size > 0) {
this.totalPageCount = (this.totalCount / this.size) + 1;
} else {
this.totalPageCount = 0;
}
setNumbers(totalPageCount);//获取展示页数集合
} public int[] getNumbers() {
return numbers;
} /**
* 设置显示页数集合
* @param totalPageCount
*/
public void setNumbers(int totalPageCount) {
if(totalPageCount>0){
//!.当前数组的长度
int[] numbers = new int[totalPageCount>10?10:totalPageCount];//页面要显示的页数集合
int k =0;
//
//1.数组长度<10 1 2 3 4 .... 7
//2.数组长度>=10
// 当前页<=6 1 2 3 4 10
// 当前页>=总页数-5 ......12 13 14 15
// 其他 5 6 7 8 当前页(10) 10 11 12 13
for(int i = 0;i < totalPageCount;i++){
//保证当前页为集合的中�?
if((i>=index- (numbers.length/2+1) || i >= totalPageCount-numbers.length) && k<numbers.length){
numbers[k] = i+1;
k++;
}else if(k>=numbers.length){
break;
}
} this.numbers = numbers;
} } public void setNumbers(int[] numbers) {
this.numbers = numbers;
} public List<T> getList() {
return list;
} public void setList(List<T> list) {
this.list = list;
} public void setBean(T bean){
if(this.list==null){
list =new ArrayList<T>();
}
list.add(bean);
} /*
public static int getTotalPageCount(int iTotalRecordCount, int iPageSize) {
if (iPageSize == 0) {
return 0;
} else {
return (iTotalRecordCount % iPageSize) == 0 ? (iTotalRecordCount / iPageSize) : (iTotalRecordCount / iPageSize) + 1;
}
}*/
}
启动ES_SEARCH web,访问 http://localhost:8080/ES_SEARCH
输入关键词 搜索:
项目代码下载连接:https://download.csdn.net/download/cac2020/11015439
【Elasticsearch学习之三】Elasticsearch 搜索引擎案例的更多相关文章
- Elasticsearch学习之快速入门案例
1. document数据格式 面向文档的搜索分析引擎 (1)应用系统的数据结构都是面向对象的,复杂的(2)对象数据存储到数据库中,只能拆解开来,变为扁平的多张表,每次查询的时候还得还原回对象格式,相 ...
- Elasticsearch学习之ElasticSearch 5.0.0 安装部署常见错误或问题
ElasticSearch 5.0.0 安装部署常见错误或问题 问题一: [--06T16::,][WARN ][o.e.b.JNANatives ] unable to install syscal ...
- Elasticsearch学习(5) Elasticsearch+logstash +filebeat+log4j的日志系统
最近需要使用Elasticsearch做一个日志系统,本文只介绍log4j内容同步到Elasticsearch,至于日志的查询和分类,会在后面介绍. 一.配置并打开Elasticsearch 这个操作 ...
- Elasticsearch 学习笔记 Elasticsearch及Elasticsearch head安装配置
一.安装与配置 1.到官网下载Elasticsearch,https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.6. ...
- Elasticsearch学习总结 (Centos7下Elasticsearch集群部署记录)
一. ElasticSearch简单介绍 ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticse ...
- Elasticsearch学习,请先看这一篇!
原文:Elasticsearch学习,请先看这一篇! 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn ...
- Elasticsearch学习,请先看这一篇
题记: Elasticsearch研究有一段时间了,现特将Elasticsearch相关核心知识.原理从初学者认知.学习的角度,从以下9个方面进行详细梳理.欢迎讨论-- 0. 带着问题上路--ES是如 ...
- ElasticSearch学习笔记-01 简介、安装、配置与核心概念
一.简介 ElasticSearch是一个基于Lucene构建的开源,分布式,RESTful搜索引擎.设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便.支持通过HTTP使用JSON进 ...
- 【转】Elasticsearch学习
原作者:铭毅天下,原文地址:blog.csdn.net/laoyang360 https://blog.csdn.net/wojiushiwo987/article/details/52244917 ...
随机推荐
- swift 灯光的打开与关闭
func lightBtnAction(sender: UIButton){ let device = AVCaptureDevice.default(for:.video) if device == ...
- CSS中position属性介绍(新增sticky)
position的含义是指定类型,取值类型可以有:static.relative.absolute.fixed.inherit 和 sticky,这里sticky是CSS3新发布的一个属性. 1.po ...
- more 命令
[root@localhost ~]# .txt # 按页显示文件内容,能向下翻页查看
- Python识别字符型图片验证码
前言 验证码是目前互联网上非常常见也是非常重要的一个事物,充当着很多系统的 防火墙 功能,但是随时OCR技术的发展,验证码暴露出来的安全问题也越来越严峻.本文介绍了一套字符验证码识别的完整流程,对于验 ...
- Python3学习之路~2.9 字符编码与转码
详细文章: http://www.cnblogs.com/yuanchenqi/articles/5956943.html http://www.diveintopython3.net/strings ...
- 技嘉B75-D3V主板BUG
故障:这块B75-D3V v1.2 主板一直会报内存故障. 详细情况是:一按下主机电源键~立即报“嘀嘀嘀声...”大约半分钟然后重启,不断的循环没有人为关闭电源会一直不停的循环这个现象. 因为连着遇到 ...
- Oracle(1)之虚拟机下安装与简单使用
Oracle介绍与安装 简介 Oracle 数据库系统是美国 ORACLE 公司(甲骨文)提供的以分布式数据库为核心的一组软件产品,是目前最流行的客户/服务器 (CLIENT/SERVER) 或 B/ ...
- oracle sql小结(主要讲横列转换的例子)group by以及wmsys.wm_concat()的使用
---计算九月每个电厂的数量select f_dcname,count(f_dcname) as 九月份的数量 from W_EC_PLACESTATION_COLLECT twhere f_coll ...
- C 函数声明及求最大值
#include <stdio.h> int main() { int a,b,c,max(int x,int y,int z); scanf("%d,%d,%d",& ...
- [django]django corepython核心编程
model meta排序 class BlogPost(models.Model): title = models.CharField(max_length=150) body = models.Te ...