news 2026/11/2 1:14:00

C HTML格式解析与生成之gumbo

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C HTML格式解析与生成之gumbo
测试
#include <fstream> #include <iostream> #include <stdlib.h> #include <string> #include "../src/gumbo.h" // 提取纯文本内容 static std::string cleantext(GumboNode* node) { if (node->type == GUMBO_NODE_TEXT) { return std::string(node->v.text.text); } else if (node->type == GUMBO_NODE_ELEMENT && node->v.element.tag != GUMBO_TAG_SCRIPT && node->v.element.tag != GUMBO_TAG_STYLE) { std::string contents = ""; GumboVector* children = &node->v.element.children; for (unsigned int i = 0; i < children->length; ++i) { const std::string text = cleantext((GumboNode*) children->data[i]); if (i != 0 && !text.empty()) { contents.append(" "); } contents.append(text); } return contents; } else { return ""; } } // 提取url链接 static void search_for_links(GumboNode* node) { if (node->type != GUMBO_NODE_ELEMENT) { return; } GumboAttribute* href; if (node->v.element.tag == GUMBO_TAG_A && (href = gumbo_get_attribute(&node->v.element.attributes, "href"))) { std::cout << href->value << std::endl; } GumboVector* children = &node->v.element.children; for (unsigned int i = 0; i < children->length; ++i) { search_for_links(static_cast<GumboNode*>(children->data[i])); } } // 查找标题 #include <assert.h> static const char* find_title(const GumboNode* root) { assert(root->type == GUMBO_NODE_ELEMENT); assert(root->v.element.children.length >= 2); const GumboVector* root_children = &root->v.element.children; GumboNode* head = NULL; for (int i = 0; i < root_children->length; ++i) { GumboNode* child = (GumboNode*) root_children->data[i]; if (child->type == GUMBO_NODE_ELEMENT && child->v.element.tag == GUMBO_TAG_HEAD) { head = child; break; } } assert(head != NULL); GumboVector* head_children = &head->v.element.children; for (int i = 0; i < head_children->length; ++i) { GumboNode* child = (GumboNode*) head_children->data[i]; if (child->type == GUMBO_NODE_ELEMENT && child->v.element.tag == GUMBO_TAG_TITLE) { if (child->v.element.children.length != 1) { return "<empty title>"; } GumboNode* title_text = (GumboNode *) child->v.element.children.data[0]; assert(title_text->type == GUMBO_NODE_TEXT || title_text->type == GUMBO_NODE_WHITESPACE); return title_text->v.text.text; } } return "<no title found>"; } static std::string find_line( const std::string& original_text, const GumboAttribute& attr) { size_t attr_index = attr.original_value.data - original_text.data(); size_t begin = original_text.rfind("\n", attr_index) + 1; size_t end = original_text.find("\n", attr_index); if (end != std::string::npos) { end--; } else { end = (size_t) original_text.length() - 1; } end = std::min(end, attr_index + 40); begin = std::max(begin, attr_index - 40); return original_text.substr(begin, end - begin); } // 查找class元素 static void search_for_class( GumboNode* node, const std::string& original_text, const char* cls_name) { if (node->type != GUMBO_NODE_ELEMENT) { return; } GumboAttribute* cls_attr; if ((cls_attr = gumbo_get_attribute(&node->v.element.attributes, "class")) && strstr(cls_attr->value, cls_name) != NULL) { std::cout << cls_attr->value_start.line << ":" << cls_attr->value_start.column << " - " << find_line(original_text, *cls_attr) << std::endl; } GumboVector* children = &node->v.element.children; for (int i = 0; i < children->length; ++i) { search_for_class( static_cast<GumboNode*>(children->data[i]), original_text, cls_name); } } int main(int argc, char** argv) { if (argc != 2) { std::cout << "Usage: clean_text <html filename>\n"; exit(EXIT_FAILURE); } const char* filename = argv[1]; std::ifstream in(filename, std::ios::in | std::ios::binary); if (!in) { std::cout << "File " << filename << " not found!\n"; exit(EXIT_FAILURE); } std::string contents; in.seekg(0, std::ios::end); contents.resize(in.tellg()); in.seekg(0, std::ios::beg); in.read(&contents[0], contents.size()); in.close(); GumboOutput* output = gumbo_parse_with_options( &kGumboDefaultOptions, contents.data(), contents.length()); std::cout << cleantext(output->root) << std::endl; //search_for_links(output->root); //find_title(output->root); //const char* cls = "article"; //search_for_class(output->root, contents, cls); gumbo_destroy_output(&kGumboDefaultOptions, output); }
效果

参考

C HTML格式解析与生成-CSDN博客

GitHub - google/gumbo-parser: An HTML5 parsing library in pure C99


创作不易,小小的支持一下吧!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/2 1:13:24

C/C++ JSON ORM

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/11/2 1:09:00

工业级SPI硬件隔离设计:MAX14431BAEE+与PIC18F86K90实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/11/2 1:07:46

黑客+AI组合拳下的西门子PLC:工控安全实战拆解与防御指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/11/2 1:07:03

正激变换器变压器设计全解析:从磁复位到绕制工艺

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/11/2 1:06:47

dsPIC33FJ256GP710A与MAX14431BAEE+的隔离SPI通信设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华