DE EN ES FR ID JA KO PT RU TH VI ZH

Cheerio FAQ

Seberapa cepat Cheerio dibandingkan dengan library parsing HTML lainnya?

Cheerio dirancang untuk kecepatan dan efisiensi. Library ini menggunakan model DOM yang ringan berbasis domhandler, yang jauh lebih cepat dibandingkan implementasi DOM browser lengkap seperti JSDOM. Tidak seperti solusi berbasis browser, Cheerio menghilangkan inkonsistensi DOM dan overhead browser, menghasilkan operasi parsing dan manipulasi yang sangat cepat.

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());

Untuk dokumen berukuran besar atau pemrosesan batch, pertimbangkan untuk menggunakan streaming API seperti cheerio.stringStream() untuk penggunaan memori yang optimal.

Kapan saya harus menggunakan Cheerio daripada DOM browser atau JSDOM?

Gunakan Cheerio untuk parsing HTML di sisi server, web scraping, dan manipulasi HTML statis. Library ini ideal ketika Anda membutuhkan sintaks seperti jQuery tanpa overhead browser. Pilih DOM browser untuk interaksi sisi klien, JSDOM untuk simulasi browser lengkap, atau Puppeteer untuk scraping konten dinamis.

// 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);

Bagaimana cara menangani parser HTML yang berbeda di Cheerio?

Cheerio mendukung htmlparser2 (cepat, toleran) dan parse5 (sesuai standar). Pilihan tergantung pada kebutuhan Anda: gunakan htmlparser2 untuk kecepatan dan fleksibilitas dengan HTML yang tidak valid, atau parse5 untuk kepatuhan ketat 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
});

Apa perbedaan antara .attr(), .prop(), dan .data()?

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)

Bagaimana cara menangani tipe TypeScript dengan benar di Cheerio?

Import tipe secara eksplisit dan gunakan parameter generik untuk keamanan tipe yang lebih baik. Library ini menyediakan dukungan TypeScript yang komprehensif dengan inferensi tipe yang tepat.

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);
});

Mengapa saya mendapat error "Cannot read property of undefined"?

Hal ini biasanya terjadi ketika selector tidak cocok dengan elemen manapun. Selalu periksa apakah elemen ada sebelum melakukan chaining method atau mengakses properti.

// ❌ 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');
}

Bagaimana cara menangani dokumen HTML atau XML yang tidak valid?

Cheerio toleran terhadap HTML yang tidak valid ketika menggunakan htmlparser2. Untuk parsing yang ketat, gunakan parser parse5 atau aktifkan mode XML untuk dokumen XML yang well-formed.

// 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 '';
}

Bagaimana cara memproses dokumen HTML berukuran besar secara efisien?

Untuk dokumen besar, gunakan streaming API untuk menghindari memuat semuanya ke memori sekaligus. Hal ini sangat penting untuk web scraping atau memproses file berukuran besar.

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' }
});

Apa implikasi memori dari penggunaan Cheerio?

Cheerio membuat representasi DOM ringan yang menggunakan memori lebih sedikit dibandingkan DOM browser lengkap. Namun, perhatikan penyimpanan referensi ke dokumen besar atau membuat banyak instance Cheerio secara bersamaan.

// ✅ 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();

Bagaimana cara meng-clone elemen tanpa merusak referensi?

Gunakan method .clone() untuk membuat salinan mendalam dari elemen. Ini penting ketika Anda perlu menggunakan elemen berulang kali atau menghindari modifikasi pada elemen asli.

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);

Bagaimana cara mengekstrak data terstruktur secara efisien dari HTML?

Gunakan method .extract() untuk pola ekstraksi data yang kompleks. Method ini menyediakan cara deklaratif untuk menarik berbagai nilai dari dokumen dengan dukungan TypeScript yang tepat.

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

Apa praktik terbaik untuk performa selector CSS?

Gunakan selector yang spesifik dan hindari query yang terlalu kompleks. Selector ID adalah yang tercepat, diikuti oleh selector class, kemudian selector atribut. Hindari selector descendant yang dalam jika memungkinkan.

// ✅ 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');

Bagaimana cara menangani data form dan serialisasi dengan benar?

Gunakan .serializeArray() untuk data terstruktur dan .serialize() untuk string yang di-encode URL. Method ini secara otomatis menangani aturan validasi form dan tipe elemen.

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

Bagaimana cara memodifikasi atribut HTML dengan aman untuk mencegah XSS?

Cheerio secara otomatis meng-encode nilai atribut untuk mencegah serangan XSS. Namun, berhati-hatilah dengan penyisipan konten HTML dan selalu validasi input pengguna.

const $ = cheerio.load('<div></div>');

// ✅ Safe - attributes are automatically encoded
const userInput = '<script>alert("XSS")</script>';
$('div').attr('title', userInput);
// Result: <div title="&lt;script&gt;alert(&quot;XSS&quot;)&lt;/script&gt;"></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));

Apa cara yang benar untuk menangani operasi asynchronous dengan Cheerio?

Cheerio sendiri bersifat synchronous, tetapi Anda dapat menggabungkannya dengan operasi async untuk tugas-tugas seperti mengambil URL atau memproses beberapa dokumen secara bersamaan.

// 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 };
}