Parsing HTML in C++: Overview of Tools and Practical Examples
Parsing HTML in C++ is a task that developers face when creating web page parsers, content analyzers, or tools for automated data collection. Unlike Python or JavaScript, C++ does not have a built-in library for working with HTML documents, but there are several mature and high-performance solutions. In this article, we will review the main libraries for parsing HTML in C++, their features, and provide code examples.
Main Libraries for Parsing HTML in C++
The choice of library depends on your tasks: whether you need support for CSS selectors, XPath, working with malformed HTML, or maximum speed. Let's look at the most popular options.
- Gumbo-parser — a library from Google that implements HTML5 parsing according to the specification. It provides a DOM tree after parsing but does not include built-in tools for navigation via selectors. Requires manual node traversal.
- MyHTML — a fork of Gumbo with improved CSS selector support and a more convenient API. Allows searching for elements by classes, tags, and attributes.
- Lexbor — a modern library focused on speed and standards compliance. Supports both HTML and CSS selectors, as well as XPath (via an additional module).
- htmlcxx — a simple library for parsing HTML into a tree. Suitable for small projects but does not support HTML5.
- Boost.PropertyTree (with XML parser) — can be used for parsing XHTML but is not intended for invalid HTML.
Installation and Setup
Let's look at installing two of the most popular libraries: Gumbo-parser and MyHTML. For C++17 projects, it is recommended to use the vcpkg or Conan package manager.
// Installation via vcpkgvcpkg install gumbo-parservcpkg install myhtml
// Setup in CMakeLists.txtfind_package(gumbo REQUIRED)target_link_libraries(your_project PRIVATE gumbo)
find_package(myhtml REQUIRED)target_link_libraries(your_project PRIVATE myhtml)Example 1: Parsing HTML with Gumbo-parser (Manual DOM Traversal)
In this example, we will parse a simple HTML document and extract all text from <p> tags.
#include <iostream>#include <string>#include <gumbo.h>
void extract_text(GumboNode* node) { if (node->type == GUMBO_NODE_TEXT) { std::cout << node->v.text.text; return; } if (node->type == GUMBO_NODE_ELEMENT && node->v.element.tag == GUMBO_TAG_P) { // Process child nodes GumboVector* children = &node->v.element.children; for (unsigned int i = 0; i < children->length; ++i) { extract_text(static_cast<GumboNode*>(children->data[i])); } std::cout << std::endl; return; } // Recursive traversal for other elements if (node->type == GUMBO_NODE_ELEMENT) { GumboVector* children = &node->v.element.children; for (unsigned int i = 0; i < children->length; ++i) { extract_text(static_cast<GumboNode*>(children->data[i])); } }}
int main() { std::string html = R"(<html><body><p>First paragraph</p><p>Second paragraph</p></body></html>)"; GumboOutput* output = gumbo_parse(html.c_str()); extract_text(output->root); gumbo_destroy_output(&kGumboDefaultOptions, output); return 0;}Example 2: Using MyHTML with CSS Selectors
MyHTML provides a more convenient interface for finding elements. In this example, we will find all links with the class link and output their href attribute.
Also in library
Recommendations