La librairie rvest

Le paquet rvest permet d’extraire du contenu des pages web à l’aide de la syntaxe XPath ou des sélecteurs CSS. On utilisera beaucoup les sélecteurs CSS; les xptah n’étant utilisés qu’en cas de besoin. N’hésutez pas d’exécuter le script suivant qui va installer rvest si ce n’est pas encore le cas pour vous.

if (! ("rvest" %in% rownames(installed.packages())) )
{install.packages("rvest", dep=TRUE)}
if (! ("httr" %in% rownames(installed.packages())) )
{install.packages("httr", dep=TRUE)}

 require("rvest")
## Loading required package: rvest
## Warning: package 'rvest' was built under R version 3.6.2
## Loading required package: xml2
## Warning: package 'xml2' was built under R version 3.6.2
 require("httr")
## Loading required package: httr
## Warning: package 'httr' was built under R version 3.6.2

L’interface rvest

rvest est un paquet assez simple d’usage. Le nombre de focntions mises à dispositon de l’utilisateur est reduit mais permet de presque tout faire : extraire les bouts de code HTML par tag, par sélecteur CSS, par xpath… rvest dispose aussi de quelques fonctions supplémentaires qui permettent de naviguer dans les pages en émulant un navigateur web. Ci-dessous, une liste non complète de fonctions d’extraction qui seront approfondies dans cette partie :

Fonction html()

La fonction html() est généralement la première à être utilisée dans un flux d’extraction car elle permet d’importer en R le contenu d’une page web. La fonction accepte donc deux paramètres, dont le deuxième (encoding) est optionnel. Elle est l’équivalent de requests.get en python.

msn = html("https://www.msn.com/en-us/money/markets/currencies")
## Warning: 'html' is deprecated.
## Use 'xml2::read_html' instead.
## See help("Deprecated")
print(msn)
## {html_document}
## <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" dir="ltr">
## [1] <head>\n<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">\n<!-- data-info:v:20200103_20520765;a:5070678a-50bb-40bd-8da2-b63ff150fbd7;cn:49;az:{di ...
## [2] <body class="currenciespage green">\n \n\n\n<div class="head">\n<div>\n<div id="topnav">\n <ul class="verticalsnav">\n<li>\n<a href="/en-us">Home</a>\n</li>\n <li> ...

Normalement vous devriez recevoir un message vous informant que la fonction html est obsolète. Cette fonction a été rendue obsolète afin de promouvoir une meilleure façon de récupérationn de pages HTMLL. En effet, la fonction html ne renvoie que le contenu de la page et rien sur le statut et les autres composants de la requête HTTP. Avec le paquet httr, on lirait récupérerait une page web de la façon suivante:

msn = GET("https://www.msn.com/en-us/money/markets/currencies" )
print(paste( "code d'état :",  msn$status_code))
## [1] "code d'état : 200"
print(msn)
## Response [https://www.msn.com/en-us/money/markets/currencies]
##   Date: 2020-01-14 07:24
##   Status: 200
##   Content-Type: text/html; charset=utf-8
##   Size: 113 kB
## <?xml version="1.0" encoding="UTF-8" ?>
## <!DOCTYPE HTML PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">
## <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" dir="ltr">
## 
## <head>
##  <!-- data-info:v:20200103_20520765;a:965b8025-7da5-428a-bdb2-b45ca4418a27;cn:41;az:{did:8df28e8681774be6b41666cd5d52d6db, rid: 41, sn: neurope-prod-entertainment, dt:...
##  <meta name="robots" content="index, follow"/>
##  
##  
## 
## ...


Fonction html_nodes()

La fonction html_nodes() est celle qui permet de faire l’essentiel du boulot du scrapeur, car elle permet d’extraire des morceaux de code HTML contenant les informations d’intérêt à partir de la page iweb. Pour extraire les données, html_nodes() met à disposition deux moyens : les sélecteurs xpaths et css. La fonction html_nodes() accepte deux arguments, qui sont tous deux obligatoires. Le format d’appel est donc html_nodes(page, [css, xpath]) L’argument page représente le code HTML de la page et le deuxième argument est un critère de sélection.

page =  content(msn)
# Extraire les paragraphes de la page
html_nodes(page, "p")
## {xml_nodeset (121)}
##  [1] <p class="truncated-string" title="Open">Open</p>
##  [2] <p class="truncated-string" title="0.8976">0.8976</p>
##  [3] <p class="truncated-string" title="Change">Change</p>
##  [4] <p class="truncated-string" title="-0.0003">-0.0003</p>
##  [5] <p class="truncated-string" title="Change%">Change%</p>
##  [6] <p class="truncated-string" title="-0.0334%">-0.0334%</p>
##  [7] <p class="truncated-string" title="52 Week High">52 Week High</p>
##  [8] <p class="truncated-string" title="0.9191">0.9191</p>
##  [9] <p class="truncated-string" title="52 Week Low">52 Week Low</p>
## [10] <p class="truncated-string" title="0.8642">0.8642</p>
## [11] <p class="truncated-string" title="Major Currencies">Major Currencies</p>
## [12] <p class="truncated-string" title="Price">Price</p>
## [13] <p class="truncated-string" title="Change">Change</p>
## [14] <p class="truncated-string" title="Change%">Change%</p>
## [15] <p class="truncated-string" title="52 Week High">52 Week High</p>
## [16] <p class="truncated-string" title="52 Week Low">52 Week Low</p>
## [17] <p class="truncated-string" title="Euro">Euro</p>
## [18] <p class="truncated-string" title="USD/EUR">USD/EUR</p>
## [19] <p class="truncated-string" title="0.8975" aria-label="Price 0.8975">0.8975</p>
## [20] <p class="truncated-string" title="-0.0004" aria-label="Change -0.0004">-0.0004</p>
## ...

On voit bien que l’équivalent python de html_nodes() est soit bs.find_all() ou bs.select. Il existe aussi un équivalent de bs.find ou bs.select_one en R : c’est html_node .

Fonctions html_text(), html_attrs(), et html_name()

Ces fonctions permettent d’avoir accès aux différents composants d’un noeud html extrait à partir des fonctions html_node ou html_nodes.

  • html_text(x, …) : extraire le texte de l’élément (passer l’argument trim = TRUE pour supprimer les espaces de début et de fin)
  • html_attr(x), html_attrs(x) : extraire les attributs du noeud x
  • html_name(x) : obtenir le nom de l’élément
currency_class <- ".mjrcurrncsitem"
cur = html_node(page, currency_class)

thead_class = '.mjrcurrncsrow.tblheaderrow'
header = html_node(cur,  thead_class)
headers = html_nodes(header, ".mctblheading") # Avez-vous pu retrouver la classe `mctblheading`  de vous mêmes ?
header_values = c()
i = 0
for (header in headers){
    header_values[i] = html_node(header, "p")%>%html_attr("title")
    i = i + 1
}
print(header_values)
## [1] "Price"        "Change"       "Change%"      "52 Week High" "52 Week Low"

Résumé

Dans cette quatrième partie du cours portant sur le scraping avec R, nous avons abordé :