为什么要进行数据清洗
获取到的原始网页信息往往包含大量冗余标签,直接处理会干扰后续的正倒排索引构建。我们需要从中精准提取出标题(title)、正文内容(content)以及对应的 URL,为后续的索引生成做准备。
数据清洗流程
整个清洗过程可以拆分为三个核心阶段:文件发现、HTML 解析与结果持久化。这种分步设计不仅逻辑清晰,还能有效隔离错误风险。
1. 文件发现
首先通过 EnumFile 函数递归扫描源路径 src_path,筛选出所有以 .html 结尾的文件,并将完整路径存入 file_list 容器。这一步的本质是过滤掉非网页资源,只保留需要处理的普通网页文件。
2. HTML 解析
接下来读取 file_list 中的每一个文件,去除 HTML 标签噪音,提取关键信息并构建 URL。之所以要执行去标签操作,是因为网页源码中充斥着字体大小、颜色样式等无用信息,必须剥离才能还原纯净文本。

3. 结果存储
最后将解析后的数据写入输出目录。这里采用分步写入的策略,而非一次性合并,主要是为了降低模块间的耦合度。一旦某个环节出错,不会导致整个程序崩溃,同时也便于'写一点编译一点'的迭代开发,避免全量代码写完后再调试带来的隐患。
typedef struct DocInfo {
std::string title; // 文档的标题
std::string content; // 文档的内容
std::string url; // 该文档在官网中的 url
} DocInfo_t;
int main() {
std::vector<std::string> file_list;
// 第一步:调用 EnumFile,通过递归方式把 src_path 里面的文件名(带路径),保存到 file_list 中
if (!EnumFile(src_path, &file_list)) {
std::cout << "EnumFile error!!!" << std::endl;
return 1;
}
// 第二步:读取 file_list 里面每一个文件的内容,并进行解析,然后解析进 results
std::vector<DocInfo_t> results;
if (!ParseHtml(file_list, &results)) {
std::cout << "ParseHtml error" << std::endl;
return 2;
}
// 第三步:把解析后的文件的内容写到 output 里面,然后按照 /3 作为每个文件的分隔符
(!(results, output)) {
std::cout << << std::endl;
;
}
;
}


