推广 热搜: 优化  广告  百度  服务  排名  设备  生活服务  账号    项目 

基于Boost库的搜索引擎

   日期:2024-12-30     作者:mip    caijiyuan  
核心提示:本专栏内容为:项目专栏💓博主csdn个人主页:小小unicorn ⏩专栏分类:基于Boots的搜索引擎 🚚

本专栏内容为:项目专栏

基于Boost库的搜索引擎

💓博主csdn个人主页:小小unicorn
⏩专栏分类:基于Boots的搜索引擎
🚚代码仓库:小小unicorn的代码仓库🚚
🌹🌹🌹关注我带你学习编程知识

本项目是一款基于 文档的站内搜索引擎。用户只需输入查询关键词,即可快速检索到相关的 在线文档,并提供相关网页链接,为用户提供了便捷的检索服务。

首先,我们对离线版本的 文档进行解析,并将解析结果整理为一个行文本文件。然后,读取并处理好的文本文件,进行分词、权重计算等操作,同时在内存中构建正排索引和倒排索引。接下来,对用户查询词进行分词和触发,根据相关度对结果进行排序。最后,将结果以 格式进行包装,并序列化为字符串返回。所有这些功能通过服务器搭载搜索页面,为外部用户提供服务。

在介绍此项目之前,我们先介绍一下项目背景

首先我们知道目前主流的开发出搜索引擎有好多

公司:百度,搜狗,360搜索,头条新闻客户端

但是像这些公司开发出来的搜索引擎,基本上都是全网搜索,我们基本上是搞不定的。虽然我们全网搜索搞不定,但是站内搜索我们可以尝试做一做

站内搜索:搜索的数据更垂直,数据量更小

是一个由社区开发和维护的开源库集合,它提供了许多功能强大且高质量的 库,可以扩展 标准库的功能。Boost 库包含了许多与 标准库相似的组件,同时还提供了一些独特的功能和工具,比如 用于网络编程、用于线程操作、用于文件系统操作等等。

库的目标是通过提供高质量、可移植、且兼容标准的 库来增强 的功能和性能。它的发展历史可以追溯到 1998 年,是一个长期积累和发展的项目。由于 的质量和广泛使用,很多 库最终被纳入了 标准库,比如智能指针、函数对象、元编程库等。

  • 高质量:库经过严格的测试和审核,确保了高质量的代码和可靠的功能。

  • 可移植性:库可以在各种平台上使用,包括等,为 程序的跨平台开发提供了便利。

  • 兼容性: 库与 标准库兼容,并且遵循的最佳实践,可以与现有的 代码很好地集成和使用。

  • 功能丰富: 库涵盖了很多领域,包括但不限于网络编程、多线程、文件系统、智能指针、正则表达式、容器和算法等,为 开发者提供了丰富的工具和组件。

总的来说,Boost 库是社区中非常重要的一个开源项目,为 程序员提供了丰富的工具和功能,有助于提高代码的质量、可移植性和性能。

  1. 网页内容获取,数据预处理模块

    这个模块代码的主要思路是从指定目录中枚举所有文件,解析出每个文件的标题、内容和,并将这些信息以特定的格式保存到一个文本文件中。我们首先使用库递归遍历目录,收集所有文件的路径,然后逐个读取文件内容,通过自定义的解析函数提取所需信息。解析出的文档数据随后被写入到一个输出文件中,使用特定分隔符来区分不同文档的记录。我们在执行过程中进行了详尽的错误检查和处理,确保了其健壮性。

  2. 建立正排索引和倒排索引,项目核心模块

    这个模块我们定义了一个名为的类,用于构建和维护一个文档索引系统。该系统采用单例模式确保只有一个索引实例,并使用正排索引和倒排索引来快速检索文档。正排索引存储了文档的基本信息,如标题、内容和,而倒排索引则根据关键词将文档分组。类中提供了构建索引、获取文档信息和获取倒排列表的方法。构建索引的过程涉及读取处理过的数据文件,解析文档数据,并根据文档内容构建索引。此外,我们还实现了简单的进度显示功能。整个索引系统的构建旨在提高文档检索的效率和准确性。

  3. 编写 http_server 模块,进行网络开放

    这个模块是一个基于的简单搜索引擎服务程序,我们整合了服务器和搜索功能。我们首先初始化一个搜索器对象,使用预先处理好的文档数据(来自第一个模块)来建立索引。然后,我们设置了一个服务器,并为服务器定义了一个请求的处理函数,该函数响应客户端对路径的访问。

当客户端发送包含搜索关键字的请求时,服务器会验证请求中是否包含关键字参数。如果没有关键字,服务器会返回错误信息。如果有关键字,服务器将调用搜索器的搜索方法,传入关键字,并获取搜索结果,这些结果被封装为字符串返回给客户端。

首先分为客户端和服务端,我们客户端就以浏览器为例,我们的服务器肯定会提供很多服务,我们就以搜索引擎为例,它肯定会提供一个,当然在搜索的时候,我们肯定是获取到网页的信息,不停的抓取网页,最后放在我们的磁盘里,而抓取网页可以用爬虫来处理,而我们拿到网页信息后,就比如放在我们磁盘下目录下,而当我们拿到所有的文件的时候,要先进行预处理,例如去标签操作和数据清理的操作,当然也会做建立索引的操作,而建立索引可以加快我们的查找工作。

准备工作做完后,我们就可以通过请求的方式进行搜索任务,通过方法来上传我们的搜索的关键字,服务端收到请求后,就会通过检索索引得到相关的信息最后在通过拼接多个网页的,构建一个新的网页,最后返回给我们的用户。

  • 技术栈
  • 项目环境:云服务器

我们先来介绍一下搜索引擎的具体原理

看下面这个

  • 文档1:张三买了两个小米手机
  • 文档2:张三发布了小米手机
文档ID文档内容1张三买了两个小米手机2张三发布了小米手机

而我们的正排索引就是从文档ID找到我们的文档内容(也可以说是文档内的关键字

当然我们还可以对我们的文档内容进行分词(而分词的目的是:方便建立倒排索引和查找

  • 文档1:分词后
  • 文档2:分词后

这样就可以分词好了,那么什么是分词呢,分词其实就是将我们的暂停词去掉,例如等,因为这些在我们分词的时候是可以不用去考虑的。

还是刚才的例子,我们看下面这个表格:通过分词处理后

关键字(具有唯一性)文档ID,Weight(权重)张三文档1,文档2买文档2两个文档1小米文档1,文档2手机文档1,文档2发布文档2小米手机文档1,文档2

而我们的倒排索引:就是根据文档内容,分词,整理不重复的各个关键字,对应联系到文档ID的方案

接下来我们可以模拟一次查找的过程

我们用户输入:小米-> 倒排索引中查找-> 提取出文档-> 根据正排索引-> 找到文档的内容-> 文档结果进行摘要-> 构建响应结果

不难发现,在查找过程中,我们是正排索引和倒排索引一起用的。

 
 
 
 
 
 
 
 

接下来我们讲解一下什么是去标签操作

接下来我们就可以编写模块了

首先将我们的目录先保存起来,存放的是所有的网页

 

接下来就是我们的对文件进行读–去标签—写的操作啦

第一步:我们首先得先把所有文件名列出来,方便后期读取

 

第二步:按照中读取每个文件的内容,并进行解析

 

注意:我们在解析网页的时候,要分三块,因此我们可以就字段定义在结构体里,像这样

 

第三步:把解析完的各个文件内容,写入到中,按照作为每个文档的分割符

 

那么数据清洗模块我们的基本框架已经出来了

Parser.cc

 

这里说明一下

  • :表示输入
  • :表示输出
  • :表示输入输出

接下来我们就将三个子模块一个一个实现即可。

编写

首先中对文件操作的维护不是很好,所以我们可以引入库:

 
 
 

点进去后随便点一个函数就会进入到我们的的库的所有函数,这里我们可能会用到其中的,还有迭代器之类的。

 
 
 
 
 
 
 

是常规文件后,我们还得在判断文件的路径名的后缀是否符合我们的要求,也就是的形式

 
 
 
 

完整代码

 

接下里我们可以测试一下我们的代码,因为现在只是实现了读的操作,所以我们将我们最后的路径信息打印出来即可。

首先编写我们的文件

 

注意:因为库是一个准标准库,所以我们要加上我们的库依赖。

到这我们的第一步已经搞定了,接下来就是解析我们的文件。

编写

在解析我们文件我们首先要读取我们的文件,我们可以再新建一个文件,此文件用于存放我们所实现的一些工具,也就是工具集。

:

 

当然,读取文件我们要用到中的流.

所以我们解析首要的工作如下

 

读取文件后,我们就需要进行解析了,而之前我们介绍过,网页会分为三个字段,所以我们解析也分三步

第一步:提取

 

第二步:提取

 

第三步:构建

 

走到这,就说明我们的解析基本上就完成了并且当前文档的相关结果都保存在了里面

 

当然,其实现在还有一个小,因为插入本质还是会发生拷贝的,效率比较低,在后续实现会进一步完善。

到这我们的基本框架已经出来了,接下来我们实现其中的功能即可。

 
编写
 
编写

而当我们进行遍历的时候,只要碰到了,就意味着,当前的标签处理完了,而只要碰到了就意味着新的标签开始了。

 
编写

boost库的官网文档,和我们下载下来的文档是有路径的对应的关系的

 
 
 

而我们拷贝到我们项目中的示例

 
 
 
 
编写

当我们结束了读文件,解析文件的操作,接下来我们就需要将我们解析的文件写入到文件中。

在写文件中,我们之前的版本1是
文档和文档之间用隔开,也就是这样

 

而这次我们写的时候,我们在写入文件的时候,一定要考虑下一次在读取的时候,也要方便操作!所以我们提取完用隔开,提取完用隔开,提取完用隔开,到这说明我们的一个文档已经弄完了,然后换行即可,依次内推,像这样

 

而我们这样做还有一个目的,那就是方便我们的函数可以直接获取到我们的文档的全部内容

 
 

到这里我们的第一个模块就结束了

遗留小问题

接下来我们接一个小插曲,将之前的遗留问题处理一下

在我们最后解析完成后要将结果返回出去的时候

 
 
 

完整

 
 

我们新建文件:我们先拉大体框架

构建索引,肯定还是需要用到我们之前的文档,首先定义结构体

 

因为涉及到我们之前讲过的正排索引和倒排索引,所以我们在原始基础上右多加了一个字段。但我们目前可以不做多的考虑、

接下来在我们的类中就要实现我们的倒排与正排。

首先定义正排,我们知道正排索引的时候,是根据id找到对应的文档,那么我们正排索引的数据结构可以用vectot数组来进行,因为数组的下标天然就是文档id.

 

而倒排,我们知道是根据来找对应文档信息,所以我们可以首先定义一个结构体用来存放我们倒排索引中的相关字段

 

其中就包含我们的文档,关键字以及权重,加上权重的目的就是,在一个关键字查找中可能会对应多个。

那么所以我们倒排索引的数据结构可以选择哈希

 

而我们可以把单另拿出来,定义成这样

 

而这个我们称为倒排拉链,那么我们的倒排索引就变成了是关键字与我们倒排拉链的映射关系。

那么接下来就可以构建我们的索引了,首先是正排
我们要根据id来找到我们的文档内容

 

其实这个函数实现很简单。我们后面会实现

倒排就是根据关键字来找到我们的倒排拉链

 

接下来,我们就可以根据去标签,格式化之后的文档,构建正排索引和倒排索引

 

我们之前将我们的干净文档写在了我们目录下,目录下中的文件。
也就是将我们之前paser处理过后的数据交付给我。

到这,我们的基本框架就已经出来了,接下来就是实现他们了。

 

根据doc_id找到文档内容

其实要实现这个模块很简单,我们是用数组来描述我们的正排,那么我们只要doc_id只要比我们的正排下标大,那肯定就说明不在这个范围内,反之就是找到了,直接返回即可。

 

根据关键字string,获得倒排拉链

要获取倒排拉链,其实也简单,我们根据映射关系即可进行获取。

 

根据去标签,格式化之后的文档,构建正排和倒排索引

构建索引是一个复杂的动作,所以我们可以先拉一下基本结构
既然要读取文件,那肯定就要涉及到我们的文件操作了

 

读取成功后,那我们就需要获取里面的内容,获取内容我们直接用我们的getline函数

 

我们在不停的读取的同时,每读取到我们就先进行正排索引,随后进行倒排索引。

我们将我们的正排索引和倒排索引定义成私有

 

接下来就是实现我们的正排和倒排索引

正排索引

我们先构建正排索引的结构

首先我们得解析我们的,并进行字符串切分
也就是把我们刚才获取到的分成3个,,,

在进行字符串切分时,我们可以用我们C++中的容器,而这里我们介绍一个新的方法
我们可以使用boost库中的split函数,该函数可以将我们的字符串进行切分。该函数定义

 

:类型是std::vectorstd::string,用于存放切割之后的字符串
:传入的字符串,可以为空
:设定切割符为,(逗号)
:将连续多个分隔符当一个,默认没有打开,当用的时候一般是要打开的。

 
 
 

如果在示例中,有很多个分隔符号,我们先将第四个参数调整成关闭状态

 
 
 
 

而我们可以将我们的字符串切分操作写在我们的工具集当中

 

那么我们的字符串切分操作就搞定了

 

接下来,我们进行第二步:将我们的字符串填充到我们的中

 

第三步,就是插入到正排索引的

 

当然在插入时为了提高效率,我们可以使用的方法。

而我们的id是在插入前就进行更新,这样做的目的是先进行保存,在插入,对应的id就是当前在中的下标

走到这,我们正排索引就肝完了,完整代码

 
倒排索引

在建立倒排索引之前,我们先简单的讲解一下大致原理,我们首先看一下我们倒排的数据结构

 

就假设我们拿到的文档为

:吃葡萄
:吃葡萄不吐葡萄皮
:http://xxxx
:123

而我们根据文档,形成一个或者多个(倒排拉链)
因为我们是一个一个带飞对文档进行处理的,一个文档会包含多个“词”,都对应到当前的

那么首先我们就需要对我们的和进行分词,统计这个词出现了多少次
:吃/葡萄()
:吃/葡萄/不吐/葡萄皮()

分词做好后,我们就要考虑相关性,也就是说我们出现的词在文档中的相关性,而这个相关性的维度就有很多,并且其中也是个复杂的东西,这里我们用词频来作为我们的相关性

那么第二步我们就得做一下词频统计:(伪代码

 

知道了在文档中,标题和内容每个词出现的次数后,接下来我们可以自己定义相关性

 

而其中我们应该如何进行分词,这里我们可以用第三方库:

核心工具,我们用分词

jieba库的安装

首先我们点击这个链接

 
 
 
 
 
 

接下来我们在运行一下

 
 
 
 

总结一下

引入jieba库

刚才我们使用了库,接下来沃我们可以将我们的引入到我们的项目中

我们首先将我们刚下的目录下的文件拷贝到我们的家目录中

 

首先在我们的工具集里引入我们的:

 

接下来我们在我们的工具集里新建一个类

 
编写倒排索引
 
 

首先我们在当前目录下新建一个文件

还是跟之前一样,我们先拉基本结构

首先我们得初始化我们的引擎

 

那肯定要获取我们刚才写的对象,而获取对象我们可以采取单例模式,然后根据对象建立索引。

 

分词完成后,我们可以进行触发工作,怎么理解触发呢?触发我们可以简单理解成就是根据分词中的各个“词”,按照相关性进行一个降序排序。接下来在进行汇总操作,在按照相关性进行排序,最后就是构建,根据我们查找出来的内容,构建一个串,返回给我们的浏览器,而这个我们后续也可以使用第三方库

到这里,我们的基本框架其实已经就出来了

 

编写单例index

接下来我们将编写我们的单例:

 

但很显然这个版本的单例是不安全的,所以我们得进行加锁操作,这里我们直接使用中的来进行加锁操作

 

构建好后,我们就可以在我们的中进行获取

 

编写查找代码

接下来编写我们的查找代码
首先我们进行分词操作

 

接下来我们既然要触发,那一定要各种各样的词,同时肯定也要进行转化、因为当时进行查找时,建立是忽略大小写的,所以搜索,关键字也需要进行转化

那现在就是要查了,那么怎么差呢,首先搜索的应该先是正排呢还是倒排呢?我们正排是根据id查找文档信息,倒排是根据关键字进行查找文档对应,换言之必须先查倒排,那既然要查倒排,那肯定需要获取倒排拉链。

 

当然,在进行获取倒排拉链的时候,是需要进行检查一下的,万一给的这个关键字就没有倒排拉链,那当然,没有倒排拉链肯定也就没有正排了。

走到这,就说明我们获取到了倒排拉链,但是这里就需要注意一下了:我们在这里获取的时候,可能会发生很多拉链,那么在这,我们其实就可以先保存一下

 
 
 
 

接下来就是合并排序了,合并我们也直接用库函数里面的即可。在写排序时,我们可以写一个,进行降序

 
 

接下来就是我们的第四步骤:进行构建,首先走到这就说明我们能拿到了,那么现在肯定就需要差正排的操作了

 

走到这,我们就可以拿到的所有信息,接下来就是我们需要通过完成序列化&&反序列化.将信息以json串的形式返回出去。所以我们得先安装第三方库:

安装库:

 

安装完后,我们可以在我们的测试目录下,先测试一下

 

我们运行一下

 
 

当然感觉这个不舒服,我们可以调整成这样的

 
 

首先在中引入我们的:

 

编写构建代码

 

走到这,我们的搜索结果就大功告成了,接下来我们新建一个文件来进行测试我们的搜索结果

编写测试代码

首先编写我们的文件,这里我们只是先简单测试一下,后面我们还会在做优化

 

然后修改一下我们的:

 

然后可以在我们的获取单例和建立索引的过程加上我们的调试信息:这样就更有利于我们进行查看

 

 
 
 
 

那么实现摘要就肯定还得需要暴露出我们的与搜索关键字相关的内容。

要是这两个情况都不满足,那么我们就用我们start和end的起始位置即可。

 
 
 

为了后续将我们的服务端代码分离开,我们将刚才的server.cc测试文件重新命名为文件,修改我们的文件:

 
 
 
 

升级

 
 

本模块我们整合了服务器和搜索功能。我们首先初始化一个搜索器对象,使用预先处理好的文档数据(来自第一个模块)来建立索引。然后,我们设置了一个服务器,并为服务器定义了一个请求的处理函数,该函数响应客户端对路径的访问。

当客户端发送包含搜索关键字的请求时,服务器会验证请求中是否包含关键字参数。如果没有关键字,服务器会返回错误信息。如果有关键字,服务器将调用搜索器的搜索方法,传入关键字,并获取搜索结果,这些结果被封装为字符串返回给客户端。

 

代码解释

  1. 配置文件路径和服务器根目录
  • 定义了两个常量,用于指定搜索引擎的数据输入文件路径,用于指定Web服务器的根目录。
  1. 初始化搜索组件
  • 在函数中,创建了一个类的实例,并调用其方法来初始化搜索索引。这通常涉及加载数据文件和构建搜索所需的数据结构。
  1. 设置服务器
  • 使用创建一个服务器实例。
  • 通过方法设置服务器的根目录,这样服务器就可以提供静态文件服务。
  • 为服务器添加一个请求的处理函数,这个函数对应于URL路径。
  1. 处理搜索请求
  • 在请求处理函数中,首先检查请求是否包含名为的查询参数,这是用户输入的搜索关键字。
  • 如果没有搜索关键字,服务器返回一个错误信息。
  • 如果有搜索关键字,服务器记录日志并提取关键字。
  • 调用实例的方法,传入关键字,并获取搜索结果。
  • 将搜索结果存储在一个格式的字符串中,准备发送给客户端。
  1. 发送搜索结果
  • 设置响应的内容和类型为格式,然后将搜索结果字符串发送给客户端。
  1. 启动服务器
  • 记录日志表示服务器已成功启动。
  • 调用方法使服务器开始监听指定端口)上的所有IP地址,准备接收客户端的请求。

整体来说,展示了如何使用和现代库来创建一个简单的搜索引擎。它处理请求,执行搜索查询,并将结果以格式返回给用户。这种设计模式适用于创建轻量级的搜索引擎或其他服务应用程序。

在我们的根目录下的的文件。

 
 
 
 

到这里我们的搜索引擎到这就结项了,历经一个月,我们完成了此项目,最后以一句话结尾吧别抱怨努力的苦,那是你去看世界的路

  1. 建⽴整站搜索
  2. 设计⼀个在线更新的⽅案,信号,爬⾍,完成整个服务器的设计
  3. 不使⽤组件,⽽是⾃⼰设计⼀下对应的各种⽅案(有时间,有精⼒
  4. 在我们的搜索引擎中,添加竞价排名(强烈推荐)
  5. 热次统计,智能显⽰搜索关键词(字典树,优先级队列)(⽐较推荐)
  6. 设置登陆注册,引⼊对mysql的使⽤(⽐较推荐的)

项目源码:搜索引擎

本文地址:http://mip.xhstdz.com/xwnews/870.html    物流园资讯网 http://mip.xhstdz.com/ , 查看更多

特别提示:本信息由相关用户自行提供,真实性未证实,仅供参考。请谨慎采用,风险自负。

 
 
更多>同类生活信息

文章列表
相关文章
最新动态
推荐图文
生活信息
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报  |  鄂ICP备2020018471号