Cheerio FAQ
Quão rápido é o Cheerio comparado a outras bibliotecas de análise HTML?
O Cheerio é projetado para velocidade e eficiência. Ele usa um modelo DOM leve baseado no domhandler, que é significativamente mais rápido que implementações DOM completas de navegador como JSDOM. Diferentemente das soluções baseadas em navegador, o Cheerio remove inconsistências do DOM e overhead de navegador, resultando em operações de análise e manipulação extremamente rápidas.
import * as cheerio from 'cheerio';
// Fast parsing - no browser overhead
const $ = cheerio.load('<div>Large HTML document...</div>');
// Efficient manipulation
$('div').addClass('processed').attr('data-timestamp', Date.now());
Para documentos grandes ou processamento em lote, considere usar APIs de streaming como cheerio.stringStream() para uso otimizado de memória.
Quando devo usar Cheerio ao invés do DOM do navegador ou JSDOM?
Use Cheerio para análise HTML server-side, web scraping e manipulação estática de HTML. É ideal quando você precisa de sintaxe similar ao jQuery sem overhead de navegador. Escolha DOM do navegador para interações client-side, JSDOM para simulação completa de navegador, ou Puppeteer para scraping de conteúdo dinâmico.
// Perfect for server-side scraping
const $ = cheerio.load(htmlResponse);
const titles = $('h1, h2, h3').map((i, el) => $(el).text()).get();
// Great for email template processing
const emailHtml = cheerio.load(template);
emailHtml('.username').text(user.name);
emailHtml('.content').html(processedContent);
Como lidar com diferentes parsers HTML no Cheerio?
O Cheerio suporta tanto htmlparser2 (rápido, tolerante) quanto parse5 (compatível com padrões). A escolha depende das suas necessidades: use htmlparser2 para velocidade e flexibilidade com HTML malformado, ou parse5 para conformidade estrita com HTML5.
// Using htmlparser2 (default, faster)
const $ = cheerio.load(html, {
xml: false,
decodeEntities: true
});
// Using parse5 (more compliant)
const $strict = cheerio.load(html, {
_useHtmlParser2: false,
xml: false
});
// For XML documents
const $xml = cheerio.load(xmlString, {
xmlMode: true,
decodeEntities: true
});
Qual é a diferença entre .attr(), .prop(), e .data()?
.attr()gerencia atributos HTML como strings.prop()lida com propriedades DOM com coerção de tipo e valores computados.data()gerencia atributos de dados HTML5 com análise automática de JSON
const $ = cheerio.load('<input type="checkbox" checked data-config=\'{"enabled": true}\'>');
// Attributes (string values)
$('input').attr('checked'); // 'checked'
$('input').attr('type'); // 'checkbox'
// Properties (computed/coerced values)
$('input').prop('checked'); // true (boolean)
$('input').prop('tagName'); // 'INPUT'
// Data attributes (with JSON parsing)
$('input').data('config'); // { enabled: true } (object)
Como lidar adequadamente com tipos TypeScript no Cheerio?
Importe tipos explicitamente e use parâmetros genéricos para melhor segurança de tipos. A biblioteca fornece suporte abrangente ao TypeScript com inferência de tipos adequada.
import * as cheerio from 'cheerio';
import type { CheerioAPI, Cheerio, Element } from 'cheerio';
// Type the main API
const $: CheerioAPI = cheerio.load('<div>Content</div>');
// Type specific selections
const $elements: Cheerio<Element> = $('div');
// Use proper typing for element extraction
const elements: Element[] = $('div').get();
const firstElement: Element | undefined = $('div').get(0);
// Type function parameters correctly
$('div').each(function(this: Element, index: number) {
// 'this' is properly typed as Element
const $this = $(this);
});
Por que estou recebendo erros "Cannot read property of undefined"?
Isso geralmente acontece quando seletores não correspondem a nenhum elemento. Sempre verifique se os elementos existem antes de encadear métodos ou acessar propriedades.
// ❌ Dangerous - may throw if no elements found
const title = $('.title').text().toUpperCase();
// ✅ Safe approach
const $title = $('.title');
const title = $title.length > 0 ? $title.text().toUpperCase() : '';
// ✅ Alternative with optional chaining
const title = $('.title').first().text() || '';
// ✅ Check before manipulating
if ($('.content').length > 0) {
$('.content').addClass('processed');
}
Como lidar com documentos HTML ou XML malformados?
O Cheerio é tolerante com HTML malformado ao usar htmlparser2. Para análise estrita, use o parser parse5 ou habilite o modo XML para documentos XML bem formados.
// Forgiving HTML parsing (default)
const $ = cheerio.load('<div><p>Unclosed paragraph</div>');
// Strict XML parsing
const $xml = cheerio.load('<root><item/></root>', {
xmlMode: true,
withStartIndices: false,
withEndIndices: false
});
// Handle parsing errors gracefully
try {
const $ = cheerio.load(possiblyBadHTML);
return $('title').text();
} catch (error) {
console.error('HTML parsing failed:', error);
return '';
}
Como posso processar documentos HTML grandes de forma eficiente?
Para documentos grandes, use APIs de streaming para evitar carregar tudo na memória de uma só vez. Isso é especialmente importante para web scraping ou processamento de arquivos grandes.
import * as cheerio from 'cheerio';
import { createReadStream } from 'fs';
// Stream processing for large files
const stream = cheerio.stringStream({}, (err, $) => {
if (err) throw err;
// Process the document
const data = $('h1, h2, h3').map((i, el) => $(el).text()).get();
console.log(data);
});
createReadStream('large-file.html', { encoding: 'utf8' }).pipe(stream);
// For URLs with automatic encoding detection
const $ = await cheerio.fromURL('https://example.com', {
encoding: { defaultEncoding: 'utf8' }
});
Quais são as implicações de memória ao usar Cheerio?
O Cheerio cria representações DOM leves que usam menos memória que DOMs completos de navegador. No entanto, seja consciente ao manter referências a documentos grandes ou criar muitas instâncias Cheerio simultaneamente.
// ✅ Good - reuse the same instance
const $ = cheerio.load(html);
const results = [];
$('article').each((i, article) => {
const $article = $(article);
results.push({
title: $article.find('h1').text(),
content: $article.find('.content').text()
});
});
// ❌ Avoid - creates many instances
const articles = $('article').map((i, article) => {
return cheerio.load(article); // Don't do this
}).get();
Como clonar elementos sem quebrar referências?
Use o método .clone() para criar cópias profundas de elementos. Isso é essencial quando você precisa reutilizar elementos várias vezes ou evitar modificar elementos originais.
const $ = cheerio.load('<div class="template">Template content</div>');
// Clone before modifying
const $template = $('.template');
const $copy1 = $template.clone().addClass('instance-1').text('Instance 1');
const $copy2 = $template.clone().addClass('instance-2').text('Instance 2');
// Original remains unchanged
console.log($template.text()); // 'Template content'
// Append clones to different parents
$('#container1').append($copy1);
$('#container2').append($copy2);
Como posso extrair dados estruturados de HTML de forma eficiente?
Use o método .extract() para padrões complexos de extração de dados. Ele fornece uma maneira declarativa de extrair múltiplos valores de documentos com suporte adequado ao TypeScript.
const $ = cheerio.load(productPageHtml);
// Extract structured data with type safety
const productData = $.root().extract({
title: 'h1.product-title',
price: '.price .amount',
images: [{ selector: '.gallery img', value: 'src' }],
features: ['.features li'],
specifications: {
selector: '.specs',
value: {
weight: '.weight',
dimensions: '.dimensions',
model: { selector: '.model', value: 'data-model' }
}
}
});
// Result is properly typed
console.log(productData.title); // string | undefined
console.log(productData.images); // string[]
console.log(productData.specifications?.model); // string | undefined
Quais são as melhores práticas para performance de seletores CSS?
Use seletores específicos e evite consultas excessivamente complexas. Seletores ID são os mais rápidos, seguidos por seletores de classe, depois seletores de atributo. Evite seletores descendentes profundos quando possível.
// ✅ Fast - specific selectors
const $navItems = $('#navigation .nav-item');
const $activeButton = $('.btn.active');
// ❌ Slower - overly complex selectors
const $badSelector = $('div > div > div span.small[data-type="special"]');
// ✅ Better - break down complex selections
const $container = $('.content-area');
const $items = $container.find('[data-type="special"]');
// ✅ Cache frequently used selections
const $document = $.root();
const $body = $document.find('body');
Como lidar adequadamente com dados de formulário e serialização?
Use .serializeArray() para dados estruturados e .serialize() para strings codificadas em URL. Esses métodos lidam automaticamente com regras de validação de formulário e tipos de elementos.
const $ = cheerio.load(formHtml);
// Get structured form data
const formData = $('form').serializeArray();
// [{ name: 'email', value: 'user@example.com' }, ...]
// Get URL-encoded string
const queryString = $('form').serialize();
// 'email=user@example.com&name=John'
// Handle specific form elements
const selectedOptions = $('select[multiple]').val(); // string[]
const checkboxValue = $('input[type="checkbox"]:checked').val(); // string | undefined
// Set form values programmatically
$('input[name="email"]').val('new@example.com');
$('select').val(['option1', 'option2']); // for multiple select
Como posso modificar atributos HTML de forma segura para prevenir XSS?
O Cheerio codifica automaticamente valores de atributos para prevenir ataques XSS. No entanto, seja cauteloso com inserção de conteúdo HTML e sempre valide entrada do usuário.
const $ = cheerio.load('<div></div>');
// ✅ Safe - attributes are automatically encoded
const userInput = '<script>alert("XSS")</script>';
$('div').attr('title', userInput);
// Result: <div title="<script>alert("XSS")</script>"></div>
// ✅ Safe text insertion
$('div').text(userInput); // Automatically escaped
// ❌ Dangerous - raw HTML insertion
$('div').html(userInput); // Don't do this with user input
// ✅ Better - sanitize first or use text()
$('div').text(sanitizeInput(userInput));
Qual é a forma correta de lidar com operações assíncronas no Cheerio?
O Cheerio em si é síncrono, mas você pode combiná-lo com operações async para tarefas como buscar URLs ou processar múltiplos documentos simultaneamente.
// Load from URL (async)
const $ = await cheerio.fromURL('https://example.com');
const title = $('title').text();
// Process multiple URLs concurrently
const urls = ['https://site1.com', 'https://site2.com'];
const results = await Promise.all(
urls.map(async (url) => {
const $ = await cheerio.fromURL(url);
return {
url,
title: $('title').text(),
links: $('a[href]').map((i, el) => $(el).attr('href')).get()
};
})
);
// Combine with other async operations
async function processDocument(html: string) {
const $ = cheerio.load(html);
// Extract image URLs
const imageUrls = $('img[src]').map((i, el) => $(el).attr('src')).get();
// Process images asynchronously
const processedImages = await Promise.all(
imageUrls.map(url => processImage(url))
);
return { processedImages };
}