浅谈搜索引擎普遍原理
--lvpei.blogcn.com,公司要做的知识分享课件摘选。
1、搜索引擎是什么?
搜索引擎就是为用户提供检索服务的系统。
2、搜索引擎如何为用户提供检索服务?
1>从互联网上抓取网页
利用能够从互联网上自动收集网页的Spider系统程序,自动访问互联网,并沿着任何网页中的所有URL爬到其它网页,(深度遍历和广度遍历)重复这过程,并把爬过的所有网页收集回来。
2>建立索引数据库
由分析索引系统程序对收集回来的网页进行分析,提取相关网页信息(包括网页所在URL、编码类型、页面内容包含的关键词、关键词位置、生成时间、大小、与其它网页的链接关系(超链分析就是通过分析链接网站的多少来评价被链接的网站质量)等),根据一定的相关度算法进行大量复杂计算,得到每一个网页针对页面内容中及超链中每一个关键词的相关度(或重要性),然后用这些相关信息建立网页索引数据库。
3>在索引数据库中搜索排序
当用户输入关键词搜索后,由搜索系统程序从网页索引数据库中找到符合该关键词的所有相关网页。因为所有相关网页针对该关键词的相关度早已算好,所以只需按照现成的相关度数值排序,相关度越高,排名越靠前。
最后,由页面生成系统将搜索结果的链接地址和页面内容摘要等内容组织起来返回给用户。
3、搜索引擎与数据库的不同?
通常比较厚的书籍后面常常附关键词索引表(比如:北京:12, 34页, 上海:3,77页……),不是前面的目录,它能够帮助读者比较快地找到相关内容的页码。而数据库索引能够大大提高查询的速度原理也是一样,想像一下通过书后面的索引查找的 速度要比一页一页地翻内容高多少倍……而索引之所以效率高,另外一个原因是它是排好序的。
在使用like查询时,数据库搜索过程又变成类似于一页页翻书的遍历过程了,所以对于含有模糊查询的数据库服务来说,LIKE对性能的危害是极大的。如果是需要对多个关键词进行模糊匹配:like"%keywordl%" and like"%keyword2%'.其效率也就可想而知了。
所以建立一个高效搜索系统的关键,是建立一个类似于书籍索引一样的反向索引机制,将数据源(比如多篇文章)顺序存储的同时,建立另外一个排好序的关键词列表,用于存储关键词=》文章映射关 系,利用这样的映射关系索引:[关键词”=>出现关键词的文章编号,出现次数、位置、 出现频率,检索过程就是把模糊查询变成多个可以利用索引的精确查询的逻辑组合的过程。从而大大提高了多关键词查询的效率。
所以,全文检索问题归结到最后是一个排序问题。
由此可以看出模糊查询相对数据库的精确查询是一个非常不确定的问题,所以大部分数据库对全文检索支持有限的原因。
Lucene面向全文检索的优化在于首次索引检索后,并不把所有的记录(Document)具体内容读取出来,而是只将所有结果中匹配度最高的头
100条结果(TopDocs)的ID放到结果集缓存中并返回,在收集结果的过程中将匹配度低的结果自动过滤掉。
4、如何建立反向索引机制?
先复习一个数据结构,这个数据结构并不在Lucene中使用,但是又不得不说。
B-tree结构
B-tree(多路搜索树,不是二叉)是一种常见的数据结构。
使用B-tree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度。
按照翻译,B 通常认为是Balance的简称.这个数据结构一般用于数据库的索引,B-tree索引是数据库中存取和查找文件(称为记录或键值)的一种方法,综合效率较高。
B-tree的特性:
1、关键字集合分布在整颗树中; 2、任何一个关键字出现且只出现在一个结点中;
3、搜索有可能在非叶子结点结束; 4、其搜索性能等价于在关键字全集内做一次二分查找;
再介绍Lucene
Lucene是一个高性能的java全文检索工具包.。
Lucene最核心的特征是通过特殊的倒排文件索索引结构实现了传统数据库不擅长的全文索引机制,并提供了扩展接口,以方便针对不同应用的定制。
该结构及相应的生成算法如下:
0)设有两篇文章1和2
文章1的内容为:Tom lives in Guangzhou,I live in Guangzhou too.
文章2的内容为:He once lived in Shanghai.
1)由于lucene是基于关键词索引和查询的,首先我们要取得这两篇文章的关键词,通常我们需要如下处理措施
a.我们现在有的是文章内容,即一个字符串,我们先要找出字符串中的所有单词,即分词。英文单词由于用空格分隔,比较好处理。中文单词间是连在一起的 需要特殊的分词处理。
b.文章中的”in”, “once” “too”等词没有什么实际意义,中文中的“的”“是”等字通常也无具体含义,这些不代表概念的词可以过滤掉
c.用户通常希望查“He”时能把含“he”,“HE”的文章也找出来,所以所有单词需要统一大小写。
d.用户通常希望查“live”时能把含“lives”,“lived”的文章也找出来,所以需要把“lives”,“lived”还原成 “live”
e.文章中的标点符号通常不表示某种概念,也可以过滤掉
在lucene中以上措施由Analyzer类完成
经过上面处理后
文章1的所有关键词为:[tom] [live] [guangzhou] [i] [live] [guangzhou]
文章2的所有关键词为:[he] [live] [shanghai]
2) 有了关键词后,我们就可以建立倒排索引了。上面的对应关系是:“文章号”对“文章中所有关键词”。倒排索引把这个关系倒过来,变成:“关键词”对“拥有该 关键词的所有文章号”。文章1,2经过倒排后变成
关键词 文章号
guangzhou 1
he 2
i 1
live 1,2
shanghai 2
tom 1
通常仅知道关键词在哪些文章中出现还不够,我们还需要知道关键词在文章中出现次数和出现的位置,通常有两种位置:a)字符位置,即记录该词是文章中第几个字符(优点是关键词亮显时定位快);b)关键词位置,即记录该词是文章中第几个关键词(优点是节约索引空间、词组(phase)查询 快),lucene 中记录的就是这种位置。
加上“出现频率”和“出现位置”信息后,我们的索引结构变为:
关键词 文章号[出现频率] 出现位置
guangzhou 1[2] 3,6
he 2[1] 1
i 1[1] 4
live 1[2],2[1] 2,5,2
shanghai 2[1] 3
tom 1[1] 1
以live 这行为例我们说明一下该结构:live在文章1中出现了2次,文章2中出现了一次,它的出现位置为“2,5,2”这表示什么呢?我们需要结合文章号和出现 频率来分析,文章1中出现了2次,那么“2,5”就表示live在文章1中出现的两个位置,文章2中出现了一次,剩下的“2”就表示live是文章2中第 2个关键字。
以上就是lucene索引结构中最核心的部分。
Lucene中没有使用商业数据库的b tree结构,也不是经过hash(hash算法不能找出范围)而得。而由.tii与.tis两个文件组成了一种二层文件结构。
这与Lucene采用segment index索引策略有关(动态索引,更新要快)。实际上采用的是最简单的折半二分。
索引的更新会导致大量的IO操作,Lucene在实现中,对此稍微有所改进:不是维护一个索引文件,而是在扩展索引的时候不断创建新的索引文件,然后定期 的把这些新的小索引文件合并到原先的大索引中(针对不同的更新策略,批次的大小可以调整),这样在不影响检索的效率的前提下,提高了索引的效率。
假设要查询单词 “live”,lucene先对词典二分查找、找到该词,通过指向频率文件的指针读出所有文章号,然后返回结果。词典通常非常小,因而,整个过程的时间是 毫秒级的。
实现时 lucene将上面三列分别作为词典文件(Term Dictionary)、频率文件(frequencies)、位置文件 (positions)保存。其中词典文件不仅保存有每个关键词,还保留了指向频率文件和位置文件的指针,通过指针可以找到该关键字的频率信息和位置信息。
Lucene中使用了field的概念,用于表达信息所在位置(如标题中,文章中,url中),在建索引中,该field信息也记录在词典文件中,每个关键词都有一个field信息(因为每个关键字一定属于一个或多个field)。
为了减小索引文件的大小,Lucene对索引还使用了压缩技术。首先,对词典文件中的关键词进行了压缩,关键词压缩为<前缀长度,后 缀>,例如:当前词为“阿拉伯语”,上一个词为“阿拉伯”,那么“阿拉伯语”压缩为<3,语>。其次大量用到的是对数字的压缩,数字只保存与上一个值的差值(这样可以减小数字的长度,进而减少保存该数字需要的字节数)。例如当前文章号是16389(不压缩要用3个字节保存),上一文章号 是16382,压缩后保存7(只用一个字节)。
5、关于中文的切分词问题
对于英文来说语句中单词之间是天然通过空格分开的,但亚洲语言的中日韩文语句中的字是一个字挨一个,所有,首先要把语句中按“词”进行索引的话,这个词如何切分出来就是一个很大的问题。
首先,肯定不能用单个字符作(si-gram)为索引单元,否则查“上海”时,不能让含有“海上”也匹配。
但一句话 :“北京天安门”,计算机如何按照中文的语言习惯进行切分呢?
“北京 天安门” 还是“北京天安门”?让计算机能够按照语言习惯进 行切分,往往需要机器有一个比较丰富的词库才能够比较准确的识别出语句中的单词。
另外一个解决的办法是采用自动切分算法:将单词按照2元语法(bigram)方式切分出来,比如:
“北京天安门” ==>”北京 京天 天安 安门”。
这样 ,在查询的时候,无论是查询”北京”还是查询”天安门”,将查询词组按同样 的规则进行切分:”北京”,”天安 安门”,多个关键词之间按与”and"的关系组合,同样能够正确地映射到相应的索引中。这种方式对于其他亚洲语言:韩文,日文都是通用的。
基于自动切分的最大优点是没有词表维护成本,实现简单,缺点是索引 效率低,但对于中小型应用来说,基于2元语法的切分还是够用的。基于2元切分后的索引一般大小和源 文件差不多,而对于英文,索引文件一般只有原文件的30%-40%不同。
目前比较大的搜索引擎的语言分析算法一般是基于以上2个机制的结合。
6、Lucene与solr
Lucene不是一个完整的全文索引应用,而是是一个用Java写的全文索引引擎工具包,它可以方便的嵌入到各种应用中实现针对应用的全文索引/检索功能。
Solr 就是应用
Solr是一个基于Lucene 库的企业级搜索服务器,包含 XML/HTTP,JSON API, 高亮查询结果,缓存,主从复制还有一个WEB管理界面。Solr运行在 Servlet容器中。
Solr和Lucene的本质区别有以下三点:搜索服务器,企业级和管理。
Lucene专注于搜索底层的建设,而Solr专注于独立的企业应用。
从数据库读取记录,对要搜索的字段分好词,存成文件索引,搜索时再分词,直接去索引查找每个词有哪些索引后文档。
7、介绍一个工具Luke
8、演示一个互联网爬取RSS,利用Lucene\Solr存储的程序
9、搜索引擎的前沿
基于链接分析的第三代搜索引擎呈现出以下几点局限性:
1、一个关键字查询词对所有用户呈现的搜索结果均相同。但是实际上,比如一个计算
机用户搜索“树”可能指数据结构,与其他用户有很大区别。
2、Pagerank基于链接反映网页质量的方法,只反映了网页制作者对于网页质量的评
价, 并没有反映网页浏览着对于网页的评价。对于一些不善于进行链接优化的网站,虽
然内容可能很优质,但是Pagerank可能并不高。同时,一些新网 站很难在短期内提高
Pagerank,而一些擅长优化技术的网站会用大量垃圾链接作弊。
3、基于关键词的搜索方法是建立在用户对于搜索有明确目的,并能清晰表述这种目的
的假设上。但是实际上,用户的搜索引擎使用水平参差不齐;并且由于存在同义词等现
象,同一个搜索请求有不同的表示方法,搜索结果也大为不同。
4、现在的图像搜索,视频搜索,音乐搜索也都是基于关键字,如图像Tag,音乐电影介
绍等,而文字对 于这些信息的表现能力是很有限的,也不直观。
5、并不是所有有价值的信息都能被搜索引擎爬取到,比如学校论坛,公司内网资料等
有价值的资料就无法被搜索引擎检索,这叫做Hidden Web现象;同时一些信息需要经过
人脑的加工,这方面问答平台更能胜任。这部分不能被爬取的信息实 际上占了人类所有
信息的大部分。
1、个性化的搜索。基于个人的网页浏览历史,搜索关键词历史,个人档案信息,使得
即使是同一个搜索关键词,也能为不同用户呈现不同的搜索结果。
个性化搜索将基本解决提到的第一点局限。
2、社交搜索大大提高网页排序质量,其影响主要在两方面:a,网页浏览者(普通用
户) 对于网页的评价(收藏行为,评分,举报等)将可以作为排序的依据b,通过用户的
社交圈推测用户兴趣,通过用户间的不同程度信任关系为其提供不同权重的网页排序推
荐。社交搜索也包括问答系统,用优质的设置提高信息的质量。
社交搜索将基本解决提到的Pagerank和关键字搜索的局限。
3、跨媒体搜索将打通文字,图像,声音,视频间的界限,使得用图像搜图像,用声音
搜声音,用图像搜 视频等都成为可能。