C++中的HTML解析:最佳库概述
解析HTML文档是开发解析器、网络爬虫和数据分析工具时的关键任务之一。尽管C++并非此类任务最流行的语言(落后于Python或JavaScript),但存在强大且高性能的库,能够高效处理HTML。在本文中,我们将介绍三种最成熟的解决方案:来自Google的Gumbo-parser、MyHTML和htmlcxx。我们将分析它们的API、特点,并提供实际代码示例。
1. Gumbo-parser (Google)
Gumbo是一个用于解析HTML5的库,由Google工程师开发。它完全符合WHATWG HTML5规范,并且对“脏”HTML代码具有很高的容错性。主要优点:
- 纯C API,无外部依赖。
- 支持所有HTML5元素,包括SVG和MathML。
- 返回完整的DOM树,嵌套关系正确。
- 高速运行(原生基准测试显示可达50 MB/s)。
Gumbo-parser使用示例
在此示例中,我们将从HTML文档中提取所有链接(<a>):
#include <iostream>#include <string>#include "gumbo.h"
void extract_links(GumboNode* node) { if (node->type != GUMBO_NODE_ELEMENT) return;
GumboAttribute* href = nullptr; if (node->v.element.tag == GUMBO_TAG_A) { href = gumbo_get_attribute(&node->v.element.attributes, "href"); if (href) { std::cout << "找到链接: " << href->value << std::endl; } }
// 递归遍历子元素 const GumboVector* children = &node->v.element.children; for (unsigned int i = 0; i < children->length; ++i) { extract_links(static_cast<GumboNode*>(children->data[i])); }}
int main() { std::string html = "<html><body><a href='https://example.com'>示例</a></body></html>"; GumboOutput* output = gumbo_parse(html.c_str()); extract_links(output->root); gumbo_destroy_output(&kGumboDefaultOptions, output); return 0;}如您所见,使用Gumbo需要手动管理内存并递归遍历树。对于大型文档,建议使用迭代方法或栈。
2. MyHTML — 快速轻量级解析器
MyHTML是一个用C编写的库,旨在实现最大性能。它不构建完整的DOM树,而是使用类似SAX的方法(顺序遍历令牌)。这使其非常适合需要快速提取数据而无需构建复杂层次结构的任务。
MyHTML的主要特点
- 模块化架构:解析器 + 序列化器 + 流式API。
- 支持多种编码(UTF-8、Windows-1251、KOI8-R等)。
- 能够处理HTML片段(无需强制使用<html>)。
- 低内存消耗 — 不存储整个树。
示例:统计所有带有"content"类的<div>标签
#include <iostream>#include "myhtml/api.h"
int main() { // 初始化解析器 myhtml_t* myhtml = myhtml_create(); myhtml_init(myhtml, MyHTML_OPTIONS_DEFAULT, 1, 0);
// 解析HTML const char* html = "<div class='content'>块1</div><div>块2</div>"; myhtml_tree_t* tree = myhtml_tree_create(); myhtml_tree_init(tree, myhtml); myhtml_parse(tree, MyENCODING_UTF_8, html, strlen(html));
// 通过CSS选择器查找元素 myhtml_collection_t* collection = myhtml_collection_create(1, 1); myhtml_css_match_selector(tree, tree->node, "div.con