知识问答

【项目】Boost 搜索引擎

文章目录

    • 1.背景
    • 2.宏观原理
    • 3.相关技术与开发环境
    • 4. 实现原理
      • 1.下载
      • 2.加载与解析文件
        • 2.1获取指定目录下的所有网页文件
        • 2.2. 获取网页文件中的关键信息
        • 2.3. 对读取文件进行保存
        • 3.索引
          • 3.1正排与倒排
          • 3.2获取正排和倒排索引
          • 3.3建立索引
            • 3.3.1正排索引
            • 3.3.2倒排索引
            • 4.搜索
              • 4.1 初始化
              • 4.2 搜索功能
              • 5. http_server
                • 5.1 升级gcc
                • 5.2 安装cpp-httplib
                • 5.3编写http_server.cc
                • 6. 编写前端模块
                  • 6.1 HTML
                  • 6.2 CSS
                  • 6.4 JavaScript
                  • 总结 与 拓展
                  • ��序
                    • 效果图:
                    • 项目源码:链接
                    • 搜索引擎测试链接:点击进入

                      1.背景

                      • 百度,360,谷歌等搜索引擎的实现门槛过高,几乎不可能由个人进行实现。
                      • 站内搜索,其中的资源相对比较垂直,适合个人进行实现,并借此达到管中窥豹的效果。
                      • Boost库是没有站内搜索的,实现更有意义。

                        搜索相关内容:

                        • 共性:都含有标题,摘要,网站的网址。

                          说明:有些网站还有图片,广告等信息,但由于我们做的是Boost库的搜索,这些信息知道即可。

                          2.宏观原理

                          3.相关技术与开发环境

                          • 技术栈:C/C++,C++11,STL,JsonCpp,Boost,Cpp-Httplib,Jquery,正排与倒排索引。
                          • 开发环境: Centos,云服务器,vim/g++/gcc/Makefile,VsDode/VS2019。

                            4. 实现原理

                            • 说明: 为了方便理解代码,博主将项目的目录进行贴出,因为下面我们include包含使用的库,使用的是绝对路径。

                            • 项目的路径为:/home/shun_hua/practical-projects/Boost_Search

                            • 原因:相对目录是基于进程的工作目录,进程的工作目录在项目的路径下,而我们写的代码是在项目的子目录的路径下,因此要么把所有的文件都放在项目的路径下,要么就用绝对路径,虽然长,但是可以把文件整理分类,看着比较简洁。

                              1.下载

                              • 进入boost官网:点击进入
                                • 第一步:
                                  • 第二步:
                                    • 第三步:下载完成之后,在对应的Linux操作系统系统上,输入上传文件,进行上传。
                                      [shun_hua@iZ2zebfc5jur5cm0zu2n3gZ Boost_Search]$rz -E [shun_hua@iZ2zebfc5jur5cm0zu2n3gZ Boost_Search]$ l***oost_1_84_0.tar.gz[shun_hua@iZ2zebfc5jur5cm0zu2n3gZ Boost_Search]$ tar xzf boost* [shun_hua@iZ2zebfc5jur5cm0zu2n3gZ Boost_Search]$ l***oost_1_84_0  boost_1_84_0.tar.gz

                                      说明:

                                      • rz - E是上传较大文件时进行使用。
                                      • tar -xzf 是对文件进行解压缩。
                                      • boost_1_84_0是解压缩之后的文件。
                                      • 安装rz : sudo yum install -y rz
                                        • 第四步:找到解压缩文件中的html提取出来用于作为搜索引擎的数据。
                                          • 路径:/boost_1_84_0/doc/html
                                            [shun_hua@iZ2zebfc5jur5cm0zu2n3gZ Boost_Search]$ l***oost_1_84_0[shun_hua@iZ2zebfc5jur5cm0zu2n3gZ Boost_Search]$ cp -r ./boost_1_84_0/doc/html ./input [shun_hua@iZ2zebfc5jur5cm0zu2n3gZ Boost_Search]$ l***oost_1_84_0  input

                                            说明:cp -r [指定路径的目录] [目标路径 + 重命名]

                                            [shun_hua@iZ2zebfc5jur5cm0zu2n3gZ input]$ ls -R | grep -E ".html" | wc -l8586

                                            说明:

                                            • ls -R 显示所有文件,目录递归显示所有文件。
                                            • grep -E [字符串] [文件], 显示出带有指定字符的信息。
                                            • wc -l [文件], 显示出文件的行数。

                                              2.加载与解析文件

                                              基本框架:

                                              2.1获取指定目录下的所有网页文件
                                              • 引入文件库:Boost文件库,具体使用里面的filesystem里面的接口。

                                              • 接口:文档

                                                命名空间:boost::filesystem

                                                类:class path

                                                string string(const codecvt_type& cvt=codecvt()) const; ————将path对象转换为string类。path  extension() const; ——文件的后缀。

                                                迭代器:class recursive_directory_iterator

                                                recursive_directory_iterator() noexcept;//默认构造,其实执向的是endexplicit recursive_directory_iterator(const path& p, directory_options opts\ = directory_options::none);//用根目录初始化,即整个多叉树根。

                                                接口:

                                                bool is_regular_file(const path& p); //判断是否是普通的文件,目录不是普通文件。bool exists(const path& p); //判断是否文件的目录是否存在。
                                                • 实现代码:
                                                  bool GetPathFiles(const string& path,vector* files){    //首先将path转化为boost库的path便于处理    //防止命名污染的情况    namespace fs = boost::filesystem;    fs::path root_path(path);    if(!exists(root_path))    {        lg(CRIT,"path is not exist!");        return false;    }    fs::recursive_directory_iterator end;    for(fs::recursive_directory_iterator cur(root_path); cur != end; cur++)    {        //如果不是普通文件,例如目录。        if(!is_regular_file(cur->path()))        {            continue;        }        string suffix = cur->path().extension().string();        if(suffix != ".html")        {            continue;        }        string path = cur->path().string();        // cout path().string());    }    return true;}
                                                  2.2. 获取网页文件中的关键信息

                                                  核心:

                                                  • 标题——title
                                                  • 内容——content
                                                  • 网址——url

                                                    网页的大致内容:

                                                    说明:

                                                    • …. 之间的为标题,即网页窗口显示的内容。
                                                    • 除去 之间的内容其余的都为内容。
                                                    • 网址,根据网页的基本内容结合本地的相对目录,获取到具体boost库的网址。

                                                      解析文件的基本流程:

                                                      1. 读取网页文件的内容
                                                      //使用命名空间,避免命名污染namespace util{    namespace filesystem    {        bool ReadFiles(const std::string& file_path,std::string *text)        {            std::ifstream fin(file_path);            if(!fin.is_open())            {                lg(WARNNING,"open file fail!");                return false;            }            string line;            while(getline(fin,line))            {                *text += line;                            }            return true;        }    }}
                                                      1. 获取标题
                                                      bool PraseTile(const string& text,string *title){    string prefix = "";    string suffix = "";    auto begin = text.find(prefix);    auto end = text.find(suffix);    if(begin == string::npos || end == string::npos) return false;    begin += prefix.size();    *title = text.substr(begin,end - begin);    return true;}
                                                      1. 获取内容
                                                        • 此处采用的是状态机的实现方式,即除了 都是内容。
                                                      bool PraseContent(const string& text,string *content){    State s = LABLE;    for(char ch : text)    {        switch (s)        {        case LABLE:            if(ch == '>')                s = CONTENT;            break;        case CONTENT:                   if(ch == '