栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【项目实现】Boost搜索引擎

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【项目实现】Boost搜索引擎

文章目录
  • 前言
  • 一. 项目的相关背景
  • 二. 搜索引擎的相关宏观原理
  • 三. 搜索引擎技术栈和项目环境
  • 四. 搜索引擎具体原理
    • 4.1 正排索引
    • 4.2 倒排索引
  • 五. 编写数据去标签与数据清洗的模块Parser
    • 5.1 数据导入
    • 5.2 数据清理
      • 5.2.1 处理Html文件与boost库的引用
      • 5.2.2 代码结构
  • 六. 编写建立索引的模块Index
    • 6.1 Index基本结构
    • 6.2 构建正排
    • 6.3 构建倒排
      • 6.3.1 倒排原理
      • 6.3.2 cppjieba的下载与链接
      • 6.3.3 cppjieba的使用
      • 6.3.4 倒排索引代码
  • 七. 编写搜索引擎模块Searcher
    • 7.1 Jsoncpp的安装与基本使用
    • 7.2 Searcher基本结构
  • 八. 编写HTTP-Server模块
  • 九. 编写前端模块
    • 9.1 VSCode远程连接云服务器
    • 9.2 编写前端代码
  • 十. 优化
    • 10.1 添加日志
    • 10.2 挂起服务
  • 十一. 效果
  • 总结


前言

Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称。

Boost库由Boost社区组织开发、维护。其目的是为C++程序员提供免费、同行审查的、可移植的程序库。Boost库可以与C++标准库完美共同工作,并且为其提供扩展功能。Boost库使用Boost License来授权使用,根据该协议,商业的非商业的使用都是允许并鼓励的。


一. 项目的相关背景

相较于对全网内容的搜索引擎,如某些互联网大型企业的搜索引擎,即:百度、谷歌、Mozilla火狐搜索引擎,我们想要自己实现是需要耗费极大的时间和物质精力的,因为这涉及我们将全网的相关网页信息抓取,以及将全网信息进行保存和建立相关的索引模块,且这些搜索引擎已经有了相当成熟的受众群体,再去实现的意义有待商榷。

Boost库由C++标准委员会库工作组成员发起,其中有些内容有望成为下一代C++标准库内容。在C++社区中影响甚大,是不折不扣的“准”标准库。即便如此,Boost库的官方网站https://www.boost.org/ 内并没有对Boost库这一庞大库配置针对性搜索的相关的搜索引擎,截止实现该项目前的Boost官网中,Boost库的发行版本已至1.79.0,测试版本已至1.80.0,无论是什么版本,我们想了解Boost库中某一具体库的功能,都需要通过按照功能分类的Boost库列表,即相关版本的Documentation进行查找,我们可以通过实现一个Boost搜索引擎实现更优地解决这个问题。我们实现的是站内搜索,这使我们搜索的数据更垂直,相关度更高,数据量更小,针对性也就更强。

通过和目前主流搜索引擎搜索到的内容做对比,可以发现搜索的展现结果:网页的标题(title)、网页内容的摘要描述(content/desc)、即将跳转的网址url(url) 等,这也将是我们重点实现的。


二. 搜索引擎的相关宏观原理


站内搜索通俗来讲是一个网站或商城的“大门口”,一般在形式上包括两个要件:搜索入口和搜索结果页面,此处我们不用考虑爬取数据,因为我们的数据是从Boost官方网站中下载下来的,所以宏观上我们主要考虑客户端和服务器的交互即可。


三. 搜索引擎技术栈和项目环境

技术栈: C/C++/C++11,STL,准标准库Boost库,Jsoncpp,cppjieba,cpp-httplib

  • 不用考虑从网站上爬取数据的过程,只考虑客户端和服务端要进行交互,于是我们采用Jsoncpp达到浏览器和服务器之间进行数据交换的目的
  • 使用cppjieba将搜索关键字进行切分

项目环境: Centos7云服务器(Xshell7),vim/gcc(g++)/Makefile,VSCode

前端实现(选学): HTML5,CSS,JavaScript,jQuery,Ajax


四. 搜索引擎具体原理

后台架构上是比较复杂的,其核心要件包括:中文分词技术、页面抓取技术、建立索引、对搜索结果排序以及对搜索关键词的统计、分析、关联、推荐等。

4.1 正排索引

正排索引:从文档ID找到文档内容(文档中的关键字)

假设此处有两个文档,如:

  • 文档1:雷军买了四斤小米
  • 文档2:雷军发布了小米手机
文档ID文档内容
1雷军买了四斤小米
2雷军发布了小米手机
4.2 倒排索引

目标文档分词:

目的: 方便建立倒排索引和查找

停止词: 的、了、a、the,一般我们在分词的时候可以不考虑

分词:

  • 雷军买了四斤小米:雷军买四斤小米
  • 雷军发布了小米手机:雷军发布小米手机

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

关键字(具有唯一性)文档ID,weight(权重)
雷军文档1、文档2
买文档1
四斤文档1
小米文档1、文档2
四斤小米文档1
发布文档2
小米手机文档2

模拟一次查找的过程:

  • 给出要查找的关键字或具体内容 -> 小米手机

  • 倒排索引中查找 ->

  • 根据文档内容分词后的关键字提取出文档ID -> 文档2(2)

  • 正排索引中查找 -> 2

  • 根据文档ID找到文档内容 -> 雷军发布了小米手机

  • title+content/desc+url文档结果进行摘要 ->

  • 构建相应结果

五. 编写数据去标签与数据清洗的模块Parser 5.1 数据导入
Boost官网:http://www.boost.org/

1. 从boost官网下载数据

此处我们下载的是最新发行版本1.79.0



2. 在我们的云服务器中打开

rz -E


3. 解压打开的boost文件

tar -xzf boost_1_79_0.tar.gz


4. 显示

所显示的内容就是我们在boost官网所看到的全部内容

5. 建立data/input,将boost文档下的html文件复制到input中,input用于存放数据源

//cd boost_searcher
//cd doc
//doc中存放着绝大多数的html文件

mkdir -p data/input//建立目录
cp -rf boost_1_79_0/doc/html/ * data/input/  //将doc下所有的网页内容html*拷贝到input下,input作为数据源


6. 此时boost文件已经用不到了,可以删除

rm boost_1_79_0/ -rf//rm -rf 命令意味着递归地、强制删除指定的目录

rm boost_1_79_0.tar.gz//删除压缩包

目前只需要boot_1_79_0/doc/html目录下的html文件,用它来建立索引


5.2 数据清理

首先在/root/boost_searcher下建立parser.cc文件,用来后续编写数据清理的代码;继续建立util.hpp作为接下来系列操作的工具包。

[root@192 boost_searcher]# touch parser.cc
[root@192 boost_searcher]# touch util.hpp
5.2.1 处理Html文件与boost库的引用
//原始数据->去标签之后的数据
<>:HTML的标签,这个标签对我们进行搜索是没有价值的,我们需要将他处理掉,标签又分为单标签和双标签,比较典型的单标签有,比较典型的双标签有、、

//代码:
[root@192 data]# mkdir raw_html
[root@192 data]# ll
总用量 16
drwxr-xr-x. 58 root root 12288 7月  22 10:51 input//这里放的是原始的html文档
drwxr-xr-x.  2 root root     6 7月  22 11:08 raw_html//这里放的是去标签之后的文档

[root@192 data]# ls -Rl | grep -E '*.html' | wc -l
8173

目标:
version1: 把每个文档都去标签,然后写入到同一个文件中,每个文档内容不需要n换行,文档和文档之间3区分:

类似于:XXXXXXXXX3YYYYYYYYYYY3ZZZZZZZZZZZZZZZ3

采用:
version2: 写入文件中,一定要考虑下一次在读取时,也要方便操作,即便于我们使用getline(ifstream,line)直接获取文档全部内容:title3content3url3

类似于:title3content3url n title3content3url n title3content3url n…

为什么要用3作为分隔符:这是因为文档中的每个字符实际上与ASCII表一一对应,ASCII表中又分为ASCII控制字符和ASCII打印字符,ASCII控制字符是不可显示的,因此,一般我们在文档中看到的字符都属于ASCII打印字符,3中的3对应Ctrl^C,字符解释为正文结束,同时它不会显示,也不会对我们去标签后的新的文档产生影响。

以上实现起来都需要我们对boost库的使用:

boost库的安装:

[root@192 data]# sudo yum install -y boost-devel //是boost的开发库

//使用boost库实现以3作为分隔符并进行压缩
class StringUtil{
public:
    static void Split(const std::string &target,std::vector *out,const std::string &sep) //sep是切分符
    {
       //boost::split(vec,test,boost::is_any_of(","),boost::token_compress_on); vec是一个数组,test是一个字符串,is_any_of()里面是分隔符
       //token_compress_on: aaa3bbb3333ccc3 即确定"bbb3"和"ccc3"之间的"333"需不需要压缩,默认是off,即不压缩
       boost::split(*out,target,boost::is_any_of(sep),boost::token_compress_on);
    }
};

ParseHtml(重点):

1. ParseTitle:

提取对应的title:

2.ParseContent:
去掉文档内容的标签: 在进行遍历时,只要碰到了" > ",就意味着当前标签被处理完毕,新的标签开始了。

3.ParseUrl:

构建url: boost库的官方文档,和我们下载下来的文档是有路径的对应关系的。

官网URL样例:https://www.boost.org/doc/libs/1_79_0/doc/html/accumulators.html

我们下载下来的URL样例:boost_1_79_0/doc/html/accumulators.html

我们拷贝到我们项目中的样例:data/input/accumuelators.html//我们把下载下来的boost库doc/html
        *{
            margin:0;
            padding:0;
        }
        
        html,
        body{
            height: 100%;
        }
        
        .container{
            width: 800px;
            margin: 0px auto; 
            margin-top: 15px;
        }
        
        .container .search{
            width: 100%;
            height: 52px;
        }
        
        .container .search input{
            float:left;
            width: 600px;
            height: 50px;
            border: 1px solid black;
            border-right: none;
            padding-left: 10px;
            color: #ccc;
            font-size: 15px;
        }
        
        .container .search button{
            float: left;
            width: 150px;
            height: 52px;
            background-color:#fc5531;
            color: #FFF;
            font-size: 17px;
            font-family:'Courier New', Courier, monospace;
        }
        .container .result{
            width: 100%;
        }
        .container .result .item{
            margin-top: 15px;
        }
        
        .container .result .item a{
            display: block;
            text-decoration: none;
            font-size: 20px;
            color: #4e6ef2;
        }
        .container .result .item a:hover{
            text-decoration: underline;
        }
        
        .container .result .item p{
            margin-top: 4px;
            display: block;
            font-size: 17px;
            font-family:Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
        }
        
        .container .result .item i{
            display: block;
            font-size: 14px;
            font-style: normal;
            color: green;
        }
    

编写JS:

如果直接使用原生的JS,成本会比较高(xml),推荐使用JQuery。

十. 优化 10.1 添加日志
#pragma once

#include
#include
#include

#define NORMAL  1
#define WARNING 2
#define DEBUG   3
#define FATAL   4

#define LOG(LEVEL,MESSAGE) log(#LEVEL,MESSAGE,__FILE__,__LINE__)                                                                                                  

void log(std::string level, std::string message, std::string file, int line)
{
    std::cout<< "[" << level << "]" << "[" << time(nullptr) << "]" << "[" << message << "]" << "[" << file << ":" << line << "]" << std::endl; 
}

10.2 挂起服务

使用挂起服务可以帮助我们即使在没有运行./http_server的情况下,依旧可以建立客户端与服务器的连接,继续使用我们的搜索引擎。

部署挂起服务:

nohup ./http_server > log.txt 2>&1 &

终止挂起服务:

kill + 进程号

十一. 效果

总结
//原创文章,请勿转载以及为个人使用。

//源代码地址

https://github.com/Ph4rynx/BOOST_SEARCHER
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1026245.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号