Парсинг HTML в C++: обзор библиотек и примеры кода

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Парсинг HTML в C++: обзор библиотек и практические примеры

Парсинг HTML на C++ — задача, с которой сталкиваются разработчики при создании веб-скраперов, анализаторов контента или инструментов для извлечения данных. В отличие от Python, где BeautifulSoup и lxml являются стандартом, в C++ нет единого доминирующего решения. Однако существует несколько зрелых и производительных библиотек, которые позволяют эффективно работать с HTML-документами.

В этой статье мы рассмотрим три наиболее популярные библиотеки для парсинга HTML на C++: Gumbo-parser (от Google), libxml2 (с HTML-модулем) и MyHTML. Приведем примеры кода, сравним их возможности и дадим рекомендации по выбору.

1. Gumbo-parser: надежность от Google

Gumbo-parser — это библиотека от Google, реализующая парсинг HTML5 в соответствии со спецификацией WHATWG. Она написана на чистом C, что делает её легковесной и быстрой. Основные преимущества:

  • Полная поддержка HTML5 (включая невалидные документы)
  • Минимальное количество зависимостей
  • Простой API для обхода DOM-дерева
  • Высокая производительность

Установка:

git clone https://github.com/google/gumbo-parser
cd gumbo-parser
./autogen.sh
./configure
make
sudo make install

Пример парсинга HTML и извлечения всех ссылок:

#include <gumbo.h>
#include <iostream>
#include <string>
#include <vector>

void extract_links(GumboNode* node, std::vector<std::string>& links) {
    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"))) {
        links.push_back(href->value);
    }

    const GumboVector* children = &node->v.element.children;
    for (unsigned int i = 0; i < children->length; ++i) {
        extract_links(static_cast<GumboNode*>(children->data[i]), links);
    }
}

int main() {
    const std::string html = R"(<html><body>
        <a href="https://pythonlib.ru">PythonLib</a>
        <a href="/about">О нас</a>
    </body></html>)";

    GumboOutput* output = gumbo_parse(html.c_str());
    std::vector<std::string> links;
    extract_links(output->root, links);

    for (const auto& link : links) {
        std::cout << "Найдена ссылка: " << link << std::endl;
    }

    gumbo_destroy_output(&kGumboDefaultOptions, output);
    return 0;
}

Вывод:

Найдена ссылка: https://pythonlib.ru
Найдена ссылка: /about

2. libxml2: универсальный парсер с HTML-модулем

libxml2 — это мощная библиотека для работы с XML и HTML. Её HTML-парсер основан на тех же принципах, что и XML-парсер, но адаптирован для нестрогого синтаксиса HTML. Преимущества:

  • Поддержка XPath для выборки элементов
  • Встроенная поддержка кодировок
  • Стабильность и широкое распространение
  • Возможность работы с XSLT

Установка (Ubuntu/Debian):

sudo apt-get install libxml2-dev libxslt1-dev

Пример использования XPath для поиска всех заголовков h2:

#include <libxml/HTMLparser.h>
#include <libxml/xpath.h>
#include <iostream>

int main() {
    const char* html = "<html><body><h2>Заголовок 1</h2><h2>Заголовок 2</h2></body></html>";
    
    htmlDocPtr doc = htmlReadDoc(
        reinterpret_cast<const xmlChar*>(html),
        nullptr,
        nullptr,
        HTML_PARSE_RECOVER | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING
    );

    xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);
    xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression(
        reinterpret_cast<const xmlChar*>("//h2"),
        xpathCtx
    );

    if (xpathObj && xpathObj->nodesetval) {
        for (int i = 0; i < xpathObj->nodesetval->nodeNr; ++i) {
            xmlNodePtr node = xpathObj-                    

Рекомендаций