实战项目:Boost搜索引擎
目录
- 1. 项目的相关背景与目标
- 2.相关宏观原理
- 3.技术栈和项目环境
- 4. 正排索引、倒排索引
- 5. 数据去标签与数据清洗 Parser
- 5.1下载文件&&准备工作
- 5.2编写parser解析文档
- 5.2.1整体架构
- 5.2.2EnumFile
- 5.2.3ParseHtml
- 5.2.3.1框架
- 5.2.3.2ns_util::FileUtil::ReadFile(); 读取文件
- 5.2.3.3ParseTitle();提取标签
- 5.2.3.4ParseContent();获取文档的Content(解析去标签)
- 5.2.3.5 ParseUrl();
- 5.2.3.6测试
- 5.3SaveHtml();将解析结果写入到文件当中
- 5.4锦上添花
- 5.5结果
- 6. 建立索引模块 Index
- 6.1 index.hpp整体框架
- 6.2GetForwardIndex();GetInvertedList();BuildIndex()框架
- 6.2.1BuildForwardIndex();构建正排索引
- 6.2.2BuildInvertedIndex();构建倒排索引
- 6.2.2.1思路
- 6.2.2.2 分词工具 cppjieba 介绍:
- 6.2.2.3将cppjieba 写入util.hpp中
- 6.2.2.4问题:暂停词
- 6.2.2.5编写倒排索引的代码
- 7.搜索引擎模块 Searcher.hpp
- 7.1整体框架
- 7.2将Index设置为单例模式
- 7.3 InitSearcher();
- 7.4Search();
- 7.4.1安装josncpp
- 7.4.2josncpp测试:
- 7.4.3Search()编写
- 7.4.4测试
- 7.4.5建立摘要
- 7.4.6GetDesc();
- 7.4.7问题:
- 7.4.7.1问题介绍:
- 7.4.7.2问题测试:
- 7.4.7.3问题解决
- 8.http_server模块
- 8.1准备工作,
- 8.1.1安装较新版本的gcc
- 8.1.2安装cpp-httplib
- 8.1.3测试
- 8.2代码:
- 9.前端
- 10.添加日志log.hpp
- 10.1代码:
- 10.2测试:
- 10.3将程序部署到服务器上
- 11.整体理解
- 11.1各个文件简介
- 整体思路
- 12.个人遇见问题整理
- 12.1点击链接自动添加ip和端口号
- 12.2关于12.1的补充
- 12.3关于网络端口号
1. 项目的相关背景与目标
针对boost网站没有搜索导航功能,为boost网站文档的查找提供搜索功能
站内搜索:搜索的数据更垂直,数据量小
类似于cplusplus.com的搜索
2.相关宏观原理
3.技术栈和项目环境
技术栈:C/C++,C++11,STL,准标准库Boost(相关文件操作),jsoncpp(客户端和数据端数据交互),cppjieba(将搜索关键字进行切分),cpp-httplib(构建http服务器)
其他技术栈(前端):html5,css,js,jQuery,Ajax
项目环境:Centos 7云服务器,vim/gcc(g++)/Makefile,vs2019/vs code(网页)
4. 正排索引、倒排索引
正排索引:从文档ID找到文档内容(文档内的关键字)
正排索引类似于书的目录,我们可以根据页数查找到对应的内容
目标文档进行分词:目的:方便建立倒排索引和查找
停止词:了,吗,的,the,a,一般情况我们在分词的时候可以不考虑
倒排索引:根据文档内容,分词,整理不重复的各个关键字,对应联系到文档ID的方案
文档ID中,各个文档ID的排序按照权重进行排序
倒排索引和正排索引是相反的概念,我们可以根据文档内容查询到这部分内容在哪些文件中出现,从而找到对应的文件
模拟查找过程
用户输入:
关键字->倒排索引中查找->提取出是文档ID(x,y,z,,,)->根据正排索引->找到文档的内容->将文档内容中的title+conent(desc)+url+文档结果进行摘要->构建响应结果
5. 数据去标签与数据清洗 Parser
5.1下载文件&&准备工作
经过测试:
edge,和360浏览器不能下载,每次的速度都是极慢(不到30KB),
并且在下载到一定时间后,会因为权限不足等情况直接不能下载
所以这个下载只能使用chrome下载,
虽然下载的速度还是很慢,但是不会因为其他问题而导致不能下载
下载好之后,
创建目录
然后将文件拖进Linux中
然后解压
我们只需要boost_1_79_0/doc/html/* 内的所有网址即可:
然后删除boost_1_79_0即可:
我们只需要:boost_1_79_0/doc/html 目录下的html文件,用它来进行建立索引
原始数据->去标签之后的数据
查看一共多少html文件
目标:
把每个文档都去标签,然后写入到同一个文件中,每个文档内容只占一行!文档和文档之间‘\3’区分。
为什么是\3?
5.2编写parser解析文档
5.2.1整体架构
#include<iostream>
#include<string>
#include<vector>//目录
const std::string src_path = "data/input/";
const std::string output = "data/raw_html/raw.txt";typedef struct DocInfo
{std::string title;//文档标题 std::string content;//文档内容 std::string url;//该文档在官网中的url
}DocInfo_t;//格式规范:const &:输入;*:输出;&:输入输出
// 运用boost库进行读取
bool EnumFile(const std::string& src_path, std::vector<std::string>* files_list);
//解析标签,
bool ParseHtml(const std::vector<std::string>& files_list, std::vector<DocInfo_t>* results);
//保存文件
bool SaveHtml(const std::vector<DocInfo_t>& results, const std::string& output);int main()
{std::vector<std::string> files_list;//(1)将每个html文件名带路径保存到file_list中if (!EnumFile(src_path, &files_list)){std::cerr << "枚举文件名失败!" << std::endl;return 1;}//(2)对files_list中的每个文件内容进行解析std::vector<DocInfo_t> results;if (!ParseHtml(files_list, &results)){std::cerr << "解析html失败" << std::endl;return 2;}//(3)解析完后,将文件内容写入ouput,用'\3'进行分割if (!SaveHtml(results, output)){std::cerr << "保存文件失败!" << std::endl;return 3;}return 0;
}
5.2.2EnumFile
我们需要使用filesystem函数(boost库中的)
boost库安装
sudo yum install -y boost-devel
//devel是boost开发库
我们用的是1.53,我们搜索的是1.79,这两个不冲突。
boost网页查看函数使用方法:
#include<boost/filesystem.hpp>
bool EnumFile(const std::string& src_path, std::vector<std::string>* files_list)
{namespace fs = boost::filesystem;fs::path root_path(src_path);//遍历时,从这个路径开始 //判断路径是否存在 if (!(fs::exists(root_path))){std::cerr << src_path << "不存在" << std::endl;return false;}//对文件进行递归遍历 //定义一个空的迭代器,用来进行判断递归结束 fs::recursive_directory_iterator end;for (fs::recursive_directory_iterator iter(root_path); iter != end; iter++){//判断文件是否为普通文件(html)都是普通文件 if (!(fs::is_regular_file(*iter))) continue;//判断文件后缀是否为 .html //path()迭代器的一种方法,用来提取路径的字符串;extension()提取带路径的文件名后缀 if (iter->path().extension() != ".html") continue;//std::cout<<"插入路径:"<<iter->path().string()<<std::endl;//测试代码,测试其是否能正常插入 //当前的路径一定是一个合法的,以.html结束的普通网页文件 //string()可以将其转化为字符串的形式 files_list->push_back(iter->path().string());}return true;
}
5.2.3ParseHtml
5.2.3.1框架
bool ParseHtml(const std::vector<std::string>& files_list, std::vector<DocInfo_t>* results)
{for (const std::string& file : files_list){//1.读取文件 Read() std::string result;//读取文件放到这里 if (!(ns_util::FileUtil::ReadFile(file, &result))) {continue;//读取失败,继续处理下一个文件 }//2.解析指定文件,提取title DocInfo_t doc;//解析title if (!(ParseTitle(result, &doc.title))) {continue;//提取报头失败 }//3.解析指令的文件,提取content(内容)(去标签) if (!(ParseContent(result, &doc.content))) {continue;}//4.解析指定的文件路径,构建url if (!(ParseUrl(file,&doc.url))){continue;}//push_back()本质是拷贝,效率低 results->push_back(doc);}return true;
}
5.2.3.2ns_util::FileUtil::ReadFile(); 读取文件
延伸知识点:
如何理解getline读取到文件结束呢?
getline返回的是一个&,
本质是因为重载了强制类型转化
#include<iostream>
#include<string>
#include<fstream> namespace ns_util
{class FileUtil{public://读取文件 static bool ReadFile(const std::string& file_path, std::string* out){//只读打开 std::ifstream in(file_path, std::ios::in);if (!in.is_open())//打开失败 {std::cerr << "打开失败!" << std::endl;return false;}std::string line;while (std::getline(in, line)){*out += line;}in.close();return true;}};
}
5.2.3.3ParseTitle();提取标签
static bool ParseTitle(const std::string& file, std::string* title)
{std::size_t begin = file.find("<title>");if (begin == std::string::npos)//没有找到 return false;std::size_t end = file.find("</title>");if (end == std::string::npos)//没有找到 return false;begin += std::string("<title>").size();if (begin > end)//判断begin和end位置关系 return false;*title = file.substr(begin, end - begin);return true;
}
5.2.3.4ParseContent();获取文档的Content(解析去标签)
在进行遍历的时候,
只要碰到了 >,就意味着,当前的标签被处理完毕
只要碰到了 <,就意味着,新的标签开始了
static bool ParseContent(const std::string& file, std::string* content)
{//去标签,基于一个简易的状态机enum status {LABLE,CONTEN};enum status s = LABLE;for (char c : file){switch (s){case LABLE:if (c == '>') s = CONTEN;break;case CONTEN:if (c == '<') s = LABLE;else{//我们不想保留原始文件的'\n',因为我们想用'\n'作为html解析文本之后的分隔符if (c == '\n') c = ' ';content->push_back(c);}break;default:break;}}return true;
}
5.2.3.5 ParseUrl();
构建URL
boost库的官方文档,和我们下载下来的文档,是有路径对应关系的
官网URL样例: https
实战项目:Boost搜索引擎相关推荐
- C++综合项目-boost搜索引擎
文章目录 一.项目简介 1.1 项目背景 1.2 相关技术和库 1.2.1 正排索引 1.2.2 倒排索引 1.2.3 相关库 1.3 搜索引擎的原理简述 二. 项目的实现过程 2.1 下载boost ...
- 【C++项目】boost搜索引擎项目
文章目录 项目的gitee地址 项目基本演示 讲解思路 一:项目相关背景 二:搜索引擎的相关宏观原理 三:搜索引擎技术栈和项目环境 四:正排索引 vs 倒排索引 - 搜索引擎具体原理 五:编写数据去标 ...
- python爬虫项目-32个Python爬虫实战项目,满足你的项目慌
原标题:32个Python爬虫实战项目,满足你的项目慌 爬虫项目名称及简介 一些项目名称涉及企业名词,小编用拼写代替 1.[WechatSogou]- weixin公众号爬虫.基于weixin公众号爬 ...
- 在线教育数据分析实战项目案例
数据分析实战项目案例 数据分析概览 数据分析经常遇到的问题 解决思路 常规产品指标 在线教育产品指标 市场效果广告指标 搭建指标系统流程 渠道的分类 针对搜索引擎,信息流广告如何稳定提高ROI 利用M ...
- python投票系统项目ppt_python fastApi实战项目 - 爱投票管理系统(一)
一.闲来无事,在工作之余自己研究了一下python的异步框架 - fastapi,并写包括 1.部门管理 2.角色管理 3.用户管理 4.菜单管理 5.登录日志 6.操作日志 六个基础功能模块,演示链 ...
- 10个Python爬虫实战项目
Python爬虫是指使用Python语言编写程序,自动化地从互联网上获取数据并进行处理和分析的技术.Python爬虫是一项复杂而且实用的技术,需要掌握多个方面的基础知识,并具备较强的编程能力和实际操作 ...
- 35个Python实战项目,完整源代码!
收集整理最新36个python实战项目源代码,系统实用,不是普通的小脚本! 多看多练是提升代码能力的最佳途径,一起操练起来! 视频转字符动画 12306 B站弹幕 B站滑块验证码破解 GUI签名 py ...
- 大型电商实战项目,助力2021年高薪
文章目录 序言 推荐背景 项目介绍 整体架构图形 热点技术栈 项目特点 适合人群 对比番外类似的项目 痛点和选择 序言 2021 新的一年开始,祝愿大家工作顺利,事事顺心.如果你有幸看到这一篇文章,请 ...
- Python网络爬虫实战项目代码大全(长期更新,欢迎补充)
Python网络爬虫实战项目代码大全(长期更新,欢迎补充) 阿橙 · 1 个月内 WechatSogou [1]- 微信公众号爬虫.基于搜狗微信搜索的微信公众号爬虫接口,可以扩展成基于搜狗搜索的爬虫, ...
- 超硬核Java学习路线图+学习资源+实战项目汇总,看完以后不用再问我怎么学Java了!
之前写过很多次关于Java学习指南.Java技术路线图的文章.但是总还是有小伙伴来问我,Java怎么学,项目怎么做,资源怎么找,真是让人头秃. 于是这次黄小斜决定来一波狠的,把所有这些内容都整理起来, ...
最新文章
- 缓存击穿!竟然不知道怎么写代码???
- centos 7 ssh 安装mysql,Centos 7 安装Airflow
- I/O模型之一:Unix的五种I/O模型
- boost::geometry::coordinate_type用法的测试程序
- MySQL之innodb与myisam:锁 事务 外键 主键 存储结构 存储大小 索引 count 注重点
- 解锁一个新技巧,让你舒服到不想起床
- java数据抽取到数据仓库_关于数据增量抽取的模拟实现——脚本实现
- Vs code 02 配置非标准的C、C++的编译环境
- 3个最典型的图表错误使用方式,赶紧看看自己是否中招
- java前端学习路线_Java前端需要学什么?Java前端学习路线分享
- 学习笔记-Bandit-WalkThrough
- verilog实现格雷码(Gray Code)与二进制编码转换
- 《分布式资本链周刊》第二期
- 如何构建你的认知体系?查理芒格的100个思维模型
- 定时器+echarts运行时间太长导致内存溢出页面崩溃
- redis报错 Error getaddrinfo ENOTFOUND
- 亲生骨肉 窥视父母遗产 为了继承遗产竟用这种方式替代...
- Windows上python读取grib2文件(不用Linux)
- 简易kafka消息服务器搭建
- Android 音视频配音之音频提取、截断、混音、合并、合成(二)——将提取的PCM根据时间戳截断
热门文章