项目:轻量级搜索引擎
一、项目简介今天给大家分享我手写的轻量级全文搜索引擎纯 C 开发无大型中间件依赖完整复刻商业搜索引擎核心逻辑HTML 网页数据清洗、结构化解析手动实现正排索引 倒排索引搜索引擎核心结巴中文分词 停用词过滤关键词权重排序、智能摘要生成基于 httplib 搭建 Web 服务浏览器直接搜索返回 JSON 结果本文拒绝纯空话全程原理 核心代码 逐行讲解适合学习、复盘、简历项目展示。二、项目整体架构代码分层整个项目分为 4 大代码模块解耦清晰数据预处理模块遍历 html、清洗网页、生成 raw.txt 数据源通用工具模块 util文件读取、字符串分割、结巴分词索引模块 index构建正排、倒排索引项目核心检索 amp; 服务模块 searcher main检索逻辑 HTTP 在线服务核心链路原始HTML → 清洗结构化 → 构建索引 → 分词检索 → 权重排序 → Web接口返回JSON三、模块一数据预处理网页解析代码详解目的本地一堆 Boost 文档 html 文件无法直接检索需要批量遍历、去标签、提取标题/内容/URL生成统一格式的 raw.txt。1. 批量遍历HTML文件代码基于 boost::filesystem 递归遍历目录过滤无效文件bool EnumFile(const std::string src_path, std::vectorstd::string *files_list) { namespace fs boost::filesystem; fs::path root_path(src_path); if(!fs::exists(root_path)){ std::cerr src_path not exists std::endl; return false; } // 递归迭代遍历所有文件 fs::recursive_directory_iterator end; for(fs::recursive_directory_iterator iter(root_path); iter ! end; iter){ // 跳过文件夹 if(!fs::is_regular_file(*iter)) continue; // 只保留html文件 if(iter-path().extension() ! .html) continue; files_list-push_back(iter-path().string()); } return true; }代码讲解recursive_directory_iterator递归遍历子目录适配多层文件结构is_regular_file过滤文件夹只保留普通文件后缀判断只筛选 html 网页文件作为数据源2. 标题解析代码字符串截取static bool ParseTitle(const std::string file, std::string *title) { std::size_t begin file.find(title); std::size_t end file.find(/title); if(begin std::string::npos || end std::string::npos || begin end){ return false; } begin std::string(title).size(); *title file.substr(begin, end - begin); return true; }原理通过 find 定位标题标签首尾substr 截取中间纯文本简单高效无需复杂解析库。3. 正文解析代码状态机去HTML标签核心亮点手动实现简易状态机剔除所有 HTML 标签保留正文纯文本static bool ParseContent(const std::string file, std::string *content) { enum status{ LABLE, CONTENT }; enum status s LABLE; for( char c : file){ switch(s){ case LABLE: if(c ) s CONTENT; break; case CONTENT: if(c ) s LABLE; else { if(c \n) c ; content-push_back(c); } break; default: break; } } return true; }代码讲解两种状态标签内舍弃、内容区保留遇到退出标签进入内容读取遇到进入标签停止内容读取自动替换换行符为空格避免文本格式混乱4. 结构化保存数据解决分隔符冲突重点踩坑正文自带换行、逗号不能用常规符号分割项目采用不可见ASCII字符 \3分割字段#define SEP \3 for(auto item : results){ std::string out_string; out_string item.title; out_string SEP; out_string item.content; out_string SEP; out_string item.url; out_string \n; out.write(out_string.c_str(), out_string.size()); }四、模块二通用工具类 util.hpp 代码详解1. 文件读取工具static bool ReadFile(const std::string file_path, std::string *out) { std::ifstream in(file_path, std::ios::in); if(!in.is_open()) return false; std::string line; while(std::getline(in, line)) *out line; in.close(); return true; }2. 结巴分词 停用词过滤核心搜索引擎不能搜「的、了、啊」这类无意义词汇这里封装单例分词工具自动过滤停用词void CutStringHelper(const std::string src, std::vectorstd::string *out) { jieba.CutForSearch(src, *out); // 遍历分词结果删除停用词 for(auto iter out-begin(); iter ! out-end(); ){ auto it stop_words.find(*iter); if(it ! stop_words.end()) iter out-erase(iter); else iter; } }作用精简索引、提升检索精准度、减小内存占用。五、模块三索引核心 index.hpp项目灵魂重点代码搜索引擎快的本质不遍历全文只查索引。依靠正排倒排双索引实现毫秒检索。1. 核心数据结构定义// 正排索引节点通过文档ID查文档内容 struct DocInfo{ std::string title; std::string content; std::string url; uint64_t doc_id; }; // 倒排索引节点通过关键词查文档 struct InvertedElem{ uint64_t doc_id; std::string word; int weight; InvertedElem():weight(0){} }; typedef std::vectorInvertedElem InvertedList;2. 线程安全单例索引类索引全局唯一禁止多次创建采用懒汉模式双重检查锁static Index* GetInstance() { if(nullptr instance){ mtx.lock(); if(nullptr instance){ instance new Index(); } mtx.unlock(); } return instance; }3. 倒排索引权重计算核心代码贴合搜索逻辑标题权重远大于正文标题命中的文档排序更靠前#define X 10 // 标题权重系数 #define Y 1 // 正文权重系数 for(auto word_pair : word_map){ InvertedElem item; item.doc_id doc.doc_id; item.word word_pair.first; // 核心权重算法 item.weight X*word_pair.second.title_cnt Y*word_pair.second.content_cnt; inverted_index[word_pair.first].push_back(std::move(item)); }代码逻辑同一个词在标题出现一次正文出现10次权重完全贴合用户搜索习惯。六、模块四检索器 searcher.hpp 核心代码详解1. 多关键词检索 权重合并用户输入多个关键词同一文档命中多个词权重累加相关性更高// 遍历每一个搜索分词 for(std::string word : words){ boost::to_lower(word); ns_index::InvertedList *inverted_list index-GetInvertedList(word); if(nullptr inverted_list) continue; // 合并相同文档的权重 for(const auto elem : *inverted_list){ auto item tokens_map[elem.doc_id]; item.doc_id elem.doc_id; item.weight elem.weight; item.words.push_back(elem.word); } }2. 权重降序排序std::sort(inverted_list_all.begin(), inverted_list_all.end(),\ [](const InvertedElemPrint e1, const InvertedElemPrint e2){ return e1.weight e2.weight; });权重越高文档和搜索词越匹配排序越靠前。3. 智能摘要生成代码自动截取关键词前后文本容错边界生成搜索摘要std::string GetDesc(const std::string html_content, const std::string word) { const int prev_step 50; const int next_step 100; // 忽略大小写查找关键词 auto iter std::search( html_content.begin(), html_content.end(), word.begin(), word.end(), [](int x, int y){ return (std::tolower(x) std::tolower(y)); } ); if(iter html_content.end()) return None1; int pos std::distance(html_content.begin(), iter); int start 0, end html_content.size() - 1; if(pos start prev_step) start pos - prev_step; if(pos end - next_step) end pos next_step; if(start end) return None2; std::string desc html_content.substr(start, end - start); desc ...; return desc; }七、模块五HTTP Web服务 main.cpp 代码详解基于 cpp-httplib 搭建轻量级服务无需部署 Nginx直接浏览器访问搜索int main() { // 1. 初始化搜索器 索引 ns_searcher::Searcher search; search.InitSearcher(input); // 2. 创建HTTP服务 httplib::Server svr; svr.set_base_dir(root_path.c_str()); // 3. 注册搜索接口 /s svr.Get(/s, [search](const httplib::Request req, httplib::Response rsp) { if (!req.has_param(word)) { rsp.set_content(必须要有搜索关键字!, text/plain; charsetutf-8); return; } std::string word req.get_param_value(word); std::string json_string; search.Search(word, json_string); rsp.set_content(json_string, application/json); }); LOG(NORMAL, 服务器启动成功...); svr.listen(0.0.0.0, 8081); return 0; }接口功能访问http://127.0.0.1:8081/s?wordxxx即可获取结构化搜索 JSON 结果。八、核心知识点总结面试/复盘重点1. 正排索引 vs 倒排索引正排索引文档ID → 文档信息用于结果展示、摘要生成倒排索引关键词 → 文档列表检索加速核心避免遍历全文2. 权重设计思想标题关键词权重 正文权重模拟真实搜索引擎相关性排序逻辑。3. 工程亮点单例模式全局复用索引、分词器避免重复IO提升性能自定义分隔符解决文本分割冲突问题停用词过滤、大小写归一化优化检索效果轻量Web服务实现前后端完整交互九、项目优化方向拔高亮点索引磁盘持久化无需每次启动重建索引增加搜索结果分页、关键词高亮增加缓存优化高频搜索词响应速度引入同义词词库实现智能联想搜索十、总结本项目不是简单的 C 语法demo是完整的后端工程实战项目。从数据清洗、索引算法、业务检索到 Web 服务上线全程手写覆盖了文件IO、STL、设计模式、算法排序、网络编程等核心知识点。非常适合写进简历、面试复盘能清晰讲出索引原理、权重算法、项目踩坑点吊打大多数初级 C 开发者。

相关新闻

STM32L073RZ驱动EPT-14A4005P蜂鸣器的低功耗警报系统设计

STM32L073RZ驱动EPT-14A4005P蜂鸣器的低功耗警报系统设计

1. 项目背景与核心需求在工业控制、安防系统和智能家居等领域,可靠的声音警报机制是不可或缺的基础功能。我最近完成了一个基于EPT-14A4005P压电蜂鸣器和STM32L073RZ微控制器的通用警报系统设计,这个组合特别适合需要低功耗但高可靠性的应用场景。为什么…

2026/7/14 18:43:08 阅读更多 →
千问导出表格行列偏移、边框丢失怎么办?AI 导出鸭针对性优化转换逻辑,横向测评五类导出途径优劣

千问导出表格行列偏移、边框丢失怎么办?AI 导出鸭针对性优化转换逻辑,横向测评五类导出途径优劣

引言 千问在生成数据表格、对比表格、统计表单时效率很高,但直接导出文件极易出现行列错位、边框消失、单元格内容溢出、格式排版崩坏等问题。手动调整表格结构耗时耗力,普通转换工具无法适配千问AI生成表格的特殊代码格式,大量职场制表、学生…

2026/7/14 18:41:08 阅读更多 →
MIPI CSI-2虚拟通道与TDES954多摄像头数据流整合实战

MIPI CSI-2虚拟通道与TDES954多摄像头数据流整合实战

1. 项目概述与核心价值 在嵌入式视觉、车载摄像头、安防监控以及机器人感知等领域,多摄像头系统正变得越来越普遍。一个典型的应用场景,比如一辆具备高级驾驶辅助系统(ADAS)的汽车,其周身可能部署了多达8个甚至更多的摄…

2026/7/14 18:41:08 阅读更多 →

最新新闻

陈,高速颅骨钻 电动颅骨钻

陈,高速颅骨钻 电动颅骨钻

主要用于实验动物开颅手术操作,标配硬质合金麻花钻与旋转锉,钻头可自动锁紧,使用过程中不易打滑、无轴向位移。机头采用空心轴结构,摒弃传统三瓣夹头,安徽,正华生物,露。技术参数1. 供电规格&am…

2026/7/14 19:29:23 阅读更多 →
智能体在科研中的应用

智能体在科研中的应用

一场静悄悄的革命2024年,斯坦福大学的一项调研显示:超过60%的科研工作者每天花费2小时以上处理重复性数据操作——格式转换、批量重命名、脚本调试、参数调优。这些工作不产生科学价值,却吞噬着研究者最宝贵的资源:思考时间。智能…

2026/7/14 19:29:23 阅读更多 →
vs2qt高级配置指南:如何使用-I和-L参数扩展头文件和库路径

vs2qt高级配置指南:如何使用-I和-L参数扩展头文件和库路径

vs2qt高级配置指南:如何使用-I和-L参数扩展头文件和库路径 【免费下载链接】vs2qt vs trans to qt and so on. 项目地址: https://gitcode.com/openeuler/vs2qt 前往项目官网免费下载:https://ar.openeuler.org/ar/ 快速掌握vs2qt跨平台转换工具…

2026/7/14 19:27:22 阅读更多 →
每天60s读懂世界:2026年7月14日8条重点新闻深度解读

每天60s读懂世界:2026年7月14日8条重点新闻深度解读

🔥个人主页:杨利杰YJlio❄️个人专栏:《Windows 疑难杂症与工单复盘案例库》 《Sysinternals实战教程》《WINDOWS教程》 《Windows PowerShell 实战》 《人工智能实战合集》《超简单:用Python让Excel飞起来》🌟 …

2026/7/14 19:25:22 阅读更多 →
【优选算法】滑动窗口专项:1.长度最小的子数组 2.无重复最长子串

【优选算法】滑动窗口专项:1.长度最小的子数组 2.无重复最长子串

🔥小龙报:个人主页 🎬作者简介:C研发,嵌入式,机器人,AI等方向学习者 ❄️个人专栏:《优选算法》 ✨ 永远相信美好的事情即将发生 文章目录前言一、长度最小的子数组1.1题目1.2 算法原…

2026/7/14 19:23:21 阅读更多 →
别再把业务规则写死在代码里:一文拆解企业统一规则管控平台(架构、模型、落地与踩坑) (PPT)

别再把业务规则写死在代码里:一文拆解企业统一规则管控平台(架构、模型、落地与踩坑) (PPT)

当一个“欠费用户不能订购套餐”的判断,同时散落在营业厅、APP、CRM、订单中心和计费系统里,它就不再是一条简单的 if,而是一笔持续膨胀的技术债。企业数字化建设走到一定阶段,最难缠的往往不是“没有系统”,而是系统太…

2026/7/14 19:23:21 阅读更多 →

日新闻

AI Agent数据越界行为如何被精准溯源?——基于GDPR/CCPA双合规的5层审计框架实战指南

AI Agent数据越界行为如何被精准溯源?——基于GDPR/CCPA双合规的5层审计框架实战指南

更多请点击: https://kaifayun.com 第一章:AI Agent数据越界行为的合规性挑战与溯源必要性 AI Agent在自主执行任务过程中,可能因提示注入、上下文污染或权限配置缺陷,无意或有意访问、缓存、传输受保护数据(如PII、G…

2026/7/14 0:01:13 阅读更多 →
Perplexity vs ChatGPT vs Claude:实测127组复杂查询任务,谁才是真正可靠的“事实型AI助手”?

Perplexity vs ChatGPT vs Claude:实测127组复杂查询任务,谁才是真正可靠的“事实型AI助手”?

更多请点击: https://codechina.net 第一章:Perplexity 怎么用 Perplexity 是衡量语言模型预测能力的核心指标,数值越低表示模型对文本序列的不确定性越小、预测越精准。它本质上是交叉熵损失的指数形式,计算公式为:…

2026/7/14 0:01:13 阅读更多 →
全球首发!五一视界定制物理AI卫星ECS-1剑指万亿赛道

全球首发!五一视界定制物理AI卫星ECS-1剑指万亿赛道

五一视界发布公告,近日,公司与环天智慧科技股份有限公司(“环天智慧”)正式达成空天领域战略合作。环天智慧是国内领先、聚焦天基对地观测遥感卫星总体研制与在轨运营的商业航天企业,同时也是西南地区规模最大、具备全自主可控遥感卫星星座建…

2026/7/14 0:03:13 阅读更多 →

周新闻

互联网大厂 Java 求职面试:燕双非的搞笑回答与技术探讨

互联网大厂 Java 求职面试:燕双非的搞笑回答与技术探讨

互联网大厂 Java 求职面试:燕双非的搞笑回答与技术探讨 在一个阳光明媚的上午,互联网大厂的面试官坐在桌前,准备迎接他的面试候选人——燕双非,一个以搞笑和幽默著称的程序员。第一轮提问 面试官:燕双非,作…

2026/7/14 16:53:23 阅读更多 →
车载以太网PMA测试设备选型:示波器、VNA、信号源3类仪器关键参数与预算评估

车载以太网PMA测试设备选型:示波器、VNA、信号源3类仪器关键参数与预算评估

车载以太网PMA测试设备选型:示波器、VNA、信号源3类仪器关键参数与预算评估在智能驾驶和车联网技术快速发展的今天,车载以太网作为新一代车载网络的核心传输技术,其物理层性能直接决定了数据传输的可靠性和稳定性。1000BASE-T1作为当前主流的…

2026/7/14 14:00:13 阅读更多 →
VSCode EIDE 插件 2.0:APM32/STM32 项目迁移实战,5步完成Keil工程转换

VSCode EIDE 插件 2.0:APM32/STM32 项目迁移实战,5步完成Keil工程转换

VSCode EIDE 插件 2.0:APM32/STM32 项目迁移实战指南嵌入式开发领域正经历一场工具链的静默革命。当传统Keil用户首次打开VSCode的扩展市场搜索EIDE时,往往会惊讶于这个看似简单的插件竟能重构十余年的开发习惯。本文将揭示如何用五个精准步骤&#xff0…

2026/7/14 7:15:24 阅读更多 →

月新闻