Créer ses propres outils et automatiser au maximum les actions répétitives est un must have pour beaucoup de SEO. Certains sont adeptes du développement « from scratch », d’autres reprennent régulièrement des briques sur github ou stack overflow pour customiser leurs outils. Je fais personnellement parti de la seconde école. C’est d’ailleurs un cas client qui m’a poussé à créer un script permettant de scraper tous les liens d’une série de page, tels les pages « plan du site », ou encore une page de liste de produits. Après quelques ajouts de codes et des tests effectués avec plus ou moins de réussite, je suis heureux de vous présenter mon tuto permettant, en une trentaine de ligne de code, de scraper les ancres ainsi que les URL de chaque éléments par pages :-).
Pour la petite histoire, mon client a cherché à faire le ménage dans les liens internes de la page « plan du site » qui n’a pas été mis à jour depuis quelques années. La finalité est donc d’identifier et ensuite supprimer tous les liens renvoyant un code 404. On partait de loin : 181 pages sur lesquelles agir, contenant chacune environ 150 URL, soit environ 27000 URL uniques à traiter. Effectuer la manipulation à la main est donc tout simplement inconcevable ! Avec mon script en R, j’ai donc pu automatiser l’extraction de la data et les traiter ensuite avec mon crawler Screaming Frog.
Explication du script en R
Dans un premier temps, j’installe et déclare chacune des librairies que je vais appeler pour lancer mes scripts. 4 librairies sont concernées :
- rvest : me permet de parser (autrement dit de parcourir et d’aller chercher) le contenu d’une page web. Par exemple : créer une liste depuis une page Wikipédia, récupérer un texte / un contenu sur une page.
- purrr : me permet d’executer de manière récursive la même tâche, sur tous les éléments d’un même vecteur.
- httr : permet de récupérer le contenu des requêtes GET, POST, PATCH, HEAD, PUT et DELETE.
- stringr : me permet de manipuler une chaîne de caractère.
1
2
3
4
5
6
7
8
9
|
#Je déclare chacune de mes librairies
install.packages(rvest)
install.packages(purrr)
install.packages(httr)
install.packages(stringr)
library(rvest)
library(purrr)
library(httr)
library(stringr)
|
Ensuite, je déclare la page dans laquelle je vais débuter mon scrap dans une variable. Attention à ne pas indiquer le numéro de page dans l’URL. Nous remplacerons le paramètre contenant le numéro de la page (p=…) par la valeur %d.
1
|
url_base <– « https://www.monsite.com/repertoire/page/nom_de_la_page?p=%d »
|
Je déclare le nombre d’itérations correspondant au nombre total de pages à crawler. C’est à cette étape que nous ouvrons l’accolade qui contient l’ensemble du contenu de notre script.
1
|
map_df(1:184, function(i) {
|
J’affecte ensuite à une variable la fonction read_html permettant de lire le code HTML de l’URL déclarée dans la variable « url_base ». Dans l’exemple ci-dessous, j’ai nommé ma variable déclarative « pg ».
1
|
pg <– read_html(sprintf(url_base, i))
|
Ensuite, j’affecte à une nouvelle variable (produitText dans l’exemple) la fonction html_nodes, issue de la librairie rvest. Elle me permet d’extraire des textes, des attributs ou des balises depuis le code HTML, présent dans la variable déclarée en amont (pg).
Il faut ensuite indiquer quel est la partie du code HTML que nous souhaitons cibler et traiter pour extraire l’information dont nous avons besoin. L’extension chrome Selector Gadget permet notamment de cibler précisément les éléments HTML et CSS que nous souhaitons récupérer dans notre code. Dans l’exemple ci-dessous, nous avons récupéré les éléments HTML de <ul><li> de la class sitemap.produit, ainsi que le contenu de la balise <a>.
1
2
|
produit <– html_nodes(pg, « ul.sitemap.produits li a »)
produitText <– html_text(produit)
|
On extrait l’ancre de lien contenu entre les balises <a></a> avec la fonctionnalité html_attr, présent dans le package rvest.
1
2
3
|
hrefproduitText <– html_attr(produit, « href »)
stringsAsFactors=FALSE
|
Je met sous forme de tableau l’ensemble des éléments extraits, à l’aide de la fonction data.frame. Dans cet exemple, j’ai placé la fonction data.frame dans la variable ScrapProduits.
C’est ici que le script se termine, n’oubliez pas de fermer les accolades et parenthèses ;). Pour finir, on enregistre l’ensemble de notre script dans un variable, appelé dans l’exemple « fichier-de-sortie ».
1
2
|
ScrapProduits <– data.frame(Title=produitText, Link=hrefproduitText) })
-> fichier–de–sortie
|
On n’oublie pas d’enregistrer le fichier dans un répertoire défini, grâve à la fonction write.csv
1
|
write.csv(fichier–de–sortie, « Mon dossier/nom-de-mon-fichier.csv »)
|
Voici l’intégralité du script, à adapter selon vos besoin. Je suis preneur de vos feedback
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
#Je déclare chacune de mes librairies
install.packages(rvest)
install.packages(purrr)
install.packages(httr)
install.packages(stringr)
library(rvest)
library(purrr)
library(httr)
library(stringr)
install.packages()
#Je déclare la page dans laquelle je vais débuter mon scrap. Attention à ne pas indiquer le numéro de page dans l’URL. Nous remplacerons le paramètre contenant le numéro de la page (p=…) par la valeur %d
url_base <– « https://www.monsite.com/repertoire/page/nom_de_la_page?p=%d »
#Je déclare le nombre d’itérations correspondant aux nombres total de pages à crawler.
map_df(1:184, function(i) {
# simple but effective progress indicator
cat(« . »)
#J’affecte à la variable pg la fonction permettant de lire le code HTML de l’URL déclaré dans la variable « url_base »
pg <– read_html(sprintf(url_base, i))
#Grace à « html_nodes », On extrait les balises A pour chaque produit
produit <– html_nodes(pg, « ul.sitemap.produits li a »)
produitText <– html_text(produit)
#On extrait les liens grâce à html_attr, présent dans le package rvest.
hrefproduitText <– html_attr(produit, « href »)
stringsAsFactors=FALSE
#Je met sous forme de tableau l’ensemble des éléments que j’ai extrait, à l’aide de la fonction data.frame
ScrapProduits <– data.frame(Title=produitText, Link=hrefproduitText)
}) ->fichier–de–sortie
#J’enregistre mon fichier dans un répertoire défini, grâce à la fonction write.csv.
write.csv(fichier–de–sortie, « Mon dossier/nom-de-mon-fichier.csv »)
|