站内搜索引擎

站内搜索引擎

在Boost官网查文档时发现Boost官网没有提供检索,于是就想着做一个可以检索Boost帮助文档的一个小型站内搜索引擎,先做了一个很简单的版本以后进行扩充

目标:实现搜索Boost帮助文档

项目依赖的第三方库 Boost, cppjieba, jsoncpp
项目源码:https://github.com/Waorange/doc-searcher

使用中文分词是为了以后可以扩充用于中文文档搜索

项目具体内容

首先可以简单的分析下需求,即实现对Boost帮助文档的搜索,我们需要实现搜索因此需要建立索引,这里我们采用正排索引和倒排索引(后面讲),而需要建立倒排索引我们就需要实现分词,同时因为Boost帮助文档为一个一个HTML文件,因此需要将HTML文件进行处理,需要找到该HTML的标题,并且去除标签,然后进行进行分词。

通过分析我们可以分成三个模块

第一个模块是对HTML文档进行处理,解析出文档标题,文档内容,和对应的Boost官网的URL

首先通过提供的HTML文件路径,对其进行遍历,获取所有文件路径,然后根据文件路进行读取文件内容,将读取的文件内容构造成一个string对象,然后进行解析,首先对通过HTML 文件格式可以很容易的通过title标签可以找到标题,另外定义了一个结构体DocInfo结构体存储文件内容,其含有标题,内容,URL,将解析的标题存入该结构体,然后解析内容,解析内容主要是去除了标签和HTML标题,通过判断<确定是否在标签中判断>确定是否标签内容结束,同样放到上面的结构体中,最后是确定URL因为所有的帮助文档均在doc目录下,有共同的前缀,因此只需要用该前缀和给定的路径进行合并得到最终URL,获取到文档全部内容后将该文档构建成一行添加到输出文件,最终构建一个行文本文件输出,在一行中三者之间通过不可见字符进行分隔,

在这个模块中文件遍历采用了Boost库中的文件系统来完成,

索引模块,构建文档的正排索引和倒排索引

正排索引:是给定文件标号,然后通过文件编号获取文件内容,
倒排索引:是给定一个词,然后通过该词可以获取和改词相关的文件编号

在这个模块构建了一个索引类,其含有倒排索引和正派索引同时还有一个分词的对象,用于分词,构建了两个接口,通过文件编号查正排索引,和通过关键词查倒排索引获取倒排拉链(存储文件编号和文件权重)和构建索引的方法

在构建索引时首先载入数据处理模块处理后的内容,读入是一行一行字符串,然后对这些字符串进行处理,构建成索引
构建正排索引的过程比较简单,首先将该字符串进行切分,然后将切分的字符串构造成DocInfo的对象,通过Boost库的split函数进行了切分,将该结构填充到正排索引中,正排索引我采用了一个vector进行处理,用vector下标作为文件编号,vector中存储一个文档的对象,
然后是构建倒排索引,首先对标题和文档内容分别进行分词,分词使用了结巴分词,然后对分词的结果进行了整理,获取不是空白字符和标点符号的词在标题和文档中分别出现的频率,分开是权重的计算,计算每个词在文章中的权重是为只是简单的采用了词频来计算,然后构造成一个Weight对象,含有文档的编号,然后是这个词,还有该词在文档中的权重,然后在倒排索引中查找是否存在该词如果不存在则添加一个该词,存在则在该词的倒排拉链(list对象)中添加该对象。

搜索模块

搜索模块分为四个部分
首先对需要查询的句子进行分词,然后针对每个分词的结果查找倒排索引,讲查到的倒排拉链按一定规则进行排序,最后将合并的倒排拉链构造为一个JSON对象,并且序列化为字符串,进行输出,

在搜索模块构造一个搜索类,含有一个索引对象,提供了初始化索引的方法,和一个搜索方法,通过一句话或者词进行搜索相关的文档

在这一部分主要完成了搜索功能,首先将需要搜索的句子进行分词,然后对每个词分别进行查倒排索引,获取其倒排拉链,将倒排拉链的内容进行合并,之后按照权重的大小进行排序,通过其中的Weight对象中的文档编号,进行查正排索引获取文档的内容,然后将获取的内容构造成JSON对象, 并且通过关键词的位置简单生成文章的相关摘要,最后将构建的JSON对象构造序列化为字符串输出返回结果即可,构造JSON对象采用了jsoncpp第三方库提供的接口。

这个项目中分对地方都简单的进行了处理,如处理HTML文件,计算权重,对倒排拉链合并后排序等都用了很简单的方法进行了排序,以后会对其修正,而且整个文件是直接下载的,后续学习了其他希望用爬虫对资源进行更新。

在做的过程中也遇到了一些问题,对分词库不熟悉,因为用了中文分词,想着以后搜其他中文文档,然后分词会含有空格,符号还有一些特殊字符,导致在索引中会有很对这些内容,然后在查找时会发现结果不正确,所以后来在建立索引时如果是特殊字符直接对其忽略了(用set做了一个特殊字符对照表),还有就是在合并文档时,刚开始的时候采用的是一种简单的直接把vector拼接起来,这样造成了两个不同的词在同一篇文档中时会有重复项,之后我将拉链改成了list在合并时相当于对有序链表的合并,不用vector是在合并时需要在中间插入。

你可能感兴趣的:(C++)