C++实现网站内搜索功能

   日期:2024-12-25    作者:shfanyu 移动:http://ljhr2012.riyuangf.com/mobile/quote/10919.html
  1. 网站的url
  2. 标题
  3. 一段随机的简介

这样我们就可以通过搜索关键字找到需要的页面的网址了

C++实现网站内搜索功能

由于我只需要title和其余的content,因此我们首先要做的是去标签工作,提取其中的标题和内容


如何拿到标题是什么?

思路:找到< title >和< /title >标签,里面的那段字符串就是标题



实现的基本思路就是使用find函数和substr函数,比较简单。
关于DocContent是什么后面再补充

 


使用状态变化来编写代码的写法会比较简单

  1. 一开始时处于LABEL状态,如果是标签状态,继续读下一个字符,直到读到字符’>",要转换成CONTENT状态
  2. 如果处于CONTENT状态,那么把每一个字符都保存下来,如果读到一个换行符’ ’,那么把它换成空格来存下来。原因是为了方便后面使用一个getline就可以把整一个文档给读进来
 
 
 

可以看到boost官网的文档都是在框框中的网址里的,所以根据这个网址,再加上每个文件的文件名,就可以构建出一个url了

逻辑就是遍历存放数据的文件夹,把所有后缀是.html的文件都做一遍数据清理即可。



遍历文件这个操作需要用到boost库里的一个函数(或者用c++17的语法,具体用法参考
std::filesystem::recursive_directory_iterator

 




上述两个函数就是用于遍历和数据清理的。这里讲一下一个c++11的语法:移动,下面的函数的std::move就是用了移动语法的一个函数

 

本来d是一个临时变量,如果要push_back到一个vector,就要发生一次拷贝。这样开销就会比较大,因为d里面的字符串长度还是挺长的。



如果使用move函数,就可以让这个这个临时变量的内存空间的所有权转让给vector使用,这样就不需要拷贝了。

读写文件用的是< fstream >中的ifstream和ofstream,具体参考链接
ifstream
ofstream


 

这里我们采用了一个策略,每一个文档之间用 来分割,文档内部的元素之间用3来分割。

使用 分割的原因:getline可以一次性把换行符之前的东西读入,这样我们每一次getline都可以读完一整个完整的文档

使用3来分隔文档内部的原因:3在ASCII码里是一个控制字符,普通html里不可能出现这个字符,所以加入3不会影响文档内容原来的正确性

正排索引就是给每个文档编号,这样我们就可以通过ID来找到对应的文档内容。单独的正排索引没什么用,它的作用是用来构建倒排索引。



索引其实就是一个vector,每一个元素是一个ForwardElem

 
 




我们之前已经把所有文档的去标签后的结果保存到一个文件里了,现在我们每一次getline都可以读出一整个文档的内容。并且在文档内加入了3的分隔符。因此我们可以通过3来把更具体的信息再挖掘出来。即标题,内容,url。


因此思路就是

  1. 用3分割字符串,构造一个文档内容
  2. 把这个文档内容放入正排索引的vector中
  3. 给这个文档内容编号

编号的逻辑很简单,vector里面有多少个元素,该文档的id就是多少

 

关于CutString这个函数怎么实现,可以使用boost库里面的split函数
下面这个写法是网上copy的,照着写即可

 
 

倒排索引是通过关键词,我们可以返回具体的文档ID。因此我们要建立关键词和文档ID的关系。在一开始的关键问题已经说了关系紧密的定义我们用关键字在文档中出现的次数和位置来衡量。 因此我们现在要开始分词了。只有先分词,我们才能知道关键字在文档中是否出现,出现几次等问题。

cppjieba安装和使用
这个库的使用有点小坑,得看这篇文章,不然无法正常编译过去

安装好之后作者会提供给你一个demo,把demo的代码复制过来就可以用了。
如下

 
 

逻辑如下

  1. 对文档中的标题,正文进行分词
  2. 统计标题的词频和正文的词频(哈希
  3. weight = title_cnt * 10 + content_cnt



有一个点:对于每个词来讲,我们不需要区分大小写,boost库里面有一个函数可以把字符串都变成小写

 



逻辑:遍历每一个文档即可,之前已经用换行符对每一个文档进行了分割。因此现在每次getline都是一个文档。

 
 

到了这一步时数据准备部分已经完成了,现在要做的是返回数据的逻辑

逻辑如下

  1. 先拿到用户提供的关键字,然后用jieba进行分词,拿到具体的关键字
  2. 用关键字去查倒排索引,得到要返回的文档的ID,并保存下它们的InvertedElem(里面存着weight,后面要根据weight来排序
  3. 根据weight来排序InvertedElem
  4. 把前x个InvertedElem保存在Json串里
  5. 返回Json串
 

关于jsoncpp的使用,参考这个链接
jsoncpp下载和简单使用
我这里直接用了apt install的方式下载jsoncpp,比较简答

因此我们只需要编写这个逻辑即可

  1. 准备好数据部分,启动searcher
  2. 拿参
  3. 把参数放入search函数中,得到返回的json
  4. 把json返回给用户

 

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


举报收藏 0评论 0
0相关评论
相关最新动态
推荐最新动态
点击排行
{
网站首页  |  关于我们  |  联系方式  |  使用协议  |  隐私政策  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报  |  鄂ICP备2020018471号