Web Scraping avec R, Extration des cours depuis le site de la Bourse de Casablanca

 

Nous avons l’habitude de manipuler des données contenues dans des fichiers ou système bien structuré et adapté à cet effet. Oui heureusement, nous avons des packages qui ont été bien conçus spécialement pour faire la partie “désagréable” du boulot. Maintenant imaginons que l’on veuille extraire un tableau contenu sur une page web comme celui de la bourse de Casablanca:

http://www.casablanca-bourse.co.ma/bourseweb/Negociation-Historique.aspx?Cat=24&IdLink=302

Capture d’écran du site de la bourse de Casablanca

Malheureusement ou heureusement pour nous, s’il existe des packages comme le fameux quantmod très utiliser par les quants pour télécharger notamment avec la fonction getSymbols(), les cours boursiers depuis la plateforme de Yahoofinance ou Googlefinance…etc, il n’en existe pas pour la bourse de Casablanca et nous allons à travers cet tutoriel concevoir une fonction qui pourra :

  • – Naviguer sur le site en cochant les différentes options que l’utilisateur aura entré
  • – Extraire le tableau des données affiché sur le site et le préparer pour son utilisation avec R (comme on peut voir l’image au début de cet article présente les cours de la société ATTIJARIWAFABANK)

Etape I : RSelenium, package pour la navigation web

Selenium, est un projet visant à automatiser la navigation web et en l’occurence sa version R, nommée RSelenium permet de naviguer via des commandes R. Bien que l’intérêt de ce package va bien au delà de la simple navigation web, nous allons l’utiliser pour communiquer avec notre site cible.

Ainsi, pour fonctionner, nous avons besoin d’un navigateur web firefox, Google Chrome…etc. Mais malheureusement ces derniers ne fonctionnent souvent pas. Mais nous avons mieux, nous allons opter pour une navigation fantome ( dans le sens où tout se passera en background et nous ne verrons rien apparaitre pendant la navigation autrement ce serait embêtant). Pour ce faire, nous allons utiliser le navigateur PhantomJS, on peut le télécharger ici. Après téléchargement, il suffit de décompresser le dossier dans un endroit facilement accessible. Ensuite on aura besoin du chemin d’accès( C:/Users/danam/Documents/phantomjs-2.1.1-windows/bin/phantomjs.exe) à l’exécutable phantomjs.exe logé dans le dossier bin .

En supposant, que l’on a déjà installé RSelenium, on le charge dans l’environnement de travail (ligne 1) et pour démarrer la navigation à distance il est nécessaire d’établir le branchement avec phantomjs(ligne 3). C’est sur la base de ce branchement à travers l’objet remDr que nous allons pouvoir accéder à une plateforme web à distance. La fonction navigate(), va nous permettre d’accéder au site web dont le lien est fourni en argument et la dernière fonction screenshot(), permet d’avoir un aperçu de la page web :

tmpscreenshot0

Si l’on obtient une image similaire, c’est dire que tout se passe bien !

Etape II: Interaction avec le site web

Pour interagir avec le site web notamment entrer le nom de la société dont nous voulons obtenir l’historique des cours, la période et valider le formulaire nous devons à chaque fois référencer l’élément de la page web. Explication : Conformement aux standards (DOM), dans une page HTML par exemple, on peut interagir avec ses composants à travers un nom, un id ou encore à travers un selecteur de style CSS.  Voyons plutôt :

Nous allons séléctionner le nom de la société dont nous voulons obtenir l’historique dans la liste déroulante (voir l’image ci-dessus) pour celà nous allons devons fournir l’id de l’objet liste déroulante à la fonction findElement(). Pour obtenir l’id il suffit de cliquer droit sur la liste déroulante et ensuite de choisir inspecter l’élément, une fénêtre s’ouvrira à côté avec le code source de l’élément dont voici l’extrait:

On voit le nom et l’id, nous prendrons l’id qui vaut “HistoriqueNegociation1_HistValeur1_DDValeur” qu’il faut passer dans la fonction findElement() comme ceci:

Une fois l’élément liste déroulante retrouver, il reste à lui envoyer le nom de la société “ALLIANCE” (abrégé “ALLI” par ce que c’est une liste déroulante les premières lettres suffisent pour faire la sélection mais il faudrait s’assurer qu’aucun autre nom ne commence pas par “ALLI” sinon il faudrait écrire le nom en toute lettre) à travers la fonction sendKeysToElement(). En aperçu nous avons :

tmpscreenshot1

Maintenant que l’on a compris le principe, on peut réitérer le processus aux autres éléments. Ici, au lieu spécifier directement la période de l’historique dont nous avons besoin(option 1 en rouge) nous allons exploiter la limitation des données à un historique de 3 ans seulement en notre faveur. Nous allons donc choisir de télécharger les donnes sur 3 ans(voir illustration pas trop top ci-dessous) :tmpscreenshot2

Nous allons d’abord chercher les id respectifs du bouton radio “Par mensualité”, de la liste déroulante et du bouton “Valider”. Ensuite nous cliquer sur le bouton radio et sélectionner “3 ans” dans la liste déroulante à droite et en fin valider en envoyant la commande de la touche “Entrer” au bouton “valider”( un peu comme quand l’on fini de remplir un formulaire on tape “Entrer” pour valider le tout) :

Si tout se passe bien nous allons voir afficher ce qui suit (il faudrait avoir une bonne connectivité où laisser s’écouler quelques fractions de secondes pour lancer la dernière commande sinon on aura une image de page en chargement et par aiIleurs, il va falloir zoomer pour bien voir comme ci-dessous) :

tmpscreenshot3

Etape III: Parsage de la page web avec XML et formatage des données en data.frame

Maintenant, Nous allons, d’abord obtenir le code source de la page que nous avons précédemment obtenue. Nous allons ensuite le parser avec la fonction htmlParse() vers un type de document objet R, hybride(car héritant à la fois des objets "HTMLInternalDocument" "XMLInternalDocument"  "XMLAbstractDocument" ) compatible au format XML et dont on peut scruter les nœuds avec la syntaxe XPath(c’est un langage (non XML) pour localiser une portion d’un document XML).

Nous allons d’abord retrouver la syntaxe XPath(chemin de localisation) du tableau en cliquant droit sur ce dernier et ensuite sur son code source (voir image ci-dessous) on copie le XPath (encerclé en rouge).C’est avec ce chemin de localisation de notre tableau que nous allons extraire le table de la page entière. Heureusement ce chemin ne change pas( à moins ce que le site soit complètement refait). Ce chemin est ensuite passé à la fonction getNodeSet() qui extrait un nœud d’une page XML(D’un point de vue formel, un document XML est un arbre, articulant différents types de nœuds (texte, éléments, attributs, commentaires…)).

tmpscreenshot4

Nous avons réduit la page à son nœud où se trouve le tableau, maintenant, nous allons extraire notre tableau vers un objet data.frame. Mais d’abord voyons le structure de l’objet node :

On voit bien que c’est une liste et notre tableau est contenu dans le dernier élément du tableau 3(en effet en affichant un par un chaque élément du tableau vous verrez que les 2 premiers sont les entêtes qui précèdent le tableau). L’extraction du tableau vers le data.frame passe par la fonction readHTMLTable():

Erreka enfin quelque chose que nous de lisible !

Etape IV: Conversion des données et formatage en série temporelle xts :

Comme on peut le voir notre data.frame est “sale”, les valeurs ne sont pas reconnaissables sous R, le format de la date non plus et les noms des colonnes ne sont pas au bon endroit …etc.

Maintenant sans trop de commentaire on fait ceci :

Nous constatons qu’il y a des colonnes intercalaires inutiles et par chance se sont  des colonnes de rang impair. Ce pattern va nous permettre de les exclure  et d’exclure aussi la colonne 4 (pas utile non plus) :

Là c’est bon maintenant ça ressemble de mieux en mieux à l’idéal. Ce qu’il reste à faire c’est de formater toutes les colonnes en type numeric() excepté la première colonne que nous allons convertir en type Date() :

C’est fini, c’était l’assaut final, vos données sont prêtes à l’emploi notamment pour l’analyse de séries temporelles ….

Maintenant me diriez-vous: Pourquoi n’a-t-on pas plutôt téléchargé manuellement le fichier excel ? la dernière étape va répondre à cette question

Etape V: Réutilisation du code et la fonction getSymbolsCasaBourse()

L’intérêt de ce travail fastidieux que nous venons d’abattre c’est que nous pouvons tout mettre dans une fonction et l’utiliser à chaque fois que nous voulons télécharger un cours et ceci pour n’importe quelle société et pour n’importe quelle période (enfin qui ne va pas au delà de 3 ans) . Ainsi, après quelque réajustement pour que notre fonction puisse faire des extractions précise pour une période fournie en argument, nous pourrions faire télécharger les cours de  ATTIJARIWAFA BANK du début de 2016 à aujourd’hui comme ceci :

Et comme nous voulons finir en beauté on va visualiser graphiquement ces données :

Pour la société ATTIJARIWAFABANK ça donne :

attijari

Pour la société ALLIANCES ça donne :

alliance

 

 

Like