詹茂森 秦勇
摘要:在基于社会计算的个性化推荐系统开发中,搜索引擎的开发是其中一个重要的环节,搜索引擎的质量直接关系系统搜索结果的性能。该文对该内容进行了专题的研究,为该模块的设计提供了良好的理论基础,也为系统相关主题的开发奠定了一定的基础。
关键词:搜索引擎;推荐;系统
中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2014)22-5370-03
基于社会计算的个性化推荐系统的搜索引擎是系统开发的一个重要环节,该搜索结果质量直接关系到系统的性能,从而直接影响到系统的整体性能。本系统中解析的文档类型以html文档为主,采用Lucene搜索引擎,独立于运行平台的方式,实现了文档的解析和索引的创建。
1 Lucene搜索引擎简介
1) Lucene
Lucene 是一个出色并且是开源的全文搜索引擎。他并不是一个完整的全文检索应用,但是它提供了大量的 API ,可以方便能够高效快捷地地对全文创建索引,最主要的是,他可以对现有的在各种各种的系统增加全文检索的功能,官方也一直维护、更新版本,使用越来越方便,深受广大编程者和用户的青睐。
Lucene是一个高效的、 可扩展的全文检索库, 仅支持纯文本文件的索引(Index)和检索(Search), 并不处理从其他格式的文件中抽取纯文本文件, 或从网络中抓取文件。简单地说, Lucene实现两个功能,分别是索引和检索。索引所做的工作是为各种各样的文档构建Lucene 所能够识别的索引文件。
Lucene作为一个非常优秀并且开源的全文搜索引擎,不仅性能高,架构清晰,扩展性强,而且其建立索引后的文件格式也独立于应用平台,从而使索引文件能够跨平台共享,对任意可转换为文本格式的数据都能够进行索引和搜索。例如html网页、本地中的ppt,txt,pdf等等都可以对其建立索引。
首先, Lucene集成了多种文档解析器, 能够对大部分主流文本文件 如:html, pdf, MS Word, Text File等等进行解析, 抽取纯文本内容。由于Lucene只能索引纯文本, 所以必须借助于上述各种不同功能的解析器对各种不同类型的文档进行解析。
然后, 使用Lucene的分词器(Analyzer),对提取出的纯文本内容进行索引, 并生成索引项,以供做搜索之用。
最后, Analyzer把生成的信息写入索引文件之后。搜索所做的工作是使用反向索引找出与用户请求相匹配的文本内容并返还给用户。 因为,Lucene 默认情况下不对用户输入的搜索关键词进行分词处理。所以,这部分不重点讨论搜索的内容,相关内容在下面的章节中讲解。
2) 引擎结构
Lucene搜索引擎对系统的要求不高,既可以运行在Windows系统上,也可以运行在Linux系统上。搜索引擎使用的一般是集中式。把多个服务器的网络资源通通下载到本地,目的是为建立索引和文本搜索做准备,这就是集中式的处理方法。如果按照按结构分,Lucene引擎结构可由搜索器、 索引器和检索器等组成。
搜索器就是网络机器人(网络蜘蛛)。利用这种爬虫程序,在遵从机器人排除协议的前提下,从某个网页开始,提取URL网址,如此循环,不断地提取到新的 URL 网址,同时取出相应 URL 的资源。
索引器的则是利用下载的到的各种网络资源,提取各种资源的索引项,为生成文档库的索引表做准备。
检索器主要任务是通过辨识用户的查询需求,在文档库中进行快速匹配查找并且检索出相应的文档,之后就是对文档进行相关性排序,并提供一个网页链接供用户操作。所以,,一个出色的搜索引擎如果把这三个部分都做得好,用户的使用需求就一定可以得到满足。
3) 解析网页和索引入库
把网页中的元素标记( Token) 及其标记之后的内容提取出来,目的的是利于入库,这就是网页的解析。一个字段都要有一个Token与之相对应。可以理解为此字段的内容就是Token 的内容。
使用的实现方法:自定义一个 Parser 解析类,接着实现网页文件流的读入,然后把这个流解析成以字符串格式输出,为下一步处理做准备,最后循环提取 Token 及其相关内容。提取每一个Token 的目的是给不同的 Token 加上不同的权值。这样在搜索出结果的时候,就可以根据不同的权值来排序。提取 Token便可以入库:
2 Lucene分词器
1) Lucene分词简介
lucene将关键词出现频率和关键词出现位置分别作为词典文件(Term Dictionary)、频率文件(frequencies)、位置文件 (positions)保存。其中词典文件不仅保存有每个关键词,还保留了指向频率文件和位置文件的指针,通过指针可以找到该关键词的频率信息和位置信息。
Lucene特点是关键词是按字符顺序排列的,其内部没有集成使用B树结构,所以可以用二元搜索算法快速定位Lucene的关键词。
Lucene中也使用了field(域)的概念,用于表达信息所在位置。如标题、内容、url等等。需要指出的是这些域(field)是可以自定义设置的。在索引文件中,每一个field(域)的信息也记录在词典文件中,每个关键词都有一个field信息,因为每个关键词一定属于一个或多个field。 关键词没有在field(域)中出现,就意味着用户想要找的内容没有出现在数据库中。
为了减小索引文件的大小,Lucene对索引使用压缩技术。首先,对词典文件中的关键词进行了压缩,关键词压缩为<前缀长度,后缀>,例如:当前词为“广东省东莞”,上一个词为“广东省”,那么“广东省东莞”压缩为<3,东莞>。
其次大量用到的是对数字的压缩,数字只保存与上一个值的差值,目的是减小数字的长度,进而减少保存该数字需要的字节数。例如当前文章号是1279(不压缩要用3个字节保存),上一文章号是1273,压缩后保存6(只用一个字节)。使用压缩技术的好处就是提高搜索的速度和效率。需要指出的是,Lucene3.5版本后,不需要手动处理索引文件,当索引的文件大到一定的程度之后,Lucene会自动的压缩索引文件。
2) Lucene分词原理
a. 建立倒排索引。同时记录关键词在文章中出现频率和出现的位置。如何用普通的顺序匹配算法,不建索引,而是对所有文章的内容进行字符串匹配,这个过程将会相当缓慢,当文章数目很大时,时间往往是长到无法忍受的。
b. 获得文章/记录中的关键词,并对关键词进行处理。如:lives,living→live
3 IKAnalyzer分词器
1) IKAnalyzer分词简介
对信息进行索引前,需要要对关键词进行分词。英文使用空格和标点来分隔单词 而中文使用表意文字,不能通过空格和标点来进行分词。Lucene 自带的分词器,有StandardAnalyzer, StopAnalyzer ,SimpleAnalyzer,WhiteSpaceAnalyzer。这些分词器要么是单字分词 要么采用停用词分词,要么采用简单的分词,要么是按空格分词。
但是,它们并不能有效地解决中文分词的问题。目前中文分词算法工具包大致包括paoding、imdict、mmseg4j、IK。其中最常用的是IKAnalyzer,下面我大致介绍一下这个中文分词器,结构图1所示。
2) IKAnalyzer特点
IKAnalyzer支持多子处理器语言分析模式:中文、数字、字母,并兼容日文、韩文。它采用“正向迭代最细粒度切分算法”的算法,支持细粒度和最大词长两种分词方式,速度最大支持80W字/秒,即1600KB/秒。此外,它扩展lucene的扩展实现,采用歧义分析算法优化查询关键词的搜索排列组合,提高lucene检索命中率。同时,它具有较小的内存占用,优化词库占有空间,用户可自定义扩展词库。
IKAnalyzer由org.wltea.analyzer.IKSegmentation和org.wltea.analyzer.lucene.IKAnalyzer两大主要类组成,其中,org.wltea.analyzer.IKSegmentation是IK分词器的核心类,真正分词的实现类。而org.wltea.analyzer.lucene.IKAnalyzer则是IK分词主类,基于Lucene的Analyzer接口实现。
4 基于Lucene的IKAnalyzer分词器
1) paoding、mmseg4j和IKAnalyzer
目前流行的几大开源分词器主要有:paoding、mmseg4j、IKAnalyzer,它们三个都是基于JAVA语言开发的,各有优劣,具体如下:
mmseg4j:有两种分词方法,Simple和Complex,目前 complex 1200kb/s左右,simple 1900kb/s左右,但内存开销了50M左右。采用MMSeg算法,代码复杂度是2500行左右代码。有英文文档,原理比较简单。有自带搜狗的词库,支持自定义词库,不支持自动检测。 自带词库16W个。Lucene和solr的支持:支持Lucene2.4、solr1.3。
Paoding:采用基于“不限制个数”的词典文件对文章进行有效切分算法,使能够将对词汇分类定义,代码复杂度是7000行左右代码。1秒可准确分词100万汉字。支持不限制个数的用户自定义词库,自动检测词库的更新。自带词库22W个。
IKAnalyzer:每秒80W字。采用正向迭代最细粒度切分算法,代码复杂度是4500行左右代码,有一个中文使用手册,支持自定义词库,不支持自动检测。 自带词库27W个。
根据上面介绍,结合本系统特点,本系统采用基于Lucene的IKAnalyzer分词器。
2) 自定义同义词分词器
Lucene分词机制:索引过程和查询过程都用到了一个关键工具分词器analyzer。它将要被索引的内容以流的形式读入,经过词语切分、过滤干扰词等一系列处理,最终输出一个语汇单元流、每个语汇单元携带了一个文本值和它的一些元数据,原文本从起点到终点的偏移量、语汇单元类型和position incremen。
同义词索引原理:索引器将语汇单元写入文件时会丢弃每个语汇单元的起点偏移量和终点偏移量。位置增量是语汇单元携带到索引文件的唯一附加元数据。这个值的意义是当前单词与前一个单词的位置偏移量。当这个值为 0 是表示当前单词与前一个单词被索引到同一个位置上。但是 Lucene 对中文语言处理能力十分有限,无法中文语义分词只能将一句话机械性的分成单字或双字 。例如: 用单字分词会将“我来自广东” 切分成 :“我” “来” “来” “自” “广” “东”。显然,这种情形为每个字添加同义词索引是没有意义的 因此 需要一个功能更强大的中文分词器来支持。
本系统采用堆栈的形式来保存同义词的词组或单词。如(“中国”,“大陆”),(“我”,“咱”)等等都可以是同义词。自定义同义词分词器使用四个类来实现。
MyDefinedSameAnalyzer类主要是加载的搜狗中文分词器。使用栈来定义过滤器是MyDefinedSameTokenFilter类。DefinedSamewordEngine类是一个接口,使用接口有利于程序的扩展。DefinedSimpleSameword类是定义同义词字典,并判断如果有同义词就返回true
3) 自定义停用词过滤分析
在关键词处理过程中,有可能会经常出现没有意义的词。如,“是”,“来”等等。除此之外,停用词分析器StopAnalyzer也已经把没有意义的英文单词收录到停用词表中。默认情况下,这个表被用来滤词用户输入关键词中的词汇,还可以过滤掉一些特定字符,如&,*等,也会把英文的大写字母自动转换成小写字母。
还有就是,当搜索系统需要屏蔽掉一些用户输入的中文敏感词的时候,就得把敏感词自动的过滤掉。这个时候就得使用lucene强大的停用词分析器。由于Luene自带有停用词分析器StopAnalyzer,这使得要过滤掉停用词就变得非常简单。而且使用Lucene3.5的版本,也支持中文分词。
自定义一个停用词表就可以过滤掉自己设定的中文或者英文的敏感词。默认情况下,Lucene会把系统自带的英文停用词加载在停用词分析器中。TokenStream读流属性中的数据即读出数据。另外,停用词分析器StopAnalyzer自动把数字给过滤掉了,所以要实现数字的搜索需要经过特别的处理。具体的处理过程可以参考GxjtController类的searchcont( )函数的代码部分。
为了实现该功能,搜索的关键词要先经过过滤器处理,再经过同义词的处理。
参考文献:
[1] 冯斌.基于 Lucene 小型搜索引擎的研究与实现[D].武汉:武汉理工大学,2008.
[2] 杨馥显,刘嘉勇.基于JSP的数据库开发技术研究[J].通信技术,2011,44(3):51-53.
[3] 梁弼,王光琼,邓小青.基于 Lucene 的全文检索系统模型的研究及应用[J].微型机与应用,2011,30(1).
[4] 费洪晓,康松林,朱小娟,等.基于词频统计的中文分词的研究[J].计算机工程与应用,2005,41(7):67-68,100.