boost搜索引擎
文章目录
- boost搜索引擎的意义
- 技术栈与项目环境
- 搜索引擎的原理
- 暂停词
- 正排索引(Forward Index)
- 倒排索引(Inverted Index)
- 数据去标签化
- 去标签
- 常用工具类
- 添加日志
- 索引的建立
- 正排索引的建立
- 倒排索引的建立
- 搜索引擎的构成
- **初始化**
- **查询处理**
- **简介生成**
- 前端网页
- 查询输入
- 搜索以及结果展示
- 分页控制
- CSS样式
- HTTP服务
- 工作流程概述
- 部署服务器
- 项目展示
- 启动页面
- 搜索结果页面
boost搜索引擎的意义
boost库是为C++语言标准库提供扩展的一些C++程序库的总称,由Boost社区组织开发、维护。Boost库可以与C++标准库完美共同工作,并且为其提供扩展功能。boost网站提供了大量的文档,实现一个搜索引擎可以帮助我们在大量的文档中准确快速找到自己所需求的文档。
技术栈与项目环境
- 技术栈
后端:C/C++、C++11、STL、准标准库Boost、Jsoncpp、cppjieba、cpp-httplib
前端:html5、css、js、jQuery、Ajax
- 项目环境
Centos7、vim、gcc(g++)/Makefile、vscode
(项目gitee仓库)
搜索引擎的原理
搜索大量的文档以及文档中包含的内容,显然是非常耗时耗力的一种行为。如果直接去一个个去遍历访问,基本会导致服务长时间得不到响应。为此需要更见快速以及便捷的方式去规划和管理大量的数据,实现快速查找,建立索引是解决这个问题的核心。
所谓的索引,就是将文档贴上一个标签,根据标签去快速查找。管理标签相对于管理文档的压力要小很多,这是建立索引的本质原因。
暂停词
暂停词(Stop Words)是指在自然语言处理中(NLP)和信息检索中,为了提高处理效率和效果而被忽略或移除的常见词语。这些词通常是高频率出现但对文档内容或语义贡献不大的词汇。
特点
- 高频率出现:暂停词在文档中出现频率非常高,例如英语中的 “the”, “is”, “in”, “and”,以及中文中的 “的”, “了”, “在” 等。
- 低语义贡献:暂停词对文档内容的实际语义贡献较小,通常不能用来区分不同的文档。
作用
- 减少数据处理量:通过移除暂停词,可以显著减少要处理的词汇数量,从而提高处理速度和效率。
- 提升检索效果:暂停词的移除可以减少噪声,提升信息检索系统的查询结果的相关性和精确度。
正排索引(Forward Index)
正排索引,也称为正向索引,是将文档与其包含的词汇进行关联的索引结构。每个文档都包含一个词汇列表及其在文档中的位置信息。
原理
文档级别:每个文档都有一个唯一的标识符(如DocID)。
词汇表:每个文档包含一个词汇表,记录了该文档中的所有词汇及其位置。
例如,有两个文档如下:
文档ID 文档内容 1 苹果的电脑 2 苹果的手机 去掉暂停词之后,正排索引可以表示为:
文档ID 文档内容 1 苹果 电脑 2 苹果 手机 优点
- 易于理解和构建。
- 适合小规模数据的全文检索。
缺点
- 查询效率低。要查找某个词语出现在哪些文档中,需要遍历所有文档的词汇表。
倒排索引(Inverted Index)
倒排索引也称为反向索引,是将词汇与其所在的文档进行关联的索引结构。每个词汇都关联一个包含该词汇的文档列表及其位置。
原理
词汇级别:每个词汇都有一个唯一的标识符。
文档列表:每个词汇包含一个文档列表,记录了该词汇出现的所有文档及其位置。
例如,有两个文档如下:
文档ID 文档内容 1 苹果的电脑 2 苹果的手机 去掉暂停词之后,倒排索引可以表示为:
关键字(具有唯一性) 文档ID 苹果 1、2 电脑 1 手机 2 使用倒排索引,此时用户搜索苹果,则会通过索引找到文档1和2。用户搜索电脑,则会找到文档1。
优点
- 查询效率高。可以快速查找到包含某个词汇的所有文档。
- 适合大规模数据的全文检索。
缺点
- 构建和维护复杂度高。需要处理大量数据和存储空间。(用户友好型)
数据去标签化
去标签
本项目的文档搜索范围均为html文件,均在https://www.boost.org/doc/libs/1_85_0/doc/html路径下,其中1_85_0是boost库的版本。
如下是该路径下的一个文件内容https://www.boost.org/doc/libs/1_85_0/doc/html/tools.html:
Chapter 1. Boost.Accumulators - 1.85.0
......
Boost
C++ Libraries
文件中的形如、
、 等处于两个小尖括号之间的是html的语法,本就是不需要的内容。这些标签一般成对出现,形如……。去标签化就是删除这些没有用处的信息,只保留下该html文件在网页所呈现的文字内容。最终的效果:将每一个文档的标签删除,得到的内容放到一个网页正文文件的一行。
- 步骤1 读取html文件内容
- 步骤2 获取文档的标题、正文、URL
- 步骤3 将获取的信息连接成一行数据,写入网页正文文件。
代码如下
parser.cc:
#include #include #include #include #include "util.hpp" #include "log.hpp" //所有的html网页的路径 const std::string src_path="data/input"; //输出文件的路径 const std::string output = "data/raw_html/raw.txt"; //每个文件的解析信息 typedef struct DocInfo { std::string title;//文档的标题 std::string content;//文档的主体 std::string url;//文档网页的链接 }DocInfo_t; //遍历文档 bool EnumFile(const std::string &src_path, std::vector* file_path_list); //去标签化 bool ParseHtml(const std::vector &file_path_list, std::vector* results); //保存文档 bool SaveHtml(const std::vector &results, const std::string &output); int main() { std::vector file_path_list; //第一步,递归式的把每个html文件名和路径保存到file_path_list if(!EnumFile(src_path,&file_path_list)) { std::cerr let query = $(".container .search input").val(); if(query == '' || query == null) { return; } $.ajax({ type: "GET", url: "/s?word=" + query, success: function(data) { searchData = data; if(searchData == '' || searchData == null) { document.write("没有找到要搜索的内容"); return; } totalPages = Math.ceil(searchData.length / pageSize); DisplayResults(); UpdatePagination(); } }); } function DisplayResults() { if(searchData == '' || searchData == null) { document.write("没有找到要搜索的内容"); return; } let result_lable = $(".container .result"); result_lable.empty(); let startIndex = (currentPage - 1) * pageSize; let endIndex = Math.min(startIndex + pageSize, searchData.length); for (let i = startIndex; i
- 构建和维护复杂度高。需要处理大量数据和存储空间。(用户友好型)
- 查询效率低。要查找某个词语出现在哪些文档中,需要遍历所有文档的词汇表。
- 项目环境
- 技术栈
