BoostCompass(数据准备预处理模块)

news2024/11/28 16:30:19

在这里插入图片描述

阅读导航

  • 一、网页数据下载
  • 二、编写数据去标签与数据清洗的模块 Parser
    • ✅boost 开发库的安装
    • 1. 基本思路
    • 2. 详细讲解
      • (1)程序递归遍历目录,收集所有HTML文件的路径
      • (2)对每个HTML文件进行解析,提取出文档标题、内容和URL
      • (3)将这些信息保存到一个文本文件中,每个文档信息之间用特定分隔符隔开
  • 三、结果验证
    • 1. 编辑makefile文件
    • 2. 生成可执行程序

一、网页数据下载

🔴下载网页界面链接

在这里插入图片描述

  1. 打开了上面的网页以后下载boost_1_84_0.tar.gz压缩包就可以了。

  2. 下载以后,打开Linux建立相关目录,在这个目录下输入rz -E命令选中刚才我们下载的压缩包,把压缩包传输进Linux机器中。

  3. 在控制台输入tar xzf boost_1_84_0.tar.gz进行解压
    在这里插入图片描述

  4. 解压出来上面的这些文件,我们需要的数据是在文件夹doc/html里面,我们把它复制到我们创建的data/input文件夹里面使用cp -rf boost_1_84_0/doc/html/* data/input

  5. 把刚才解压过的文件删除了就可以了。

我们已经收集到了网页的初始信息,但是在这些信息中存在着一些无用的网页标签和其他数据,需要进行清理处理,以便我们能够更好地分析和利用这些数据。

二、编写数据去标签与数据清洗的模块 Parser

✅boost 开发库的安装

PS:我们要先在Linux机器上安装Boost库:sudo yum install -y boost-devel

1. 基本思路

  1. 程序递归遍历目录,收集所有HTML文件的路径;
  2. 对每个HTML文件进行解析,提取出文档标题、内容和URL;
  3. 将这些信息保存到一个文本文件中,每个文档信息之间用特定分隔符隔开。

✅整个处理流程由main函数协调,涉及文件操作、字符串解析和错误处理等技术,旨在高效地从HTML文件中提取结构化数据,为后续的数据使用或分析提供便利。

2. 详细讲解

(1)程序递归遍历目录,收集所有HTML文件的路径

  • 程序代码
// 遍历目录,获取所有HTML文件的路径
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 << " 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;
        }
        // 将HTML文件路径添加到列表中
        files_list->push_back(iter->path().string());
    }
    return true;
}

  • 代码解释

函数接受一个字符串参数src_path,这个参数表示需要遍历的目录路径。函数的返回类型是bool,表示操作的成功与否。函数还接受一个指向std::vector<std::string>的指针作为参数,这个向量用于存储找到的HTML文件路径。

在函数内部,首先创建了一个boost::filesystempath对象,用于表示传入的源路径。接着,使用fs::exists函数检查这个路径是否存在。如果路径不存在,函数输出错误信息并返回false

如果路径存在,函数使用fs::recursive_directory_iterator来创建一个迭代器,这个迭代器可以遍历目录及其所有子目录。迭代器的结束状态由end变量表示。在迭代过程中,函数检查每个文件是否是普通文件(fs::is_regular_file),如果不是,则跳过。然后,检查文件扩展名是否为.html,如果不是HTML文件,也跳过。

对于每个符合条件的HTML文件,使用iter->path().string()获取其完整的路径字符串,并将其添加到传入的files_list向量中。

(2)对每个HTML文件进行解析,提取出文档标题、内容和URL

  • 程序代码
// 辅助函数,用于解析HTML文件中的标题
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(); // 调整起始位置,跳过"<title>"

    if(begin > end){ // 如果起始位置在结束位置之后
        return false; // 返回失败
    }
    // 提取标题内容
    *title = file.substr(begin, end - begin);
    return true; // 返回成功
}

// 辅助函数,用于解析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 {
                    //这里不需要保留原始文件中的\n,因为后面要用\n作为html解析之后文本的分隔符
                    if(c == '\n') c = ' '; // 将换行符替换为空格
                    content->push_back(c); // 将字符添加到内容中
                }
                break;
            default:
                break;
        }
    }

    return true; // 返回成功
}

// 辅助函数,用于构建文档的URL
static bool ParseUrl(const std::string &file_path, std::string *url)
{
    // 构造URL头部
    std::string url_head = "https://www.boost.org/doc/libs/1_78_0/doc/html";  
    // 提取URL尾部
    std::string url_tail = file_path.substr(src_path.size());
    // 拼接URL
    *url = url_head + url_tail;
    return true; // 返回成功
}

// 解析HTML文件,提取标题、内容和URL
bool ParseHtml(const std::vector<std::string> &files_list, std::vector<DocInfo_t> *results) {
    for (const std::string &file : files_list) {
        // 读取文件内容
        std::string file_content;
        if (!ns_util::FileUtil::ReadFile(file, &file_content)) {
            continue;
        }
        // 解析标题
        DocInfo_t doc;
        if (!ParseTitle(file_content, &doc.title)) {
            continue;
        }
        // 解析内容(去除HTML标签)
        if (!ParseContent(file_content, &doc.content)) {
            continue;
        }
        // 解析URL
        if (!ParseUrl(file, &doc.url)) {
            continue;
        }
        // 将解析结果添加到结果集中
        results->push_back(std::move(doc));
    }
    return true;
}
  • 代码解释
  1. ParseTitle 函数

    • 这个函数的目的是从一个HTML文件字符串中提取标题(<title>标签内的内容)。
    • 它首先查找<title>标签的开始位置,如果没有找到,返回false
    • 然后,它查找</title>标签的结束位置,如果没有找到,同样返回false
    • 如果找到了开始和结束位置,函数会计算标题的实际长度,并使用substr方法提取标题内容。
    • 最后,将提取的标题内容通过指针参数title返回,并返回true表示成功。
  2. ParseContent 函数

    • 此函数用于去除HTML文件内容中的所有标签,只保留纯文本。
    • 它使用一个简单的状态机来区分标签和内容状态。
    • 遍历文件中的每个字符,如果是标签状态(LABLE),遇到>字符则切换到内容状态(CONTENT)。
    • 在内容状态下,遇到<字符则切换回标签状态,其他字符(除了换行符\n,将其替换为空格)则添加到内容字符串中。
    • 最终,通过指针参数content返回处理后的纯文本内容,并返回true表示成功。
  3. ParseUrl 函数

    • 这个函数用于构建一个文档的完整URL。
    • 它首先定义了一个URL的基础部分,然后从文件路径中提取特定部分作为URL的尾部。
    • 通过拼接基础URL和尾部路径,构建完整的URL字符串。
    • 通过指针参数url返回构建的URL,并返回true表示成功。
  4. ParseHtml 函数

    • 这是一个整合函数,它接收一个包含HTML文件路径的向量,并返回一个包含解析结果的DocInfo_t类型的向量。
    • 对于每个文件路径,它首先读取文件内容,然后依次调用ParseTitleParseContentParseUrl函数来提取标题、内容和URL。
    • 如果任何一个步骤失败,它会跳过当前文件并继续处理下一个文件。
    • 最后,将所有解析成功的文档信息添加到结果集中,并返回true表示解析过程完成。

🍁这些函数共同工作,提供了一个从HTML文件中提取有用信息的解决方案。它们可以用于构建搜索引擎索引、内容摘要或其他需要从HTML中提取数据的场景。代码结构清晰,通过模块化的设计提高了可读性和可维护性。

(3)将这些信息保存到一个文本文件中,每个文档信息之间用特定分隔符隔开

  • 程序代码
// 保存解析结果到文件
#define SEP '\3' // 定义分隔符
bool SaveHtml(const std::vector<DocInfo_t> &results, const std::string &output) {
    std::ofstream out(output, std::ios::out | std::ios::binary); // 以二进制方式进行写入
    if (!out.is_open()) {
        std::cerr << "open " << output << " failed!" << std::endl;
        return false;
    }
    // 遍历结果集,将每个文档的信息写入文件
    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());
    }

    out.close(); // 关闭文件
    return true;
}
  • 代码解释
  1. 定义分隔符

    • 使用预处理器指令#define定义了一个名为SEP的宏,其值为\3。这个宏用于在保存到文件的文档信息之间创建一个分隔符,以便在后续读取文件时能够区分不同的文档记录。
  2. 打开文件

    • 使用std::ofstream创建一个输出文件流out,尝试以二进制模式打开指定的输出文件。这种模式可以确保写入的数据不会被转换或解释为文本文件中的字符,而是以原始字节形式保存。
  3. 检查文件是否成功打开

    • 通过调用out.is_open()检查文件是否成功打开。如果文件没有成功打开,则输出错误信息到标准错误流std::cerr,并返回false
  4. 写入文档信息

    • 如果文件成功打开,函数遍历results向量中的每个DocInfo_t结构体。
    • 对于每个结构体,创建一个字符串out_string,并将结构体中的titlecontenturl字段依次拼接,每个字段后跟一个定义好的分隔符SEP,并在每条记录的末尾添加换行符\n
    • 使用out.write()函数将out_string的内容写入到文件中。out.write()接受两个参数:指向要写入数据的指针和要写入的字节数。
  5. 关闭文件

    • 在所有文档信息都写入文件后,调用out.close()关闭文件。这是一个好的编程实践,可以确保所有的数据都已经被刷新到磁盘,并且释放与文件相关的资源。

整体而言,SaveHtml函数负责将解析后的文档信息以一种结构化的方式保存到文件中,以便后续的处理或分析。通过使用二进制模式和特定的分隔符,该函数确保了数据的完整性和可读性。

三、结果验证

完成了上述代码后,我们的基本架构已经基本完成。接下来,我们需要编写一个名为makefile的文件,以便进行编译和验证结果。

1. 编辑makefile文件

Parser=parser

.PHONY:all
all:$(Parser)

$(Parser):parser.cpp
	$(cpp) -o $@ $^ -lboost_system -lboost_filesystem -std=c++11

.PHONY:clean
clean:
	rm -f $(Parser) 

2. 生成可执行程序

  1. 在控制台输入:make指令,会生成一个名字为parser的可执行程序
    在这里插入图片描述
  2. 输入:./parser命令,执行可执行程序
  3. 打开文件data/raw_html/raw.txt就可以看到数据处理后的结果了,如下图(PS:/3在ASCII码表中表示^c

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1581777.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

政安晨:【深度学习神经网络基础】(五)—— 霍普菲尔德神经网络和玻尔兹曼机

目录 简述 霍普菲尔德神经网络 训练霍普菲尔德神经网络 Hopfield-Tank神经网络 玻尔兹曼机 总之 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 政安晨的机器学习笔记 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&am…

Python学习笔记10 - 程序的组织结构

1. if 语句 2. pass语句 3. 内置函数range() 4. while 循环语句 5. for-in 循环语句 6. 流程控制语句 break 7. 流程控制语句 continue 8. else 语句 9. 嵌套循环

申请GeoTrust证书

GeoTrust是全球知名的数字证书颁发机构&#xff08;CA&#xff09;和安全解决方案提供商。它成立于1999年&#xff0c;后来成为DigiCert旗下的一部分。GeoTrust专注于提供SSL证书和其他安全产品&#xff0c;以保护网站流量、电子邮件通信和企业身份的安全。 GeoTrust的SSL证书在…

Vue+node.js蔬菜水果农产品网上商城管理系统

用户能够及时掌握最新的数据&#xff0c;并能有效地提升用户的服务水平。本制度的优势在于&#xff1a; &#xff08;1&#xff09;该系统将蔬菜信息及时地提供给使用者。使用者可以在任何时候登陆该网站查询相关资讯&#xff0c;所有资讯均真实可信&#xff0c;并严肃处理各项…

test4102

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…

YUDAO源码中的正序倒序表格ElmentUI的实现,与后端的配合?

前端展示和实现&#xff1a; 1. elmentUI表格的定义 2. JS请求参数改造 <!-- 列表 --><el-table v-loading"loading" :data"list" sort-change"handleSortChange"><el-table-column label"Expiry Date" prop"…

人体跟随小车(旭日x3派、yolov5、目标检测)

人体跟随小车&#xff08;yolov5、目标检测&#xff09; 前言最终结果接线实现注意 前言 上板运行的后处理使用cython封装了&#xff0c;由于每个版本的yolo输出的形状不一样&#xff0c;这里只能用yolov5-6.2这个版本。 ①训练自己的模型并部署于旭日x3派参考&#xff1a; ht…

直播系统的短视频直播源码,带有多功能后台系统的直播短视频平台 APP 源码。

内容目录 一、详细介绍二、效果展示1.部分代码2.效果图展示 三、学习资料下载 一、详细介绍 此源码是一个直播系统&#xff0c;集直播、短视频等功能&#xff0c;根据市场趋势开发并推出思乐直播APP&#xff0c;APP功能丰富且可在后台管理系统进行配置&#xff0c;做到按需求来…

【算法一则】贪心加双指针-盛水最多的容器

目录 题目题解贪心算法双指针解题思路暴力破解法双指针 总结 题目 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器…

设计模式学习笔记 - 设计模式与范式 -行为型:7.责任链模式(下):框架中常用的过滤器、拦截器是如何实现的?

概述 上篇文章《6.责任链模式&#xff08;上&#xff09;&#xff1a;原理与实现》&#xff0c;学习了职责链模式的原理与实现&#xff0c;并且通过一个敏感词过滤框架的例子&#xff0c;展示了职责链模式的设计意图。本质上来说&#xff0c;它跟大部分设计模式一样&#xff0…

不到6毛钱的I2C总线实时时钟日历芯片LK8563

前言 8563实时时钟芯片&#xff0c;国内外均有多家生产&#xff0c;今推荐一个性价比极高的RTC芯片&#xff0c;LK8563&#xff0c;一片不到6毛钱. 特点 基于32.768kHz晶体的秒&#xff0c;分&#xff0c;小时&#xff0c;星期&#xff0c;天&#xff0c;月和年的计时 带有世…

【堡垒机】堡垒机的介绍

目前&#xff0c;常用的堡垒机有收费和开源两类。 收费的有行云管家、纽盾堡垒机&#xff1b; 开源的有jumpserver&#xff1b; 这几种各有各的优缺点&#xff0c;如何选择&#xff0c;大家可以根据实际场景来判断 什么是堡垒机 堡垒机&#xff0c;即在一个特定的网络环境下&…

第十届蓝桥杯大赛个人赛省赛(软件类) CC++ 研究生组-RSA解密

先把p&#xff0c;q求出来 #include<iostream> #include<cmath> using namespace std; typedef long long ll; int main(){ll n 1001733993063167141LL, sqr sqrt(n);for(ll i 2; i < sqr; i){if(n % i 0){printf("%lld ", i);if(i * i ! n) pri…

Matlab|【防骗贴】【免费】基于主从博弈的主动配电网阻塞管理

目录 1 主要内容 程序亮点 2 部分代码 3 程序结果 4 下载链接 1 主要内容 《基于主从博弈的主动配电网阻塞管理》文献介绍&#xff1a;主要采用一种配电网节点边际电价统一出清的主从博弈双层调度框架。上层框架解决用户在负荷聚合商引导下的用电成本最小化问题&#xff0…

电脑更新到win11后不能上网,更新win11后无法上网

越来越多的用户升级了win11系统使用&#xff0c;然而有些用户发现电脑更新到win11后不能上网了&#xff0c;这是怎么回事呢?而且奇怪的是&#xff0c;网络状态显示已连接&#xff0c;但就是无法上网&#xff0c;原本以为重置网络就能搞定&#xff0c;但结果相反。针对这一情况…

DRF的认证、权限、限流、序列化、反序列化

DRF的认证、权限、限流、序列化、反序列化 一、认证1、直接用&#xff0c;用户授权2、认证组件源码 二、权限1. 直接使用&#xff0c;用户权限2.权限组件源码 三、序列化1. 序列化1.1 自定义Serailizer类序列化1.2 在视图APIView中使用1.3 自定义ModelSerializer类序列化1.4 不…

vue3 +Taro 页面实现scroll-view 分页功能

需求 现在分页列表 后端只给你一个分页的数据列表 没有总页数 没有当前的分页 页数 只有这么一个list 、、、 如何去分页 我这使用的是scroll-view 组件 滑动到底部的事件 根据你当前设定的每页的数据数量和后端返回给你的数据列表数量 当某一次分页 两个数量不相等了以后 就…

ActiveMQ介绍及linux下安装ActiveMQ

ActiveMQ介绍 概述 ActiveMQ是Apache软件基金下的一个开源软件&#xff0c;它遵循JMS1.1规范&#xff08;Java Message Service&#xff09;&#xff0c;是消息队列服务&#xff0c;是面向消息中间件&#xff08;MOM&#xff09;的最终实现&#xff0c;它为企业消息传递提供高…

目标检测——YOLO系列学习(一)YOLOv1

YOLO可以说是单阶段的目标检测方法的集大成之作&#xff0c;必学的经典论文&#xff0c;从准备面试的角度来学习一下yolo系列。 YOLOv1 1.RCNN系列回顾 RCNN系列&#xff0c;无论哪种算法&#xff0c;核心思路都是Region Proposal&#xff08;定位&#xff09; classifier&am…

DJI无人机二次开发:模拟航线飞行

1.下载大疆行业调参软件&#xff08;大疆官网下载&#xff0c;有mac系统和win系统&#xff09;。 2.安装软件以后用数据线连接电脑和无人机 3.识别无人机点击进去进入模拟器设置和遥控器相同的经纬坐标 4.在遥控器上载入航线 5.开始执行以后在上云api可以看到无人机在地图上移动…