Proposition de Clément Garbay (LinkedIn).
Un navigateur de type Chrome Headless ainsi que l'API puppeteer sont utilisés.
Il est nécessaire d'utiliser une version de node >=8 (besoin de async/await
).
yarn install
yarn start
Pour avoir le détail des opérations effectuées :
yarn start:log
Contient tous les outils métier nécessaires à récupérer les transactions du site.
scraper.js
: Permet grâce à la fonctiongetTransactions
de récupérer les objets transactions à partir d'une URL d'une page et d'une instance de navigateur puppeteer.scraper-runner.js
: Gère toute la logique de scraping entre les différentes pages. Le fichier contient une seule fonctionrun
qui à partir d'une instance de navigateur puppeteer démarre le scraping avec comme stratégie de paralléliser le scraping en lançeant plusieurs pages en même temps, en utilisant une queue évènementielle.
Contient un ensemble de fonctions permettant d'aider à manipuler et récupérer des informations sur une instance de page puppeteer.
Contient les éléments nécessaires à la création d'une queue asynchrone, ainsi que quelques objets permettant de structurer les tâches de la queue.
- Le scraping est lancé sur la page commençant à 0 afin de récupérer le nombre d'éléments par page.
- Un pool (selon le nombre de tâches concurrentes spécifié) de tâches de scraping est lancé dans la queue, et donc sur différents onglets du navigateur.
- Dès qu'une tâche termine en succès, elle relance une nouvelle tâche de scraping avec comme paramètre de début de page
pageStart
la dernière valeur depageStart
utiliser + le nombre d'éléments que la page contenait. /!\ Si la page ne contenait pas d'élément (tableau vide) alors aucune tâche n'est ajoutée dans la queue. - Quand toutes les tâches de la queue sont terminées, le résultat est retourné.
Lors du scraping d'une page, on trouve plusieurs cas de figures :
- Le tableau HTML est dans la page racine (cas nominal).
- Le tableau HTML est dans une iframe.
- Une alerte JS est lancée et le tableau est chargé qu'après le clique sur le bouton "Reload Transactions".
Le résultat est enregistré dans le fichier res.json
du dossier res
. Il contient un tableau d'objets JSON représentant les transactions récupérées.
Structure d'une transaction :
{
"account": "Checking",
"transaction": "Transaction X",
"amount": "54",
"currency": "€"
}
Environ 5000 résultats sont récupérés en ~23 secondes.
-
Seules les pages ayant un paramètre d'URL allant de 0 à +∞ (i.e. positif) sont considérées.
-
Les pages ayant un paramètre négatif ne sont pas scrapées pour deux raisons :
- Ce paramètre est infini et les résultats sont incohérents (la page https://web.bankin.com/challenge/index.html?start=-5000000000000000000000000000000000000 donne par exemple des résultats mais avec des numéros de transactions sans sens).
- Un système de pagination avec des index négatifs est un peu (beaucoup) étrange !
-
Le lien "Next -->" n'est pas utilisé (inutile).
- Permettre d'annuler des tâches lancées inutilement. Par exemple, il s'agirait de lancer encore plus de tâches au départ, mais que la queue annule les tâches qu'elle aurait lancé en trop inutilement (
startPage
trop grand) suivant la valeur destartPage
de la dernière page (i.e. première page qui ne contient plus aucun élément). J'ai commencé ce travail dans la branchewith-cancellation
, mais je n'ai pas eu le temps de finir. - Multibrowser / multithread