C++项目 Boost搜索引擎

选取boost库官网中的一个网页作为根目录,用它来建立索引。用户在搜索引擎首页搜索,搜索关键字在服务端(searcher)进行分词,查找index(供系统进行查找索引)。

使用单例模式,只有一个index对象。在获取index的代码文件(index.hpp)中实现的单例模式:所有的搜索都是在唯一一个倒排索引和唯一一个正排索引中进行的. 也就是说 最终一个程序中只需要建立一次索引. 所以我们可以将索引的相关函数实现为单例。

关于线程安全问题使用了加锁保护,懒汉模式(吃完饭, 先把碗放下, 然后下一顿饭用到这个碗了再洗碗。第一次用的时候会创建对象,后面就直接传入地址。延时加载,优化服务器的启动速度)

对去标签,数据清洗,提取title+content(desc)+url,格式化后的文档(parser.cc)建立索引(index.hpp)正排索引(得到title,desc,url,建立文档id-->当前正排索引数组的大小),倒排索引(当前我们是一个一个文档进行处理的,一个文档会包含多个”词“, 都应当对应到当前的doc_id。 对title,content进行分词,词频统计-->忽略大小写,自定义相关性-->有多个不同的词,指向同一个文档的时候,此时该优先显示谁:标题权重大。 构成一个或者多个倒排拉链) (得到unordered_map[关键字,倒排拉链]。一组倒排拉链和关键字的映射关系)由于多个文档可能包含相同的关键字

可以根据搜索词分词的关键词在倒排数组里获取倒排拉链(数组里面放结构体:文档id,分好的词,权重)。

查找(searcher),对查询进行jieba分词

std::vector title_words;
ns_util::JiebaUtil::CutString(doc.title, &title_words);
jieba. CutForSearch

->根据分词得到的各个词语进行index查找。遇到的问题就是:通过倒排,把所有词的倒排拉链都合并一起,在可能会出现重复文档id,搜索关键词可能对应着同一个id,导致查询后出现重复结果,解决方案是把倒排拉链先放进map里去重。 ->汇总查找结果,对文档内容合并,对权重降序排序,倒排索引找到文档,取出文档ID,正排索引找到内容。在正排索引中的查找顺序 实际就是搜索结果的显示顺序, 所以在查找之前, 需要先排序;

->根据查找出来的结果,构建json串(title+conent(desc)+url 返回给用户浏览器的搜索结果),jsoncpp。遇到的问题是显示出来的内容太多了,解决方案是:getdesc()找到html_content(去标签后的文档)中首次出现的word,往前50(不够,就到开头),往后100(不够就到结尾)

去掉停用词

搜索the a an都能搜出文档, 但是我们输入的并不是具有目的的有效内容. 空格都能搜出文档.

而, 我们的目的是 防止用户通过停用词查找到了一些无关的文档.

所以, 我们可以将这些 停用词 在分词之后, 去除掉.

stop_words.utf8文件 把 about any move 删除掉. 因为data/input目录下存在以这三个单词为名的文档:

需要将停用词从文件加载到内存中, 而且只需要加载一次, 所以可以考虑将jiebaUtil设置为单例

而jieba库提供的停用词都是小写的, 也就是说_stopKeywordMap内存储的内容都是小写的 // 如果拿着有大小写之分的分词, 在停用词表中查找, 是查找不到的. // 所以在查找之前, 要先将iter指向的分词 小写化, 然后再在停用词表中找

日志文件

定义错误等级,等级越高输出的日志内容越少。定义输出到终端,文件(要把数据刷新到磁盘)。在想要传日志时,调用log(传入日志等级,日志内容),设置输出到哪里。输出日志等级,日志内容,行数,文件。析构函数关闭文件

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

部署到linux

 nohup ./http_server > log/log.txt 2>&1 &一旦启动之后. 除非用户手动关闭, 否则不会被关闭 会一直运行。设置进程为不挂起状态

网络(使用httplib)

日志文件(log)define和预定义符号:记录错误等级,错误信息,那个文件,第几行

nohup ./http_server & nohup ./http_server > log/log.txt 2>&1 & 启动服务,追加到log.txt,可以后台以首部进程启动

用于不挂断地运行指定命令,退出终端不会影响程序的运行 &:让命令在后台运行 后台运行http.server,并将错误日志输出到lot.txt

cppjieba使用

结巴库里面提供了分词的方式,比如 小明/买了/四斤/鸡蛋(四斤鸡蛋),停止词不考虑。 下载库,引入库的头文件,输入要分词的字符串,准备好一个字符串vector,

jieba. CutForSearch (src,out);//分割src,放进out的数组

jsoncpp的使用

安装库,引入头文件 有很多组数据,设置Json::Value root;//是vector,然后再设置Json::Value a, a["title"]=要放入的具体内容。root.append(a)。

Json::FastWriter writer;

*json_string =writer.write(root);//序列化root,放入字符串里。

httplib 库

引入头文件

int main()

{   

        httplib::Server svr;

        请求方法(“/hi要输入的 ”,仿函数);

  svr.Get("/hi", {       rsp.set_content("你好,世界!", "text/plain; charset=utf-8");      });

  svr.listen("0.0.0.0", 8081); 监听ip,端口号   

return 0;

}

这是一个目录,下面放的是所有的html网页 const std::string src_path = "data/input";

下面是一个文本文件,该文件保存所有的 网页清洗后的数据

const std::string output = "data/raw_html/raw.txt";

你可能感兴趣的:(C++项目,c++,搜索引擎,javascript)