当前位置: 首页 > article >正文

4.完成html文件读取|获取title|获取content|构建url|调试(C++)

解析html代码结构编写
  1. 建立一个util.hpp,是一个工具集,把所有的工具内容写到这里
touch util.hpp

![[Pasted image 20250215140053.png]]

  1. 编写util.hpp
#include <iostream>
#include <string>
#include <fstream>

namespace ns_util{
	class FileUtil{
		public:
			static bool ReadFile(const std::string &file_path, std::string *out)
			{
				return true;
			}
	};
}   

提取title
![[Pasted image 20250215141021.png]]

提取content,本质是进行去标签
3. 编写parser.cc第二步的代码结构

static bool ParseTiltle(const std::string &file, std::string *title)
{
	return true;
}

static bool ParseContent(const std::string &file, std::string *content)
{
	return true;
}

static bool ParseUrl()
{
	return true;
}

bool ParseHtml(const std::vector<std::string> &files_list, std::vector<DocInfo_t> *results)
{
	for(const std::string &file : files_list){
		//读取文件,Read();
		std::string result;
		if(!ns_util::FileUtil::ReadFile(file, &result)){
			continue;
		}
		DocInfo_t doc;
		//解析指定的文件,提取title
		if(!ParseTitle(result, &doc.title)){
			continue;
		}
		//解析指定的文件,提取content,就是去标签
		if(!ParseContent(result, &doc.content)){
			continue;
		}
		//解析指定的文件路径,构建url
		if(!ParseUrl()){
			continue;
		}

		//done,一定是完成了解析任务,当前文档的所有的相关结果都保存在了doc里面
		results->push_back(doc); 
		//bug:todo;细节,本质会发生拷贝,效率可能会比较低
	}
	return true;
}
编写文件读取代码
  1. 编写util文件
#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 << "open file" << file_path << " error" << std::endl;
					return false;
				}

				std::string line;
				while(std::getline(in, line)){ //如何理解getline读取到文件结束:getline的返回值是一个&,while判断的是一个bool类型,本质是因为返回的对象当中重载了强制类型转化
					*out += line;
				}

				in.close();
				return true;
			}
	};
}
编写获取title代码

在整个文档里面去搜索title关键字和/title关键字
![[Pasted image 20250215152947.png]]

找到title关键字的开始位置,和/title关键字的开始位置
让头位置+上title的大小,就是有效区的起始,后面的查找到的位置,这是一个前闭后开的区间

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){
		return false;
	}

	*title = file.substr(begin, end - begin);
	return true;
}
获取文档的content内容

在进行遍历的时候,只要碰到了>右标签,就意味着当前的标签被处理完毕
只要碰到了<左标签,就意味着新的标签开始了

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代码

boost库的官方文档,和下载下来的文档是有路径的对应关系的

官⽹URL样例:
https://www.boost.org/doc/libs/1_78_0/doc/html/accumulators.html  

我们下载下来的url样例:
boost_1_78_0/doc/html/accumulators.html  

我们拷⻉到我们项⽬中的样例:
data/input/accumulators.html 
//我们把下载下来的boost库  doc/html/* copy data/input/

url_head = "https://www.boost.org/doc/libs/1_78_0/doc/html";  
url_tail = [data/input](删除) /accumulators.html -> url_tail =  /accumulators.html  
url = url_head + url_tail ; 相当于形成了⼀个官⽹链接

编写parser.cc

static bool ParseUrl(const std::string &file_path, std::string *url)
{
	std::string url_head = "https://www.boost.org/doc/libs/1_87_0/doc/html";
	std::string url_tail = file_path.substr(src_path.size());
	
	*url = url_head + url_tail;
	return true;
}

bool ParseHtml(const std::vector<std::string> &files_list, std::vector<DocInfo_t> *results)
{
	for(const std::string &file : files_list){
		//读取文件,Read();
		std::string result;
		if(!ns_util::FileUtil::ReadFile(file, &result)){
			continue;
		}
		DocInfo_t doc;
		//解析指定的文件,提取title
		if(!ParseTitle(result, &doc.title)){
			continue;
		}
		//解析指定的文件,提取content,就是去标签
		if(!ParseContent(result, &doc.content)){
			continue;
		}
		//解析指定的文件路径,构建url
		if(!ParseUrl(file, &doc.url)){
			continue;
		}
		//done,一定是完成了解析任务,当前文档的所有的相关结果都保存在了doc里面
		results->push_back(doc); //bug:todo;细节,本质会发生拷贝,效率可能会比较低
	}
	return true;
}
调试
void ShowDoc(const DocInfo_t &doc)
{
	std::cout << "title: " << doc.title << std::endl;
	std::cout << "content: " << doc.content << std::endl;
	std::cout << "url: " << doc.url << std::endl;
}

make链接,运行文件
![[Pasted image 20250215171014.png]]

Chapter 46. Boost.YAP - 1.87.0
![[Pasted image 20250215171623.png]]

成功获取到官方url


http://www.kler.cn/a/549153.html

相关文章:

  • DeepSeek 助力 Vue 开发:打造丝滑的瀑布流布局(Masonry Layout)
  • JAVA EE初阶 - 预备知识(一)
  • 计算机视觉:卷积神经网络(CNN)基本概念(二)
  • 全方位养生指南:打造健康生活蓝图
  • 【论文笔记】On Generative Agents in Recommendation
  • Docker 数据卷的使用与数据持久化(二)
  • 数位dp入门详解
  • GDB QUICK REFERENCE (GDB 快速参考手册)
  • Vue2 中使用 UniApp 时,生命周期钩子函数总结
  • 案例-04.部门管理-删除
  • 负载测试工具有哪些?
  • unity学习44:学习Animator 的一个动作捕捉网站,实测好用
  • 蓝桥杯篇---IAP15F2K61S2串口
  • 【第13章:自监督学习与少样本学习—13.2 少样本学习(FSL)与元学习(Meta-Learning)的基础理论与应用案例】
  • 29、深度学习-自学之路-深入理解-NLP自然语言处理-做一个完形填空,让机器学习更多的内容程序展示
  • Ubuntu 下 nginx-1.24.0 源码分析 - ngx_log_error 函数
  • MQ常见面试题
  • 神经网络新手入门(1)目录
  • Ubuntu 下 nginx-1.24.0 源码分析 - ngx_ssl_init 函数
  • 搭建一个经典的LeNet5神经网络