O Gumbo-Parser é uma biblioteca de análise HTML5 implementada em C99 puro, projetada para converter documentos HTML em uma árvore DOM estruturada. Esta ferramenta permite o processamento eficiente de conteúdo HTML, facilitando operações como extração de dados ou manipulação de elementos.
Características Técnicas do Gumbo-Parser
- Implementação em C99: Oferece portabilidade para diversas plataformas sem dependências externas.
- Conformidade com HTML5: Garante análise correta de estruturas complexas, seguindo especificações padrão.
- Desempenho Otimizado: Algoritmos eficientes para processamento rápido de documentos grandes.
- API Simplificada: Interface intuitiva que reduz a curva de aprendizagem para desenvolvedores.
Instalação do Gumbo-Parser
Para instalar a bibliotcea, siga estas etapas:
- Obtenha o código-fonte diretamente do repositório oficial.
- Execute os scripts de configuração e compile utilizando ferramentas como autotools.
- Instale os binários e cabeçalhos no sistema.
cd gumbo-parser
autoreconf -i
./configure --prefix=/usr/local
make -j4
sudo make install
Após a instalação, o cabeçalho principal estará disponível em /usr/local/include/gumbo.h.
Estruturas de Dados Fundamentais
A biblioteca define tipos essenciais para representar o documento HTML:
GumboParser: Instância responsável pela análise.GumboNode: Representa um nó genérico na árvore DOM.GumboElement: Especialização para elementos HTML com atributos e filhos.GumboAttribute: Armazena pares nome-valor de atributos.
Exemplo Prático: Extração de Títulos
O código a seguir demonstra como localizar e imprimir o conteúdo da tag <title> em um arquivo HTML:
#include <stdio.h>
#include <stdlib.h>
#include "gumbo.h"
void extract_title(GumboNode* current) {
if (current->type != GUMBO_NODE_ELEMENT) return;
GumboElement* elem = ¤t->v.element;
if (elem->tag == GUMBO_TAG_TITLE) {
if (elem->children.length > 0) {
GumboNode* child = elem->children.data[0];
if (child->type == GUMBO_NODE_TEXT) {
printf("Título encontrado: %s\n", child->v.text.text);
}
}
}
GumboVector* siblings = &elem->children;
for (unsigned int idx = 0; idx < siblings->length; ++idx) {
extract_title(siblings->data[idx]);
}
}
int main(int argc, char** argv) {
if (argc != 2) {
fprintf(stderr, "Uso: %s <arquivo.html>\n", argv[0]);
return EXIT_FAILURE;
}
FILE* file_handle = fopen(argv[1], "rb");
if (!file_handle) {
perror("Erro ao abrir arquivo");
return EXIT_FAILURE;
}
fseek(file_handle, 0, SEEK_END);
long file_size = ftell(file_handle);
rewind(file_handle);
char* html_buffer = malloc(file_size + 1);
fread(html_buffer, 1, file_size, file_handle);
html_buffer[file_size] = '\0';
fclose(file_handle);
GumboParser* parser_instance = gumbo_parse(html_buffer);
extract_title(parser_instance->root);
gumbo_destroy_parser(parser_instance);
free(html_buffer);
return EXIT_SUCCESS;
}
Exemplo Avançado: Coleta de Links
Este exemplo em C++ percorre a árvore DOM para extrair todos os hiperlinks presentes no documento:
#include <iostream>
#include <fstream>
#include <vector>
#include "gumbo.h"
void collect_links(GumboNode* node, std::vector<std::string>& links) {
if (node->type != GUMBO_NODE_ELEMENT) return;
GumboElement* element_data = &node->v.element;
if (element_data->tag == GUMBO_TAG_A) {
GumboAttribute* href_attr = gumbo_get_attribute(&element_data->attributes, "href");
if (href_attr) {
links.emplace_back(href_attr->value);
}
}
for (unsigned int i = 0; i < element_data->children.length; ++i) {
collect_links(static_cast<GumboNode*>(element_data->children.data[i]), links);
}
}
int main(int argc, char** argv) {
if (argc != 2) {
std::cerr << "Sintaxe: " << argv[0] << " <arquivo.html>" << std::endl;
return 1;
}
std::ifstream input_file(argv[1], std::ios::binary | std::ios::ate);
if (!input_file.is_open()) {
std::cerr << "Falha ao ler arquivo." << std::endl;
return 1;
}
std::streamsize size = input_file.tellg();
input_file.seekg(0, std::ios::beg);
std::vector<char> buffer(size);
if (!input_file.read(buffer.data(), size)) {
std::cerr << "Erro na leitura." << std::endl;
return 1;
}
std::string html_content(buffer.begin(), buffer.end());
GumboParser* parser = gumbo_parse(html_content.c_str());
std::vector<std::string> found_links;
collect_links(parser->root, found_links);
for (const auto& link : found_links) {
std::cout << link << std::endl;
}
gumbo_destroy_parser(parser);
return 0;
}
Validação e Testes
A suíte de testes incluída no repositório verifica a conformidade do analisador com diversos cenários HTML. Para executar os testes após a compilação, utilize o comando make check.