L’art du scraping I : Introduction à PhantomJS & CasperJS

Cet article a pour but de vous introduire au ”web scraping”. Vous allez découvrir quelles sont les techniques et les outils qui permettent d’extraire du contenu de sites Web. Cet article présente des cas concrets d’extraction de données.

Vous apprendrez comment :

  • Récupérer le titre du site internet de LeReacteur.IO
  • Récupérer les résultats du moteur de recherche de Google
  • Récupérer les avis des produits vendus par LDLC (voir l’article Medium “L’art du scraping II : Projet LDLC”)
  • Et d’autres exemples sont prévus !
Une connaissance des bases du développement - notamment JavaScript, JQuery, HTML5, CSS3 - est nécessaire pour pouvoir comprendre les techniques présentées.

La boîte à outils : PhantomJS & CasperJS

Pour récupérer les données de n’importe quel site Internet, nous allons avoir besoin de deux outils complémentaires :

  • PhantomJS
  • CasperJS

PhantomJS est un navigateur web complet mais sans tête (headless)☠. C’est à dire que vous pourrez faire tout ce que vous faîtes avec notre navigateur web préféré (Chrome, Firefox, Safari et même IE), mais sans fenêtre de navigation. Par exemple, vous allez pouvoir simuler :

  • le comportement d’un utilisateur : cliquer sur un bouton, compléter un champ texte, soumettre un formulaire, etc …
  • la navigation sur différentes pages
  • la capture d’écrans
  • l’attente du chargement de données en ajax

CasperJS est un utilitaire de navigation et de tests pour le navigateur - sans tête - PhantomJS. CasperJS a été développé au dessus de PhantomJS. Cette librairie fournit des fonctions, des méthodes et une syntaxe utile et simple pour effectuer les tâches courantes évoquées précédemment (navigation, clic sur un bouton, capture d’écrans, etc…), ET SURTOUT, récupérer toutes ces données 😇

Si PhantomJS était JavaScript, CasperJS serait JQuery.

Installation (2–3 min)

3 étapes sont nécessaires pour l’installation de ces outils.

1- Installer Python 2 ou 3

Vous avez probablement une version de Python déjà installée sur votre ordinateur. Verifier de quelle version il s’agit, auquel cas, suivez les instructions d’installation sur le site officiel : https://www.python.org/downloads/

~ python -V
Python 2.7.10

2- Installer PhantomJS via NPM

~ npm install phantomjs-prebuilt

3- Installer CasperJS via NPM

~ npm install -g casperjs

Tester votre installation

Créez un nouveau dossier et un nouveau fichier JavaScript, appelé lereacteur.js :

~ mkdir scraping && cd scraping && touch lereacteur.js

Ouvrez lereacteur.js avec votre éditeur de texte préféré et copiez-collez le code ci-dessous :

var casper = require('casper').create();

casper.start('http://lereacteur.io/', function() {
this.echo(this.getTitle());
});

Ce script va permettre de récupérer le titre du site LeReacteur.IO.

Lancez le programme avec CasperJS pour obtenir le résultat suivant :

~ casperjs lereacteur.js
Formations développement Web et Mobile | Le Reacteur

Vous venez de scraper votre premier site ! Bien joué 😎

Vous êtes maintenant prêt pour aller plus loin (et récupérer bien plus que le titre d’une page web !).

Scraper les résultats d’une recherche Google

Dans ce projet, nous allons récupérer les adresses URLs d’une recherche issue de la première page de Google.

Notions abordées :

  • Architecture d’un script CasperJS
  • Les fonctions inhérentes à chaque projet : start(), then(), run()
  • Les fonctions : waitForSelector() et fill()
Attention cet exemple est donné à titre éducatif uniquement ! Il est repris de l’exemple du site officiel de CasperJS.
~ touch hooli.js

Ouvrez votre fichier, puis créez une instance casper avec la fonction create().

Ensuite créez une variable links égale à un tableau (array) qui permettra de stocker les adresses URLs.

var casper = require('casper').create();
var links = [];

Tous vos scripts vont commencer en appelant la fonction start(), qui prend au minimum comme argument une adresse URL (http://google.fr/).

casper.start('http://google.fr/')

Ensuite, nous allons faire appel à la fonction .waitForSelector() qui permet d’attendre le chargement d’un sélecteur HTML, ici le champ de recherche.

.waitForSelector('form[action="/search"]')
Pour rappel, c’est l’inspecteur de votre navigateur (clic droit -> Inspecter), qui vous permettra de trouver le sélecteur du champ de recherche.

Nous allons pouvoir passer à la prochaine étape grâce à la fonction then(). Puis notre objectif va être de remplir le champ de recherche avec la fonction fill(). Le premier argument est le sélecteur du champ de recherche que nous attendions, le second est le paramètre de recherche (q), le troisième argument est un boolean, la valeur true est nécessaire pour lancer la recherche.

// Compléter le champ de recherche de Google avec la requête "Pied Piper"
.then(function() {
this.fill('form[action="/search"]', { q: 'Pied Piper' }, true);
})

Puis toujours grâce à la fonction then() nous allons “concaténer” les liens retourner par la fonction getLinks() (que vous écrirons après).

.then(function() {
links = links.concat(this.evaluate(getLinks));
})

Puis, nous allons renvoyer les données dans le terminal d’une manière lisible grâce à la fonction echo() - équivalente à un console.log() -.

// Renvoyer les données dans le terminal
.then(function() {
this.echo(links.length + ' links found:');
this.echo(' - ' + links.join('\n - ')).exit();
});

Enfin, votre script se terminera en appelant la fonction run qui permet de le lancer.

.run();

Le coeur de votre script doit donc ressembler à ça :

casper.start('http://google.fr/')
.waitForSelector('form[action="/search"]')
.then(function() {
this.fill('form[action="/search"]', { q: 'Pied Piper' }, true);
})
.then(function() {
links = links.concat(this.evaluate(getLinks));
})
.then(function() {
this.echo(links.length + ' links found:');
this.echo(' - ' + links.join('\n - ')).exit();
})
.run();

Avant de terminer notre programme, nous allons devoir écrire la fonction getLinks(), juste avant la fonction start(). Cette fonction va récupérer tous les sélecteurs ‘h3.r a’ qui correspondent aux titres puis retourner un tableau contenant toutes les URLs.

function getLinks() {
// Identifier les titres et retourner les URLs dans un tableau
var links = document.querySelectorAll('h3.r a');
return Array.prototype.map.call(links, function(e) {
return e.getAttribute('href').replace(/(\/url\?q=)/g, "").replace(/(\/search\?q=)/g, "https://google.fr/search?q=");
});
};

La fonction getLinks est écrite en “vanilla” JavaScript. Plus tard, nous verrons comment la simplifier grâce à l’utilisation des librairies JQuery et Lodash.

.replace(/(\/url\?q=)/g, "").replace(/(\/search\?q=)/g, "https://google.fr/search?q=")

Grâce à l’utilisation de ces deux regex, nous “nettoyons” les données récupérées afin de garder uniquement l’URL. La première va supprimer “/url?q=” devant les liens récupérer et la seconde rajouter “https://google.fr devant les liens menant vers la catégorie Images de Google (lien n°5).

Lancer le script - et prier bien fort - !

~ casperjs hooli.js
10 links found:
- http://www.piedpiper.com/&sa=U&ved=0ahUKEwjKpv2B7ZLVAhXHORoKHUxNCfEQFggUMAA&usg=AFQjCNGSPUfYqDcl-4OGlB1vpjOEmqTKuw
- https://en.wikipedia.org/wiki/Pied_Piper_of_Hamelin&sa=U&ved=0ahUKEwjKpv2B7ZLVAhXHORoKHUxNCfEQFggaMAE&usg=AFQjCNFprs5CWGBZCb8OGY4TByYstlr1-w
- https://fr.wikipedia.org/wiki/The_Pied_Piper_of_Hamelin&sa=U&ved=0ahUKEwjKpv2B7ZLVAhXHORoKHUxNCfEQFgglMAI&usg=AFQjCNHTt25jzH9hC-qJnLgfQwtTgXB6uw
- https://fr.wiktionary.org/wiki/pied_piper&sa=U&ved=0ahUKEwjKpv2B7ZLVAhXHORoKHUxNCfEQFggrMAM&usg=AFQjCNHFGDq-exSTroWBFC742s-fBW42JQ
- https://google.fr/search?q=Pied+Piper&hl=fr&gbv=2&prmd=ivns&tbm=isch&tbo=u&source=univ&sa=X&ved=0ahUKEwjKpv2B7ZLVAhXHORoKHUxNCfEQsAQIMA
- https://www.crunchbase.com/organization/pied-piper&sa=U&ved=0ahUKEwjKpv2B7ZLVAhXHORoKHUxNCfEQFgg8MAk&usg=AFQjCNEZCFk6p_uI4aCsB3R-ru9ksVQwMg
- http://www.ancient-origins.net/myths-legends/disturbing-true-story-pied-piper-hamelin-001969&sa=U&ved=0ahUKEwjKpv2B7ZLVAhXHORoKHUxNCfEQFghCMAo&usg=AFQjCNEtFsXRURCIIT6HMSwttsNogPxx7Q
- https://www.fastcompany.com/3050180/these-engineers-just-built-their-own-pied-piper-compression-algorithm&sa=U&ved=0ahUKEwjKpv2B7ZLVAhXHORoKHUxNCfEQFghJMAs&usg=AFQjCNHKP5pszgmNvUt1U6XUuJClBo-nNA
- http://silicon-valley.wikia.com/wiki/Pied_Piper_(company)&sa=U&ved=0ahUKEwjKpv2B7ZLVAhXHORoKHUxNCfEQFghPMAw&usg=AFQjCNGqSJsFPAeMqGnIbTrk-7P6vjcP8A
- https://play.google.com/store/apps/details%3Fid%3Dcom.techhgeeks.piedpiper&sa=U&ved=0ahUKEwjKpv2B7ZLVAhXHORoKHUxNCfEQFghUMA0&usg=AFQjCNGQjmlPgTbrBive6C-shPEQnGzN3A
Tada 🎉🎉🎉🎉🎉🎉🎉

Code complet :

var casper = require('casper').create();
var links = [];
function getLinks() {
// Identifier les titres et retourner les URLS
var links = document.querySelectorAll('h3.r a');
return Array.prototype.map.call(links, function(e) {
return e.getAttribute('href').replace(/(\/url\?q=)/g, "").replace(/(\/search\?q=)/g, "https://google.fr/search?q=");
});
};
casper.start('http://google.fr/')
      .waitForSelector('form[action="/search"]')
      .then(function() {
this.fill('form[action="/search"]', { q: 'Pied Piper' }, true);
})
      .then(function() {
links = links.concat(this.evaluate(getLinks));
})
      .then(function() {
this.echo(links.length + ' links found:');
this.echo(' - ' + links.join('\n - ')).exit();
})
      .run();

Si vous souhaitez vous former au JavaScript auprès de passionnés, nous proposons des formations au développement web (React JS) ou mobile (React Native). N’hésitez pas à visiter LeReacteur.IO