Extraire les URL d'un sitemap en CSV ou en JSON : 5 méthodes
Pour extraire les URL d'un sitemap, il suffit du texte de ses éléments loc. Le piège, c'est l'espace de noms XML : une simple requête //loc ne trouve rien. Voici cinq façons d'obtenir cette liste en CSV, en JSON ou en texte brut, d'un outil dans le navigateur sans aucune installation à un script Python qui suit aussi un index de sitemaps.
Pourquoi //loc ne renvoie-t-il rien sur un sitemap ?
Chaque sitemap déclare un espace de noms sur son élément racine : <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">. Le protocole sitemaps.org l’exige. Comme il s’agit d’un espace de noms par défaut, sans préfixe, tous les éléments <url> et <loc> du fichier lui appartiennent.
XPath 1.0 traite un nom sans préfixe comme un nom sans espace de noms. //loc cherche donc un élément <loc> qui n’a pas d’espace de noms, et un sitemap valide n’en contient aucun. La requête est du XPath correct. Elle ne trouve simplement aucun nœud, et c’est pour cela que tant de scripts et de formules renvoient un résultat vide.
Il existe deux solutions, et chaque méthode ci-dessous utilise l’une d’elles :
- Désigner l’élément par son seul nom local :
//*[local-name()='loc']. Cela fonctionne dans n’importe quel outil XPath 1.0, sans réglage. - Associer un préfixe à l’URI de l’espace de noms et l’utiliser :
//sm:loc, oùsmreprésentehttp://www.sitemaps.org/schemas/sitemap/0.9. Python et la plupart des bibliothèques le permettent.
Vous pouvez essayer les deux sur votre propre fichier dans notre testeur XPath en ligne. Il donne le préfixe d à l’espace de noms par défaut : //d:loc liste alors chaque URL avec sa ligne.
Dernier piège : l’index de sitemaps. Sa racine est <sitemapindex>, et ses éléments <loc> pointent vers d’autres sitemaps, pas vers des pages. Google en accepte jusqu’à 50 000 par index, tous sur le même site, sauf si l’envoi pour plusieurs sites est configuré. WordPress en sert un par défaut, comme le montre notre guide sur les adresses du sitemap WordPress. Chaque méthode ci-dessous précise comment elle traite un index.
Un sitemap en CSV dans le navigateur, sans installation
Notre vérificateur de sitemap gratuit lit un sitemap que vous collez, ouvrez ou déposez sur la page, en .xml ou en .xml.gz. Le fichier reste dans votre navigateur. Après la vérification, l’onglet « URL » affiche un tableau de quatre colonnes : URL, dernière modification, fréquence et priorité.
- Ouvrez le sitemap dans votre navigateur et enregistrez-le, ou copiez sa source.
- Collez-le dans le vérificateur, ou utilisez « Ouvrir un fichier… », puis appuyez sur « Vérifier le sitemap ».
- Ouvrez l’onglet « URL ». Tapez une partie d’adresse dans « Filtrer les URL » pour ne garder que certaines lignes, et cliquez sur un en-tête de colonne pour trier.
- Appuyez sur « Exporter en CSV ».
Le CSV contient les lignes telles que le tableau les affiche, filtre et tri compris, avec les colonnes loc, lastmod, changefreq et priority. Il est encodé en UTF-8 avec une marque d’ordre des octets (BOM) : Excel affiche donc correctement les caractères accentués. Une cellule qui commence par =, +, - ou @ reçoit une apostrophe devant, pour qu’un tableur ne l’exécute pas comme une formule. Le fichier prend le nom du fichier ouvert, ou sitemap.csv pour un texte collé.
Deux limites. L’outil n’exporte qu’en CSV, pas en JSON. Et il ne se connecte jamais à d’autres sites : il ne peut ni lire un sitemap depuis son URL, ni suivre les sitemaps listés dans un index. Sur un index, l’onglet s’appelle « Sitemaps » et le CSV n’a que deux colonnes, loc et lastmod : ce sont les sitemaps enfants, pas les pages.
Pour obtenir du JSON à partir d’un fichier, le convertisseur XML en JSON convertit tout le sitemap. Vous obtenez sa structure, avec chaque <url> sous forme d’objet, plutôt qu’une liste plate de lignes.
Exporter un sitemap en ligne depuis Chrome, en CSV ou en JSON
L’extension XMLNest pour Chrome, disponible sur le Chrome Web Store, ouvre dans Chrome l’URL d’un sitemap en ligne et l’affiche sous forme de tableau dans sa vue Lecture. Trois boutons se trouvent au-dessus du tableau :
- Exporter en CSV enregistre les colonnes URL, dernière modification, fréquence et priorité, plus le nombre d’images et de versions linguistiques quand le sitemap contient des entrées image ou hreflang.
- Exporter en JSON enregistre un tableau d’objets avec les clés
loc,lastmod,changefreq,priority,imagesetalternates. - Copier les URL copie seulement les adresses, une par ligne, prêtes à coller dans une colonne ou dans un crawler.
Les trois boutons utilisent les lignes affichées, dans l’ordre affiché. « Filtrer les URL » garde les adresses qui contiennent un texte, et « Modifiées depuis » garde les URL modifiées à une date donnée ou après. Filtrez sur /blog/ et choisissez une date : vous n’exportez que les articles récents. Comme dans le vérificateur de sitemap, les cellules CSV qui commencent par =, +, - ou @ sont échappées.
Sur un index, « Charger tous les sitemaps enfants » lit les sitemaps du même site listés dans l’index, 50 au maximum, un par un. L’extension ne demande jamais de sitemap situé sur un autre site. « Afficher toutes les URL » les réunit ensuite dans un seul tableau, avec une colonne Sitemap en plus qui indique de quel fichier vient chaque URL, et les trois exports fonctionnent aussi sur ce tableau.
Lister les URL avec curl et xmllint
xmllint fait partie de libxml2. macOS l’inclut, Debian et Ubuntu le proposent dans le paquet libxml2-utils, et sous Windows vous pouvez l’utiliser via WSL. Son option --xpath exécute une expression et affiche le résultat :
curl -s https://www.example.com/sitemap.xml \
| xmllint --xpath "//*[local-name()='loc']/text()" - > urls.txt
Le - indique à xmllint de lire depuis le tube. Avec //loc à la place, d’après le manuel, xmllint affiche « XPath set is empty » et se termine avec le code 11 : c’est le problème d’espace de noms décrit plus haut. Le manuel ne documente aucune option pour associer un préfixe d’espace de noms avec --xpath, et c’est pourquoi la forme local-name() est la plus pratique ici.
Le manuel dit seulement que chaque nœud du résultat est sérialisé en entier. Vérifiez que votre version affiche une URL par ligne avant de transmettre urls.txt à un autre script.
Un sitemap compressé en gzip demande une étape de plus, gunzip, entre le téléchargement et xmllint :
curl -s https://www.example.com/sitemap.xml.gz | gunzip \
| xmllint --xpath "//*[local-name()='loc']/text()" -
Sur un index, la même commande renvoie les adresses des sitemaps enfants. Relancez-la sur chacun d’eux pour obtenir les pages :
curl -s https://www.example.com/sitemap_index.xml \
| xmllint --xpath "//*[local-name()='loc']/text()" - \
| while read -r sm; do
curl -s "$sm" | xmllint --xpath "//*[local-name()='loc']/text()" -
done > all-urls.txt
Nous avons exécuté l’exemple Python ci-dessous ; les commandes xmllint suivent le manuel de l’outil.
Python : un sitemap en JSON ou en CSV, index compris
L’ElementTree de Python intègre l’espace de noms par défaut au nom de la balise : la racine d’un sitemap devient {http://www.sitemaps.org/schemas/sitemap/0.9}urlset. Dans notre test avec Python 3.14, root.findall(".//loc") a renvoyé zéro élément. La documentation de Python donne la solution : passer un dictionnaire de préfixes à find() et findall().
Ce script lit un sitemap ou un index depuis son URL, suit les sitemaps enfants d’un index, décompresse les fichiers gzip et écrit loc, lastmod et le sitemap d’origine dans urls.csv :
import csv
import gzip
import sys
import urllib.request
import xml.etree.ElementTree as ET
NS = {"sm": "http://www.sitemaps.org/schemas/sitemap/0.9"}
def read(url):
with urllib.request.urlopen(url) as response:
data = response.read()
if data[:2] == b"\x1f\x8b": # gzip
data = gzip.decompress(data)
return ET.fromstring(data)
def collect(url, rows):
root = read(url)
if root.tag == "{%s}sitemapindex" % NS["sm"]:
for child in root.findall("sm:sitemap/sm:loc", NS):
collect(child.text.strip(), rows)
else:
for entry in root.findall("sm:url", NS):
rows.append([entry.findtext("sm:loc", "", NS).strip(),
entry.findtext("sm:lastmod", "", NS).strip(),
url])
rows = []
collect(sys.argv[1], rows)
with open("urls.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["loc", "lastmod", "sitemap"])
writer.writerows(rows)
print(len(rows), "URLs written to urls.csv")
Lancez-le avec python sitemap_to_csv.py https://www.example.com/sitemap_index.xml. Sur notre index de test, qui listait un sitemap simple et un sitemap .xml.gz, il a écrit quatre lignes. Une URL écrite ?page=2&sort=new dans le XML est ressortie sous la forme ?page=2&sort=new, car l’analyseur décode les entités.
Pour du JSON, remplacez le dernier bloc par json.dump(), de la bibliothèque standard, par exemple avec une liste d’objets aux clés loc, lastmod et sitemap. Si vous analysez des sitemaps de sites que vous ne contrôlez pas, lisez d’abord la section sur la sécurité XML de la documentation de Python.
Google Sheets et IMPORTXML : une liste d’URL dans une colonne
La page d’aide de Google sur IMPORTXML cite le XML parmi les types de données que la fonction lit. Sa syntaxe est IMPORTXML(url, xpath_query, locale), et l’URL peut être une référence de cellule. Utilisez la forme local-name() dans une cellule :
=IMPORTXML("https://www.example.com/sitemap.xml", "//*[local-name()='loc']")
Dans une feuille réglée sur les paramètres régionaux de la France, séparez les arguments par un point-virgule au lieu d’une virgule.
La page d’aide ne dit rien des espaces de noms XML. L’expression local-name() ne dépend pas de la façon dont Sheets les gère, puisqu’elle désigne l’élément par son seul nom. Fichier > Télécharger > Valeurs séparées par des virgules (.csv) enregistre ensuite la feuille au format CSV. Nous n’avons pas testé IMPORTXML pour cet article ; cette section suit la page d’aide de Google.
Pour un index, la formule renvoie les sitemaps enfants. Placez une adresse enfant par cellule dans la colonne A, puis utilisez =IMPORTXML(A2, "//*[local-name()='loc']") dans la colonne suivante pour chacune d’elles.
Si le sitemap lui-même ne se charge pas, commencez par notre article sur un sitemap impossible à récupérer : une page d’erreur HTML ne renvoie aucun élément <loc>.
Sources
- sitemaps.org : Protocole (vérifiée le 29 octobre 2026)
- Google Search Central : Gérer vos sitemaps avec des fichiers d'index de sitemaps (vérifiée le 29 octobre 2026)
- W3C : XML Path Language (XPath) 1.0, tests de nœuds (vérifiée le 29 octobre 2026)
- libxml2 : page de manuel de xmllint (vérifiée le 29 octobre 2026)
- Documentation Python : xml.etree.ElementTree, analyser du XML avec des espaces de noms (vérifiée le 29 octobre 2026)
- Documentation Python : sécurité XML (vérifiée le 29 octobre 2026)
- IMPORTXML - Aide Éditeurs Google Docs (vérifiée le 29 octobre 2026)
- Test fait par XMLNest : Testé par XMLNest le 29 octobre 2026 avec Python 3.14.3 : findall('.//loc') d'ElementTree a renvoyé 0 élément sur un sitemap déclarant l'espace de noms de sitemaps.org, et le script ci-dessous, qui gère l'espace de noms, a écrit 4 lignes à partir d'un index listant un sitemap simple et un sitemap compressé en gzip, avec & décodé en &. lxml 6, construit sur libxml2 comme xmllint, a lui aussi renvoyé 0 nœud pour //loc et toutes les URL pour //*[local-name()='loc']. Les commandes xmllint n'ont pas été exécutées ; elles suivent son manuel. (vérifiée le 29 octobre 2026)