谈谈个人网站的建立(二)—— lucene的使用

news/2024/5/14 14:08:48/文章来源:https://blog.csdn.net/weixin_30530939/article/details/98171899

首先,帮忙点击一下我的网站http://www.wenzhihuai.com/ 。谢谢啊,如果可以,GitHub上麻烦给个star,以后面试能讲讲这个项目,GitHub地址https://github.com/Zephery/newblog 。

Lucene的整体架构

image

搜索引擎的几个重要概念:

  1. 倒排索引:将文档中的词作为关键字,建立词与文档的映射关系,通过对倒排索引的检索,可以根据词快速获取包含这个词的文档列表。倒排索引一般需要对句子做去除停用词。
    fewfwaefawe20170903183124.png

  2. 停用词:在一段句子中,去掉之后对句子的表达意向没有印象的词语,如“非常”、“如果”,中文中主要包括冠词,副词等。
  3. 排序:搜索引擎在对一个关键词进行搜索时,可能会命中许多文档,这个时候,搜索引擎就需要快速的查找的用户所需要的文档,因此,相关度大的结果需要进行排序,这个设计到搜索引擎的相关度算法。

Lucene中的几个概念

  1. 文档(Document):文档是一系列域的组合,文档的域则代表一系列域文档相关的内容。
  2. 域(Field):每个文档可以包含一个或者多个不同名称的域。
  3. 词(Term):Term是搜索的基本单元,与Field相对应,包含了搜索的域的名称和关键词。
  4. 查询(Query):一系列Term的条件组合,成为TermQuery,但也有可能是短语查询等。
  5. 分词器(Analyzer):主要是用来做分词以及去除停用词的处理。

索引的建立

fweafwe170903175148.png

索引的搜索

fwefawfagergwerg20170903184512.png

lucene在本网站的使用:

  1. 搜索 2. 自动分词

一、搜索

注意:本文使用最新的lucene,版本6.6.0。lucene的版本更新很快,每跨越一次大版本,使用方式就不一样。首先需要导入lucene所使用的包。使用maven:

<dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-core</artifactId><!--lucene核心--><version>${lucene.version}</version>
</dependency>
<dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-analyzers-common</artifactId><!--分词器--><version>${lucene.version}</version>
</dependency>
<dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-analyzers-smartcn</artifactId><!--中文分词器--><version>${lucene.version}</version>
</dependency>
<dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-queryparser</artifactId><!--格式化--><version>${lucene.version}</version>
</dependency>
<dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-highlighter</artifactId><!--lucene高亮--><version>${lucene.version}</version>
</dependency>
  1. 构建索引
Directory dir = FSDirectory.open(Paths.get("blog_index"));//索引存储的位置
SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer();//简单的分词器
IndexWriterConfig config = new IndexWriterConfig(analyzer);
IndexWriter writer = new IndexWriter(dir, config);
Document doc = new Document();
doc.add(new TextField("title", blog.getTitle(), Field.Store.YES)); //对标题做索引
doc.add(new TextField("content", Jsoup.parse(blog.getContent()).text(), Field.Store.YES));//对文章内容做索引
writer.addDocument(doc);
writer.close();
  1. 更新与删除
IndexWriter writer = getWriter();
Document doc = new Document();
doc.add(new TextField("title", blog.getTitle(), Field.Store.YES));
doc.add(new TextField("content", Jsoup.parse(blog.getContent()).text(), Field.Store.YES));
writer.updateDocument(new Term("blogid", String.valueOf(blog.getBlogid())), doc);   //更新索引
writer.close();
  1. 查询
private static void search_index(String keyword) {try {Directory dir = FSDirectory.open(Paths.get("blog_index")); //获取要查询的路径,也就是索引所在的位置IndexReader reader = DirectoryReader.open(dir);IndexSearcher searcher = new IndexSearcher(reader);SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer();QueryParser parser = new QueryParser("content", analyzer); //查询解析器Query query = parser.parse(keyword); //通过解析要查询的String,获取查询对象TopDocs docs = searcher.search(query, 10);//开始查询,查询前10条数据,将记录保存在docs中,for (ScoreDoc scoreDoc : docs.scoreDocs) { //取出每条查询结果Document doc = searcher.doc(scoreDoc.doc); //scoreDoc.doc相当于docID,根据这个docID来获取文档System.out.println(doc.get("title")); //fullPath是刚刚建立索引的时候我们定义的一个字段}reader.close();} catch (IOException | ParseException e) {logger.error(e.toString());}
}
  1. 高亮
Fragmenter fragmenter = new SimpleSpanFragmenter(scorer);
SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<b><font color='red'>", "</font></b>");
Highlighter highlighter = new Highlighter(simpleHTMLFormatter, scorer);
highlighter.setTextFragmenter(fragmenter);
for (ScoreDoc scoreDoc : docs.scoreDocs) { //取出每条查询结果Document doc = searcher.doc(scoreDoc.doc); //scoreDoc.doc相当于docID,根据这个docID来获取文档String title = doc.get("title");TokenStream tokenStream = analyzer.tokenStream("title", new StringReader(title));String hTitle = highlighter.getBestFragment(tokenStream, title);System.out.println(hTitle);
}

结果

<b><font color='red'>Java</font></b>堆.栈和常量池 笔记
  1. 分页
    目前lucene分页的方式主要有两种:
    (1). 每次都全部查询,然后通过截取获得所需要的记录。由于采用了分词与倒排索引,所有速度是足够快的,但是在数据量过大的时候,占用内存过大,容易造成内存溢出
    (2). 使用searchAfter把数据保存在缓存里面,然后再去取。这种方式对大量的数据友好,但是当数据量比较小的时候,速度会相对慢。
    lucene中使用searchafter来筛选顺序
ScoreDoc lastBottom = null;//相当于pageSize
BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder();
QueryParser parser1 = new QueryParser("title", analyzer);//对文章标题进行搜索
Query query1 = parser1.parse(q);
booleanQuery.add(query1, BooleanClause.Occur.SHOULD);
TopDocs hits = search.searchAfter(lastBottom, booleanQuery.build(), pagehits);  //lastBottom(pageSize),pagehits(pagenum)
  1. 使用效果
    全部代码放在这里,代码写的不太好,光从代码规范上就不咋地。在网页上的使用效果如下:

bervererfwaefewf20170903200915.png

二、lucene自动补全

百度、谷歌等在输入文字的时候会弹出补全框,如下图:
QQ%E6%88%AA%E5%9B%BE20170728102929.png

在搭建lucene自动补全的时候,也有考虑过使用SQL语句中使用like来进行,主要还是like对数据库压力会大,而且相关度没有lucene的高。主要使用了官方suggest库以及autocompelte.js这个插件。
suggest的原理看这,以及索引结构看这。

使用:

  1. 导入maven包
<dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-suggest</artifactId><version>6.6.0</version>
</dependency>
  1. 如果想将结果反序列化,声明实体类的时候要加上:
public class Blog implements Serializable {
  1. 实现InputIterator接口
    InputIterator的几个方法:
    long weight():返回的权重值,大小会影响排序,默认是1L
    BytesRef payload():对某个对象进行序列化
    boolean hasPayloads():是否有设置payload信息
    Set contexts():存入context,context里可以是任意的自定义数据,一般用于数据过滤
    boolean hasContexts():判断是否有下一个,默认为false
public class BlogIterator implements InputIterator {/*** logger*/private static final Logger logger = LoggerFactory.getLogger(BlogIterator.class);private Iterator<Blog> blogIterator;private Blog currentBlog;public BlogIterator(Iterator<Blog> blogIterator) {this.blogIterator = blogIterator;}@Overridepublic boolean hasContexts() {return true;}@Overridepublic boolean hasPayloads() {return true;}public Comparator<BytesRef> getComparator() {return null;}@Overridepublic BytesRef next() {if (blogIterator.hasNext()) {currentBlog = blogIterator.next();try {//返回当前Project的name值,把blog类的name属性值作为keyreturn new BytesRef(Jsoup.parse(currentBlog.getTitle()).text().getBytes("utf8"));} catch (Exception e) {e.printStackTrace();return null;}} else {return null;}}/*** 将Blog对象序列化存入payload* 可以只将所需要的字段存入payload,这里对整个实体类进行序列化,方便以后需求,不建议采用这种方法*/@Overridepublic BytesRef payload() {try {ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream out = new ObjectOutputStream(bos);out.writeObject(currentBlog);out.close();BytesRef bytesRef = new BytesRef(bos.toByteArray());return bytesRef;} catch (IOException e) {logger.error("", e);return null;}}/*** 文章标题*/@Overridepublic Set<BytesRef> contexts() {try {Set<BytesRef> regions = new HashSet<BytesRef>();regions.add(new BytesRef(currentBlog.getTitle().getBytes("UTF8")));return regions;} catch (UnsupportedEncodingException e) {throw new RuntimeException("Couldn't convert to UTF-8");}}/*** 返回权重值,这个值会影响排序* 这里以产品的销售量作为权重值,weight值即最终返回的热词列表里每个热词的权重值*/@Overridepublic long weight() {return currentBlog.getHits();   //change to hits}
}
  1. ajax 建立索引
/*** ajax建立索引*/
@Override
public void ajaxbuild() {try {Directory dir = FSDirectory.open(Paths.get("autocomplete"));SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer();AnalyzingInfixSuggester suggester = new AnalyzingInfixSuggester(dir, analyzer);//创建Blog测试数据List<Blog> blogs = blogMapper.getAllBlog();suggester.build(new BlogIterator(blogs.iterator()));} catch (IOException e) {System.err.println("Error!");}
}
  1. 查找
    因为有些文章的标题是一样的,先对list排序,将标题短的放前面,长的放后面,然后使用LinkHashSet来存储。
@Override
public Set<String> ajaxsearch(String keyword) {try {Directory dir = FSDirectory.open(Paths.get("autocomplete"));SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer();AnalyzingInfixSuggester suggester = new AnalyzingInfixSuggester(dir, analyzer);List<String> list = lookup(suggester, keyword);list.sort(new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {if (o1.length() > o2.length()) {return 1;} else {return -1;}}});Set<String> set = new LinkedHashSet<>();for (String string : list) {set.add(string);}ssubSet(set, 7);return set;} catch (IOException e) {System.err.println("Error!");return null;}
}
  1. controller层
@RequestMapping("ajaxsearch")
public void ajaxsearch(HttpServletRequest request, HttpServletResponse response) throws IOException {String keyword = request.getParameter("keyword");if (StringUtils.isEmpty(keyword)) {return;}Set<String> set = blogService.ajaxsearch(keyword);Gson gson = new Gson();response.getWriter().write(gson.toJson(set));//返回的数据使用json
}
  1. ajax来提交请求
    autocomplete.js源代码与介绍:https://github.com/xdan/autocomplete
<link rel="stylesheet" href="js/autocomplete/jquery.autocomplete.css">
<script src="js/autocomplete/jquery.autocomplete.js" type="text/javascript"></script>
<script type="text/javascript">/******************** remote start **********************/$('#remote_input').autocomplete({source: [{url: "ajaxsearch.html?keyword=%QUERY%",type: 'remote'}]});/********************* remote end ********************/
</script>
  1. 效果:
    QQ%E6%88%AA%E5%9B%BE20170728105628.png

欢迎访问我的个人网站

参考:
https://www.ibm.com/developerworks/cn/java/j-lo-lucene1/

http://iamyida.iteye.com/blog/2205114

转载于:https://www.cnblogs.com/w1570631036/p/7470519.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_775288.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网址导航类的网站为什么会没落

今天要谈论的话题是关于网址导航的&#xff0c;在我看来&#xff0c;其实这是一种已经没落的网站行业。目前还能生存下来的网址导航有hao123网址导航、2345网址导航&#xff0c;除此之外&#xff0c;还有很多互联网公司推出了适配自己产品的网址导航&#xff0c;例如搜狗网址导…

网站优化怎么做?怎么才会有排名,流量收录

什么是推送&#xff1f; 对于SEO人员应该都不陌生吧&#xff0c;推送就是把网站的链接主动提交给搜索引擎&#xff0c; 确保新的链接可以尽快被收录&#xff0c;同时保护原创&#xff08;防止别人抄袭&#xff0c;以及转载后导致自己的网站没收录&#xff09; 为什么我们要去…

免费采集工具之打造网站高质量内容

搜索引擎为什么一直不收录我的网站&#xff1f;为什么我的网站一直没有排名是不是我网站被K了&#xff1f;怎么让搜索引擎快速收录我的网站呢&#xff1f;这是最近很多站长问我的问题&#xff0c;今天笔者就针对这些问题发表一些我的见解。 首先我们要知道SEO做到最后做的是什…

如何使用免费采集器实现高质量网站内容布局

Hello的大家好&#xff01;昨天我分享了搜狗泛收录怎么做。今天我要分享的是关于网站免费采集器的使用以及如何利用好免费的文章采集器打造网站高质量内容&#xff0c;让你的网站快速收录大量收录&#xff0c;快速上网站SEO排名的方法攻略。 笔者作为一个SEO老油子&#xff0c…

1分钟学会网站采集方法详解

最近很多站长朋友跟我诉苦说网站采集应该怎么做&#xff0c;手动更新难以坚持。网站定时发布文章内容是一件必须要解决的问题&#xff0c;因此今天我将分享一些网站采集的技巧。非常适合想做大量收录以及高权重网站的站长。 首先很多朋友会说&#xff0c;纯采集可能被搜索引擎算…

搜狗批量提交软件-批量提交网站链接

最近很多做搜狗的站长朋友问我搜狗推送工具有用吗&#xff1f;可以批量推送吗&#xff1f;关于搜狗的提交方式有哪些&#xff1f;搜狗推送应该怎么做&#xff1f;搜狗收录怎么大量泛收录&#xff1f;有没有好的搜狗口子可以让搜狗快速收录我的网站呢&#xff1f; 首先搜狗推送肯…

360推送工具-批量推送360网站工具

最近很多站长问我&#xff0c;我的网站360一直不收录是什么原因&#xff1f;360收录到底应该怎么做&#xff1f;别人的360收录几万&#xff0c;几十万是怎么做的&#xff1f;还有实用的做360收录的工具或者说方法技巧。今天笔者统一发表一下我个人的见解。 首先我们网站发布后的…

百度SEO教程-利于百度推送工具实现百度快速收录

最近很多做百度的站长问我&#xff0c;百度收录怎么做&#xff1f;有没有什么方法让百度大量收录我的网站&#xff1f;百度推送到底有没有用&#xff1f;如何利用百度推送工具&#xff0c;实现百度的快速收录&#xff0c;这期我说下我的个人见解。 一、百度链接提交的作用 链接…

知名网站的 404 页面长啥样?你的404长啥样?

2019独角兽企业重金招聘Python工程师标准>>> 每天浏览各大网站&#xff0c;难免会碰到404页面啊。你注意过404页面么&#xff1f;猿妹搜罗来了下面这些知名网站的404页面&#xff0c;以供大家欣赏&#xff0c;看看哪个网站更有创意&#xff1a; 我有几张阿里云幸运券…

数据收集,网站数据采集伪原创发布(图文)

数据收集&#xff0c;最近很多站长问我有没有好用的文章数据收集系统&#xff0c;因为不同CMS的文章采集伪原创发布是一件让人头痛的事。我们都知道网站的收录离不了日常的文章更新。网站有了收录之后网站的一个SEO排名才能够起来&#xff0c;数据收集对网站的收录起着重要的作…

网站管理之如何批量网站管理(python爬虫全网文章采集发布)

网站管理&#xff0c;最近很多站长问我不同CMS见得网站我们应该怎么管理&#xff0c;因为不同CMS的web发布接口是不一样的。我们如何实现不同网站的批量采集伪原创发布的网站管理&#xff0c;更重要是怎么做相应的SEO优化设置如网站文章发布之后进行一键自动批量推送给各大搜索…

网站托管,免费网站托管,全自动网站托管方法详解

网站托管&#xff0c;为什么我们做网站托管&#xff0c;做网站托管有哪些作用&#xff1f;第一我们网站托管之后我们不需要亲自做网站的SEO优化包括站内优化和站外优化。网站托管可以通过全网文章关键词泛采集、文章聚合、Tag标签聚合等做为文章内容来源&#xff0c;然后通过批…

网站维护-批量网站维护-不同CMS批量采集发布管理

网站维护&#xff0c;最近很多站长问我大量网站维护怎么样才能做到批量管理和维护。因为每个站对应的建站系统是不一样的&#xff0c;每个网站的文章自动更新是一件让人头疼的事情。市面上很少同时支持织梦、帝国、zblog、WordPress、pbootCMS等各种cms的批量采集伪原创发布已经…

网站漏洞检测工具对discuzX3.2 X3.4网站漏洞修复

2019独角兽企业重金招聘Python工程师标准>>> 2018年12月9日&#xff0c;国内某安全组织&#xff0c;对discuz X3.2 X3.4版本的漏洞进行了公开&#xff0c;这次漏洞影响范围较大&#xff0c;具体漏洞是discuz 的用户前段SQL注入与请求伪造漏洞&#xff0c;也俗称SSRF…

网页采集器,全自动网站采集发布(图文)

网页采集器&#xff0c;最近很多站长朋友问我指定网站怎么做&#xff0c;市场上的网页采集工具都是基本都是需要写采集规则&#xff0c;这需求站长朋友们会正则表达式&#xff0c;还有html代码基础。这对小白站长来是很难的一件事情。网页采集器可视化批量采集指定网站以及自动…

帝国CMS模板,免费帝国CMS模板,帝国CMS建站教程

帝国CMS模板&#xff0c;很多帝国CMS站长问我没有好用的帝国CMS模板。人们都知道那种经常被使用帝国CMS模板&#xff0c;是不利于网站SEO优化。好的帝国CMS模板内置了很多SEO优化设置&#xff0c;结合批量采集、伪原创、发布并一键自动百度、神马、360、搜狗推送。 如何选择一个…

wp网站,wordpress网站搭建,wp网站建设教程

wp网站&#xff0c;wordpress是很多站长建站选择的CMS内容管理系统。Wp网站建设的网站&#xff0c;我们应该怎么去优化呢&#xff1f;首先wp网站SEO优化我们需要做好SEO站内优化和站外优化。具体可以走wordpress采集、wordpress伪原创、wordpress自动定时发布路线。 wp网站建站…

PbootCMS教程-PbootCMS建站教程-Pboot模板开发教程

PbootCMS教程&#xff0c;织梦开始收费之后&#xff0c;很多织梦老站长问我有没有可以代替织梦的CMS程序&#xff0c;我向他推荐开源的网站内容管理系统PbootCMS。那到底PbootCMS怎么样&#xff0c;使用PbootCMS建站网站好优化嘛&#xff1f;PbootCMS建设的网站我们可以PbootCM…

网站数据采集-网站采集工具-SEO文章聚合采集(免费采集教程)

网站数据采集。最近很多站长问我&#xff0c;要采集几百几千个域名的网站数据&#xff0c;更新网站文章&#xff0c;应该怎么做&#xff1f;尤其是pbootcms、织梦、帝国、易游、wordpress、迅锐cms、云优CMS等各种CMS搭建的网站。那么多种我们要思考的网站的文章更新应该怎么做…

数据采集软件-SEO网站采集工具-文章采集工具免费

免费数据采集软件&#xff0c;最近很多站长问我大量网站一个人怎么更新。首先手动更新是不可能的事情&#xff0c;我们需要免费数据采集软件以大量长尾关键词对全网文章进行关键词泛采集伪原创发布&#xff0c;最后结合相应的SEO优化设置对网站进行优化。然后通过推送一键自动将…