Estrarre gli URL da una sitemap in CSV o JSON: 5 metodi

Estrarre gli URL da una sitemap in CSV o JSON: 5 metodi

Per estrarre URL da una sitemap basta il testo dei suoi elementi loc. L'ostacolo è lo spazio dei nomi XML: una semplice query //loc non trova nulla. Ecco cinque modi per ottenere l'elenco in CSV, JSON o testo semplice, da uno strumento nel browser che non richiede alcuna configurazione a uno script Python che segue anche un indice delle sitemap.

Perché //loc non restituisce nulla su una sitemap?

Ogni sitemap dichiara uno spazio dei nomi nel suo elemento radice: <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">. Il protocollo di sitemaps.org lo rende obbligatorio. Poiché è uno spazio dei nomi predefinito, senza prefisso, ogni elemento <url> e <loc> del file vi appartiene.

XPath 1.0 tratta un nome senza prefisso come un nome privo di spazio dei nomi. Quindi //loc cerca un elemento <loc> senza spazio dei nomi, e in una sitemap valida non ce n’è nessuno. La query è un XPath corretto. Semplicemente non corrisponde ad alcun nodo, ed è per questo che tanti script e formule restituiscono un risultato vuoto.

Le soluzioni sono due, e ogni metodo descritto qui sotto ne usa una:

  • Cercare l’elemento solo in base al suo nome locale: //*[local-name()='loc']. Funziona in qualsiasi strumento XPath 1.0, senza configurazione.
  • Associare un prefisso all’URI dello spazio dei nomi e usarlo: //sm:loc, dove sm sta per http://www.sitemaps.org/schemas/sitemap/0.9. Python e la maggior parte delle librerie lo permettono.

Puoi provarle entrambe sul tuo file nel nostro tester XPath online. Lo strumento assegna allo spazio dei nomi predefinito il prefisso d, quindi //d:loc elenca ogni URL con la sua riga.

C’è un’altra trappola: l’indice delle sitemap. La sua radice è <sitemapindex> e i suoi elementi <loc> puntano ad altre sitemap, non a pagine. Google ne ammette fino a 50.000 per indice, tutte sullo stesso sito, a meno che non sia configurato l’invio tra siti diversi. WordPress ne pubblica uno per impostazione predefinita, come mostra la nostra guida agli indirizzi della sitemap di WordPress. Per ogni metodo indichiamo come gestisce un indice.

Da sitemap a CSV nel browser, senza installare nulla

Il nostro Sitemap Checker gratuito legge una sitemap che incolli, apri o trascini sulla pagina, in formato .xml o .xml.gz. Il file resta nel tuo browser. Dopo il controllo, la scheda «URL» mostra una tabella con quattro colonne: URL, ultima modifica, frequenza di modifica e priorità.

  1. Apri la sitemap nel browser e salvala, oppure copiane il sorgente.
  2. Incollala nel Sitemap Checker, oppure usa «Apri file…», poi premi «Verifica sitemap».
  3. Apri la scheda «URL». Scrivi una parte di indirizzo in «Filtra gli URL» per tenere solo alcune righe, e fai clic sull’intestazione di una colonna per ordinarle.
  4. Premi «Esporta CSV».

Il CSV contiene le righe come le mostra la tabella, con filtro e ordinamento, nelle colonne loc, lastmod, changefreq e priority. È in UTF-8 con BOM (byte order mark), così Excel mostra correttamente i caratteri accentati. A una cella che inizia con =, +, - o @ viene anteposto un apostrofo, perché un foglio di calcolo non la esegua come formula. Il file prende il nome del file che hai aperto, oppure sitemap.csv per il testo incollato.

I limiti sono due. Lo strumento esporta solo in CSV, non in JSON. E non si collega mai ad altri siti, quindi non può leggere una sitemap dal suo URL né seguire le sitemap elencate in un indice. Su un indice la scheda si chiama «Sitemap» e il CSV ha due colonne, loc e lastmod: le sitemap figlie, non le pagine.

Per ottenere JSON da un file, il convertitore da XML a JSON converte l’intera sitemap. Ottieni la sua struttura, con ogni <url> come oggetto, invece di un semplice elenco di righe.

Esportare una sitemap online da Chrome in CSV o JSON

L’estensione XMLNest per Chrome, disponibile nel Chrome Web Store, apre in Chrome l’URL di una sitemap online e la mostra come tabella nella vista Lettura. Sopra la tabella ci sono tre pulsanti:

  • Esporta CSV salva le colonne URL, Last modified, Change frequency e Priority (le intestazioni del file restano in inglese), più i conteggi Images e Alternates quando la sitemap contiene voci di immagini o hreflang.
  • Esporta JSON salva un array di oggetti con le chiavi loc, lastmod, changefreq, priority, images e alternates.
  • Copia URL copia solo gli indirizzi, uno per riga, pronti da incollare in una colonna o in un crawler.

Tutti e tre usano le righe mostrate, nell’ordine mostrato. «Filtra URL» tiene gli indirizzi che contengono un certo testo, e «Modificati dal» tiene gli URL modificati in una data o dopo. Filtra /blog/, scegli una data, ed esporti solo gli articoli recenti. Come nel Sitemap Checker, le celle CSV che iniziano con =, +, - o @ vengono neutralizzate.

Su un indice delle sitemap, «Carica tutte le sitemap figlie» legge le sitemap dello stesso sito elencate nell’indice, al massimo 50, una alla volta. Non richiede mai sitemap su altri siti. «Mostra tutti gli URL» le riunisce poi in un’unica tabella, con una colonna Sitemap in più che indica il file da cui proviene ogni URL, e le tre esportazioni funzionano anche su questa tabella.

Estrarre gli URL della sitemap con curl e xmllint

xmllint fa parte di libxml2. È incluso in macOS, su Debian e Ubuntu si trova nel pacchetto libxml2-utils, e su Windows si può usare tramite WSL. La sua opzione --xpath esegue un’espressione e ne stampa il risultato:

curl -s https://www.example.com/sitemap.xml \
  | xmllint --xpath "//*[local-name()='loc']/text()" - > urls.txt

Il - indica a xmllint di leggere dalla pipe. Con //loc, invece, secondo il manuale xmllint stampa «XPath set is empty» ed esce con il codice 11: è il problema dello spazio dei nomi descritto sopra. Il manuale non documenta alcuna opzione per associare un prefisso a uno spazio dei nomi con --xpath, ed è per questo che qui la forma con local-name() è quella pratica.

Il manuale dice solo che ogni nodo del risultato viene serializzato per intero. Verifica che la tua versione stampi un URL per riga prima di passare urls.txt a un altro script.

Una sitemap compressa con gzip richiede un passaggio in più, gunzip, tra il download e xmllint:

curl -s https://www.example.com/sitemap.xml.gz | gunzip \
  | xmllint --xpath "//*[local-name()='loc']/text()" -

Su un indice, lo stesso comando restituisce gli indirizzi delle sitemap figlie. Eseguilo di nuovo su ciascuna per ottenere le pagine:

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

Abbiamo eseguito l’esempio Python qui sotto; i comandi xmllint seguono il manuale.

Python: da sitemap a JSON o CSV, indici compresi

ElementTree di Python espande lo spazio dei nomi predefinito nel nome del tag, quindi la radice di una sitemap diventa {http://www.sitemaps.org/schemas/sitemap/0.9}urlset. Nel nostro test con Python 3.14, root.findall(".//loc") ha restituito zero elementi. La documentazione di Python indica la soluzione: passare un dizionario di prefissi a find() e findall().

Questo script legge una sitemap o un indice dal suo URL, segue le sitemap figlie di un indice, decomprime i file gzip e scrive loc, lastmod e la sitemap di origine in 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")

Eseguilo con python sitemap_to_csv.py https://www.example.com/sitemap_index.xml. Sul nostro indice di prova, che elencava una sitemap normale e una .xml.gz, ha scritto quattro righe. Un URL scritto ?page=2&amp;sort=new nell’XML è uscito come ?page=2&sort=new, perché il parser decodifica le entità.

Per il JSON, sostituisci l’ultimo blocco con json.dump() della libreria standard, per esempio con un elenco di oggetti con le chiavi loc, lastmod e sitemap. Se analizzi sitemap di siti che non controlli, leggi prima la sezione sulla sicurezza XML della documentazione di Python.

Google Sheets IMPORTXML: un elenco di URL in una colonna

La pagina di assistenza di Google su IMPORTXML elenca l’XML tra i tipi di dati che la funzione legge. La sua sintassi è IMPORTXML(url, xpath_query, locale), e l’URL può essere un riferimento a una cella. In una cella, usa la forma con local-name():

=IMPORTXML("https://www.example.com/sitemap.xml", "//*[local-name()='loc']")

La pagina di assistenza non dice nulla sugli spazi dei nomi XML. L’espressione con local-name() non dipende da come Sheets li gestisce, perché trova l’elemento solo in base al nome. Con File > Scarica > Valori separati da virgola (.csv) salvi poi il foglio come file CSV. Non abbiamo testato IMPORTXML per questo articolo: questa sezione segue la pagina di assistenza di Google.

Per un indice, la formula restituisce le sitemap figlie. Metti l’indirizzo di una sitemap figlia per cella nella colonna A, poi usa =IMPORTXML(A2, "//*[local-name()='loc']") nella colonna accanto per ciascuna.

Se la sitemap stessa non si carica, parti da perché Google non recupera la sitemap: una pagina di errore HTML non restituisce alcun elemento <loc>.

Fonti

  1. sitemaps.org: Protocollo (verificata il 29 ottobre 2026)
  2. Google Search Central: Gestire le sitemap con i file indice (verificata il 29 ottobre 2026)
  3. W3C: XML Path Language (XPath) 1.0, test dei nodi (verificata il 29 ottobre 2026)
  4. libxml2: pagina di manuale di xmllint (verificata il 29 ottobre 2026)
  5. Documentazione di Python: xml.etree.ElementTree, analisi di XML con spazi dei nomi (verificata il 29 ottobre 2026)
  6. Documentazione di Python: sicurezza XML (verificata il 29 ottobre 2026)
  7. IMPORTXML - Guida di Editor di documenti Google (verificata il 29 ottobre 2026)
  8. Test di XMLNest : Testato da XMLNest il 29 ottobre 2026 con Python 3.14.3: findall('.//loc') di ElementTree ha restituito 0 elementi su una sitemap con lo spazio dei nomi di sitemaps.org, e lo script con spazio dei nomi riportato qui sotto ha scritto 4 righe a partire da un indice che elencava una sitemap normale e una compressa con gzip, con &amp; decodificato in &. Anche lxml 6, basato su libxml2 come xmllint, ha restituito 0 nodi per //loc e tutti gli URL per //*[local-name()='loc']. I comandi xmllint non sono stati eseguiti; seguono il manuale. (verificata il 29 ottobre 2026)