C++之基于正倒排索引的Boost搜索引擎项目数据清洗代码及详解(下)

C++之基于正倒排索引的Boost搜索引擎项目数据清洗代码及详解(下)

1.  第一步详解

我们要使用到boost里面filesystem这个命名空间里面的函数,所以我在这里先给它取个别名。然后我们把src_path里面的路径交给root_path。接着我们判断这个路径是否存在,如果不存在那就直接结束代码。接着我们通过迭代器循环的方式来对root_path里面的每一个文件。

第一个if用来判断是否是普通文件,第二个if来判断文件的扩展名是否为 .html,接着走到最后就书面是扩展名为 .html的普通文件。然后我们就把它的路径转化为string类型。

注意:在这里不可以把.string()换成to_string()。这是因为:

.string() 是 std::filesystem::path 类的成员函数,专门用于将路径对象转换为 std::string 类型的字符串(返回路径的字符串表示)。to_string() 是 C++ 标准库中的全局函数(或针对基础类型的重载),用于将数值类型(如 intdouble 等)转换为字符串,不能直接用于路径对象
bool EnumFile(const std::string &src_path,std::vector<std::string> *file_list) { namespace fs=boost::filesystem;//可以理解为对filesystem区别名 fs::path root_path(src_path);//把src_path文件的路径交给root_path if(!fs::exists(root_path))//判断路径是否存在,如果不存在,那就结束 { std::cout<<src_path<<"is not exist"<<std::endl; return false; } fs::recursive_directory_iterator end;//recursive_directory_iterator是一个递归迭代器,现在这个end是指向空 for(fs::recursive_directory_iterator iter(root_path); iter!=end; iter++)//创建一个iter迭代器,如果=end就代表访问完了 { //is_regular_file是用来判断是否是普通文件(html是普通文件),是的话就返回true if(!fs::is_regular_file(*iter)) continue;//走到这里说明不是普通文件,那就跳过 //这行代码的作用是判断当前遍历到的文件的扩展名是否为 .html,只有扩展名是 .html 的文件才会被处理(加入到 files_list 中 ) if(iter->path().extension()!=".html") continue; //代码走到这里说明是以.html结尾的普通网页文件 file_list->push_back(iter->path().string());//.string()的意思就是把iter->path()的内容转化成string类型 } return 0; }

2. 第二步详解

2.1读取并解析(去标签化)

这个就是去标签化的函数,通过一步步对文件的解析分别提出title和content,然后构建出url,接下来就是把doc里面的内容交给results。

这是分开处理是因为写在一起会显得代码很多,不好找错误。

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 tr;//temporary results临时结果 if(!ns_util::FileUtil::ReadFile(file,&tr)); continue; //2. 解析指定的文件,提取title DocInfo doc; if(!ParseTitle(tr,&doc.title)) continue; //3. 解析指定的文件,提取content if(!ParseContent(tr,&doc.content)) continue; //4.解析指定的文件路径,构建url if(!ParseUrl(file,&doc.url)) continue; //走到这里就是已经完成了上面的4个任务,同时文档的标题,内容和url都已经存储到doc里面了 //接下来就是把doc里面的内容交给results results->push_back(doc); } return 0; }

2.2 提取title

因为网页的标题一般是<title>XXXXXXXXXXXXXXXXXXX</title>,然后我们实际上只要XXXXXXXXXXXXXXXXXXX这个部分,所以我们通过找位置的方式来确定实际想要的内容的位置,然后把它全部获取。

//这边加上static是因为不想被别的文件使用(其实加不加都大差不差) static bool ParseTitle(std::string &file,std::string *title) { //因为网页的标题一般是<title>XXXXXXXXXXXXXXXXXXX</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) return false; *title+=file.substr(begin,end-begin);//把标题加入到*title里面 return true; }

2.3提取content

我们在这里先创建一个 enum类型的结构体,用来判断是标签还是我们想要的内容。

然后通过迭代器和switch判断的方式,来把所有的<>的部分去掉。如果是在标签内就一直跳过,如果遇到>就判断下一个是不是<,不是的话就代表是我们想要的内容。

PS:在这里我们不用和提取title一样的方式是因为在content里面,有各种各样的标签,而title里面的标签就只有<title>这一种。

static bool ParseContent(std::string &file,std::string *content) { typedef enum status{//创建一个enum类型,用于判断s当前是什么状态 LABLE, CONTENT }judge; judge s=LABLE; //下面这个的逻辑就是遇到<就一直跳过去找>,然后下一个不是<的话就+=到content 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+=c; } break; default: break; } } return true; }

2.4构建url

用于构建完整 URL 的函数,其作用是将本地文件路径转换为对应的在线 URL 地址。(类似于通过本地连接跳转在线)

建立本地文件与在线文档的对应关系。通过将本地文件的相对路径(相对于src_path)拼接到固定的 URL 头后面,实现从本地文件路径到在线文档 URL 的转换。

注释中提到 不写死 的好处是:当需要处理同一基础 URL 下的多个不同页面时,只需提供不同的本地文件路径,就能自动生成对应的在线 URL,无需为每个页面单独编写 URL。

PS:就像拼图一样,固定一个底座(网址开头),再拼上不同的零件(相对路径),就能得到不同的完整图片(完整网址)。

static bool ParseUrl(const std::string &file_path,std::string *url) { std::string url_head="https://www.boost.org/doc/libs/1_89_0/doc/html"; std::string url_tail=file_path.substr(src_path.size()); //std::string url_head="accumulators.html"; //这边没有像注释里面那样写是因为不写死,这样可以访问多个head一样,tail不一样的网页 *url=url_head+url_tail; return true; }

3. 第三步详解

先以二进制的方式打开output,接着通过迭代器访问results的方式把处理完的信息一段一段的放入临时创建的out_string里面,接着当收集完一个网页的信息后在放入output里面。

PS:在out.write这里要加上C_str是因为这个write()函数是C语言的函数,不认识C++的string,所以我们要转换成它认识的。

最后关闭out,完成所有的读取。

 bool SaveHtml(const std::vector<DocInfo_t> &results,const std::string &output) { //output存结果,这个函数是把results里面的值处理后交给output //std::ofstream out(output,std::ios::out | std::ios::binarry); std::ofstream out(output); //上面这行的意思是以二进制模式打开文件 if(!out.is_open())//判断是否打开成功,如果失败就报错返回 { std::cout<<"open "<<output<<" failed!"<<std::endl; return false; } //通过迭代器把results里面的东西放入临时变量out_string里面,然后 for(auto& item:results) { std::string out_string; out_string+=item.title; out_string+='\3'; out_string+=item.content; out_string+='\3'; out_string+=item.url; out_string+='\n'; out.write(out_string.c_str(),out_string.size()); //这边就是把out_string转换成C语言认识的字符窜类型然后以out_string.size()的大小传入output里面 //out_string也是字符窜类型的,在这里要c_string转换是因为write是C语言的接口不认识C++的string类型,所以要转换成C语言的字符窜 } out.close(); return 0; } 

Read more

Brave Search MCP服务器安装以及客户端连接配置

Brave Search MCP服务器安装以及客户端连接配置

版权声明 * 本文原创作者:谷哥的小弟 * 作者博客地址:http://blog.ZEEKLOG.net/lfdfhl Brave Search概述 Brave Search 是一个由开发隐私浏览器 Brave 的公司推出的独立搜索引擎,其核心特点是专注于用户隐私保护,承诺不追踪用户的搜索历史或个人数据。与依赖谷歌、必应等第三方索引的传统搜索引擎不同,它主要基于自己构建的独立网络索引(约92%的查询来自自有索引)来提供结果,确保了技术自主性。该搜索引擎可通过网页端 search.brave.com 访问,并深度集成于Brave浏览器中作为默认引擎,其商业模式主要依靠与搜索词相关、而非基于用户追踪的广告。除了基本搜索,它还提供特色功能如允许用户自定义结果排序规则的 Goggles,以及能在结果顶部生成简洁答案的AI Summarizer 摘要引擎。自2021年推出以来,Brave Search 保持着增长,月查询量已达约8.43亿次。 官方网站 https://s

By Ne0inhk
【CentOS】中的Firewalld:全面介绍与实战应用(下)

【CentOS】中的Firewalld:全面介绍与实战应用(下)

🐇明明跟你说过:个人主页 🏅个人专栏:《Linux :从菜鸟到飞鸟的逆袭》🏅 🔖行路有良友,便是天堂🔖 目录 一、引言 1、iptables 时代 2、firewalld 时代 二、服务管理  1、Firewalld中的服务定义  2、查看已定义的服务 3、启用/禁用特定服务 启用服务 禁用服务 4、自定义服务配置 1. 创建服务配置文件 2. 编辑服务配置文件 3. 重新加载 Firewalld 配置 4. 验证自定义服务 5. 启用自定义服务 三、端口管理  1、开放特定端口 2、关闭特定端口 3、查看当前开放的端口 4、

By Ne0inhk
Flutter 三方库 flutter_lokalise 的鸿蒙化适配指南 - 同步 Lokalise 云端翻译、自动化 OTA 热更新多语言资源

Flutter 三方库 flutter_lokalise 的鸿蒙化适配指南 - 同步 Lokalise 云端翻译、自动化 OTA 热更新多语言资源

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 flutter_lokalise 的鸿蒙化适配指南 - 同步 Lokalise 云端翻译、自动化 OTA 热更新多语言资源 前言 在 Flutter for OpenHarmony 应用的敏捷开发中,硬编码多语言文本或频繁手动更新翻译文件是低效的。Lokalise 是领先的云端翻译管理平台,而 flutter_lokalise 则让应用能够直接与云端同步最新的翻译。通过该库,开发者可以实现多语言资源的“热更新”,即无需发布新版 App 即可修复翻译错误或增加新语言。本文将讲解如何在鸿蒙端集成这一强大的 OTA 翻译方案。 一、原理解析 / 概念介绍 1.1 基础原理 flutter_lokalise 通过连接 Lokalise API,

By Ne0inhk
Docker方式安装你的私人AI电脑助手Moltbot

Docker方式安装你的私人AI电脑助手Moltbot

简介 Moltbot 是什么? Moltbot(之前叫 Clawdbot ,现在最新的名字叫 OpenClaw)是一个开源的、高度可自托管的 AI 个人助手项目。它最大的特点是: * 不依赖任何专用客户端:你可以用自己已经有的聊天软件(Telegram、WhatsApp、Discord、Slack、企业微信、飞书等)来和 AI 对话。 * 真正的“电脑控制”能力:支持让 AI 直接操作你的电脑(浏览器、文件、终端命令、截图、鼠标键盘等),而不是只能聊天。 * 本地优先 + 云模型混合:可以接本地大模型(Ollama、Llama.cpp),也可以用 Claude、GPT-4o、Gemini 等云模型。 * 完全自托管:数据、记忆、

By Ne0inhk