Extraire les liens et leurs ancres d’un site web

En référencement, les liens et les ancres ont un impact. Pour analyser le maillage interne de votre site, il est donc intéressant de pouvoir extraire l’ensemble de liens avec la source, la destination et l’ancre utilisée. Un simple script Bash peut vous aider pour cette tâche.

Le script Bash pour extraire vos liens et ancres

Récupérer le script

#! /bin/bash
# internal-external-links-lists.sh
# Script to list all internal & external links with sources, destinations & anchors.
# Originally written by Armand Philippot <contact@armandphilippot.com>.

###############################################################################
#
# MIT License

# Copyright (c) 2020 Armand Philippot

# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
###############################################################################

echo -e "Ce script permet de générer une liste des liens internes et externes avec la source, la destination et l'ancre.\n"

# We ask for the website to crawl
read -rp "Saisir l'URL du site: " _site_url

# We create a spinner
# Thanks to Louis Marascio - http://fitnr.com/showing-a-bash-spinner.html
spinner() {
    local pid=$!
    local delay=0.75
    local spinstr='|/-\'
    while [ "$(ps a | awk '{print $1}' | grep $pid)" ]; do
        local temp=${spinstr#?}
        printf " [%c]  " "$spinstr"
        local spinstr=$temp${spinstr%"$temp"}
        sleep $delay
        printf "\b\b\b\b\b\b"
    done
    printf "    \b\b\b\b"
}

# We display a warning message.
echo -e "Nous parcourons le site pour récupérer la liste d'URL. Cela peut prendre du temps, d'autant plus si votre site en comporte beaucoup.\n"
echo -e "Veuillez patienter.\n"

# We store the output of wget (urls list) in a temporary text file.
wget --spider --no-check-certificate --force-html -nd --delete-after -r -l 0 "$_site_url" 2>&1 | grep '^--' | awk '{ print $3 }' | grep -v '\.\(css\|js\|png\|gif\|jpg\|ico\|webmanifest\|svg\|pdf\|txt\)$' | grep -v '\/feed\/\|selectpod\.php\|xmlrpc\.php\|matomo-proxy\.php' | sort | uniq >internal-external-links-list.txt &
spinner

# We define a separator for our CSV file.
_sep="§"

# We create our CSV files and write headers.
echo "Source${_sep}Destination${_sep}Ancre" >internal-links-list.csv
echo "Source${_sep}Destination${_sep}Ancre" >external-links-list.csv

# We display a warning message.
echo -e "Nous traitons les URLs. Cela peut prendre du temps.\n"
echo -e "Veuillez patienter."

# We read each entry, we extract links and we write values in CSV files.
while read -r _url; do
    _url_list_with_anchor="$(curl -s "$_url" | grep -o '<a .*href=.*>.*</a>' | grep -v '\.\(css\|js\|png\|gif\|jpg\|ico\|webmanifest\|svg\|pdf\|txt\)' | sed -e 's/<a/\n<a/g' | perl -pe 's/(.*?)<a .*?href=['"'"'"]([^'"'"'"]{1,})['"'"'"][^>]*?>(?:<[^>]*>){0,}([^<]*)(?:<.*>){0,}<\/a>(.*?)$/\2'"$_sep"'\3/g' | sed -e '/^$/ d')"

    # We read only internal links and we write the source and destination in CSV file.
    _int_links="$(echo "$_url_list_with_anchor" | grep -E "(${_site_url%/}|^[/#])")"
    while read -r _internal; do
        echo "${_url}${_sep}${_internal}"
    done <<<"${_int_links}" >>internal-links-list.csv &
    spinner

    # We read only external links and we write the source and destination in CSV file.
    _ext_links="$(echo "$_url_list_with_anchor" | grep -Ev "(${_site_url%/}|^[/#])")"
    while read -r _external; do
        echo "${_url}${_sep}${_external}"
    done <<<"${_ext_links}" >>external-links-list.csv &
    spinner
done <internal-external-links-list.txt &
spinner

# We delete our temporary file internal-external-links-list.txt
rm internal-external-links-list.txt

# End.
echo -e "Les fichiers internal-links-list.csv et external-links-list.csv ont été générés. Le script est terminé."

Vous pouvez également retrouver le script sur mon repo Github ou Gitlab.

Utilisation du script

Il faut enregistrer le code dans un fichier ayant pour extension .sh. Puis, dans un terminal, il vous suffit de saisir la commande :

sh nom-du-script.sh

Le script va vous demander de saisir une URL. Tous les formats (avec ou sans http, avec sous sans / de fin) sont acceptés. Si vous utilisez le sous domaine www, il est préférable de le saisir avant le nom de domaine lorsque vous n’écrivez pas http/https (exemple : www.armandphilippot.com plutôt que armandphilippot.com). Il va alors parcourir le site pour récupérer toutes les URL.

Ensuite, pour chaque URL, il va récolter l’ensemble des liens présents dans la page avec l’ancre associée. Ces liens et ces ancres seront séparés en deux fichiers : les liens externes (ceux qui pointent vers un autre site) et les liens internes. Le séparateur par défaut pour les colonnes et le caractère § (placé au dessus du point d’exclamation sur les claviers AZERTY français).

Il ne vous reste plus qu’à ouvrir les fichiers CSV générés dans un tableur en précisant le caractère séparateur à utiliser.

Exemple : liens externes et ancres
external-links-list.csv

Le script en détail

Pour ce script, nous utilisons plusieurs commandes intégrées par défaut sur la plupart des distributions Linux je pense. Afin de mieux comprendre ce que le script fait, je vous propose de passer en revue son fonctionnement et les commandes utilisées.

Son fonctionnement

Nous commençons par afficher un prompt permettant à l’utilisateur de saisir l’URL du site à analyser. Ensuite, nous déclarons la fonction pour notre spinner. Ce dernier permet de montrer que le script est toujours actif et qu’il faut patienter. Nous l’utiliserons à chaque fois qu’une commande sera un peu longue à traiter. Je ne rentre pas dans le détail du spinner : comme indiqué, il provient du site de Louis Marascio et il explique son fonctionnement dans son article.

Nous poursuivons avec l’utilisation de wget. Cet outil permet de télécharger des fichiers depuis le web, mais avec ces options il peut faire office de spider (robot d’indexation). J’en ai déjà parlé dans mon article sur les commandes utiles pour le référencement. Vous y trouverez le détail des options donc je ne les expliquerai pas ici.

Ensuite, nous définissons un séparateur pour nos fichiers CSV. J’ai choisi le caractère § puisque je suis sûr qu’il ne sera pas présent dans une URL ou une ancre. Vous pouvez évidemment le modifier. Puis, nous préparons nous deux fichiers CSV en leur attribuant trois colonnes : le lien source, la destination et l’ancre utilisée.

Maintenant, nous allons lire l’ensemble des URL obtenues et nous allons les parcourir, récupérer les liens et extraire uniquement les informations qui nous intéressent : le lien et l’ancre. Nous séparons les liens externes des liens internes et nous insérons chacun des liens dans le fichier correspondant.

Finalement, nous supprimons le fichier texte qui contenait les URL obtenues avec wget puisque ce fichier ne nous est plus utile.

Les commandes en détail

Pour le prompt, nous utilisons la commande read -rp. L’option -p permet d’afficher le prompt sur la même ligne. Avec l’option -r, la barre oblique inverse (backslash) n’agit plus comme un caractère d’échappement. Même si, ce n’est pas vraiment utile pour une URL.

Nous utilisons curl pour parcourir les URL obtenues avec wget. L’option -s permet d’utiliser le mode silencieux : rien ne s’affichera à l’écran.

Nous utilisons deux fois grep pour cibler les liens qui nous intéressent.

  • L’option -o indique à grep de n’afficher que la partie correspondante à la requête. Ici nous ciblons uniquement <a href=>…</a>.
  • L’option -v permet d’indiquer à grep que nous souhaitons l’inverse de la requête. Ici, nous ne voulons pas des URL pointant sur une image ou un PDF par exemple.

Ensuite, nous utilisons sed avec l’option -e qui indique le script à interpréter. Ici, nous insérons un retour à ligne entre chaque URL.

Nous pouvons maintenant utiliser perl pour récupérer les informations qui nous intéressent grâce aux expressions régulières. L’option -p permet à perl d’agir comme sed et l’option -e indique le script à interpréter. Nous capturons deux groupes : le lien et l’ancre. Nous ne garderons que ça, et nous insérons notre séparateur entre les deux données. Nous utilisons perl plutôt que sed parce qu’il permet les groupes non capturés, ce qui est utile avec des expressions régulières plus complexe.

Enfin, nous utilisons à nouveau sed pour supprimer les éventuelles lignes sans liens. Le résultat de ces commandes est stocké dans une variable. Nous utilisons cette variable pour séparer les liens internes des liens externes grâce à grep. L’option -E agit comme l’option -e en y ajoutant des fonctionnalités supplémentaires.

Voilà, je pense que nous avons fait le tour des commandes utilisées pour mieux comprendre le script !

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.