Retour au blog
Guides
Mihai Maxim31 janvier 202311 min de lecture

Comment extraire les données d'un tableau HTML en JavaScript

Comment extraire les données d'un tableau HTML en JavaScript

Comprendre la structure d'un tableau HTML

Les tableaux HTML constituent un outil puissant pour baliser des données tabulaires structurées et les afficher d'une manière facile à lire et à comprendre pour les utilisateurs. Les tableaux sont composés de données organisées en lignes et en colonnes, et le HTML fournit plusieurs éléments différents pour définir et structurer ces données. Un tableau doit inclure au moins les éléments suivants : <table>, <tr> (ligne du tableau) et <td> (données du tableau). Pour plus de structure et de valeur sémantique, les tableaux peuvent également inclure l'élément <th> (en-tête de tableau), ainsi que les éléments <thead>, <tbody> et <tfoot>.

Explorons ces balises à l'aide d'un petit exemple.

Side-by-side code snippets comparing a basic HTML table to a version using thead, tbody, and tfoot sections

Remarquez comment le deuxième tableau utilise une syntaxe plus spécifique

Two small HTML tables side by side listing fruit and color rows for apple, banana, and a total

La balise <thead> appliquera une police en gras aux cellules « Fruit » et « Color » du deuxième tableau. À part cela, vous pouvez constater que les deux syntaxes permettent d’obtenir la même organisation des données.

Lorsque vous extrayez des tableaux du Web, il est important de garder à l'esprit que vous pouvez rencontrer des tableaux rédigés avec des degrés de spécificité sémantique variables. En d'autres termes, certains tableaux peuvent inclure des balises HTML plus détaillées et descriptives, tandis que d'autres peuvent utiliser une syntaxe plus simple et moins descriptive.

Extraction de tableaux HTML avec Node.js et cheerio

Bienvenue dans la partie amusante ! Nous avons découvert la structure et l'objectif des tableaux HTML, et il est maintenant temps de mettre ces connaissances en pratique. Notre cible pour ce tutoriel est le tableau des artistes les plus vendus de tous les temps, disponible sur https://chartmasters.org/best-selling-artists-of-all-time/. Nous commencerons par configurer notre environnement de travail et installer les bibliothèques nécessaires. Ensuite, nous explorerons le site web cible et définirons des sélecteurs pour extraire les données du tableau. Après cela, nous écrirons le code pour extraire les données, puis nous les exporterons vers différents formats tels que CSV et JSON.

Configuration de l&#x27;environnement de travail

Très bien, commençons notre tout nouveau projet ! Avant de commencer, assurez-vous que Node.js est bien installé. Vous pouvez le télécharger sur https://nodejs.org/en/.

Ouvrez maintenant votre éditeur de code préféré, accédez au répertoire de votre projet et exécutez (dans le terminal) :

npm init -y

Cela initialisera un nouveau projet et créera un fichier package.json par défaut.

{

  "name": "html_table_scraper", // the name of your project folder

  "version": "1.0.0",

  "description": "",

  "main": "index.js",

  "scripts": {

    "test": "echo \"Error: no test specified\" && exit 1"

  },

  "keywords": [],

  "author": "",

  "license": "ISC"

}

Pour simplifier les choses, nous importerons nos modules avec « require ». Mais si vous souhaitez importer des modules à l’aide de l’instruction « import », ajoutez ceci à votre fichier package.json :

 "type": "module",

 // this will enable you to use the import statement 

 // ex: import * as cheerio from 'cheerio';

L'option « main » : « index.js » spécifie le nom du fichier qui sert de point d'entrée à notre programme. Cela étant dit, vous pouvez maintenant créer un fichier index.js vide.

Nous utiliserons la bibliothèque cheerio pour analyser le code HTML de notre site web cible. Vous pouvez l'installer avec :

npm install cheerio

Ouvrez maintenant le fichier index.js et incluez-la en tant que module :

const cheerio = require('cheerio');

L'environnement de travail de base est configuré. Dans le chapitre suivant, nous explorerons la structure du tableau des artistes les plus vendus de tous les temps.

Tester le site cible à l&#x27;aide de DevTools

Chartmasters best-selling artists table with artist rows and sales figures, shown next to browser developer tools inspecting the table HTML

En inspectant l'onglet « Éléments » des Outils de développement, nous pouvons extraire des informations précieuses sur la structure du tableau :

Le tableau est stocké au format <thead>, <tbody>.

Tous les éléments du tableau se voient attribuer des identifiants, des classes et des rôles descriptifs.

Dans le contexte d'un navigateur, vous avez un accès direct au code HTML d'une page web. Cela signifie que vous pouvez utiliser des fonctions JavaScript telles que getElementsByTagName ou querySelector pour extraire des données du code HTML.

Dans cette optique, nous pouvons utiliser la console des outils de développement pour tester certains sélecteurs.

Extrayons les noms des en-têtes à l'aide de l'attribut role="columnheader"

Browser console snippet extracting table column headers with document.querySelectorAll('[role=columnheader]') and printing header names

Extrayons maintenant les données de la première ligne à l'aide des attributs role="cell" et role="row" :

Browser console code selecting the first table row and mapping its cells to text or image URLs, outputting an array of row values

Comme vous pouvez le voir :

Nous pouvons utiliser « [role=columnheader] » pour sélectionner tous les éléments d'en-tête.

Nous pouvons utiliser « tbody [role=row] » pour sélectionner tous les éléments de ligne.

Pour chaque ligne, nous pouvons utiliser « [role=cell] » pour sélectionner ses cellules.

Il convient de noter que la cellule PIC contient une image et que nous devons écrire une règle spéciale pour extraire son URL.

Implémentation d&#x27;un scraper de tableau HTML

Il est maintenant temps de passer à un niveau un peu plus avancé en utilisant Node.js et cheerio.

Pour récupérer le code HTML d’un site web dans un projet Node.js, vous devrez effectuer une requête fetch vers le site. Cela renvoie le code HTML sous forme de chaîne de caractères, ce qui signifie que vous ne pouvez pas utiliser les fonctions DOM de JavaScript pour extraire les données. C’est là que cheerio entre en jeu. Cheerio est une bibliothèque qui vous permet d'analyser et de manipuler la chaîne HTML comme si vous étiez dans le contexte d'un navigateur. Cela signifie que vous pouvez utiliser des sélecteurs CSS familiers pour extraire des données du code HTML, exactement comme vous le feriez dans un navigateur.

Il est également important de noter que le code HTML renvoyé par une requête fetch peut être différent de celui que vous voyez dans le navigateur. En effet, le navigateur exécute du JavaScript, ce qui peut modifier le code HTML affiché. Dans une requête fetch, vous obtenez uniquement le code HTML brut, sans aucune modification JavaScript.

À des fins de test uniquement, effectuons une requête fetch vers notre site web cible et écrivons le code HTML résultant dans un fichier local :

//index.js

const fs = require('fs');

(async () => {

    const response =  await fetch('https://chartmasters.org/best-selling-artists-of-all-time/');

    const raw_html = await response.text();

    fs.writeFileSync('raw-best-selling-artists-of-all-time.html', raw_html);

})();

// it will write the raw html to raw-best-selling-artists-of-all-time.html

// try it with other websites: https://randomwordgenerator.com/

Vous pouvez l'exécuter avec :

node index.js

Et vous obtiendrez :

Chartmasters best-selling artists table with artist rows and sales figures, shown next to browser developer tools inspecting the table

La structure du tableau reste la même. Cela signifie que les sélecteurs que nous avons trouvés dans le chapitre précédent sont toujours valables.

Bon, passons maintenant au code proprement dit :

Après avoir envoyé la requête de récupération vers https://chartmasters.org/best-selling-artists-of-all-time/, vous devrez charger le code HTML brut dans cheerio :

const cheerio = require('cheerio');

(async () => {

    const response =  await fetch('https://chartmasters.org/best-selling-artists-of-all-time/');

    const raw_html = await response.text();

    const $ = cheerio.load(raw_html);

})();

Une fois cheerio chargé, voyons comment extraire les en-têtes :

    const headers = $("[role=columnheader]")

    const header_names = []

    headers.each((index, el) => {

        header_names.push($(el).text())

    })
 //header_names

    [

        '#',

        'PIC',

        'Artist',

        'Total CSPC',

        'Studio Albums Sales',

        'Other LPs Sales',

        'Physical Singles Sales',

        'Digital Singles Sales',

        'Sales Update',

        'Streams EAS (Update)'

    ]

Et la première ligne :

    const first_row = $("tbody [role=row]")[0]

    const first_row_cells = $(first_row).find('[role=cell]')

    const first_row_data = []

    first_row_cells.each((index, f_r_c) => {

        const image = $(f_r_c).find('img').attr('src')

        if(image) {

            first_row_data.push(image)

        }

        else {

            first_row_data.push($(f_r_c).text())

        }

    })
   //first_row_data

     [

        '1',

        'https://i.scdn.co/image/ab6761610000f178e9348cc01ff5d55971b22433',

        'The Beatles',

        '421,300,000',

        '160,650,000',

        '203,392,000',

        '116,080,000',

        '35,230,000',

        '03/01/17',

        '17,150,000 (01/03/23)'

      ]

Vous vous souvenez lorsque nous avons extrait le code HTML du tableau à l'aide de JavaScript dans la console des outils de développement du navigateur ? À ce stade, nous avons reproduit la même fonctionnalité que celle que nous avions mise en œuvre là-bas, mais dans le contexte du projet Node.js. Vous pouvez revoir le chapitre précédent et observer les nombreuses similitudes entre les deux implémentations.

Passons à la suite et réécrivons le code pour extraire toutes les lignes :

    const rows = $("tbody [role=row]")

    const rows_data = []

    rows.each((index, row) => {

        const row_cell_data = []

        const cells = $(row).find('[role=cell]')

        cells.each((index, cell) => {

            const image = $(cell).find('img').attr('src')

            if(image) {

                row_cell_data.push(image)

            }

            else {

                row_cell_data.push($(cell).text())

            }

        })
        rows_data.push(row_cell_data)

    })

    //rows_data

    [

        [

          '1',

          'https://i.scdn.co/image/ab6761610000f178e9348cc01ff5d55971b22433',

          'The Beatles',

          '421,300,000',

          '160,650,000',

          '203,392,000',

          '116,080,000',

          '35,230,000',

          '03/01/17',

          '17,150,000 (01/03/23)'

        ],

        [

          '2',

          'https://i.scdn.co/image/ab6761610000f178a2a0b9e3448c1e702de9dc90',

          'Michael Jackson',

          '336,084,000',

          '182,600,000',

          '101,997,000',

          '79,350,000',

          '79,930,000',

          '09/27/17',

          '15,692,000 (01/06/23)'

        ],

        ...

    ]

Maintenant que nous avons obtenu les données, voyons comment les exporter.

Exporter les données

Une fois que vous avez obtenu les données que vous souhaitez extraire, il est important de réfléchir à la manière dont vous souhaitez stocker ces informations. Les formats les plus courants sont .json et .csv. Choisissez le format qui répond le mieux à vos besoins et exigences spécifiques.

Exportation des données au format json

Si vous souhaitez exporter les données au format .json, vous devez d'abord regrouper les données dans un objet JavaScript qui ressemble au format .json.

Nous disposons d'un tableau de noms d'en-têtes (header_names) et d'un autre tableau (rows_data, un tableau de tableaux) qui contient les données des lignes. Le format .json stocke les informations sous forme de paires clé-valeur. Nous devons regrouper nos données de manière à respecter cette règle :

[ // this is what we need to obtain

  {

    '#': '1',

    PIC: 'https://i.scdn.co/image/ab6761610000f178e9348cc01ff5d55971b22433',

    Artist: 'The Beatles',

    'Total CSPC': '421,300,000',

    'Studio Albums Sales': '160,650,000',

    'Other LPs Sales': '203,392,000',

    'Physical Singles Sales': '116,080,000',

    'Digital Singles Sales': '35,230,000',

    'Sales Update': '03/01/17',

    'Streams EAS (Update)': '17,150,000 (01/03/23)'

  },

  {

    '#': '2',

    PIC: 'https://i.scdn.co/image/ab6761610000f178a2a0b9e3448c1e702de9dc90',

    Artist: 'Michael Jackson',

    'Total CSPC': '336,084,000',

    'Studio Albums Sales': '182,600,000',

    'Other LPs Sales': '101,997,000',

    'Physical Singles Sales': '79,350,000',

    'Digital Singles Sales': '79,930,000',

    'Sales Update': '09/27/17',

    'Streams EAS (Update)': '15,692,000 (01/06/23)'

  } 

  ...

]

Voici comment procéder :

     // go through each row

 const table_data = rows_data.map(row => {

        // create a new object

        const obj = {};

        // forEach element in header_names

        header_names.forEach((header_name, i) => {

          // add a key-value pair to the object where the key is the current header name and the value is the value at the same index in the row

          obj[header_name] = row[i];

        });

        // return the object

        return obj;

 });

Vous pouvez désormais utiliser la fonction JSON.stringify() pour convertir l'objet JavaScript en une chaîne .json, puis l'écrire dans un fichier.

 const fs = require('fs');

 const table_data_json_string = JSON.stringify(table_data, null, 2)

 fs.writeFile('table_data.json', table_data_json_string, (err) => {

if (err) throw err;

console.log('The file has been saved as table_data.json!');

 })

Exporter les données au format CSV

Le format .csv signifie « valeurs séparées par des virgules ». Si vous souhaitez enregistrer votre tableau au format .csv, vous devrez l'écrire dans un format similaire à celui-ci :

id,name,age // the table headers followed by the rows

1,Alice,20

2,Bob,25

3,Charlie,30

Les données de notre tableau se composent d'un tableau de noms d'en-têtes (header_names) et d'un autre tableau (rows_data, un tableau de tableaux) qui contient les données des lignes. Voici comment vous pouvez écrire ces données dans un fichier .csv :

    let csv_string = header_names.join(',') + '\n'; // add the headers

    // forEach row in rows_data

    rows_data.forEach(row => {

      // add the row to the CSV string

      csv_string += row.join(',') + '\n';

    });

   

    // write the string to a file

    fs.writeFile('table_data.csv', csv_string, (err) => {

      if (err) throw err;

      console.log('The file has been saved as table_data.csv!');

    });

Évitez d&#x27;être bloqué

Avez-vous déjà rencontré le problème suivant : vous essayez de scraper un site web et vous vous rendez compte que la page dont vous essayez d’extraire des informations ne se charge pas complètement ? Cela peut être frustrant, surtout si vous savez que le site web utilise JavaScript pour générer son contenu. Nous n’avons pas la possibilité d’exécuter du JavaScript comme le ferait un navigateur classique, ce qui peut entraîner des données incomplètes, voire un bannissement du site web pour avoir effectué trop de requêtes en peu de temps.

Une solution à ce problème est WebScrapingApi. Grâce à notre service, il vous suffit d'envoyer des requêtes à notre API et celle-ci se chargera de toutes les tâches complexes à votre place. Elle exécutera le JavaScript, changera de proxy et gérera même les CAPTCHA.

Voici comment effectuer une simple requête fetch vers une <target_url> et enregistrer la réponse dans un fichier :

const fs = require('fs');

(async () => {

    const result = await fetch('https://api.webscrapingapi.com/v1?' + new URLSearchParams({

        api_key: '<api_key>',

        url: '<target_url>',

        render_js: 1,

        proxy_type: 'residential',

    }))

   

    const html = await result.text();

    fs.writeFileSync('wsa_test.html', html);

})();

Vous pouvez obtenir une clé API gratuite en créant un nouveau compte sur https://www.webscrapingapi.com/

En spécifiant le paramètre render_js=1, vous activerez la fonctionnalité de WebScrapingAPI permettant d'accéder à la page Web ciblée à l'aide d'un navigateur sans interface graphique, ce qui permet aux éléments JavaScript de la page de s'afficher avant de vous renvoyer le résultat final du scraping.

Consultez https://docs.webscrapingapi.com/webscrapingapi/advanced-api-features/proxies pour découvrir les fonctionnalités de nos proxys rotatifs.

Conclusion

Dans cet article, nous avons découvert la puissance du web scraping des tableaux HTML avec JavaScript et comment cela peut nous aider à extraire des données précieuses des sites web. Nous avons exploré la structure des tableaux HTML et appris à utiliser la bibliothèque cheerio en combinaison avec Node.js pour en extraire facilement des données. Nous avons également examiné différentes façons d'exporter les données, notamment aux formats CSV et JSON. En suivant les étapes décrites dans cet article, vous devriez désormais disposer d'une base solide pour extraire des données de tableaux HTML sur n'importe quel site web.

Que vous soyez un professionnel chevronné ou que vous vous lanciez dans votre premier projet de scraping, WebScrapingAPI est là pour vous aider à chaque étape. Notre équipe se fera un plaisir de répondre à toutes vos questions et de vous conseiller sur vos projets. Alors si jamais vous vous sentez bloqué ou si vous avez simplement besoin d'un coup de main, n'hésitez pas à nous contacter.

À propos de l'auteur
Mihai Maxim, Développeur Full Stack @ WebScrapingAPI
Mihai MaximDéveloppeur Full Stack

Mihai Maxim est développeur Full Stack chez WebScrapingAPI ; il participe à l'ensemble du produit et contribue à la création d'outils et de fonctionnalités fiables pour la plateforme.

Commencez à créer

Prêt à faire évoluer votre système de collecte de données ?

Rejoignez plus de 2 000 entreprises qui utilisent WebScrapingAPI pour extraire des données Web à l'échelle de l'entreprise, sans aucun coût d'infrastructure.