Introduction au webscraping avec R

Auteur·rice

Thomas Delclite

Date de publication

31 mai 2024

1 Introduction

Le webscraping est une technique permettant de récupérer des informations accessibles sur Internet, les transformant en données exploitables pour diverses analyses et applications. En pratique, un programme de webscraping est conçu pour naviguer sur Internet, collecter des informations et même remplir des formulaires. Cette capacité d’émuler les actions humaines sur les plateformes numériques permet une collecte de données à grande échelle.

Pour autant, le webscraping n’est pas une technique pouvant se substituer aux enquêtes de terrain réalisées actuellement par les instituts de statistiques. Ces données, bien qu’abondantes et apparemment riches en informations, manquent fréquemment d’un élément essentiel : le contexte explicatif, ou le « pourquoi » des actions observées. Les données collectées, en particulier celles qui sont obtenues de manière indirecte comme les « traces » laissées sur Internet, ne nous permettent pas toujours de comprendre les motivations sous-jacentes des utilisateur·rice·s derrière leurs actions, achats ou commentaires. De plus, notre connaissance de ces personnes se limite souvent à ce que leur comportement en ligne révèle, rendant difficile une analyse sociologique complète qui intègre des variables comme la classe sociale ou le genre, sans informations supplémentaires.

Cela signifie-t-il pour autant que nous devons rejeter cette source de données ? Non, Internet offre en effet une multitude de données qui peuvent être utilisées seules ou en complément d’autres méthodes de collecte de données. Ce cours explorera comment extraires des données suffisamment riches, parfois pouvant être analysées directement, parfois pouvant enrichir d’autres données ou recherches. Nous voyons ici l’apprentissage de l’outil mais vous devez en questionner la pertinence lors de vos propres usages.

Le webscraping est restreint à une contrainte importante à évoquer ici : les données ciblées doivent être accessibles légalement. Ce cours ne prévoit aucune utilisation de techniques de piratage ou d’autres moyens illicites pour accéder à des données privées. Toutes les données exploitables doivent être disponibles ouvertement sur le réseau Internet, que ce soit librement ou derrière une authentification.

Nous aborderons les principes fondamentaux du webscraping en utilisant le langage de programmation R. En maîtrisant les bases du webscraping, vous serez en mesure de naviguer sur le web, collecter des informations, compléter des formulaires automatiquement, et plus encore, tout cela programmable et répétable à volonté. Ce cours vous guidera à travers les étapes initiales de la mise en place de R, de l’extraction de données web et de la création de base de données. Mais avant cela, nous allons aborder quelques notions importantes sur les objectifs du cours et sur la nature des données disponible sur Internet.

1.1 Objectif : tableau(x) de données

Il est possible d’extraire des quantités astronomiques d’informations en copiant le contenu d’une page web. Avec l’ensemble de ces données, non structurées, il est envisageable de réaliser de l’analyse de données en masse. L’analyse de données en masse, ou “Big Data”, permet de découvrir des tendances cachées et des relations entre les différentes variables. Les modèles d’intelligence artificielle, tels que les réseaux de neurones, peuvent être utilisés pour identifier des patrons complexes dans les données, tels que les relations entre les produits achetés et les habitudes de consommation des clients.

Il y a plusieurs défis qui accompagne l’analyse des données en masse. La qualité des données peut varier considérablement, ce qui peut rendre difficile l’obtention de résultats précis. De plus, les données peuvent provenir de sources hétérogènes, ce qui nécessite une normalisation et une structuration adéquate pour pouvoir être utilisées efficacement. En outre, les données peuvent être volumineuses et nécessiter des techniques de traitement parallèle pour être traitées efficacement.

Ce n’est pas ce que nous ferons ici dans le cadre de ce cours. De tels volumes de données nécessitent ensuite des programmes informatiques complexes dont les paramètres et étapes de décision sont souvent caché·e·s à l’utilisateur·rice. Le tout pour produire des corrélations entre des phénomènes dont personne ne sait comprendre la raison, seulement que cette corrélation est significative. L’objectif de ce cours est justement de vous permettre de garder un contrôle sur chaque étape de l’extraction et de la structuration des données. Pour cela, notre objectif ici sera simple : produire un ou plusieurs tableaux de données (à deux dimensions) dont chaque ligne sera une extraction issue d’Internet et chaque colonne sera une information concernant cette extraction.

Un soin tout particulier doit être apporté à la définition de la ligne du tableau à obtenir : que signifie une observation du tableau ? S’agit-il d’un film, d’un billet de train pour un trajet donné, d’un article scientifique, d’un commentaire sur un réseau social ? Comme pour toute analyse de bases de données, mais surtout avant même de commencer à écrire votre programme d’extraction, vous devez avoir une idée clair de ce que vous voulez obtenir à chaque ligne.

Un point important à noter dès à présent : si votre projet de webscraping ne concerne qu’une centaine de données, je vous conseille de faire cela à la main, c’est à dire de parcourir le site web et de stocker vos données dans un tableau Excel. Cela sera plus rapide au final, car le webscraping est davantage prévu pour des extractions de grande ampleur (plusieurs milliers ou dizaine de milliers de lignes) ou fréquence (une même extraction tous les jours/semaines/mois). Le but de ce cours est justement d’apprendre à coder un programme qui collecte et structure une quantité importante de données.

1.2 Les données sur Internet

Il faut avoir à l’esprit que toute information visible sur Internet est potentiellement récupérable. Que ce soit du texte, des chiffres, des images, pourquoi pas du son, si vous savez le voir, il est possible, en théorie, de collecter l’information. Il y a même des données non visibles à l’écran et pourtant essentielles pour votre travail. Voyons d’abord les types de données et nous aborderons ensuite l’impact sur leur extraction.

1.2.1 Données et métadonnées

L’extraction la plus évidente concerne les données visibles sur votre écran d’ordinateur. Le nom du film, le prix du billet de train, la liste des auteurs et autrices de l’article, etc. Ces données consisteront souvent le cœur de votre recherche. Nous le verrons par la suite, mais disons le dès à présent, ne soyez pas trop économe dans les données à collecter. Hormis s’il s’agit de long textes, ou d’une extraction ayant lieu à une régularité trop importante, vous ne risquez rien à collecter plus de données que nécessaire. Si une information concerne votre sujet d’étude et qu’elle est disponible aisément (nous définirons davantage par la suite ce terme), n’hésitez pas à la collecter.

D’autres informations ne sont pas perceptibles à l’écran et sont pourtant tout aussi importantes, voire même sont plus importantes encore. Il s’agit des métadonnées, c’est à dire les informations “entourant” votre extraction et permettant de la situer, dans l’espace et dans le temps. Par exemple, il va s’agir de collecter la date et l’heure de votre extraction, car Internet est une source de données dynamique et les informations contenues peuvent évoluer au fil du temps.

Rappelons à ce titre que l’analyse de vos données se déroulera fréquemment bien après l’extraction de vos données. Dès lors, si une information a été oubliée lors de l’étape d’extraction, il ne sera pas toujours faisable de l’ajouter par la suite à vos tableaux de données.

1.2.2 Format des données

1.2.2.1 Données alphanumériques

La majorité des informations disponibles sur le web sont encodées sous forme de texte. Les éléments tels que les articles, les publications sur les réseaux sociaux, et même les métadonnées imbriquées dans les balises HTML, sont sous ce format. Les données numériques sont initialement traités comme des séquences de caractères lors du webscraping. L’interprétation de ces informations en tant que données numériques exploitables est effectuée après le webscraping dans le traitement des données. Nous aborderons certaines des manipulations durant nos exemples.

Il convient de noter que certains textes sur Internet sont affichés sous la forme d’images. Ces images requièrent l’emploi de technologies de reconnaissance optique de caractères (OCR) pour leur conversion en texte exploitable. La mise en œuvre de l’OCR s’avère parfois complexe et est susceptible de générer des erreurs, en particulier lorsque la qualité de l’image est médiocre ou le texte stylisé. Cette démarche nécessite donc des outils spécifiques et peut compromettre la fiabilité des données extraites.

Enfin, vous trouverez parfois des données directement sous la forme de tableaux. Les tableaux, en raison de leur disposition structurée sur les pages web, représentent une source de données particulièrement adaptée au webscraping. Une table bien formée, marquée par des balises HTML telles que <table>, <tr>, <th> et <td> peut être exploitée de manière efficace et précise. Les outils de webscraping identifient ces balises et extraient systématiquement les contenus de chaque cellule, offrant ainsi un accès direct à des ensembles de données organisées et prêtes à l’analyse.

1.2.3 Données audiovisuelles

À l’heure actuelle, il n’existe pas de méthode permettant l’extraction directe de données sous forme multimédia pour les stocker immédiatement dans un tableau structuré. Cette contrainte ne relève pas tant d’un problème d’extraction de données que de la conversion de contenu multimédia — tel que des images ou des enregistrements sonores — en un format qui pourrait être intégré dans une structure de tableau de données traditionnelle.

Pour les données audiovisuelles, la pratique courante consiste à télécharger le contenu dans un répertoire spécifiquement dédié, tout en enregistrant le nom du fichier dans une base de données. Bien que ce manuel ne traite pas des logiciels spécifiques à l’analyse de ces types de données, il est essentiel de reconnaître que des outils existent pour traiter ultérieurement ces informations. Le stockage structuré des noms de fichiers permet une récupération et une analyse facilitées par d’autres applications dédiées.

1.2.4 Accessibilité des données

1.2.4.1 Données archivées

Les sites web qui servent de dépôts pour des archives, tels que des recueils d’articles, d’ouvrages et d’informations diverses, présentent une dynamique particulière : les données y sont relativement stables. Les modifications sur ces plateformes sont généralement lentes, ce qui offre un avantage significatif pour le webscraping. Les chercheur·euse·s peuvent planifier des extractions en plusieurs phases sans risque majeur de perdre des données entre les sessions. De plus, il est souvent possible de retourner sur le site pour extraire des informations initialement négligées, garantissant ainsi une flexibilité dans la gestion des données recueillies.

1.2.4.2 Données éphémères

À l’opposé, nous trouvons des sites dont le contenu est dynamique. Ces plateformes, qui incluent notamment des sites d’actualités en temps réel et des réseaux sociaux, nécessitent une approche méthodologique spécifique en raison de la nature éphémère de leurs données. Une extraction effectuée à un moment donné peut être totalement différente d’une autre réalisée ultérieurement, rendant toute reprise de données impossible une fois l’extraction effectuée. La métadonnée temporelle devient alors cruciale : il est impératif de documenter précisément quand les données ont été collectées. Ce caractère définitif de l’extraction sur de tels sites implique de planifier soigneusement le programme de webscraping pour garantir l’intégralité et la pertinence des données recueillies.

1.3 Déontologie et règles en webscraping

Respect des conditions d’utilisation des sites web : La pratique du webscraping doit toujours commencer par une consultation des conditions d’utilisation du site ciblé ainsi que de son fichier robots.txt, qui indique les directives d’accès pour les robots des moteurs de recherche. Ces conditions définissent les limites légales et techniques de ce qu’il est possible de faire avec les données du site.

Minimisation de l’impact sur les serveurs web : Les actions de webscraping doivent être conçues de manière à minimiser l’impact sur les serveurs web des sites ciblés. Cela implique de limiter la fréquence des requêtes pour ne pas surcharger les serveurs.. Il est recommandé d’étaler les requêtes sur des périodes plus longues ou de les effectuer durant les heures creuses.

Gestion respectueuse et éthique des données : Il est impératif de gérer les données collectées de manière éthique. Cela signifie éviter la collecte de données personnelles sans le consentement explicite des individus concernés et anonymiser toute information qui pourrait être utilisée pour identifier une personne.

Utilisation éthique et crédit des sources : vous devez réfléchir aux implications éthiques de votre extraction et s’assurer que l’utilisation des données ne porte pas préjudice aux individus ou aux entités impliquées. Il est également fondamental de créditer les sources des données collectées.

1.4 Découverte du logiciel

1.4.1 R et RStudio

RStudio est un environnement de développement intégré (IDE) populaire pour R, un langage de programmation principalement utilisé pour les statistiques et l’analyse de données. RStudio est conçu pour faciliter le travail des utilisateur·rice·s de R en proposant une interface claire et fonctionnelle. Vous devez installer à la fois R et RStudio sur votre ordinateur, puis lancez uniquement RStudio. Ce logiciel est divisé en quatre fenêtres principales, chacune ayant un rôle spécifique.

La fenêtre de script : La première fenêtre, souvent située en haut à gauche, est celle du script. C’est ici que les utilisateurs écrivent et éditent leurs scripts R. Cette zone permet de créer des fichiers de script (.R), de les exécuter en partie ou en totalité, et de sauvegarder le travail. L’éditeur de script supporte également des fonctionnalités telles que la coloration syntaxique, le balisage automatique et le repliement de code, ce qui facilite la lecture et la rédaction du code. Les scripts ne sont “que” des fichiers texte, et ne contiennent aucune information (comme les programmes SAS).

La fenêtre de console : Juste en dessous de la fenêtre de script se trouve la console. C’est ici que le code R est exécuté, et où les résultats des commandes sont affichés. Les utilisateurs peuvent également y entrer directement des commandes pour une exécution instantanée. Cette interaction directe avec l’environnement R est essentielle pour tester des morceaux de code rapidement, vérifier les résultats des analyses et gérer les packages R.

Remarque : il est souvent plus pratique d’afficher la fenêtre de console en haut à droite. Cela se fait dans le menu View -> Panes -> Console on Right.

Les fenêtres d’environnement et d’historique : En haut à droite, la fenêtre d’environnement montre une liste des objets R actuellement chargés, comme les vecteurs, les data frames, et les fonctions. Cette fenêtre offre une vue d’ensemble et un accès rapide à l’ensemble des données avec lesquelles l’utilisateur travaille. Juste à côté, la fenêtre d’historique enregistre toutes les commandes qui ont été exécutées, permettant aux utilisateurs de revoir ou de réutiliser des commandes antérieures facilement.

La fenêtre de fichiers, graphiques, packages et aide : En bas à droite, cette fenêtre multifonctionnelle permet aux utilisateur·rice·s de naviguer dans les fichiers du système, de visualiser les graphiques générés, de gérer les packages R et d’accéder aux fichiers d’aide. L’onglet des fichiers est essentiel pour organiser les scripts et données associées. L’onglet des graphiques affiche les visualisations créées par le code R. L’onglet des packages permet d’installer, de mettre à jour et de charger les packages nécessaires, et l’onglet d’aide fournit une assistance rapide sur les fonctions et les packages R.

1.4.2 Gestion du proxy

L’utilisation d’un proxy dans le contexte du webscraping avec R est souvent nécessaire pour contourner des restrictions géographiques ou simplement prendre en compte les restrictions de votre organisation. Pour configurer un proxy en R, vous devez utiliser cette fonction : Sys.setenv(https_proxy = "http://login:mdp@proxy:port"). Cette fonction définit l’environnement du proxy. Ici, vous devez remplacer login, mdp, proxy, et port par vos informations d’authentification et les détails du proxy. Cette ligne indique à R de router toutes les connexions HTTPS à travers le proxy spécifié.

1.4.3 Gestion des packages

Le logiciel R est fourni avec une série de fonctions de “base”. Il est possible ensuite, selon les besoins, d’ajouter des packages, qui peuvent être vu comme des lots de fonctions pour des domaines spécifiques d’analyse. R étant un logiciel libre, chacun·e peut proposer de nouveaux packages, il n’y a aucune garantie de fiabilité de tous les packages. Néanmoins, le CRAN est un organisme regroupant les packages et garantissant (du mieux possible) leur qualité. Il est conseillé de passer par le CRAN pour l’installation de nouveaux packages.

Le logiciel R est équipé d’une série de fonctions qui constituent la base de son fonctionnement. Pour répondre à des besoins spécifiques, il est nécessaire d’ajouter des packages. Ces derniers sont des collections de fonctions ciblées, conçues pour des domaines d’analyse particuliers. En tant que logiciel open-source, R permet à quiconque de développer et de proposer de nouveaux packages. Toutefois, tous les packages ne bénéficient pas de la même garantie de fiabilité. À cet égard, le Comprehensive R Archive Network (CRAN) joue un rôle essentiel en regroupant les packages et en s’efforçant de garantir leur qualité autant que possible. Je vous conseille donc de vous limiter aux packages accessibles directement via le CRAN, ou de faire preuve de prudence pour les autres packages.

Dans le cadre du cours, nous aurons essentiellement besoin de deux packages : tidyverse et rvest. Le package tidyverse est une collection de packages devenus populaire en analyse de données. Il contient les packages ggplot2 pour réaliser des graphiques, dyplyr pour manipuler des bases de données, tidyr pour nettoyer des bases de données, readr pour importer, purrr pour automatiser certaines étapes, stringr pour manipuler des chaînes de caractères, forcats pour manipuler des données stockées sous forme de facteurs (vous pouvez retrouver la présentation de ces packages ici : https://www.tidyverse.org/packages/). Tous ces packages facilitent l’écriture de code en R. Le package rvest permet spécifiquement de réaliser du webscraping. Il permet d’extraire le code source d’une page web puis de localiser et d’extraire des informations. Il permet même, depuis une mise à jour de 2024, de simuler un navigateur web et ainsi s’attaquer à des site Internet dynamique. Par ailleurs, rvest utilise le même language que celui développé dans le tidyverse.

La fonction install.packages est utilisée pour installer de nouveaux packages dans R. L’installation d’un package se fait généralement une seule fois par machine, sauf éventuelle mise à jour. L’installation nécessite une connexion internet pour télécharger le package.

install.packages('tidyverse')
install.packages('rvest')

La fonction library est utilisée pour charger un package dans votre session R. Une fois chargé, toutes les fonctions et les données du package deviennent disponibles durant cette session. Contrairement à install.packages, la fonction library doit être exécutée à chaque nouvelle session R dans laquelle vous souhaitez utiliser le package.

library(tidyverse) 
Warning: le package 'tidyverse' a été compilé avec la version R 4.2.3
Warning: le package 'ggplot2' a été compilé avec la version R 4.2.3
Warning: le package 'tibble' a été compilé avec la version R 4.2.3
Warning: le package 'tidyr' a été compilé avec la version R 4.2.3
Warning: le package 'readr' a été compilé avec la version R 4.2.3
Warning: le package 'purrr' a été compilé avec la version R 4.2.3
Warning: le package 'dplyr' a été compilé avec la version R 4.2.3
Warning: le package 'stringr' a été compilé avec la version R 4.2.3
Warning: le package 'lubridate' a été compilé avec la version R 4.2.3
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.0     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(rvest)
Warning: le package 'rvest' a été compilé avec la version R 4.2.3

Attachement du package : 'rvest'

L'objet suivant est masqué depuis 'package:readr':

    guess_encoding

Remarque : en chargeant les librairies, vous risquez de voir beaucoup de messages d’informations et de warnings. Tout apparaît en rouge, mais cela n’est pas forcément grave. Il faut lire pour savoir quels sont les éventuels problèmes. Notamment, le package tidyverse génère souvent des conflits avec d’autres fonctions déjà présentes. Il faut alors vérifier si vous utiliser déjà ces fonctions et si le remplacement par la version du tidyverse est problématique ou non.

2 Extraction du site web Statbel

2.1 Première extraction de données

2.1.1 Explorer une page web

Pour l’ensemble de cette section, nous allons scraper le site web de Statbel et plus précisément la page des actualités de Statbel (ici nommé Nouvelles). Cela permet par exemple d’étudier comment Statbel a réagit face à des crises comme celle du COVID ou celle de l’accueil des migrant·e·s. Voici à quoi ressemblait la page web au 31 mai 2024 :

Page d’actualité de Statbel

Pour chaque actualité, il est possible de collecter le titre, le thème, la date de publication et le résumé. Il sera aussi possible d’accéder à la page de l’article complet avant de collecter plus de texte. L’objectif est d’obtenir in fine une base de données avec une ligne par actualité et une colonne par information sur l’actualité. Voici à quoi cela pourrait ressembler d’après la capture d’écran ci-dessus :

Objectif d’extraction
TX_TITRE TX_DATE TX_CATEGORIE TX_RESUME TX_TEXTE
Les entreprises laitières belges accroissent leur production de fromage et de crème en 2023 30 mai 2024 Agriculture & pêche Les entreprises laitières belges ont produit 80.900 tonnes de mozzarella en 2023, soit une augmentation de la production de 12.300 tonnes (+18%). La production de crème de consommation a augmenté…
L’inflation s’élève à 3,36% 30 mai 2024 Prix à la consommation Indice des prix à la consommation de mai 2024 En mai, l’inflation passe de 3,37% à 3,36%. L’indice des prix à la consommation a augmenté ce mois de 0,48 point…

2.1.1.1 Extraction de la page web

Pour extraire la page web, la fonction read_html requiert simplement une URL à scraper :

read_html("https://statbel.fgov.be/fr/nouvelles")
{html_document}
<html lang="fr" dir="ltr" prefix="content: http://purl.org/rss/1.0/modules/content/  dc: http://purl.org/dc/terms/  foaf: http://xmlns.com/foaf/0.1/  og: http://ogp.me/ns#  rdfs: http://www.w3.org/2000/01/rdf-schema#  schema: http://schema.org/  sioc: http://rdfs.org/sioc/ns#  sioct: http://rdfs.org/sioc/types#  skos: http://www.w3.org/2004/02/skos/core#  xsd: http://www.w3.org/2001/XMLSchema# " class="no-js" xml:lang="fr">
[1] <head>\n<meta http-equiv="Content-Type" content="text/html; charset=UTF-8 ...
[2] <body class="path-news has-glyphicons">\n    <a href="#page" class="visua ...

Ici, R affiche le résultat de la fonction dans la console. Cela permet de comprendre l’effet de la fonction. Néanmoins, pour conserver l’information en mémoire et la réutiliser ensuite, il faut l’assigner à un objet R. Cela se fait à l’aide d’une flèche ( <- ) ou d’un égal ( = ). Dans le cadre de ce cours, j’utilise toujours la flèche.

page_actualites <- read_html("https://statbel.fgov.be/fr/nouvelles")

L’objet crée contient ce qu’on appelle le code source de la page web. C’est ce code source que nous allons explorer pour trouver des informations à l’intérieur. Pour cela, il nous faut comprendre la structure d’un code source.

2.1.1.2 Code source

Le code source d’une page web est ce que votre navigateur Internet reçoit comme information, afin de générer le site web. Le code source est une suite de commandes et d’instructions écrites généralement en HTML. Le HTML utilise ce qu’on appelle des “balises” pour organiser le contenu et les éléments sur une page web. Ces balises sont des mots clés entourés de chevrons (par exemple, <html>, <body>, etc.) qui indiquent au navigateur web comment afficher le contenu. Chaque page web commence par la balise <html> et se termine par </html>, encadrant toutes les informations de la page. Voici les balises de contenu les plus courantes :

  • <h1>, <h2>, <h3>, etc. : Ces balises de titre permettent de structurer le contenu textuel en hiérarchie, allant du plus important au moins important. <h1> est généralement utilisé pour le titre principal de la page, tandis que les autres servent pour les sous-titres et autres titres secondaires.
  • <p> : Cette balise est utilisée pour créer des paragraphes de texte, permettant d’organiser le contenu en blocs de texte clairement définis.
  • <a> : Cette balise crée des liens hypertextes. Elle nécessite l’attribut href qui spécifie l’URL de la page ou de la ressource vers laquelle le lien doit conduire.
  • <div> ou <span> : Les balises <div> et <span> sont utilisées pour définir une division ou une section dans un document HTML. Elle est souvent employée pour structurer la page et appliquer styles spécifiques.

Ces balises forment le squelette de la mise en page d’une page web. Nous n’abordons pas ici le développement web, donc vous n’avez pas besoin de comprendre exactement ce que chaque balise a comme effet sur le format d’une page web. Par contre, ces balises sont récurrentes de page en page sur un même site internet. Il est donc possible de comprendre cette structure pour ensuite demander à votre programme de trouver un élément spécifique d’une page.

Pour visualiser et interagir avec le code source d’une page web, vous pouvez utiliser l’un des navigateurs web tels que Chrome, Firefox ou Edge. Dans tous ces navigateurs, la procédure est assez similaire. Vous devez faire un clic droit sur l’élément que vous souhaitez explorer, puis sélectionner l’option “Inspecter” ou “Inspecter l’élément” dans le menu contextuel qui apparaît. Cette action ouvrira la console de développement du navigateur sur le côté ou en bas de votre fenêtre de navigateur, affichant le code HTML, CSS, et parfois JavaScript de la page. Voici la partie du code source de Statbel concernant le titre de la première actualité :

Code source de Statbel

Aussi, lorsque vous déplacez votre souris sur le code source ainsi affiché, vous voyez la partie du site web correspondante en surbrillance. Vous pouvez ainsi interactivement découvrir le code source de la page.

2.1.1.3 Explorer le code source

Il y a deux langages principaux pour extraire une balise avec rvest : CSS3 et XPath. XPath est un langage plus détaillé, mais plus lourd à écrire. Dans ce cours, j’utiliserai essentiellement CSS3 tout en montrant les cas pertinents en XPath. La fonction R est par contre toujours la même : html_element. En CSS3, pour récupérer les balises <h3>, il suffit d’indiquer “h3” comme argument de la fonction html_element. En XPath, il faut commencer par indiquer “//” pour signifier de parcourir tout le site web jusqu’à localiser cette balise <h3>.

page_actualites %>% html_element(xpath="//h3") #XPath

Ces deux requêtes permettent de récupérer la première balise <h3> dans le code source. Pour extraire toutes les balises, il faut utiliser la fonction html_elements (avec un ‘s’ à la fin) :

page_actualites %>% html_elements("h3") #CSS3
page_actualites %>% html_elements(xpath="//h3") #XPath
{xml_nodeset (10)}
 [1] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/ind ...
 [2] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/ind ...
 [3] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/nouvelles/ ...
 [4] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/ind ...
 [5] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/agr ...
 [6] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/pri ...
 [7] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/ent ...
 [8] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/nouvelles/ ...
 [9] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/dat ...
[10] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/ent ...

Ici, c’est bon signe, nous collectons dix balises, ce qui équivaut aux dix titres d’articles sur le site de Statbel. Attention, une requête trop large vous donne beaucoup trop de résultats et sera inexploitable :

page_actualites %>% html_elements("div")
{xml_nodeset (164)}
 [1] <div class="dialog-off-canvas-main-canvas" data-off-canvas-main-canvas>\ ...
 [2] <div id="page">\n  <div class="wrapper-header">\n\n                      ...
 [3] <div class="wrapper-header">\n\n                              <div class ...
 [4] <div class="navbar navbar-default container" id="navbar">\n              ...
 [5] <div class="wrapper-toolbar">\n                <div class="toolbar">\n   ...
 [6] <div class="toolbar">\n                    <div class="region region-too ...
 [7] <div class="region region-tools">\n    <nav class="language-switcher-lan ...
 [8] <div id="openfed-federal-header-wrapper">\n  <div id="openfed-federal-he ...
 [9] <div id="openfed-federal-header-link">\n   Autres informations et servic ...
[10] <div id="openfed-federal-header-logo">\n    <img src="/themes/custom/sta ...
[11] <div class="navbar-header">\n                                            ...
[12] <div class="region region-navigation">\n    \n<div id="block-sitebrandin ...
[13] <div id="block-sitebranding" class="block block--system-branding">\n     ...
[14] <div id="navbar-collapse" class="navbar-collapse collapse">\n            ...
[15] <div class="region region-navigation-collapsible">\n    <nav role="navig ...
[16] <div class="exposed-form form--inline form-inline">\n  <div class="form- ...
[17] <div class="form-item js-form-item form-type-textfield js-form-type-text ...
[18] <div data-drupal-selector="edit-actions-4" class="form-actions form-grou ...
[19] <div class="wrapper-main js-quickedit-main-content">\n\n                 ...
[20] <div class="container">\n            <div class="row">\n              <d ...
...

Dans ce cas, si une balise <div> vous intéresse, vous serez contraint·e d’utiliser des attributs afin de cibler plus efficacement votre balise. Deux attributs sont classiques en langage HTML : ‘id’ qui est un identifiant unique de la balise (par convention HTML, id doit être unique) et ‘class’ qui indique la classe de la balise (permettant d’appliquer un format en CSS).

En CSS3, il est très facile de demander à extraire une balise en connaissant son id ou sa classe. Pour l’id, vous devez indiquer après la balise un # suivi de l’id. Pour la classe, vous devez indiquer après la balise un point suivi de la classe :

# Ecriture générique
page_actualites %>% html_elements("div#ID")
page_actualites %>% html_elements("div.class")

Il y a aussi la possibilité d’extraire une balise à l’aide de n’importe lequel de ses attributs. Voici l’écriture à respecter :

# Ecriture générique
page_actualites %>% html_elements("div[attribut='value']")

En XPath, il n’y a aucun raccourci pour spécifier un id ou une classe, l’écriture standard est la suivante :

page_actualites %>% html_elements(xpath="//div[@attribut='value']")

Ainsi, pour extraire les titres des actualités de Statbel, il est possible d’écrire la commande suivante :

page_actualites %>% html_elements("h3.field-content") 
page_actualites %>% html_elements(xpath="//h3[@class = 'field-content']")
{xml_nodeset (10)}
 [1] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/ind ...
 [2] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/ind ...
 [3] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/nouvelles/ ...
 [4] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/ind ...
 [5] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/agr ...
 [6] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/pri ...
 [7] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/ent ...
 [8] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/nouvelles/ ...
 [9] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/dat ...
[10] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/ent ...

Si nous cherchons à extraire la balise <div> qui est parent à la balise <h3>, il est possible d’écrire la commande suivante :

page_actualites %>% html_elements("div.views-field-title") 
page_actualites %>% html_elements(xpath="//div[@class = 'views-field views-field-title']")
{xml_nodeset (10)}
 [1] <div class="views-field views-field-title"><h3 class="field-content"><a  ...
 [2] <div class="views-field views-field-title"><h3 class="field-content"><a  ...
 [3] <div class="views-field views-field-title"><h3 class="field-content"><a  ...
 [4] <div class="views-field views-field-title"><h3 class="field-content"><a  ...
 [5] <div class="views-field views-field-title"><h3 class="field-content"><a  ...
 [6] <div class="views-field views-field-title"><h3 class="field-content"><a  ...
 [7] <div class="views-field views-field-title"><h3 class="field-content"><a  ...
 [8] <div class="views-field views-field-title"><h3 class="field-content"><a  ...
 [9] <div class="views-field views-field-title"><h3 class="field-content"><a  ...
[10] <div class="views-field views-field-title"><h3 class="field-content"><a  ...

Remarque importante : en CSS3, il ne faut indiquer qu’une classe. En XPath, il faut toutes les indiquer. Mais par contre, il est possible de demander en Xpath à ce que seule une partie d’un attribut corresponde. Cela peut justement servir à isoler un seul attribut :

page_actualites %>% html_elements(xpath="//div[contains(@class,'views-field-title')]")

Le langage HTML est en arborescence à partir de la balise <html>. Ainsi, en CSS3 comme en XPath, il est possible de parcourir cette arborescence pour, à partir d’une balise facile à localiser, arriver à la balise que l’on souhaite extraire. Par exemple, voici comme atteindre la balise <h3> présente en descendante de la balise <div> localisée précédemment :

page_actualites %>% html_elements("div.views-field-title h3") # En CSS3
page_actualites %>% html_elements(xpath="//div[contains(@class,'views-field-title')]/h3") # En XPath
{xml_nodeset (10)}
 [1] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/ind ...
 [2] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/ind ...
 [3] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/nouvelles/ ...
 [4] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/ind ...
 [5] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/agr ...
 [6] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/pri ...
 [7] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/ent ...
 [8] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/nouvelles/ ...
 [9] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/dat ...
[10] <h3 class="field-content"><a href="https://statbel.fgov.be/fr/themes/ent ...

Comme vous pouvez le voir, le XPath et le CSS3 sont deux langages proches mais avec des subtilités. Pour comprendre davantage des différences, vous pouvez consulter cette ressource : https://www.testim.io/blog/xpath-vs-css-selector-difference-choose/.

Une grande partie de l’apprentissage en webscraping consiste à comprendre comment localiser un élément. Cela ne concerne directement le langage R mais uniquement l’exploration d’un code source. Les sélecteurs CSS3 ne sont pas forcément intuitifs au premier abord, et il faut s’entraîner pour ensuite être à l’aise et réaliser n’importe quelle extraction. Voici une ressource intéressante et très ludique pour vous exercer à ce sujet :https://flukeout.github.io/.

2.1.1.4 Extraire des éléments d’une balise

Les balises que nous extrayons contiennent l’ensemble de l’information entre l’ouverture et la fermeture de la balise. Bien souvent, vous souhaiterez extraire le texte contenu dans cette balise et visible sur le site web. Pour cela, la fonction html_text doit être utilisée à la suite de la fonction html_element :

page_actualites %>% html_element("h3") %>% html_text()
[1] "Hausse de l’indice du coût de la main-d’œuvre au premier trimestre 2024"

Ici, nous obtenons le texte du titre de la première actualité visible sur le site de Statbel. Pour obtenir les dix titres, il faut utiliser la fonction html_elements puis la fonction html_text :

page_actualites %>% html_elements("h3") %>% html_text()
 [1] "Hausse de l’indice du coût de la main-d’œuvre au premier trimestre 2024"                    
 [2] "Indice du chiffre d'affaires industriel : mars 2024"                                        
 [3] "Mortalité jusqu’au 19 mai"                                                                  
 [4] "Avril 2024 : Indice des prix à la production +1,1%"                                         
 [5] "Les entreprises laitières belges accroissent leur production de fromage et de crème en 2023"
 [6] "L’inflation s’élève à 3,36%"                                                                
 [7] "144 faillites durant la semaine 21"                                                         
 [8] "Mortalité jusqu’au 12 mai"                                                                  
 [9] "Chiffres communaux de la pauvreté 2021"                                                     
[10] "7.510 nouvelles entreprises en mars"                                                        

Remarque : pour faciliter la lecture de votre code R, il est possible de faire un retour à la ligne après chaque commande %>% :

page_actualites %>% 
  html_elements("h3") %>% 
  html_text()

La fonction html_text permet d’extraire les informations visible à l’écran sur le site web, mais ne permet pas d’explorer le contenu des balises. Or, il y a un usage courant en webscraping qui nécessite d’extraire le contenu des balises : les lien URL. En effet, une balise <a> génère à l’écran un lien cliquable, et il est souvent très utile d’extraire ce lien pour ensuite extraire le code source de cette nouvelle page web (cela s’appelle du spider en webscraping, car on peut ainsi voyager de lien en lien). Chaque balise <a> contient un attribut href qui contient l’URL de la page web cible. Pour extraire ce lien, il faut utiliser la fonction html_attr avec comme argument l’attribut à extraire. Voici le code R pour extraire l’URL de tous les liens cliquables sur le site web (la fonction head permet d’afficher que les cinq premières URL pour ne pas encombrer l’affichage) :

page_actualites %>% html_elements("a") %>% html_attr("href") %>% head()
[1] "#page"                     "/nl/nieuws"               
[3] "/fr/nouvelles"             "/de/news"                 
[5] "/en/news"                  "https://www.belgium.be/fr"

À présent, à vous de parcourir le code source de la page de Statbel et d’extraire les informations suivantes : Thème, Résumé, Date de publication, URL de la page de l’article. Ouvrez RStudio et copiez le code ci-dessous :

# Configuration du proxy (si nécessaire)
# Sys.setenv(https_proxy = "http://login:mdp@proxy:port")

# Installation des packages
install.packages('tidyverse')
install.packages('rvest')

# Chargement en mémoire des packages
library(tidyverse)
library(rvest)

page_actualites <- read_html("https://statbel.fgov.be/fr/nouvelles")

# Titre 
page_actualites %>% html_elements("h3") %>% html_text()

# Thème

# Résumé

# Date de publication

# URL de l'article

Vous pouvez exécuter les différentes lignes afin d’installer puis charger les packages, extraire la page web de Statbel, puis d’afficher les dix titres d’actualité. Vous pouvez ensuite explorer le code source de Statbel et extraire le thème, le résume, la date de publication et l’URL de l’article.

Voici la correction pour poursuivre ce cours, en utilisant html_element afin d’extraire uniquement la première actualité et ne pas alourdir le document :

# Catégories
page_actualites %>% html_element("div.views-field-field-theme") %>% html_text()
[1] "Indicateurs conjoncturels"
# Résumé 
page_actualites %>% html_element("div.views-field-body") %>% html_text()
[1] "Au premier trimestre 2024, le coût salarial par heure travaillée augmente de 2,1% sur base annuelle. Au niveau des secteurs, le coût salarial par heure travaillée connaît sa plus forte..."
# Dates de publication
page_actualites %>% html_element("div.field-content time") %>% html_text()
[1] "31 mai 2024"
page_actualites %>% html_element("time") %>% html_text()
[1] "31 mai 2024"
# URL de l'article
page_actualites %>% html_element("h3 a") %>% html_attr("href")
[1] "https://statbel.fgov.be/fr/themes/indicateurs-conjoncturels/emploi/indice-du-cout-de-la-main-doeuvre"

2.1.2 Risques des extractions isolées

Il est important de penser que la structure des contenus est variable. Tenter d’extraire chaque vecteur d’informations séparément, comme nous venons de faire, est risqué car certains articles peuvent omettre des éléments présents dans d’autres, tels qu’un texte d’introduction ou un thème. Cela va entraîner des vecteurs de tailles différentes, et vous serez incapable de savoir regrouper les données collectées.

La solution idéale pour contourner ce problème consiste à cibler votre extraire à partir d’une balise englobante l’ensemble de l’information que vous voulez obtenir. Et ensuite d’extraire, dans chaque ensemble les éléments que vous souhaitez. Cette méthode assure que chaque vecteur d’informations correspond à un article entier, avec des données positionnées de manière cohérente, même si certaines informations sont manquantes.

Balise regroupant une actualité

Pour Statbel, il faut donc extraire le bloc contenant toute l’actualité. Sur la capture ci-dessus, vous pouvez voir que la balise div avec la classe “views-row” contient tous les éléments que nous recherchons. Et, si vous faites l’expérience, vous découvrirez que toutes les actualités sont contenues, chacune, dans une balise identique. Le code ci-dessous devrait donc être efficace pour extraire les dix actualités :

page_actualites %>% html_elements("div.views-row")
{xml_nodeset (12)}
 [1] <div class="views-row">\n<div class="views-field views-field-field-image ...
 [2] <div class="views-row">\n<div class="views-field views-field-field-image ...
 [3] <div class="views-row">\n<div class="views-field views-field-field-image ...
 [4] <div class="views-row">\n<div class="views-field views-field-field-image ...
 [5] <div class="views-row">\n<div class="views-field views-field-field-image ...
 [6] <div class="views-row">\n<div class="views-field views-field-field-image ...
 [7] <div class="views-row">\n<div class="views-field views-field-field-image ...
 [8] <div class="views-row">\n<div class="views-field views-field-field-image ...
 [9] <div class="views-row">\n<div class="views-field views-field-field-image ...
[10] <div class="views-row">\n<div class="views-field views-field-field-image ...
[11] <div class="views-row">Index van werknemers en werkzame personen - t-202 ...
[12] <div class="views-row">Bouwvergunningen - m-2024-02 <br><time datetime=" ...

En l’exécutant, on découvre que ce code extrait plus de dix actualités, ce qui n’est pas normal. Notre code collecte donc plus d’éléments et nous devons résoudre cela avant de poursuivre. En observant le code source, on remarque que le calendrier de diffusion est balisé de manière identique aux actualités, notre extraction est donc trop “large” et doit être reprise.

En analysant le code source, on remarque que le bloc d’actualité est entouré par une balise <div class='view-news-list'> et cette balise exclue le calendrier de diffusion. Nous devons donc demander en CSS3 d’extraire les balises <div class='view-row'> contenues dans la balise <div class='view-news-list'>. Voici le code pour faire cela :

page_actualites %>% html_elements("div.view-news-list div.views-row")
{xml_nodeset (10)}
 [1] <div class="views-row">\n<div class="views-field views-field-field-image ...
 [2] <div class="views-row">\n<div class="views-field views-field-field-image ...
 [3] <div class="views-row">\n<div class="views-field views-field-field-image ...
 [4] <div class="views-row">\n<div class="views-field views-field-field-image ...
 [5] <div class="views-row">\n<div class="views-field views-field-field-image ...
 [6] <div class="views-row">\n<div class="views-field views-field-field-image ...
 [7] <div class="views-row">\n<div class="views-field views-field-field-image ...
 [8] <div class="views-row">\n<div class="views-field views-field-field-image ...
 [9] <div class="views-row">\n<div class="views-field views-field-field-image ...
[10] <div class="views-row">\n<div class="views-field views-field-field-image ...

Le premier segment du code cible tous les éléments <div> qui possèdent la classe view-news-list. Le deuxième segment du code indique, qu’à l’intérieur du <div> précédemment sélectionné avec la classe view-news-list, le sélecteur doit maintenant chercher d’autres <div> ayant la classe views-row. Voici l’écriture en langage XPath :

page_actualites %>% html_elements(xpath="//div[contains(@class,'view-news-list')]//div[@class = 'views-row']")

Nous savons maintenant extraire la liste des dix actualités, nous allons conserver cette liste en créant un nouveau objet liste_actu :

liste_actu <- page_actualites %>% html_elements("div.view-news-list div.views-row")

Cet objet R est une liste de dix éléments (vous pouvez d’ailleurs observer cet objet directement en RStudio à partir de votre environnement). Et chaque élément de cette liste est une partie de code source à partir de laquelle il est possible d’appliquer de nouvelle fonction html_element et html_text. En R, pour parcourir une liste, il faut utiliser le sélecteur [[ ]] en indiquant l’index de l’élément que l’on cherchant (l’index début à 1). Pour illustrer, nous allons à présent créer un objet actu à partir du premier élément de la liste (donc de la première actualité). À partir de ce nouveau objet actu, on peut appliquer les mêmes sélecteurs CSS3 pour obtenir le titre, la date, le thème et le résume de cette actualité :

# Exploration de la première actu 
actu <- liste_actu[[1]]

actu %>% html_element("h3") %>% html_text() # Titre
[1] "Hausse de l’indice du coût de la main-d’œuvre au premier trimestre 2024"
actu %>% html_element("time") %>% html_text() # Date
[1] "31 mai 2024"
actu %>% html_element("div.views-field-field-theme") %>% html_text() # Thème
[1] "Indicateurs conjoncturels"
actu %>% html_element("div.views-field-body") %>% html_text() # Résumé
[1] "Au premier trimestre 2024, le coût salarial par heure travaillée augmente de 2,1% sur base annuelle. Au niveau des secteurs, le coût salarial par heure travaillée connaît sa plus forte..."

En XPath, il faut indiquer un . pour spécifier que l’on souhaite repartir de la dernière balise extraite. En effet, l’objet conserve l’information sur l’ensemble du site web. Voici l’ecriture :

actu %>% html_element(xpath = ".//h3") %>% html_text()
actu %>% html_element(xpath = ".//time") %>% html_text()
actu %>% html_element(xpath = ".//div[@class='views-field-field-theme']") %>% html_text()
actu %>% html_element(xpath = ".//div[@class='views-field-body']") %>% html_text()

2.1.3 Rebond sur d’autres URL

Nous avons ainsi extrait le titre, le thème, la date de publication et le résumé de chaque actualité sur la première page d’actualités de Statbel. Pour terminer cette première étape d’exploration, nous allons à présent extraire le texte complet de l’actualité, et non simplement le résumé. Pour cela, nous avons besoin d’accéder à l’article complet, et donc avant à l’URL de l’article. Nous devons donc localiser la balise <a> contenant l’URL puis extraire celle-ci à l’aide de la fonction html_attr.

url_article <- actu %>% html_element("h3 a") %>% html_attr("href")

Maintenant que nous avons extrait l’URL de cet article, nous pouvons extraire le code source de cette URL. Notez que contrairement à l’URL initiale de la liste des actualités de Statbel, cette URL n’est pas connue au moment de lancer le programme de webscraping. Il s’agit là d’une collecte dynamique d’information et de rebond d’une URL à une autre. Une fois l’extraction effectuée, il est possible d’explorer cette nouvelle page et d’en extraire les données comme pour la page initiale.

page_article <- read_html(url_article)

Dans cette section, nous avons exploré les fonctions essentielles pour localiser et extraire des informations à partir d’une page web, en utilisant des sélecteurs CSS ou avec le language XPath. Dans le cas d’une extraction d’un bloc d’informations, Le processus commence par bien analyser le code source de la page web, d’identifier la balise générale qui encapsule l’ensemble des informations du bloc et, ensuite d’extraire chaque élément individuellement. Cette méthode assure que toutes les données seront collectées de manière structurée, même en l’absence de certains éléments.

Pour autant, les extractions abordées dans cette section sont ponctuelles et ne permettent pas d’obtenir une base de données complètes. Pour cela, nous allons voir comment systématiser l’extraction et regrouper les données obtenues.

2.2 Récupération d’un article d’actualité

A partir des éléments abordés lors de la section précédente, nous allons voir dans cette section comment extraire une actualité de Statbel et structurer toute l’information sous la forme de tableau. Cette section aborde les étapes de création et de remplissage de tableau. Pour autant, ce cours ne se substitue pas à une formation d’utilisation de R, et nous nous limiterons aux étapes les plus élémentaires.

2.2.1 Création d’une base de données

Avant de créer une base de données pour y stocker les informations collectées, vous devez réfléchir à la structure de vos données. Dans un premier temps, posez vous la question de la définition d’une ligne. Est-ce une actualité, un jour de données, un individu, un ménage, un post facebook ? Comprendre clairement la nature de chaque ligne est essentiel pour pouvoir ensuite préciser les colonnes de votre base de données. Ici, nous cherchons à collecter des actualités, et chaque ligne constituera une actualité distincte. Et chaque colonne sera un élément de cette actualité.

Avec le package tidyverse, il est possible de créer une base de données avec la fonction tibble. Il faut alors indiquer le nom de chaque colonne à créer ainsi que le format de la colonne (character ou numeric). Je vous conseille de créer initialement des colonnes en format caractère, puis éventuellement de convertir ces données plus tard :

tableau_actu <- tibble(
  TX_TITRE = character(),
  TX_DATE = character(),
  TX_CATEGORIE = character(),
  TX_RESUME = character(),
  TX_TEXTE = character()
)

tableau_actu
# A tibble: 0 × 5
# ℹ 5 variables: TX_TITRE <chr>, TX_DATE <chr>, TX_CATEGORIE <chr>,
#   TX_RESUME <chr>, TX_TEXTE <chr>

Vous pouvez également employer la fonction tibble pour créer une base de données en y incluant automatiquement une première ligne de données. Pour ce faire, il est nécessaire de spécifier le nom de chaque colonne ainsi que l’information correspondante à y stocker lors de la création du tibble. Dans ce cas, le type de données de chaque colonne (character ou numeric) est déterminé automatiquement en fonction de la nature des valeurs ajoutées. Cette fonctionnalité sera exploitée lors de l’automatisation du code plus tard.

2.2.2 Extraction de l’actualité

Le code ci-dessous reprend tous les éléments présentés dans la section précédente. Nous commençons par extraire la page des actualités de Statbel et lister les 10 blocs d’actualités. Puis, en sélectionnant la première actualité, nous extrayons chaque information que nous assignons dans des objets séparés. Ici, le code n’affiche rien à l’écran car tout est stocké sous forme d’objet R.

url <- "https://statbel.fgov.be/fr/nouvelles"

page_actualites <- read_html(url)

liste_actu <- page_actualites %>% html_elements("div.view-news-list div.views-row")

actu <- liste_actu[[1]]

# Extraire les informations de l'actualité
titre <- actu %>% html_element("h3") %>% html_text()
date <- actu %>% html_element("time") %>% html_text()
categorie <- actu %>% html_element("div.views-field-field-theme") %>% html_text()
resume <- actu %>% html_element("div.views-field-body") %>% html_text()

# Récupérer l'URL de l'article et l'extraire
url_article <- actu %>% html_element("h3 a") %>% html_attr("href")
page_article <- read_html(url_article)

# Extraire le texte de l'article
texte_article <- page_article %>% html_element("div.field--name-body") %>% html_text()

2.2.3 Compléter le tableau

Les objets ainsi créés ne constituent pas encore une base de données. Nous devons ajouter une ligne dans le tableau pour structurer l’information. La fonction add_row permet, à partir d’un tableau précédemment créé, d’ajouter une ligne en indiquant la valeur à assigner à chaque colonne. En utilisant la fonction add_row, vous vous assurez de ne jamais écraser les données de votre tableau.

tableau_actu <- tableau_actu %>% 
  add_row(TX_TITRE = titre,
          TX_DATE = date,
          TX_CATEGORIE = categorie,
          TX_RESUME = resume,
          TX_TEXTE = texte_article)

tableau_actu
# A tibble: 1 × 5
  TX_TITRE                               TX_DATE TX_CATEGORIE TX_RESUME TX_TEXTE
  <chr>                                  <chr>   <chr>        <chr>     <chr>   
1 Hausse de l’indice du coût de la main… 31 mai… Indicateurs… Au premi… "Au pre…

Voilà, nous savons à présent collecter l’ensemble des informations d’une actualité et stocker cette information dans une base de données. Celle-ci comporte une seule ligne et autant de colonnes que le nombre d’information distinctes à stocker.

Néanmoins, à ce stade, on peut douter de la pertinence d’utiliser R et autant de ligne de code pour collecter aussi peu d’informations. Un simple copier-coller sera de fait bien plus efficace. Mais, avec quelques changements, les codes présentés ci-dessus vont permettre de collecter d’abord les 10 actualités d’une page web de Statbel, puis l’ensemble des actualités de tout le site web.

2.3 Extraction d’une page d’actualités

Nous allons à présent appliquer les fonctions vues précédemment pour extraire l’ensemble des dix actualités présentes sur la première page d’actualités de Statbel. En observant le code ci-dessus, la seule différence consistera à modifier l’étape suivante :

actu <- liste_actu[[1]]

2.3.1 Création d’une fonction

En effectuant une incrémentation de 1 à 10, nous modifions le contenu de l’objet actu, pour ensuite extraire et stocker les informations dans le tableau tableau_actu. Nous allons développer une fonction actu_to_table qui, à partir d’une actualité donnée en entrée, retourne un tableau. Ce tableau contiendra une ligne avec les informations précisément extraites de l’actualité correspondante.

actu_to_table <- function(actu){
  
  # Extraire les informations de l'actualité
  titre <- actu %>% html_element("h3") %>% html_text()
  date <- actu %>% html_element("time") %>% html_text()
  categorie <- actu %>% html_element("div.views-field-field-theme") %>% html_text()
  resume <- actu %>% html_element("div.views-field-body") %>% html_text()
  
  # Récupérer l'URL de l'article et l'extraire
  url_article <- actu %>% html_element("h3 a") %>% html_attr("href")
  page_article <- read_html(url_article)
  Sys.sleep(2)
  
  # Extraire le texte de l'article
  texte_article <- page_article %>% html_element("div.field--name-body") %>% html_text()
  
  tibble(TX_TITRE = titre,
          TX_DATE = date,
          TX_CATEGORIE = categorie,
          TX_RESUME = resume,
          TX_TEXTE = texte_article)
}

Remarque : Dans le cadre d’une fonction, toute assignation faite avec <- reste confinée à la fonction, et les modifications sont perdues après l’exécution de la fonction. Au lieu d’utiliser l’opérateur d’assignation habituel <-, vous pouvez utiliser la flèche <<-. L’utilisation de <<- permet d’assigner des valeurs à des variables qui résident dans l’environnement global, plutôt que dans l’environnement local de la fonction.

La fonction actu_to_table contient une étape de scraping avec la fonction read_html. Lorsque vous exécutez un programme de webscraping qui interroge fréquemment un site web, il est crucial de gérer attentivement la fréquence à laquelle les requêtes sont envoyées. Ceci est important pour plusieurs raisons, notamment pour éviter de surcharger les serveurs du site avec un volume élevé de requêtes en peu de temps, ce qui pourrait mener à un ralentissement du serveur, voire à un blocage de votre accès par l’administrateur·rice du site. Pour contrôler la cadence des requêtes, on utilise souvent la fonction Sys.sleep en R, qui permet de mettre en pause l’exécution du script pendant un nombre spécifié de secondes.

Intégrer Sys.sleep après chaque appel à read_html est une pratique courante en webscraping. Cette méthode aide à simuler un comportement de navigation plus “humain”, réduisant ainsi le risque d’être identifié comme un robot par les mécanismes de protection du site. Par exemple, après avoir extrait le contenu d’une page, le script peut attendre quelques secondes avant de passer à la suite.

2.3.2 Usage des boucles

A présent, nous devons aborder les boucles pour appliquer cette nouvelle fonction aux dix actualités. La boucle for est l’une des plus simples à utiliser dans ce cadre, voici l’écriture avec un exemple simple qui incrémente de 1 à 10 une variable i pour en prendre la racine carré :

for (i in 1:10){
  print(sqrt(i))
}
[1] 1
[1] 1.414214
[1] 1.732051
[1] 2
[1] 2.236068
[1] 2.44949
[1] 2.645751
[1] 2.828427
[1] 3
[1] 3.162278

Remarque : lors de l’utilisation de boucles for en programmation, les résultats des calculs effectués à l’intérieur de la boucle ne sont pas automatiquement affichés dans la console. Pour visualiser ces résultats pendant l’exécution de la boucle, il est nécessaire d’intégrer explicitement la fonction print. Cette pratique est particulièrement utile pour le débogage ou le suivi de l’avancement des calculs, notamment dans des processus itératifs longs ou complexes.

Avec le package tidyverse, il est possible d’utiliser la fonction map pour appliquer une même fonction à un vecteur. Nous pouvons appliquer ceci avec notre exemple ci-dessus. La commande 1:10 permet d’obtenir un vecteur numérique allant de 1 à 10. On peut donc appliquer à ce vecteur la fonction sqrt via la fonction map.

1:10 %>% map(sqrt)
[[1]]
[1] 1

[[2]]
[1] 1.414214

[[3]]
[1] 1.732051

[[4]]
[1] 2

[[5]]
[1] 2.236068

[[6]]
[1] 2.44949

[[7]]
[1] 2.645751

[[8]]
[1] 2.828427

[[9]]
[1] 3

[[10]]
[1] 3.162278

Remarque : la sortie d’une fonction map est une liste dont les éléments sont identifiés avec des [[ ]]. Les listes permettent de contenir des éléments de nature différentes. Si vous souhaitez annuler cette liste et obtenir les éléments sous la forme d’un vecteur, il faut utiliser la fonction unlist :

1:10 %>% map(sqrt) %>% unlist
 [1] 1.000000 1.414214 1.732051 2.000000 2.236068 2.449490 2.645751 2.828427
 [9] 3.000000 3.162278

2.3.3 Application de la fonction

Avec cette nouvelle fonction disponible, quelques lignes de codes permettent d’extraire les dix premières actualités de la page web d’actualité de Statbel. Voyons d’abord comment faire cela avec la boucle for :

page_actualites <- read_html("https://statbel.fgov.be/fr/nouvelles")

liste_actu <- page_actualites %>% html_elements("div.view-news-list div.views-row")

tableau_actu <- tibble(
  TX_TITRE = character(),
  TX_DATE = character(),
  TX_CATEGORIE = character(),
  TX_RESUME = character(),
  TX_TEXTE = character()
)

for (i in 1:10){
  print(i) # Afficher la progression de la boucle
  tableau_actu <- tableau_actu %>% 
    add_row(actu_to_table(liste_actu[[i]]))
}

La fonction map permet également d’atteindre le même objectif. Comme expliqué ci-dessus, la fonction map renvoit une liste d’élément, ce qui ne convient pas à notre objectif, nous souhaitons obtenir, à partir des éléments obtenue, une base de données. La fonction map_df (pour dataframe) permet d’appliquer à un vecteur une fonction, et de mettre les résultats sous la forme d’un tableau. Ici, cette fonction permet d’obtenir directement le tableau_actu :

La fonction map peut aussi être utilisée pour atteindre un objectif similaire, mais comme mentionné précédemment, elle renvoie une liste d’éléments, ce qui ne correspond pas tout à fait à notre besoin de structurer les données sous forme d’une base de données. Pour résoudre ce problème, la fonction map_df (où “df” signifie dataframe) s’avère utile. Cette fonction permet d’appliquer une fonction spécifique à chaque élément d’un vecteur et de compiler les résultats directement sous forme de tableau. Dans notre cas, map_df facilite la création et le remplissage du tableau_actu, en transformant chaque résultat en une ligne du tableau de données :

page_actualites <- read_html("https://statbel.fgov.be/fr/nouvelles")
liste_actu <- page_actualites %>% html_elements("div.view-news-list div.views-row")

tableau_actu <- liste_actu %>% map_df(actu_to_table)

Le tableau tableau_actu contient à présent dix lignes et cinq colonnes et l’ensemble des dix actualités de la première page de Statbel.

tableau_actu
# A tibble: 10 × 5
   TX_TITRE                              TX_DATE TX_CATEGORIE TX_RESUME TX_TEXTE
   <chr>                                 <chr>   <chr>        <chr>     <chr>   
 1 194 faillites durant la semaine 20    23 mai… Entreprises  Durant l… "Durant…
 2 Modification des codes INS des commu… 22 mai… À propos de… Le code … "Le cod…
 3 Hausse de 1,6% du volume des ventes … 22 mai… Indicateurs… Le volum… "Le vol…
 4 Les femmes et les jeunes générations… 22 mai… Census       En Belgi… "En Bel…
 5 Baisse de 2,2% du volume des ventes … 22 mai… Indicateurs… Services… "Servic…
 6 28.157.734 animaux abattus en avril … 22 mai… Agriculture… Abattage… "Abatta…
 7 59 millions de litres de lait de con… 21 mai… Agriculture… En janvi… "En jan…
 8 2.444.610 nuitées en février 2024     21 mai… Entreprises  Le nombr… "Le nom…
 9 Mortalité jusqu’au 5 mai              17 mai… Population   Statbel … "Statbe…
10 Avril 2024: 925 faillites             17 mai… Entreprises  En avril… "En avr…

Comme vous pouvez observer, une fois la fonction actu_to_table, quelques lignes de code permettent d’obtenir toute l’information d’une page web. Nous obtenons un tableau en format R, mais il est aisé de l’exporter en format CSV ou Excel. Attention, lorsque vous indiquez le chemin d’accès où exporter le fichier, vous devez indiquer les slash / au lieu des habituels antislash de Windows \. Il faut indiquer la version 2 de la fonction pour avoir le format CSV lisible en Europe avec des points virgules.

write_excel_csv2(tableau_actu,file="C:/chemin/vers/vos/données/data.csv")

Voilà, nous savons comment créer un tableau, une fonction, puis extraire une page web et en collecter les informations pour les structurer en base de données. Nous savons également à présent comment sauvegarder l’information sur la forme d’un fichier lisible en Excel. Mais ici, nous nous sommes limités à une seule page web. Bien que le code est à présent efficace pour l’extraction des dix actualités, l’objectif est à présent d’aller sur les pages web suivantes du même site Internet pour collecter non plus 10, mais plusieurs milliers d’actualité. C’est l’objet de la prochaine section.

Nous avons appris à créer un tableau et une fonction, à extraire les informations d’une page web et à les structurer en base de données. De plus, nous savons comment sauvegarder ces informations sous forme d’un fichier compatible avec Excel. Cependant, jusqu’ici, notre approche s’est limitée à une seule page web. Bien que notre code soit optimisé pour extraire les informations de dix actualités, notre objectif est d’étendre le webscraping aux pages suivantes du même site internet. L’objectif est de collecter non pas seulement une dizaine, mais des centaines ou millieurs d’actualités.

2.4 Extraction de l’ensemble du site web

2.4.1 Comprendre comment accéder aux autres pages

En date du 31/05/2024, le site de Statbel contient 288 pages d’actualités, chacune contenant 10 actualités. Il y a donc près de 3.000 actualités pouvant être collectées. Il faut pour cela comprendre comment avoir accès aux différentes pages web. En observant la première page, on découvre qu’il existe une pagination en bas de page avec un bouton pour accéder à la page 2 à 9, un bouton pour accéder à la page suivante et un bouton pour accéder pour accéder à la dernière page. Une méthode possible serait de localiser le bouton ‘page suivante’ pour en extraire l’URL. Ainsi, après chaque boucle sur les 10 actualités, on changerait de page web à partir de cette nouvelle URL. Il s’agit d’un exercice intéressant à faire en terme alogrithmique, mais ce n’est pas ce que nous allons faire ici.

Au 1er juin 2024, le site de Statbel présente 288 pages d’actualités, chacune contenant 10 articles, totalisant ainsi près de 3 000 actualités à collecter. Pour accéder à toutes ces pages, vous devez comprendre le mécanisme de navigation entre les différentes pages du site. L’observation de la première page révèle un système de pagination situé au bas de la page. Ce système inclut des boutons permettant de passer directement aux pages 2 à 9, un bouton pour aller à la page suivante, ainsi qu’un bouton pour atteindre la dernière page. Une approche pour automatiser le parcours de ces pages consisterait à identifier et extraire l’URL du bouton ‘page suivante’ à chaque fois, permettant ainsi de naviguer progressivement à travers les pages après chaque lot de 10 actualités. Cela représente un exercice en R intéressant, cependant nous allons explorer une méthode différente dans ce contexte, bien plus simple.

Lorsqu’on clique sur le bouton de la page 2 du site web, on change de page web et on obtient cette URL de destination : https://statbel.fgov.be/fr/nouvelles?fulltext=&field_publication_date_value%5Bmin%5D=&field_publication_date_value%5Bmax%5D=&page=1. Nous allons décoder tous les éléments de cette URL :

  • https://statbel.fgov.be/fr/nouvelles : Il s’agit de l’URL de base du site Internet. C’est cette URL que nous utilisons pour notre première extraction, et elle reste identique pour les pages suivantes

  • ?fulltext= : Le ? permet de déclarer un premier paramètre à cette URL, ici sans doute une mise en format du texte. Le paramètre reste vide car immédiatemment après le = se trouve & qui est un séparateur entre deux paramètres.

  • &field_publication_date_value%5Bmin%5D=&field_publication_date_value%5Bmax%5D=& : De manière identique au paramètre ‘fulltext’, tous ces paramètres sont vides, nous pouvons les ignorer ici

  • page=1 : il s’agit de l’index de la page web d’actualités. ‘page=1’ correspond donc à la deuxième page du site Internet. Nous pouvons donc en déduire (et vous pouvez le vérifier) que ‘page=0’ correspond à la première page d’actualités

Les paramètres vides peuvent être ignorés, aussi l’URL https://statbel.fgov.be/fr/nouvelles?page=1 renvoit le même résultat. Voilà, nous allons exploiter cette possibilité d’accès aux pages à partir de l’URL de base et non en cherchant des URL dans les pages web, ce système aura l’avantage d’être bien plus simple à programmer.

Les paramètres vides dans une URL peuvent souvent être omis sans changer le résultat final. Par exemple, l’URL simplifiée https://statbel.fgov.be/fr/nouvelles?page=1 produit le même résultat que des versions avec paramètres vides. Le fait que l’index de la page peut être déclaré dans l’URL simplifie grandement notre approche de programmation, car elle permet de naviguer entre les pages en manipulant uniquement le paramètre de pagination directement depuis l’URL de base. En optant pour cette méthode, plutôt que de chercher et d’extraire des URL à partir du contenu de chaque page, nous bénéficions d’une programmation moins complexe et plus directe.

Nous allons commencer par créer un vecteur contenant les 288 pages à extraire. En pratique, pour éviter toute surcharge inutile des serveurs de Statbel, je vais me limiter ici aux 5 premières pages. Nous avons vu précédemment que la commande 1:5 crée un vecteur de 1 à 5. Nous allons combiner cela avec une nouvelle fonction paste permettant de concaténer des valeurs et/ou des vecteurs. Nous allons concaténer la chaîne de caractère “https://statbel.fgov.be/fr/nouvelles?page=” avec le vecteur 1:5, provoquant en sortie en vecteur de 5 chaînes de caractères pour les cinq URL. La fonction paste requiert un argument sep pour indiquer le séparateur à utiliser. Par défaut, paste utilise un espace comme séparateur entre chaque élément à concaténer :

vecteur_url <- paste("https://statbel.fgov.be/fr/nouvelles?page=",1:5,sep="") 
vecteur_url
[1] "https://statbel.fgov.be/fr/nouvelles?page=1"
[2] "https://statbel.fgov.be/fr/nouvelles?page=2"
[3] "https://statbel.fgov.be/fr/nouvelles?page=3"
[4] "https://statbel.fgov.be/fr/nouvelles?page=4"
[5] "https://statbel.fgov.be/fr/nouvelles?page=5"

2.4.2 Code complet

Nous avons à présent toutes les informations et toutes les fonctions nécessaires pour extraire toutes les actualités du site web. Comme précédemment, nous allons voir comment rédiger le code avec des boucles for puis avec des fonctions map.

2.4.2.1 Avec des boucles for

Nous allons commencer par déclarer le tableau qui contiendra toutes les données et le vecteur des pages à scraper. Ensuite, nous devons effectuer une première boucle for pour parcourir chaque page web. Puis, au sein de chaque page, nous devons effectuer une seconde boucle for pour parcourir chaque actualité. Chaque actualité sera ajouté dans le tableau global. Dans ce genre de double boucle, il est intéressant d’ajouter des fonctions print afin de savoir en temps réel l’état d’avancement du code.

# Déclaration du tableau
tableau_actu <- tibble(
  TX_TITRE = character(),
  TX_DATE = character(),
  TX_CATEGORIE = character(),
  TX_RESUME = character(),
  TX_TEXTE = character()
)

# Déclaration des pages d'actualités
vecteur_url <- paste("https://statbel.fgov.be/fr/nouvelles?page=",1:5,sep="") 

# Boucle sur les pages
for (url in vecteur_url){
  
  print(url) # Afficher l'URL en cours d'extraction
  
  page_actualites <- read_html(url)
  Sys.sleep(1)
  liste_actu <- page_actualites %>% html_elements("div.view-news-list div.views-row")
  
  # Boucle sur les actualités
  for (i in 1:10){
    
    print(i) # Afficher la progression de la boucle
    tableau_actu <- tableau_actu %>% 
      add_row(actu_to_table(liste_actu[[i]]))
    
  }
}

2.4.2.2 Avec la fonction map

Avec la fonction map, il n’est pas nécessaire de créer le tableau en avance, car nous allons regrouper toutes les lignes de la fontion actu_to_table sous forme du tableau souhaité. Par contre, enchaîner deux étapes map peut rendre le code assez complexe à lire (même si cela est tout à fait faisable. Une manière plus élégante est de passer à nouveau par la logique de la création de fonction. Nous allons créer une fonction qui prend en entrée une url et qui donne en sortir le tableau avec les dix actualités.

L’utilisation de la fonction map présente l’avantage de ne pas nécessiter la création préalable du tableau, car elle permet de regrouper directement toutes les lignes issues de la fonction actu_to_table dans le tableau désiré. Cependant, enchaîner plusieurs étapes avec map peut rendre le code difficile à lire, même si techniquement, cela reste une approche viable. Pour rendre le code plus clair et élégant, il est judicieux de revenir à une approche basée sur la création de fonctions spécifiques. Nous allons donc développer une nouvelle fonction qui prend une URL en entrée et retourne en sortie un tableau contenant les dix actualités extraites de cette URL.

url_to_table <- function(url){
  
  # Extraction de l'URL
  page_actualites <- read_html(url)
  Sys.sleep(1)
  
  # Liste des actualités
  liste_actu <- page_actualites %>% html_elements("div.view-news-list div.views-row")
  
  # actu_to_table sur la liste des actualités
  liste_actu %>% map_df(actu_to_table)
  
}

Avec cette nouvelle fonction, l’ensemble du code se résume à deux lignes de code : une pour définir les url à scraper, l’autre pour scraper ces URL pour stocker l’ensemble des informations sous forme d’une base de données.

Avec l’introduction de cette nouvelle fonction, l’ensemble du processus de scraping se simplifie considérablement, se réduisant à seulement deux lignes de code. La première ligne est destinée à définir la liste des URLs à scraper. La seconde ligne utilise la fonction créée pour extraire et compiler les informations de ces URLs, stockant les informations extraites dans une base de données.

# Déclaration des pages d'actualités
vecteur_url <- paste("https://statbel.fgov.be/fr/nouvelles?page=",1:5,sep="")

tableau_actu <- vecteur_url %>% map_df(url_to_table)

Et voici notre tableau avec toutes les données :

tableau_actu
# A tibble: 50 × 5
   TX_TITRE                              TX_DATE TX_CATEGORIE TX_RESUME TX_TEXTE
   <chr>                                 <chr>   <chr>        <chr>     <chr>   
 1 194 faillites durant la semaine 20    23 mai… Entreprises  Durant l… "Durant…
 2 Modification des codes INS des commu… 22 mai… À propos de… Le code … "Le cod…
 3 Hausse de 1,6% du volume des ventes … 22 mai… Indicateurs… Le volum… "Le vol…
 4 Les femmes et les jeunes générations… 22 mai… Census       En Belgi… "En Bel…
 5 Baisse de 2,2% du volume des ventes … 22 mai… Indicateurs… Services… "Servic…
 6 28.157.734 animaux abattus en avril … 22 mai… Agriculture… Abattage… "Abatta…
 7 59 millions de litres de lait de con… 21 mai… Agriculture… En janvi… "En jan…
 8 2.444.610 nuitées en février 2024     21 mai… Entreprises  Le nombr… "Le nom…
 9 Mortalité jusqu’au 5 mai              17 mai… Population   Statbel … "Statbe…
10 Avril 2024: 925 faillites             17 mai… Entreprises  En avril… "En avr…
# ℹ 40 more rows

A l’issue de ce première exemple avec le site Internet Statbel, nous avons exploré les étapes fondamentales pour extraire et manipuler des données depuis le web. Vous avez appris à configurer votre environnement dans RStudio, à installer et charger des packages essentiels, et à exécuter vos premiers scripts de webscraping. Le webscraping doit surtout être appris en étant confronté à des situations différentes, aussi nous allons reprendre les mêmes techniques de webscraping pour extraire des informations sur le site Internet Wikipédia. Ce sera l’objet de la section suivante. Par ailleurs, l’expérimentation est une technique d’apprentissage très efficace en webscraping. Donc si vous avec dès à présent une idée d’un site web contenant des données archivées sous un format plus ou moins proches que celles présentes sur le site de Statbel, n’hésitez pas à explorer dès à présent son code source et coder votre propre programme de webscraping.

3 Extraction du site web Wikipédia

Ce deuxième exemple de webscraping va réutiliser les fonctions vu précédemment pour les appliquer sur un nouveau projet. Chaque site web est différent donc les sélecteurs CSS3 devront être adaptés. Mais aussi, chaque logique d’extraction est différente. Ainsi, tout en gardant identique le niveau de webscraping et les fonctions à connaître, analyser un autre projet permettant de généraliser les procédures. Pour cet exemple, sauf nécessité particulière, nous n’utiliseront que les sélecteurs CSS3 dans nos codes.

Il y a plusieurs raisons pour choisir Wikipédia pour ce deuxième exemple :

  • Wikipédia est librement accessible : Toute production réalisée sur Wikipédia est libre d’accès à quiconque, nous pouvons donc extraire sans problème des contenus pour les analyser

  • Wikipédia est pérenne : Bien sûr, il n’est pas possible de prédire l’avenir du site web, mais il s’agit d’un des plus vieux site web de compilation d’information, avec une structure HTML n’ayant que très peu évolué au fil du temps. Ceci permettra au code présenté ici de fonctionner encore dans quelques années, à moindre frais d’adaptation.

  • Wikipédia contient des informations structurées, des tableaux, des corpus, des images, tout ce dont nous pourrons avoir à traiter comme exemple.

  • Wikipédia a une structure HTML simple à comprendre et à exploiter

Notre première cible sera l’article wikipédia sur la France. Celui-ci contient un long contenu texte, des encarts, des tableaux, des images, un historique riche. L’extraction se réalise à nouveau avec la fonction read_html :

page_france <- read_html("https://fr.wikipedia.org/wiki/France")

3.1 Extraction d’un encadré

Il nous faut à présent choisir un objectif d’extraction, c’est à dire une partie du site web que nous souhaitons obtenir sous la forme d’un tableau. Dans la grande majorité des articles de Wikipédia, un tableau récapitulatif est est affiché en haut à droite de l’article avec certaines informations structurées. Voici la capture de d’une partie de ce tableau en février 2023 pour l’article sur la France :

Pour ce premier exercice, nous allons extraire les informations de cet encadré “Administration” et les structurer en tableau :

Objectif d’extraction
TX_ENCADRE TX_CATEGORIE TX_INFO
Administration Forme de l’état République unitaire semi-présidentielle
Administration Président de la république Emmanuel Macron
Administration

Nous allons réaliser ceci en conversant en mémoire deux objectifs plus généraux :

  1. de pouvoir extraire ensuite les autres encadrés de l’article sur la France (exemples : géographie, histoire, démographie, économie, divers)

  2. de pouvoir extraire ces encadrés pour d’autres pages Wikipédia sur d’autres pays. Ainsi, comme objectif de long terme, nous visons l’obtention d’un tableau récapitulatif de tous les pays avec chaque information correctement structurée.

Bien entendu, comme pour l’exemple de Statbel, si vous n’avez besoin que de ce tableau pour la France, il sera bien plus rapide de le créer et le remplir manuellement. Néanmoins, réaliser un copier-coller des données de Wikipédia est long et nous envisageons ici, à la fin de cette section, d’avoir toutes les valeurs des encadrés de tous les pays, c’est à dire plusieurs milliers de lignes. Nous avons également stocké la date de l’extraction des données, ainsi vous pourrons par la suite récupérer l’information à intervalle régulier, portant la taille de la base de données à plusieurs dizaines ou centaines de milliers de lignes. Le webscraping est alors tout indiqué pour réaliser cette tâche. Mais avant de voir si grand, revenons à l’extraction et la structuration de l’encadré “Administration” pour la page Wikipédia sur la France. Voici le code source ce cet encadré :

Vous remarquez que le titre “Administration” est présent ainsi que les premières entrées du tableau (“Forme de l’état”, “République”, etc.), englobés dans des balises HTML que nous allons utiliser pour extraire les informations. Nous allons commencer par lister toutes les balises <caption> de la page web avec la commande html_elements :

html_elements(page_france,"caption")
{xml_nodeset (10)}
 [1] <caption class="hidden" style=""> </caption>\n
 [2] <caption style="background-color:#e3e3e3;">Administration</caption>\n
 [3] <caption style="background-color:#e3e3e3;">Géographie</caption>\n
 [4] <caption style="background-color:#e3e3e3;">Histoire</caption>\n
 [5] <caption style="background-color:#e3e3e3;">Démographie</caption>\n
 [6] <caption style="background-color:#e3e3e3;">Économie</caption>\n
 [7] <caption style="background-color:#e3e3e3;">Développement</caption>\n
 [8] <caption style="background-color:#e3e3e3;">Divers</caption>\n
 [9] <caption>\nListe des membres du gouvernement Gabriel Attal depuis le <ti ...
[10] <caption>Principaux organismes\n</caption>

On remarque ici que neuf balises sont listées, et nous retrouvons notre balise concernant “Administration” en deuxième position. Nous détectons les autres titres de l’encadré de Wikipédia, mais aussi d’autres éléments ne concernant pas cet encadré. Il y a donc plusieurs balises <caption> dans le code source, 6 d’entre elles (2 à 7) concernent des titres dans l’encart Wikipédia, les autres étant d’autres éléments présents ailleurs sur la page. Pour nous limiter aux résultats de l’encart, nous devons être plus précis dans notre recherche.

En regardant les balises HTML parentes de notre balise <caption>, on trouve une balise <table> contenant l’encadré “Administration”, ainsi qu’une balise <div> contenant l’ensemble des encadrés. Pour trouver cela, une fois la fenêtre du code source ouverte sur votre navigateur, vous pouvez survoler les différentes balises et voir la partie du site web correspondante être surligné.

Ainsi, la balise <div> contenant l’attribut class = "infobox_v3 noarchive" contient les encadrés que nous cherchons à extraire, et uniquement ces encadrés. Et dans cette balise <div>, la deuxième balise <table> contient l’encadré “Administration”, et nous pouvons anticiper que chaque encadré est contenu dans une balise <table>. L’enjeu du webscraping se situe essentiellement sur ce point : trouver une balise HTML contenant ce que vous cherchez, sans oublier des éléments et aussi sans extraire trop d’éléments.

Ici, la balise <div> contient deux classes : “infobox_v3” et “noarchive”. Les différentes classes d’une balise sont séparées par un espace, et il possible d’extraire la balise en précisant l’une des classes. Ici nous allons utiliser la classe “infobox_v3”, car on anticipe qu’elle sera utilisé pour les autres encadrés :

html_elements(page_france,"div.infobox_v3")
{xml_nodeset (1)}
[1] <div class="infobox_v3 infobox infobox--frwiki noarchive">\n<div class="e ...

Ici, nous obtenons bien une seule balise <div>, mais notre objectif reste d’obtenir l’encadré “Administration”. Nous allons donc, à partir de cette première balise <div>, descendre dans l’arborescence du code source pour atteindre la balise <table> :

html_elements(page_france,"div.infobox_v3 table")
{xml_nodeset (9)}
[1] <table style="width:100%"><tbody>\n<tr>\n<td colspan="1" align="center">\ ...
[2] <table>\n<caption class="hidden" style=""> </caption>\n<tbody>\n<tr>\n<th ...
[3] <table>\n<caption style="background-color:#e3e3e3;">Administration</capti ...
[4] <table>\n<caption style="background-color:#e3e3e3;">Géographie</caption>\ ...
[5] <table>\n<caption style="background-color:#e3e3e3;">Histoire</caption>\n< ...
[6] <table>\n<caption style="background-color:#e3e3e3;">Démographie</caption> ...
[7] <table>\n<caption style="background-color:#e3e3e3;">Économie</caption>\n< ...
[8] <table>\n<caption style="background-color:#e3e3e3;">Développement</captio ...
[9] <table>\n<caption style="background-color:#e3e3e3;">Divers</caption>\n<tb ...

On remarque ici que l’on extrait huit tables, mais le code ici ne nous permet pas de savoir ce que nous avons effectivement extrait. Dans ce cas, vous devez manuellement afficher certains éléments de la liste pour en comprendre le contenu. Pour cela, il faut d’abord assigner le résultat de la fonction html_elements à un objet (qui sera une liste), puis de demander à R d’afficher un élément précis de cette liste avec son index entre deux crochets :

liste_encadres <- html_elements(page_france,"div.infobox_v3 table")
liste_encadres[[1]]
{html_node}
<table style="width:100%">
[1] <tbody>\n<tr>\n<td colspan="1" align="center">\n<span class="mw-image-bor ...
liste_encadres[[2]]
{html_node}
<table>
[1] <caption class="hidden" style=""> </caption>\n
[2] <tbody>\n<tr>\n<th scope="row" style="width:9em;"><a href="/wiki/Liste_de ...
liste_encadres[[3]]
{html_node}
<table>
[1] <caption style="background-color:#e3e3e3;">Administration</caption>\n
[2] <tbody>\n<tr>\n<th scope="row" style="width:9em;">Forme de l'État</th>\n< ...

Ici, la table “Administration” se trouve en troisième position de la liste, on retrouve ce texte dans la balise <caption>. Le premier élément de la liste ne contient pas de balise <caption>, tandis que le deuxième contient une balise <caption>vide. A ce stade, nous allons simplement choisir le troisième encadré, avant d’obtenir l’encadré “Administration” :

encadre_administration <- liste_encadres[[3]]

Une fonction du package rvest permet d’obtenir, l’ensemble du texte de cet élément, c’est à dire celui qui est affiché sur un navigateur internet. Néanmoins, ceci est tout aussi inutile que de sauvegarder l’ensemble du texte de la page Wikipédia. Sans structuration des données en tableaux, ces données restent essentiellement inutilisables (voir ci-dessous). On remarque tout de même que l’ensemble des informations que l’on souhaite obtenir s’y trouve (Forme de l’état, président de la république, …)

html_text(encadre_administration)
[1] "AdministrationForme de l'État\n\nRépublique unitaire semi-présidentielle\nPrésident de la République\n\nEmmanuel Macron\nPremier ministre\n\nGabriel Attal\nPrésident du Sénat\n\nGérard Larcher\nPrésidente de l'Assemblée nationale\n\nYaël Braun-Pivet\nParlement\n\nParlement\nChambre hauteChambre basse\n\nSénatAssemblée nationale\nLangue officielle\n\nFrançais\nCapitale\n\nParis48° 52′ N, 2° 19,59′ E\n"

En observant le code source de la table, vous remarquez qu’il s’agit d’un enchaînement de balises <tr> pour indiquer une nouvelle ligne, de balises <th> pour la colonne de gauche et de balises <td> pour la colonne de droite. Il serait possible d’extraire ainsi chaque information (il s’agirait même d’un bel exercice de boucles en R), mais nous allons ici récupérer l’information souhaitée d’une manière bien plus simple. En effet, le package rvest contient la fonction html_table qui automatise cette extraction et structure une table directement dans un tableau, dès lors que le tableau respecte le formatage HTML standard (ce qui est le cas ici).

html_table(encadre_administration)
# A tibble: 9 × 2
  X1                                  X2                                     
  <chr>                               <chr>                                  
1 Forme de l'État                     République unitaire semi-présidentielle
2 Président de la République          Emmanuel Macron                        
3 Premier ministre                    Gabriel Attal                          
4 Président du Sénat                  Gérard Larcher                         
5 Présidente de l'Assemblée nationale Yaël Braun-Pivet                       
6 Parlement                           Parlement                              
7 Chambre hauteChambre basse          SénatAssemblée nationale               
8 Langue officielle                   Français                               
9 Capitale                            Paris48° 52′ N, 2° 19,59′ E            

Nous obtenons ainsi un tableau avec deux colonnes, l’une pour la catégorie d’informations, et un pour l’information elle-même. Nous sommes très proches du résultat attendu, il nous faut pour cela renommer les deux colonnes, ajouter la colonne avec le nom de l’encadré, le nom du pays et la date d’extraction. Ces trois informations seront identiques pour toutes les lignes du tableau, mais rappelez vous l’objectif final d’extraire tous les encadrés, tous les pays, et à des moments différents.

Renommer les colonnes et ajouter la date nécessite l’utilisation de fonction commune de R :

table_administration <- html_table(encadre_administration) %>% 
  rename(TX_CATEGORIE = X1,
         TX_INFO = X2)

table_administration
# A tibble: 9 × 2
  TX_CATEGORIE                        TX_INFO                                
  <chr>                               <chr>                                  
1 Forme de l'État                     République unitaire semi-présidentielle
2 Président de la République          Emmanuel Macron                        
3 Premier ministre                    Gabriel Attal                          
4 Président du Sénat                  Gérard Larcher                         
5 Présidente de l'Assemblée nationale Yaël Braun-Pivet                       
6 Parlement                           Parlement                              
7 Chambre hauteChambre basse          SénatAssemblée nationale               
8 Langue officielle                   Français                               
9 Capitale                            Paris48° 52′ N, 2° 19,59′ E            

Pour ajouter le nom de l’encadré (ici “Administration”), il serait de créer manuellement une nouvelle colonne “TX_ENCADRE” avec la valeur “Administration”. Mais faire ceci ne serait pas très efficace, car nous devons anticiper l’automatisation pour l’ensemble des encadrés. Ainsi, il est préférable d’extraire le nom de l’encadré directement dans le code. Nous avions vu précédemment que le nom de l’encadré est contenu dans la balise <caption>, nous allons ici l’extraire à partir de l’objet encadre_administration. Comme nous nous attendons à un seul élément à extraire, nous pouvons utiliser la fonction html_element (sans le “s” en fin de fonction), celle-ci renvoi un objet seul et non une liste (dans le cas où plusieurs élément HTML serait disponible, la fonction renvoi le premier). Cet objet seul est plus facile à manipuler qu’une liste, et cela est cohérent dès lors que nous n’attendons qu’un seul titre d’encadré. Avec la fonction html_text, on extrait le texte de cet élément. Ensuite, il est possible d’ajouter une colonne dans une base de données à l’aide de la fonction mutate :

titre_encadre <- encadre_administration %>% html_element("caption") %>% html_text()

table_administration <- table_administration %>% 
  mutate(TX_ENCADRE = titre_encadre)

table_administration
# A tibble: 9 × 3
  TX_CATEGORIE                        TX_INFO                         TX_ENCADRE
  <chr>                               <chr>                           <chr>     
1 Forme de l'État                     République unitaire semi-prési… Administr…
2 Président de la République          Emmanuel Macron                 Administr…
3 Premier ministre                    Gabriel Attal                   Administr…
4 Président du Sénat                  Gérard Larcher                  Administr…
5 Présidente de l'Assemblée nationale Yaël Braun-Pivet                Administr…
6 Parlement                           Parlement                       Administr…
7 Chambre hauteChambre basse          SénatAssemblée nationale        Administr…
8 Langue officielle                   Français                        Administr…
9 Capitale                            Paris48° 52′ N, 2° 19,59′ E     Administr…

Nous avons à présent un tableau de 9 lignes et de 3 colonnes, structurant toutes les informations de l’encadré “Administration”. Il y aurait encore du nettoyage à réaliser (par exemple la catégorie de la ligne 7 est “Chambre hauteChambre basse”, l’erreur provient de Wikipédia qui indique ces deux termes à la suite, avec uniquement un saut de ligne qui disparaît ici.), mais notre objectif d’extraction de données est atteint. La suite du travail va consister en une boucle pour obtenir plus d’encadrés, puis pour plus de pays. Mais pour l’instant, résumons les premières commandes abordées :

La fonction read_html permet d’extraire le code source d’une page web. L’objet ainsi obtenu peut ensuite être explorer avec la fonction html_elements en indiquant les balises ainsi que les attributs recherché·e·s. Une fois l’élément ou les éléments correctement identifiés, la fonction html_text permet d’extraire le contenu affiché à l’écran de la ou des balises. Si les données sont directement affichées sur le site internet sur la forme d’un tableau, la fonction html_table permet d’extraire et de structurer directement les données dans une base de données R.

Voici résumé les quelques commandes nécessaires pour obtenir le tableau d’encadré sur l’administration pour la France :

page_france <- read_html("https://fr.wikipedia.org/wiki/France")
liste_encadres <- html_elements(page_france,"div.infobox_v3 table")
encadre_administration <- liste_encadres[[3]]
table_administration <- html_table(encadre_administration) %>% 
  rename(TX_CATEGORIE = X1,TX_INFO = X2)
titre_encadre <- encadre_administration %>% html_element("caption") %>% html_text()
table_administration <- table_administration %>% 
  mutate(TX_ENCADRE = titre_encadre)

3.2 Extraction de plusieurs encadrés

Dans ce premier exemple, l’encadré “Administration” est localisé par le troisième élément de la liste liste_encadres. Pour localiser et structurer un autre encadré, il faut modifier cet index de liste. Pour traiter chaque encadré, il est utile de créer une fonction qui reproduira automatiquement ce résultat à partir d’un encadré à fournir en entrée de la fonction. Une fonction R prend plusieurs paramètres en entrée (ici un seul, le code source de l’encadré que l’on veut structurer), et renvoi généralement un objet en sortie (ici la base de données de l’encadré). Cette nouvelle fonction encadre_to_table permet, à partir d’un encadré, d’obtenir le tableau structuré. Voici l’écriture de cette fonction ainsi qu’un exemple d’utilisation de cette fonction :

encadre_to_table <- function(encadre){
  titre_encadre <- encadre %>% html_element("caption") %>% html_text()
  table_encadre <- html_table(encadre) %>% 
    rename(TX_CATEGORIE = X1,TX_INFO = X2) %>% 
    mutate(TX_ENCADRE = titre_encadre)
  
  table_encadre
}

encadre_to_table(liste_encadres[[4]])
# A tibble: 4 × 3
  TX_CATEGORIE        TX_INFO                                         TX_ENCADRE
  <chr>               <chr>                                           <chr>     
1 Plus grandes villes Paris, Marseille, Lyon                          Géographie
2 Superficie totale   672 051[1],[2],[N 1] km2(classé 41e)            Géographie
3 Superficie en eau   0,26 %                                          Géographie
4 Fuseau horaire      UTC +1 (HNEC, heure d'hiver)UTC +2 (HAEC, heur… Géographie

Une nouvelle fonction personnalisée permet de simplifier l’écriture d’un long code. En effet, si la structuration d’un encadré sur Wikipédia est similaire quelle que soit la page extraite, il est plus efficace de créer une telle fonction et de la stocker dans un fichier spécifique (nous parlerons plus tard de la structuration globale d’un projet de Webscraping sur R). Ainsi, si le site web change de code source1, vous devrez uniquement mettre à jour la fonction et non chercher dans l’intégralité de votre code R là où la mise à jour est nécessaire.

L’utilisation d’une fonction personnalisée permet également d’utiliser les fonctionnalités du package purrr du tidyverse afin de réaliser, en une fois, la structuration de tous les encadrés pour obtenir une seule base de données en sortie. La fonction map permet, en indiquant une liste et une fonction, d’appliquer cette fonction à l’ensemble des éléments de la liste. Le résultat en sortie est une liste, de la même taille que la liste initiale. Une variante de la fonction map est la fonction map_df, qui regroupe les sorties sous la forme d’un tableau. C’est ainsi la fonction la plus pertinente, car nous souhaitons obtenir une unique base de données avec tous les encadrés. Voici la commande a écrire pour cela :

liste_encadres %>% map_df(encadre_to_table)
# A tibble: 55 × 3
   TX_CATEGORIE                        TX_INFO                        TX_ENCADRE
   <chr>                               <chr>                          <chr>     
 1 Drapeau de la France                "Armoiries de la France"        <NA>     
 2 Devise                              "Liberté, Égalité, Fraternité" " "       
 3 Hymne                               "La Marseillaise"              " "       
 4 Fête nationale                      "14 juillet"                   " "       
 5 · Événement commémoré               "La prise de la Bastille (178… " "       
 6 Forme de l'État                     "République unitaire semi-pré… "Administ…
 7 Président de la République          "Emmanuel Macron"              "Administ…
 8 Premier ministre                    "Gabriel Attal"                "Administ…
 9 Président du Sénat                  "Gérard Larcher"               "Administ…
10 Présidente de l'Assemblée nationale "Yaël Braun-Pivet"             "Administ…
# ℹ 45 more rows

3.3 Extraction de plusieurs pages

Nous avons à présent la possibilité d’extraire l’ensemble des encadrés de la page Wikipédia sur la France de les structurer dans une base de données R. Pour généraliser cela est obtenir les encadrés pour plusieurs pays, nous allons créer une fonction qui prendra en entrée une URL à extraire et en sortie la base de données des encadrés. Une telle fonction se servira de notre fonction personnalisée encadre_to_table, mais devra ajouter une nouvelle variable à la base de données. En effet, pour l’instant, le nom du pays n’est pas indiqué, donc si une extraction devait avoir lieu sur plusieurs pays à la suite, il ne serait pas possible, après coup, de retrouver le pays concerné dans les données.

En parcourant de nouveau le code source du site web Wikipédia, le nom du pays peut s’extraire avec une balise <div> ayant pour classe “entete” au début de l’infobox que nous avons extrait. Il est également possible de l’extraire avec une balise <span> ayant pour classe “mw-page-title-main”. Les deux résultats sont différents (ici “République Française” contre “France”), Lorsque vous êtes dans un tel cas de figure, à vous de choisir l’information qui semble la plus pertinente et la plus simple à extraire. Nous choisirons ici la deuxième solution, afin de récupérer uniquement “France”.

page_france %>% html_element("div.infobox_v3 div.entete") %>% html_text()
[1] "\nRépublique française\n"
page_france %>% html_element("span.mw-page-title-main") %>% html_text()
[1] "France"

Voici l’écriture d’une fonction personnalisée permettant d’extraire une page web Wikipédia quelconque puis d’en structurer les encadrés. Nous testons ensuite cette fonction avec la page Wikipédia sur la Belgique :

url_to_encadres <- function(url){
  page <- read_html(url)
  nom_pays <- page %>% html_element("span.mw-page-title-main") %>% html_text()
  liste_encadres <- html_elements(page,"div.infobox_v3 > table")
  table_encadres <- map_df(liste_encadres,encadre_to_table) %>% 
    mutate(TX_PAGE = nom_pays)
  
  table_encadres 
}
url_to_encadres("https://fr.wikipedia.org/wiki/Belgique")
# A tibble: 54 × 4
   TX_CATEGORIE                               TX_INFO         TX_ENCADRE TX_PAGE
   <chr>                                      <chr>           <chr>      <chr>  
 1 Drapeau de la Belgique                     "Armoiries de …  <NA>      Belgiq…
 2 Devise                                     "en français :… " "        Belgiq…
 3 Hymne                                      "La Brabançonn… " "        Belgiq…
 4 Fête nationale                             "21 juillet"    " "        Belgiq…
 5 · Événement commémoré                      "Prestation de… " "        Belgiq…
 6 Forme de l'État                            "Monarchie con… "Administ… Belgiq…
 7 Roi                                        "Philippe"      "Administ… Belgiq…
 8 Premier ministre                           "Alexander De … "Administ… Belgiq…
 9 Présidente de la Chambre des représentants "Éliane Tillie… "Administ… Belgiq…
10 Présidente du Sénat                        "Stephanie D'H… "Administ… Belgiq…
# ℹ 44 more rows

Notre nouvelle fonction personnalisé extraction_encadres permet, à partir d’un élément donné (une URL Wikipédia), d’obtenir une base de données. De manière analogue à la fonction structuration_encadre, il est maintenant possible d’extraire, en une seule fois, plusieurs page web Wikipédia, et d’en extraire les encadrés. La fonction map_df est utilisable de la même manière, une fois listées les pages web Wikipédia souhaitées. Nous allons créer un vecteur avec toutes les URL que nous souhaitons parcourir. Pour conserver la thématique des pays, et en ciblant les pays européens, voici un exemple d’usage à partir d’un vecteur d’URL. La première commande prépare un vecteur de nom de pays (j’ai pris soin ici de prendre des noms de pays en un mot et sans caractères spéciaux, afin d’être certain que l’URL des pages Wikipédia soit facile à créer. Nous verrons plus loin comment s’assurer de la validité des URL). La deuxième commande concatène l’URL de base de Wikipédia avec ce vecteur, créant ainsi un vecteur d’URL de pages à extraire.

vecteur_nom_pays <- c("France","Belgique","Allemagne","Espagne","Italie","Danemark")
vecteur_url_pays <- paste("https://fr.wikipedia.org/wiki/",vecteur_nom_pays,sep="")

vecteur_url_pays
[1] "https://fr.wikipedia.org/wiki/France"   
[2] "https://fr.wikipedia.org/wiki/Belgique" 
[3] "https://fr.wikipedia.org/wiki/Allemagne"
[4] "https://fr.wikipedia.org/wiki/Espagne"  
[5] "https://fr.wikipedia.org/wiki/Italie"   
[6] "https://fr.wikipedia.org/wiki/Danemark" 

Il reste à présent à utiliser une dernière fois la fonction map_df pour obtenir, à partir de ce vecteur d’URL, un tableau contenant toutes les informations des encadrés.

table_encadres <- vecteur_url_pays %>% map_df(url_to_encadres)
table_encadres
# A tibble: 303 × 4
   TX_CATEGORIE                        TX_INFO                TX_ENCADRE TX_PAGE
   <chr>                               <chr>                  <chr>      <chr>  
 1 Drapeau de la France                "Armoiries de la Fran…  <NA>      France 
 2 Devise                              "Liberté, Égalité, Fr… " "        France 
 3 Hymne                               "La Marseillaise"      " "        France 
 4 Fête nationale                      "14 juillet"           " "        France 
 5 · Événement commémoré               "La prise de la Basti… " "        France 
 6 Forme de l'État                     "République unitaire … "Administ… France 
 7 Président de la République          "Emmanuel Macron"      "Administ… France 
 8 Premier ministre                    "Gabriel Attal"        "Administ… France 
 9 Président du Sénat                  "Gérard Larcher"       "Administ… France 
10 Présidente de l'Assemblée nationale "Yaël Braun-Pivet"     "Administ… France 
# ℹ 293 more rows

Ce code permet d’extraire une base de données de 275 lignes, aussi il devient difficile de comprendre ce que nous avons extrait et de vérifier que la validité de notre code. Les fonctions count et pivot_wider du package tidyverse permettent de générer un tableau de synthèse comptant le nombre de lignes par page Wikipédia extraite et nom de l’encadré :

table_encadres %>%
  count(TX_PAGE,TX_ENCADRE) %>%
  pivot_wider(names_from = TX_PAGE, values_from = n)
# A tibble: 9 × 7
  TX_ENCADRE       Allemagne Belgique Danemark Espagne France Italie
  <chr>                <int>    <int>    <int>   <int>  <int>  <int>
1 " "                      4        4        4       4      4      3
2 "Administration"         7        9        6      10      9      7
3 "Divers"                 5        5        5       5      5      5
4 "Démographie"            3        3        3       3      3      3
5 "Développement"          5        5        5       5      5      5
6 "Géographie"             4        4        4       4      4      4
7 "Histoire"              12       16        6      18     18     13
8 "Économie"               7        7        7       7      6      7
9  <NA>                    1        1        1       1      1      1

L’extraction fonctionne ainsi sur tous les pays, car chaque page Wikipédia possède le même code source pour structurer les encadrés. Aussi, l’homogénéité de Wikipédia permet d’avoir les mêmes noms d’encadrés sur les différentes pages web.

Notes de bas de page

  1. Les site web voient leur code source modifier régulièrement, de manière plus ou moins radicale selon les mises à jour. Le code présenté dans ce manuel sera sans doute obsolète au moment de votre lecture. Néanmoins, la stabilité de Wikipédia permet d’espérer que les modifications seront mineures.↩︎