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

Guides Tutoriels Complets Cheerio

Guide 1 : Comment Extraire des Données de Tableaux HTML avec Cheerio

Le scraping de données de tableaux web est l'une des tâches les plus courantes lors du travail avec des documents HTML. Cheerio facilite grandement l'analyse des structures de tableaux et l'extraction de données significatives. Ce guide vous accompagnera à travers diverses techniques pour extraire des données de tableaux HTML en utilisant Cheerio.

Configuration de Votre Environnement

D'abord, installez Cheerio dans votre projet :

npm install cheerio

Comprendre la Structure de Base des Tableaux

Avant de plonger dans les techniques d'extraction, comprenons une structure typique de tableau HTML :

<table id="products">
  <thead>
    <tr>
      <th>Product Name</th>
      <th>Price</th>
      <th>Stock</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Laptop</td>
      <td>$999</td>
      <td>15</td>
    </tr>
    <tr>
      <td>Mouse</td>
      <td>$25</td>
      <td>50</td>
    </tr>
  </tbody>
</table>

Étape 1 : Chargement du HTML et Sélection de Base des Tableaux

Commencez par charger votre contenu HTML avec Cheerio :

import * as cheerio from 'cheerio';

const html = `
<table id="products">
  <thead>
    <tr>
      <th>Product Name</th>
      <th>Price</th>
      <th>Stock</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Laptop</td>
      <td>$999</td>
      <td>15</td>
    </tr>
    <tr>
      <td>Mouse</td>
      <td>$25</td>
      <td>50</td>
    </tr>
  </tbody>
</table>
`;

const $ = cheerio.load(html);

Étape 2 : Extraction des En-têtes de Tableau

Les en-têtes de tableau fournissent la structure pour vos données. Extrayez-les en premier :

const headers: string[] = [];
$('#products thead th').each((index, element) => {
  headers.push($(element).text().trim());
});

console.log('Headers:', headers);
// Output: ['Product Name', 'Price', 'Stock']

Étape 3 : Extraction des Données de Lignes

Maintenant extrayez les données réelles du tableau. Il existe plusieurs approches selon vos besoins :

Méthode 1 : Extraction ligne par ligne

const rows: string[][] = [];
$('#products tbody tr').each((index, row) => {
  const rowData: string[] = [];
  $(row).find('td').each((cellIndex, cell) => {
    rowData.push($(cell).text().trim());
  });
  rows.push(rowData);
});

console.log('Rows:', rows);
// Output: [['Laptop', '$999', '15'], ['Mouse', '$25', '50']]

Méthode 2 : Création d'objets structurés

interface Product {
  productName: string;
  price: string;
  stock: number;
}

const products: Product[] = [];
$('#products tbody tr').each((index, row) => {
  const cells = $(row).find('td');
  const product: Product = {
    productName: $(cells[0]).text().trim(),
    price: $(cells[1]).text().trim(),
    stock: parseInt($(cells[2]).text().trim())
  };
  products.push(product);
});

console.log('Products:', products);

Étape 4 : Gestion des Tableaux Complexes

Les tableaux du monde réel ont souvent des cellules fusionnées, des éléments imbriqués, ou un formatage spécial. Voici comment les gérer :

const complexHtml = `
<table class="sales-data">
  <tr>
    <td rowspan="2">Q1</td>
    <td>January</td>
    <td>$<span class="amount">15000</span></td>
    <td class="status success">✓</td>
  </tr>
  <tr>
    <td>February</td>
    <td>$<span class="amount">18000</span></td>
    <td class="status pending">⏳</td>
  </tr>
</table>
`;

const $complex = cheerio.load(complexHtml);

const salesData = [];
$complex('.sales-data tr').each((index, row) => {
  const cells = $complex(row).find('td');
  const record = {
    quarter: cells.length === 4 ? $complex(cells[0]).text() : 'Q1', // Handle rowspan
    month: $complex(cells[cells.length === 4 ? 1 : 0]).text(),
    amount: $complex(cells[cells.length === 4 ? 2 : 1]).find('.amount').text(),
    status: $complex(cells[cells.length === 4 ? 3 : 2]).attr('class')?.includes('success') ? 'Complete' : 'Pending'
  };
  salesData.push(record);
});

Étape 5 : Filtrage Avancé et Traitement des Données

Utilisez les sélecteurs puissants de Cheerio pour filtrer et traiter vos données :

// Extract only rows with specific conditions
const highStockProducts = [];
$('#products tbody tr').each((index, row) => {
  const stock = parseInt($(row).find('td:nth-child(3)').text());
  if (stock > 20) {
    highStockProducts.push({
      name: $(row).find('td:first-child').text(),
      stock: stock
    });
  }
});

// Extract data using attribute selectors
$('table[data-category="electronics"] tbody tr').each((index, row) => {
  // Process electronics category tables only
});

Exemple Complet Fonctionnel

Voici un exemple complet qui démontre l'extraction de données de tableau :

import * as cheerio from 'cheerio';

// Sample HTML with a product catalog table
const html = `
<!DOCTYPE html>
<html>
<body>
  <table id="product-catalog" class="data-table">
    <thead>
      <tr>
        <th>ID</th>
        <th>Product Name</th>
        <th>Category</th>
        <th>Price</th>
        <th>Stock</th>
        <th>Rating</th>
      </tr>
    </thead>
    <tbody>
      <tr data-id="1">
        <td>001</td>
        <td><a href="/laptop-pro">Laptop Pro</a></td>
        <td>Electronics</td>
        <td>$<span class="price">1299</span></td>
        <td class="stock-high">25</td>
        <td><span class="rating" data-score="4.5">★★★★☆</span></td>
      </tr>
      <tr data-id="2">
        <td>002</td>
        <td><a href="/wireless-mouse">Wireless Mouse</a></td>
        <td>Electronics</td>
        <td>$<span class="price">35</span></td>
        <td class="stock-medium">12</td>
        <td><span class="rating" data-score="4.2">★★★★☆</span></td>
      </tr>
      <tr data-id="3">
        <td>003</td>
        <td><a href="/desk-lamp">LED Desk Lamp</a></td>
        <td>Office</td>
        <td>$<span class="price">89</span></td>
        <td class="stock-low">3</td>
        <td><span class="rating" data-score="4.7">★★★★★</span></td>
      </tr>
    </tbody>
  </table>
</body>
</html>
`;

interface Product {
  id: string;
  name: string;
  category: string;
  price: number;
  stock: number;
  rating: number;
  url: string;
  stockLevel: 'low' | 'medium' | 'high';
}

function extractTableData(html: string): Product[] {
  const $ = cheerio.load(html);
  const products: Product[] = [];

  $('#product-catalog tbody tr').each((index, row) => {
    const $row = $(row);
    
    // Extract basic data
    const id = $row.find('td:nth-child(1)').text().trim();
    const nameElement = $row.find('td:nth-child(2) a');
    const name = nameElement.text().trim();
    const url = nameElement.attr('href') || '';
    const category = $row.find('td:nth-child(3)').text().trim();
    
    // Extract and parse price
    const priceText = $row.find('.price').text();
    const price = parseFloat(priceText);
    
    // Extract stock with level detection
    const stockCell = $row.find('td:nth-child(5)');
    const stock = parseInt(stockCell.text().trim());
    let stockLevel: 'low' | 'medium' | 'high' = 'medium';
    
    if (stockCell.hasClass('stock-low')) stockLevel = 'low';
    else if (stockCell.hasClass('stock-high')) stockLevel = 'high';
    
    // Extract rating
    const rating = parseFloat($row.find('.rating').attr('data-score') || '0');
    
    products.push({
      id,
      name,
      category,
      price,
      stock,
      rating,
      url,
      stockLevel
    });
  });

  return products;
}

// Usage
const products = extractTableData(html);
console.log('Extracted Products:', JSON.stringify(products, null, 2));

// Additional processing examples
const highRatedProducts = products.filter(p => p.rating >= 4.5);
const lowStockProducts = products.filter(p => p.stockLevel === 'low');
const expensiveProducts = products.filter(p => p.price > 100);

console.log(`Found ${highRatedProducts.length} high-rated products`);
console.log(`Found ${lowStockProducts.length} low-stock products`);
console.log(`Found ${expensiveProducts.length} expensive products`);

Cette approche complète gère les structures de tableaux complexes, extrait divers types de données, et fournit une base pour toute tâche de scraping de tableaux avec Cheerio.


Guide 2 : Comment Scraper les Données de Formulaires et les Valeurs d'Entrée avec Cheerio

Les formulaires sont des composants essentiels des pages web, contenant des données précieuses comme les saisies utilisateur, les sélections et les configurations. Ce guide démontre comment extraire les données de formulaires, les valeurs d'entrée et les structures de formulaires en utilisant les puissantes capacités de manipulation de formulaires de Cheerio.

Comprendre les Éléments de Formulaire

Les formulaires contiennent divers types d'entrée qui nécessitent différentes approches d'extraction :

<form id="user-registration">
  <input type="text" name="username" value="john_doe">
  <input type="email" name="email" value="john@example.com">
  <input type="password" name="password" value="secret123">
  <input type="checkbox" name="newsletter" checked>
  <select name="country">
    <option value="us" selected>United States</option>
    <option value="ca">Canada</option>
  </select>
  <textarea name="bio">Software developer...</textarea>
</form>

Étape 1 : Configuration de l'Extraction des Données de Formulaire

Commencez par charger votre HTML et comprendre la structure du formulaire :

import * as cheerio from 'cheerio';

const formHtml = `
<form id="contact-form" method="post" action="/submit">
  <div class="form-group">
    <label for="name">Full Name:</label>
    <input type="text" id="name" name="fullName" value="Jane Smith" required>
  </div>
  
  <div class="form-group">
    <label for="email">Email:</label>
    <input type="email" id="email" name="email" value="jane@company.com">
  </div>
  
  <div class="form-group">
    <label>Gender:</label>
    <input type="radio" name="gender" value="male" id="male">
    <label for="male">Male</label>
    <input type="radio" name="gender" value="female" id="female" checked>
    <label for="female">Female</label>
  </div>
  
  <div class="form-group">
    <label for="interests">Interests:</label>
    <input type="checkbox" name="interests" value="coding" checked>
    <label>Coding</label>
    <input type="checkbox" name="interests" value="design">
    <label>Design</label>
    <input type="checkbox" name="interests" value="marketing" checked>
    <label>Marketing</label>
  </div>
  
  <div class="form-group">
    <label for="country">Country:</label>
    <select name="country" id="country">
      <option value="">Select Country</option>
      <option value="us" selected>United States</option>
      <option value="uk">United Kingdom</option>
      <option value="ca">Canada</option>
    </select>
  </div>
  
  <div class="form-group">
    <label for="message">Message:</label>
    <textarea name="message" id="message" rows="4">Hello, I'm interested in your services...</textarea>
  </div>
  
  <button type="submit">Submit</button>
</form>
`;

const $ = cheerio.load(formHtml);

Étape 2 : Extraction des Valeurs d'Entrée Texte

Les entrées texte, champs email et mots de passe peuvent être extraits en utilisant la méthode val() :

// Extract individual input values
const fullName = $('input[name="fullName"]').val();
const email = $('input[name="email"]').val();

console.log('Full Name:', fullName); // "Jane Smith"
console.log('Email:', email); // "jane@company.com"

// Extract all text-type inputs at once
const textInputs: Record<string, string> = {};
$('input[type="text"], input[type="email"], input[type="password"]').each((index, element) => {
  const $input = $(element);
  const name = $input.attr('name');
  const value = $input.val() as string;
  
  if (name) {
    textInputs[name] = value || '';
  }
});

console.log('Text Inputs:', textInputs);

Étape 3 : Gestion des Boutons Radio

Les boutons radio nécessitent de vérifier quelle option est sélectionnée :

// Get selected radio button value
const selectedGender = $('input[name="gender"]:checked').val();
console.log('Selected Gender:', selectedGender); // "female"

// Get all radio button options for a field
const genderOptions: { value: string; label: string; checked: boolean }[] = [];
$('input[name="gender"]').each((index, element) => {
  const $radio = $(element);
  const value = $radio.val() as string;
  const isChecked = $radio.prop('checked') as boolean;
  const label = $radio.next('label').text() || $radio.attr('id') || '';
  
  genderOptions.push({
    value,
    label: label.trim(),
    checked: isChecked
  });
});

console.log('Gender Options:', genderOptions);

Étape 4 : Travailler avec les Cases à Cocher

Les cases à cocher peuvent avoir plusieurs valeurs sélectionnées :

// Get all checked checkbox values for a field
const selectedInterests: string[] = [];
$('input[name="interests"]:checked').each((index, element) => {
  selectedInterests.push($(element).val() as string);
});

console.log('Selected Interests:', selectedInterests); // ["coding", "marketing"]

// Get detailed checkbox information
const interestOptions = [];
$('input[name="interests"]').each((index, element) => {
  const $checkbox = $(element);
  const value = $checkbox.val() as string;
  const isChecked = $checkbox.prop('checked') as boolean;
  const label = $checkbox.next('label').text().trim();
  
  interestOptions.push({
    value,
    label,
    checked: isChecked
  });
});

Étape 5 : Extraction des Valeurs de Listes Déroulantes Select

Les éléments select nécessitent une gestion spéciale pour les options :

// Get selected option value
const selectedCountry = $('select[name="country"]').val();
console.log('Selected Country:', selectedCountry); // "us"

// Get selected option text
const selectedCountryText = $('select[name="country"] option:selected').text();
console.log('Selected Country Text:', selectedCountryText); // "United States"

// Get all select options
const countryOptions: { value: string; text: string; selected: boolean }[] = [];
$('select[name="country"] option').each((index, element) => {
  const $option = $(element);
  const value = $option.val() as string;
  const text = $option.text().trim();
  const selected = $option.prop('selected') as boolean;
  
  countryOptions.push({ value, text, selected });
});

console.log('Country Options:', countryOptions);

Étape 6 : Gestion des Éléments Textarea

Les textareas contiennent leur contenu comme texte, pas dans un attribut value :

// Extract textarea content
const message = $('textarea[name="message"]').text();
console.log('Message:', message); // "Hello, I'm interested in your services..."

// Alternative method using val()
const messageAlt = $('textarea[name="message"]').val();
console.log('Message (alt):', messageAlt);

Étape 7 : Validation de Formulaires et Extraction de Métadonnées

Extrayez les métadonnées de formulaire et les règles de validation :

interface FormMetadata {
  action: string;
  method: string;
  enctype?: string;
  fieldCount: number;
  requiredFields: string[];
}

function extractFormMetadata(formSelector: string): FormMetadata {
  const $form = $(formSelector);
  
  const action = $form.attr('action') || '';
  const method = ($form.attr('method') || 'get').toLowerCase();
  const enctype = $form.attr('enctype');
  
  // Count form fields
  const fieldCount = $form.find('input, select, textarea').length;
  
  // Find required fields
  const requiredFields: string[] = [];
  $form.find('input[required], select[required], textarea[required]').each((index, element) => {
    const name = $(element).attr('name');
    if (name) requiredFields.push(name);
  });
  
  return {
    action,
    method: method as 'get' | 'post',
    enctype,
    fieldCount,
    requiredFields
  };
}

const formMetadata = extractFormMetadata('#contact-form');
console.log('Form Metadata:', formMetadata);

Étape 8 : Sérialisation Complète des Données de Formulaire

Utilisez les méthodes de sérialisation intégrées de Cheerio :

// Using Cheerio's serialize method
const serializedData = $('#contact-form').serialize();
console.log('Serialized Form:', serializedData);

// Using serializeArray for structured data
const formArray = $('#contact-form').serializeArray();
console.log('Form Array:', formArray);

// Convert to object format
const formObject: Record<string, string | string[]> = {};
formArray.forEach(field => {
  if (formObject[field.name]) {
    // Handle multiple values (checkboxes)
    if (Array.isArray(formObject[field.name])) {
      (formObject[field.name] as string[]).push(field.value);
    } else {
      formObject[field.name] = [formObject[field.name] as string, field.value];
    }
  } else {
    formObject[field.name] = field.value;
  }
});

Exemple Complet Fonctionnel

Voici une solution complète d'extraction de données de formulaire :

import * as cheerio from 'cheerio';

interface FormData {
  textFields: Record<string, string>;
  radioButtons: Record<string, string>;
  checkboxes: Record<string, string[]>;
  selects: Record<string, { value: string; text: string }>;
  textareas: Record<string, string>;
  metadata: {
    action: string;
    method: string;
    fieldCount: number;
    requiredFields: string[];
  };
}

const complexFormHtml = `
<form id="survey-form" action="/submit-survey" method="post">
  <fieldset>
    <legend>Personal Information</legend>
    <input type="text" name="firstName" value="John" required>
    <input type="text" name="lastName" value="Doe" required>
    <input type="email" name="email" value="john.doe@email.com" required>
    <input type="tel" name="phone" value="+1-555-123-4567">
  </fieldset>
  
  <fieldset>
    <legend>Preferences</legend>
    <div>
      <p>Preferred Contact Method:</p>
      <input type="radio" name="contactMethod" value="email" checked>
      <label>Email</label>
      <input type="radio" name="contactMethod" value="phone">
      <label>Phone</label>
      <input type="radio" name="contactMethod" value="mail">
      <label>Mail</label>
    </div>
    
    <div>
      <p>Interests (select all that apply):</p>
      <input type="checkbox" name="interests" value="technology" checked>
      <label>Technology</label>
      <input type="checkbox" name="interests" value="sports">
      <label>Sports</label>
      <input type="checkbox" name="interests" value="music" checked>
      <label>Music</label>
      <input type="checkbox" name="interests" value="travel">
      <label>Travel</label>
    </div>
  </fieldset>
  
  <fieldset>
    <legend>Location</legend>
    <select name="country" required>
      <option value="">Select Country</option>
      <option value="us" selected>United States</option>
      <option value="ca">Canada</option>
      <option value="uk">United Kingdom</option>
      <option value="au">Australia</option>
    </select>
    
    <select name="timezone">
      <option value="est">Eastern Time</option>
      <option value="cst" selected>Central Time</option>
      <option value="mst">Mountain Time</option>
      <option value="pst">Pacific Time</option>
    </select>
  </fieldset>
  
  <fieldset>
    <legend>Additional Information</legend>
    <textarea name="comments" rows="4">Looking forward to hearing from you!</textarea>
    <textarea name="suggestions" placeholder="Any suggestions?"></textarea>
  </fieldset>
  
  <button type="submit">Submit Survey</button>
  <button type="reset">Reset Form</button>
</form>
`;

function extractCompleteFormData(html: string, formSelector: string): FormData {
  const $ = cheerio.load(html);
  const $form = $(formSelector);
  
  // Extract text fields
  const textFields: Record<string, string> = {};
  $form.find('input[type="text"], input[type="email"], input[type="tel"], input[type="password"]').each((_, element) => {
    const $input = $(element);
    const name = $input.attr('name');
    const value = $input.val() as string;
    if (name) textFields[name] = value || '';
  });
  
  // Extract radio buttons
  const radioButtons: Record<string, string> = {};
  const radioGroups = new Set<string>();
  $form.find('input[type="radio"]').each((_, element) => {
    const name = $(element).attr('name');
    if (name) radioGroups.add(name);
  });
  
  radioGroups.forEach(groupName => {
    const selectedValue = $form.find(`input[name="${groupName}"]:checked`).val() as string;
    if (selectedValue) radioButtons[groupName] = selectedValue;
  });
  
  // Extract checkboxes
  const checkboxes: Record<string, string[]> = {};
  const checkboxGroups = new Set<string>();
  $form.find('input[type="checkbox"]').each((_, element) => {
    const name = $(element).attr('name');
    if (name) checkboxGroups.add(name);
  });
  
  checkboxGroups.forEach(groupName => {
    const values: string[] = [];
    $form.find(`input[name="${groupName}"]:checked`).each((_, element) => {
      values.push($(element).val() as string);
    });
    checkboxes[groupName] = values;
  });
  
  // Extract selects
  const selects: Record<string, { value: string; text: string }> = {};
  $form.find('select').each((_, element) => {
    const $select = $(element);
    const name = $select.attr('name');
    if (name) {
      const $selectedOption = $select.find('option:selected');
      selects[name] = {
        value: $selectedOption.val() as string || '',
        text: $selectedOption.text().trim()
      };
    }
  });
  
  // Extract textareas
  const textareas: Record<string, string> = {};
  $form.find('textarea').each((_, element) => {
    const $textarea = $(element);
    const name = $textarea.attr('name');
    if (name) {
      textareas[name] = $textarea.val() as string || '';
    }
  });
  
  // Extract metadata
  const metadata = {
    action: $form.attr('action') || '',
    method: ($form.attr('method') || 'get').toLowerCase(),
    fieldCount: $form.find('input, select, textarea, button').length,
    requiredFields: $form.find('[required]').map((_, el) => $(el).attr('name')).get().filter(Boolean)
  };
  
  return {
    textFields,
    radioButtons,
    checkboxes,
    selects,
    textareas,
    metadata
  };
}

// Usage
const formData = extractCompleteFormData(complexFormHtml, '#survey-form');

console.log('=== EXTRACTED FORM DATA ===');
console.log('Text Fields:', formData.textFields);
console.log('Radio Buttons:', formData.radioButtons);
console.log('Checkboxes:', formData.checkboxes);
console.log('Select Fields:', formData.selects);
console.log('Textareas:', formData.textareas);
console.log('Metadata:', formData.metadata);

// Additional utility functions
function validateFormData(data: FormData): { isValid: boolean; errors: string[] } {
  const errors: string[] = [];
  
  // Check required fields
  data.metadata.requiredFields.forEach(fieldName => {
    if (!data.textFields[fieldName] && 
        !data.radioButtons[fieldName] && 
        !data.selects[fieldName]?.value) {
      errors.push(`Required field '${fieldName}' is missing`);
    }
  });
  
  return {
    isValid: errors.length === 0,
    errors
  };
}

const validation = validateFormData(formData);
console.log('Validation Result:', validation);

Cette approche complète gère tous les éléments de formulaire courants et fournit une extraction de données structurées avec des capacités de validation, la rendant parfaite pour l'analyse de formulaires et les tâches de traitement de données.


Guide 3 : Comment Naviguer et Modifier les Éléments DOM avec Cheerio

La navigation et modification DOM sont des aspects centraux du web scraping et de la manipulation HTML. Ce guide démontre comment traverser efficacement l'arbre DOM, trouver des éléments liés, et modifier le contenu en utilisant les puissantes méthodes de navigation de Cheerio.

Comprendre la Structure de l'Arbre DOM

Avant de plonger dans les techniques de navigation, il est important de comprendre la nature hiérarchique du HTML :

<div class="container">           <!-- Parent -->
  <header class="main-header">    <!-- First child -->
    <h1>Page Title</h1>           <!-- Grandchild -->
    <nav>Navigation</nav>         <!-- Sibling to h1 -->
  </header>
  <main class="content">          <!-- Next sibling to header -->
    <article>Article content</article>
    <aside>Sidebar</aside>
  </main>
  <footer>Footer content</footer> <!-- Last child -->
</div>

Étape 1 : Sélection d'Éléments et Navigation de Base

Commencez avec les méthodes de navigation fondamentales :

import * as cheerio from 'cheerio';

const html = `
<div class="blog-post" data-id="123">
  <header class="post-header">
    <h1 class="post-title">Understanding Web Scraping</h1>
    <div class="post-meta">
      <span class="author">John Smith</span>
      <time class="published" datetime="2024-01-15">January 15, 2024</time>
      <div class="tags">
        <span class="tag">web-scraping</span>
        <span class="tag">javascript</span>
        <span class="tag">cheerio</span>
      </div>
    </div>
  </header>
  
  <div class="post-content">
    <p class="intro">Web scraping is a powerful technique...</p>
    <p>In this article, we'll explore...</p>
    <blockquote>
      <p>"Data is the new oil of the digital economy."</p>
      <cite>— Industry Expert</cite>
    </blockquote>
    <p class="conclusion">To summarize...</p>
  </div>
  
  <footer class="post-footer">
    <div class="social-share">
      <button class="share-btn twitter" data-url="https://example.com/post/123">Twitter</button>
      <button class="share-btn facebook" data-url="https://example.com/post/123">Facebook</button>
      <button class="share-btn linkedin" data-url="https://example.com/post/123">LinkedIn</button>
    </div>
    <div class="post-actions">
      <button class="like-btn" data-likes="42">❤️ 42</button>
      <button class="comment-btn" data-comments="8">💬 8</button>
    </div>
  </footer>
</div>
`;

const $ = cheerio.load(html);

// Basic selection
const postTitle = $('.post-title').text();
console.log('Post Title:', postTitle);

// Navigate to parent
const postHeader = $('.post-title').parent();
console.log('Parent class:', postHeader.attr('class')); // "post-header"

// Navigate to closest ancestor with specific selector
const blogPostContainer = $('.post-title').closest('.blog-post');
console.log('Container data-id:', blogPostContainer.attr('data-id')); // "123"

Étape 2 : Navigation entre Éléments Frères

Naviguez efficacement entre les éléments frères :

// Get next sibling
const titleNextSibling = $('.post-title').next();
console.log('Next sibling class:', titleNextSibling.attr('class')); // "post-meta"

// Get all following siblings
const allFollowingSiblings = $('.post-header').nextAll();
console.log('Following siblings count:', allFollowingSiblings.length); // 2

// Get previous sibling
const metaPrevSibling = $('.post-meta').prev();
console.log('Previous sibling tag:', metaPrevSibling.get(0)?.tagName); // "h1"

// Get all preceding siblings
const allPrecedingSiblings = $('.post-footer').prevAll();
console.log('Preceding siblings count:', allPrecedingSiblings.length); // 2

// Get all siblings
const headerSiblings = $('.post-header').siblings();
headerSiblings.each((index, element) => {
  console.log(`Sibling ${index + 1}:`, $(element).attr('class'));
});

Étape 3 : Navigation des Enfants et Descendants

Travaillez avec les éléments enfants et les descendants profonds :

// Get direct children
const postContentChildren = $('.post-content').children();
console.log('Direct children count:', postContentChildren.length);

// Get first child
const firstChild = $('.post-content').children().first();
console.log('First child class:', firstChild.attr('class')); // "intro"

// Get last child