Scraper n’importe quel site avec Pupeteer
Article rédigé le 3 février 2021 par Amaury Lopin
Scraper un site internet pour récupérer toutes ses données, à quoi cela peut servir ? Tout d'abord, cela vous permet de faire de la veille sur vos clients, connaitre les variations de prix, les soldes … Mais cela peut également vous permettre de vérifier que les concurrents ne proposent pas les mêmes produits que vous à un prix inférieur !

Sommaire

Les pré-requis

  • Un éditeur de fichier comme l’excellent Sublime Text (gratuit) ou simplement Notepad ou TextEdit si vous ne souhaitez pas installer de logiciel
  • Un Mac
  • Un accès administrateur
  • Un accès au terminal

Étape 1 : Installation de puppeteer

Première étape : lancer le terminal. Si vous ne savez pas comment ouvrir le terminal, je vous ai créé un rapide tuto : Ouvrir le terminal sous mac

Seconde étape : se rendre sur notre dossier. Ici il se situe dans ma librairie :

/Users/amaury/cours/

L’objectif est donc d’arriver au dossier et de créer un dossier afin d’installer Puppeteer.

Pour cela, une seule, il suffit de taper 2 lignes que je vous ai écrites ci-dessous.

NB : pensez à changer amaury avec le nom de votre ordinateur. Si vous ne connaissez pas le nom de votre ordinateur, tapez la commande suivante: ls /Users/

Term

cd /Users/amaury/cours/
mkdir puppeteer

Il ne nous reste plus qu’à installer Puppeteer en saississant une commande très simple 

Term

npm install puppeteer

Il ne vous reste plus qu’à attendre 1 à 2 minutes selon votre connexion. Lorsque Puppeteer sera installé, vous aurez un écran semblable à celui ci. À noter que les erreurs présentes ici sont dues à la version sélectionnée. Dans cet exemple, cela ne changera rien.

Term

mba:cours amaury$ cd /Users/amaury/cours/
mba:cours amaury$ mkdir puppeteer
mba:cours amaury$ npm install puppeteer

> puppeteer@6.0.0 install /Users/amaury/cours/node_modules/puppeteer
> node install.js

(node:16155) ExperimentalWarning: The fs.promises API is experimental
Downloading Chromium r843427 - 108 Mb [====================] 100% 0.0s
Chromium (843427) downloaded to /Users/amaury/cours/node_modules/puppeteer/.local-chromium/mac-843427
npm WARN saveError ENOENT: no such file or directory, open '/Users/amaury/cours/package.json'
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN enoent ENOENT: no such file or directory, open '/Users/amaury/cours/package.json'
npm WARN ws@7.4.3 requires a peer of bufferutil@^4.0.1 but none is installed. You must install peer dependencies yourself.
npm WARN ws@7.4.3 requires a peer of utf-8-validate@^5.0.2 but none is installed. You must install peer dependencies yourself.
npm WARN cours No description
npm WARN cours No repository field.
npm WARN cours No README data
npm WARN cours No license field.

+ puppeteer@6.0.0
added 54 packages from 76 contributors and audited 54 packages in 39.356s
found 0 vulnerabilities

Étape 2 : Création du script

Attaquons nous à la mise en place du script !

Ici, nous utiliserons du Node JS mais pas de panique, je vous explique tout !

Commençons par les bases : les commentaires.

Dans le script que je vous fourni, chaque ligne est commentée afin que vous puissiez comprendre le code. Les commentaires sont précédés de double slash // 

Commençons par le code complet

Node

// Ici, on importe Puppeteer
const puppeteer = require('puppeteer')



//  PREMIÈRE PARTIE DU SCRIPT //

// On déclare la fonction "récupèrelesurls" qui va gérer toute la première partie du script
const récupèrelesurls = async browser => {
	// On indique à Puppeteer que dès que la fonction "page" est appelée, il faut ouvrir une nouvelle page
  const page = await browser.newPage()
  // On indique l'URL à travers la fonction "page"
  await page.goto('http://books.toscrape.com/')
  // On demande au script d'attendre le chargement de la page à travers la fonction "page"
  await page.waitFor('body')
  // On indique au script, ce qu'on souhaite récupérer : ici les hrefs inclus dans la class .product_pod à travers la fonction "result"
  const result = await page.evaluate(() =>
    [...document.querySelectorAll('.product_pod a')].map(link => link.href),
  )
  // on affiche le résultat de la fonction "result"
  return result
}

//  FIN DE LA PREMIÈRE PARTIE DU SCRIPT //





//  DEUXIÈME PARTIE DU SCRIPT //

	// On déclare la fonction "récupèrelesrésultats" qui va gérer toute la deuxième partie du script
const récupèrelesrésultats = async (browser, url) => {
	// On indique à Puppeteer que dès que la fonction "page" est appelée, il faut ouvrir une nouvelle page
  const page = await browser.newPage()
  // On indique à Puppeteer qu'il faut aller rester sur la page actuelle, appellée nativement "url"
  await page.goto(url)
  // On demande au script d'attendre le chargement de la page à travers la fonction "page"
  await page.waitFor('body')
  return page.evaluate(() => {
  	// On indique au script, ce qu'on souhaite récupérer : ici les h1 et la class ".price_color" qui définit les prix sur le site
    let Produit = document.querySelector('h1').innerText
    let Prix = document.querySelector('.price_color').innerText
     // on affiche le résultat de la fonction "result"
    return { Produit, Prix }
  })
}

//  FIN DEUXIÈME PARTIE DU SCRIPT //


//  TROISIÈME PARTIE DU SCRIPT //


// Création de la fonction "scraping"
const scraping = async () => {
	// On indique à Puppeteer que l'on souhaite voir qu'il lance une instance (puppeteer.launch()) et que l'on souhaite que Chromium s'ouvre { headless: false } (mettre à true pour qu'il se lance silencieusement)
  const browser = await puppeteer.launch({ headless: false })
  // On récupère toutes nos données scrapées
  const urlList = await récupèrelesurls(browser)
  const results = await Promise.all(
    urlList.map(url => récupèrelesrésultats(browser, url)),
  )
  // On ferme tout
  browser.close()
  // On affiche
  return results
}

//  FIN TROISÈME PARTIE DU SCRIPT //




//  DERNIÈRE PARTIE DU SCRIPT //
// On appelle la fonction "scraping" et on affiche les résultats dans la console log
scraping()
  .then(résultats => {
    console.log(résultats)
  })

Dans l’étape suivante, je vais décrypter le script afin que vous puissiez comprendre comment il marche et que vous puissiez reproduire la même chose chez vous.

Si vous souhaitez directement accéder à la mise en fonction du plugin, cliquez ici pour aller à la dernière étape

Étape 3 : Décryptage du script

Étape par étape, je vais vous expliquer chaque ligne du code, pour que vous puissiez me comprendre comment il fonctionne
1. Importation de Puppeteer

Pour commencer à utiliser le script, il convient d’appeler Puppeteer

Node

// Ici, on importe Puppeteer
const puppeteer = require('puppeteer')

 Dans le cas présent, nous utiliserons la déclaration const pour l’appeler.

C’est un peu comme un raccourci.

Ici, const puppeteer = require(puppeteer')

Pourrait être traduit par puppeteer = require('puppeteer')

Enfin,  require('puppeteer') indique au script que nous aurons besoin de Puppeteer tout le long du code. En cas d’absence de Puppeteer, le script s’arrêtera.

1. Première partie du script

Première partie du script : on indique au script ses principales tâches

Node

// On déclare la fonction "récupèrelesurls" qui va gérer toute la première partie du script
const récupèrelesurls = async browser => {
	// On indique à Puppeteer que dès que la fonction "page" est appelée, il faut ouvrir une nouvelle page
  const page = await browser.newPage()
  // On indique l'URL à travers la fonction "page"
  await page.goto('http://books.toscrape.com/')
  // On demande au script d'attendre le chargement de la page à travers la fonction "page"
  await page.waitFor('body')
  // On indique au script, ce qu'on souhaite récupérer : ici les hrefs inclus dans la class .product_pod à travers la fonction "result"
  const result = await page.evaluate(() =>
    [...document.querySelectorAll('.product_pod a')].map(link => link.href),
  )
  // on affiche le résultat de la fonction "result"
  return result
}

Comme lors de l’appel de Puppeteer, on va utiliser les déclarations const pour créer des raccourcis qui sera appelés tout au long du script.

Dans la première partie de ce script, on utilisera donc 3 const :

  1. const récupèrelesrésultats = async (browser, url) => { déclare le raccourci récupèrelesrésultats dans lequel est inclu tout le code compris entre l’accolade d’ouverture { et l’accolade de fermeture }
  2. const page déclare le raccourci page qui indique qu’il faut ouvrir un nouvel onglet
  3. const result déclare le raccourci result qui de son côté va récupérer le contenu de la page compris dans les liens incluant la class .product_pod

Ces déclarations expliquées, il nous reste à comprendre le reste du code !

Si vous avez quelques notions d’anglais, l’excercice devrait être relativement facile. Voyons le code en 4 points :

  • Await : await browser.newPage() indique qu’il faut ouvrir un nouvel onglet / une nouvelle page. Await page.goto(‘http://books.toscrape.com/’), qu’il faut aller à la page http://books.toscrape.com/ …
  • Page.waitFor(‘body’) indique qu’il faut attendre le chargement du body (ndlr de la page)
  • Await page.evaluate indique ce que l’on souhaite récupérer. Ici, document.querySelectorAll(‘.product_pod a’), soit le contenu de la page compris dans les liens incluant la class .product_pod
  • Enfin, return result qui est chargé d’afficher la décaration result
1. Deuxième partie du script

Seconde partie du script : on indique au script les données à scraper

Node

// On déclare la fonction "récupèrelesrésultats" qui va gérer toute la deuxième partie du script
const récupèrelesrésultats = async (browser, url) => {
	// On indique à Puppeteer que dès que la fonction "page" est appelée, il faut ouvrir une nouvelle page
  const page = await browser.newPage()
  // On indique à Puppeteer qu'il faut aller rester sur la page actuelle, appellée nativement "url"
  await page.goto(url)
  // On demande au script d'attendre le chargement de la page à travers la fonction "page"
  await page.waitFor('body')
  return page.evaluate(() => {
  	// On indique au script, ce qu'on souhaite récupérer : ici les h1 et la class ".price_color" qui définit les prix sur le site
    let Produit = document.querySelector('h1').innerText
    let Prix = document.querySelector('.price_color').innerText
     // on affiche le résultat de la fonction "result"
    return { Produit, Prix }
  })
}

Si vous avez suivi la première partie du script, aucune surprise ici, à l’exception d’une déclaration let que l’on retrouve à travers la commande let Produit = document.querySelector(‘h1’).innerText. Let est un peu comme const avec quelques différences que j’expliquerai dans un prochain article.

1. Troisième partie du script

Troisième partie du script : on scrape

Node

// Création de la fonction "scraping"
const scraping = async () => {
	// On indique à Puppeteer que l'on souhaite voir qu'il lance une instance (puppeteer.launch()) et que l'on souhaite que Chromium s'ouvre { headless: false } (mettre à true pour qu'il se lance silencieusement)
  const browser = await puppeteer.launch({ headless: false })
  // On récupère toutes nos données scrapées
  const urlList = await récupèrelesurls(browser)
  const results = await Promise.all(
    urlList.map(url => récupèrelesrésultats(browser, url)),
  )
  // On ferme tout
  browser.close()
  // On affiche
  return results
}

Ici, quelques fonctions importantes.

Tout d’abord, vous remarquerez que de nombreuses déclarations const sont appelées. C’est le cas de puppeteer à travers puppeteer.launch, mais également de récupèrelesurls ou encore récupèrelesrésultats

Enfin, à la quatrième ligne, on écrit l’une des lignes les plus importante de notre script : const browser = await puppeteer.launch({ headless: false }). Sans elle, notre script ne fonctionnera pas. Ici, cette ligne indique au script de se lancer avec puppeteer (await puppeteer.launch) et d’ouvrir le navigateur{ headless: false } )

1. Dernière partie du script

Dernière partie du script : on envoi les résultats à la console

Node

scraping()
.then(résultats => {
console.log(résultats)
})

Étape 4 : Lancement du script

Une fois le code écrit, il ne nous reste plus qu’à l’exécuter. À nouveau dans le Terminal, rendez vous dans votre dossier et tapez la commande suivante :

 

Term

node puppeteer.js

Chromium va s’ouvrir comme dans la vidéo ci-dessous. Laissez le faire, il se ferma tout seul et vous aurez le même résultat que moi !