La mayoría de los rastreadores descubren páginas de la manera costosa: obtienen una página, extraen sus enlaces, los ponen en cola y repiten. Funciona, pero gasta la mayor parte de su presupuesto en navegación, listados y páginas que ya se han visto, y aun así puede pasar por alto páginas que no tienen enlaces entrantes.
Muchos sitios publican a propósito una lista de sus URLs. Los sitemaps XML existen para que los motores de búsqueda puedan encontrar páginas de forma eficiente, y ese mismo archivo le indica a un equipo de datos qué existe en un sitio, cómo está organizado y, a veces, qué ha cambiado recientemente. Esta guía trata sobre cómo encontrar y leer sitemaps correctamente, y por qué el campo más útil que contienen, lastmod, necesita ser verificado antes de confiar en él. Lo comprobamos en dos sitios reales, y falló de dos maneras distintas.
Puntos clave
- Un sitemap enumera hasta 50.000 URLs por archivo, y un índice de sitemaps puede enumerar hasta 50.000 sitemaps, así que incluso los sitios muy grandes pueden publicar un inventario completo.
- Los sitemaps suelen declararse en robots.txt con una línea
Sitemap:; conviene comprobarlo antes de adivinar una ubicación. lastmodes el campo que podría ahorrarte más peticiones, y es el menos fiable. Google dice que solo usalastmodsi es “consistente y verificablemente” preciso.- En nuestra comprobación, el sitemap de noticias de un gran editor de noticias asignaba a todas las entradas la misma marca temporal, el momento en que se generó el archivo. Un gran archivo documental publicó más de 10.000 URLs sin ningún
lastmod. - Usa los sitemaps para el descubrimiento, verifica
lastmodpor sitio antes de programar tareas sobre él, y mantén el rastreo por enlaces como red de seguridad.
Qué permite el protocolo
El protocolo de sitemaps es breve y merece la pena conocerlo con precisión:
| Regla | Detalle |
|---|---|
| Límites de tamaño | ”no más de 50.000 URLs” y “no más de 50MB (52.428.800 bytes)” por archivo de sitemap, sin comprimir |
| Índices de sitemaps | Un archivo que enumera otros sitemaps, con los mismos límites de 50.000 entradas y 50MB |
| Compresión | Los archivos pueden comprimirse con gzip, siempre que estén dentro del límite una vez descomprimidos |
lastmod | Opcional, en formato W3C Datetime, que puede ser solo una fecha, como YYYY-MM-DD |
| Descubrimiento | Una línea Sitemap: en robots.txt; un sitio puede enumerar varias |
Dos campos opcionales que verás, changefreq y priority, pueden ignorarse. Google dice claramente que “ignora los valores de <priority> y <changefreq>”, y hay pocos motivos para que nadie más confíe en ellos tampoco.
Los sitios de noticias suelen publicar un sitemap de noticias independiente que cubre solo los artículos recientes, con campos adicionales como una fecha de publicación. Son pequeños, se regeneran con frecuencia y son muy útiles para monitorizar contenido reciente.
Leer sitemaps correctamente
Un lector robusto debe hacer cuatro cosas: encontrar los sitemaps a partir de robots.txt, gestionar gzip, seguir los índices de sitemaps de forma recursiva, y analizar lastmod para convertirlo en algo comparable. También debería limitar cuántos archivos obtiene, ya que un índice puede apuntar a miles de ellos.
import gzip
import io
import re
import urllib.request
from datetime import datetime, timezone
from defusedxml.ElementTree import fromstring # pip install defusedxml
NS = "{http://www.sitemaps.org/schemas/sitemap/0.9}"
UA = "Mozilla/5.0 (compatible; sitemap-reader)"
MAX_BYTES = 52_428_800 # the protocol's 50MB limit, uncompressed
def fetch(url, opener=None):
opener = opener or urllib.request.build_opener()
req = urllib.request.Request(url, headers={"User-Agent": UA})
with opener.open(req, timeout=45) as r:
body = r.read(MAX_BYTES + 1)
if body[:2] == b"\x1f\x8b":
body = gzip.GzipFile(fileobj=io.BytesIO(body)).read(MAX_BYTES + 1)
if len(body) > MAX_BYTES:
raise ValueError(f"{url} exceeds the 50MB sitemap limit")
return body
def sitemap_roots(origin, opener=None):
"""Sitemaps declared in robots.txt, falling back to /sitemap.xml."""
try:
robots = fetch(origin.rstrip("/") + "/robots.txt", opener).decode("utf-8", "replace")
found = re.findall(r"(?im)^\s*sitemap:\s*(\S+)", robots)
except OSError:
found = []
return found or [origin.rstrip("/") + "/sitemap.xml"]
def parse_lastmod(value):
if not value:
return None
value = value.strip().replace("Z", "+00:00")
try:
dt = datetime.fromisoformat(value)
except ValueError:
return None
return dt if dt.tzinfo else dt.replace(tzinfo=timezone.utc)
def walk(url, opener=None, max_files=20, _seen=None):
"""Yield (loc, lastmod) from a sitemap or sitemap index, following nested indexes."""
seen = _seen if _seen is not None else set()
if url in seen or len(seen) >= max_files:
return
seen.add(url)
root = fromstring(fetch(url, opener))
if root.tag == NS + "sitemapindex":
children = sorted(root.findall(NS + "sitemap"),
key=lambda s: parse_lastmod(s.findtext(NS + "lastmod")) or datetime.min.replace(tzinfo=timezone.utc),
reverse=True)
for child in children:
yield from walk(child.findtext(NS + "loc").strip(), opener, max_files, seen)
else:
for u in root.findall(NS + "url"):
yield u.findtext(NS + "loc").strip(), parse_lastmod(u.findtext(NS + "lastmod"))
def changed_since(origin, since, opener=None, max_files=20):
"""URLs whose sitemap lastmod is newer than `since`, plus those with no lastmod at all."""
changed, undated, total = [], [], 0
for root in sitemap_roots(origin, opener):
for loc, lastmod in walk(root, opener, max_files):
total += 1
if lastmod is None:
undated.append(loc)
elif lastmod > since:
changed.append((loc, lastmod))
return {"total": total, "changed": changed, "undated": undated}
El recorrido del índice visita los sitemaps hijos empezando por los más recientes cuando el índice proporciona fechas, de modo que una ejecución con límite lee primero las partes actualizadas más recientemente de un sitio grande. Hay dos detalles pensados por seguridad. Un sitemap es una entrada no confiable procedente del servidor de otra persona, así que el código lo analiza con defusedxml, que rechaza los trucos de entidades que pueden hacer que los analizadores XML estándar expandan un archivo pequeño hasta convertirlo en gigabytes, y limita tanto la descarga como el tamaño descomprimido al límite de 50MB del protocolo, de modo que un archivo comprimido no pueda inflarse sin límite. El parámetro opener permite enrutar las peticiones a través de un proxy cuando necesitas ver una versión de un sitio específica de un mercado, el mismo planteamiento que para cualquier otra petición.
Confía en lastmod solo después de comprobarlo
lastmod promete exactamente lo que la recopilación incremental necesita: una lista de lo que ha cambiado desde la última ejecución. Si fuera fiable en todas partes, un rastreador podría obtener solo las páginas cambiadas y omitir todo lo demás. No es fiable en todas partes, y nuestros dos sitios de prueba muestran ambos fallos habituales.
Fallo uno: lastmod es la hora de generación. Leímos el sitemap de noticias de un gran editor de noticias. Todas las entradas con fecha llevaban una de dos marcas temporales, separadas por un segundo: el momento en que se generó el archivo, no el momento en que cambió cada artículo. Filtrar por “cambiado en las últimas seis horas” devolvía todas las URLs del archivo. Usado sin verificación, ese lastmod provocaría una nueva obtención de todo, cada vez.
Fallo dos: no hay lastmod en absoluto. Leímos el sitemap de un gran archivo de documentos técnicos. Enumeraba 10.236 URLs, y ninguna llevaba lastmod. Eso es una fuente de descubrimiento perfectamente válida y de ninguna ayuda para decidir qué volver a obtener.
Por eso la propia documentación de Google dice que usa lastmod solo “si es consistente y verificablemente (por ejemplo, comparándolo con la última modificación de la página) preciso”, y por eso deberías aplicar tú mismo la misma prueba. Antes de programar tareas sobre el lastmod de un sitio:
- Comprueba la dispersión. Si la mayoría de las entradas comparten una única marca temporal, o los valores siguen el momento de generación del archivo, el campo no está describiendo cambios en las páginas.
- Toma muestras y compara. Obtén una muestra de páginas y compara
lastmodcon una señal independiente, como el propiodateModifiedde la página en datos estructurados o una huella de contenido. Cómo extraerdateModifiedse trata en deja de analizar HTML, y cómo comparar contenido sin ahogarse en ruido en detección de cambios a escala. - Puntúa el sitio. Registra, por sitio, con qué frecuencia
lastmodcambió cuando el contenido cambió, y con qué frecuencia el contenido cambió cuandolastmodno lo hizo. Usalastmodpara la programación solo en los sitios que superen esta prueba, y sigue comprobándolo, porque el generador de sitemaps de un sitio puede cambiar sin previo aviso.
Dónde encajan los sitemaps en una canalización de recopilación
Los sitemaps son más útiles como primer paso, no como el único:
- Descubrimiento. Un sitemap te da el inventario directamente, incluidas las páginas con pocos enlaces. Para sitios de catálogo y contenido, suele ser la lista de URLs más completa disponible.
- Segmentación. Los sitemaps suelen dividirse por tipo de contenido o sección, como productos, categorías, artículos y vídeos. La división te dice cómo está organizado un sitio antes de obtener una sola página.
- Recopilación incremental, en sitios cuyo
lastmodsupera las comprobaciones anteriores, y mediante sitemaps de noticias para artículos recientes. - Comprobaciones de cobertura. Comparar lo que ha encontrado tu rastreador con lo que enumera el sitemap muestra lo que te estás perdiendo.
Mantén el rastreo basado en enlaces como red de seguridad. Los sitemaps pueden estar desactualizados, ser incompletos o estar deliberadamente limitados a lo que un sitio quiere que se indexe. Y respeta el robots.txt del sitio para las páginas en sí: que una URL aparezca en un sitemap es una invitación a los motores de búsqueda para indexarla, no una renuncia a ninguna otra cosa que el sitio haya solicitado, como se trata en robots.txt, exclusiones de IA y señales de reserva.
Usados de esta manera, los sitemaps reducen el presupuesto de obtención en los dos puntos donde normalmente se desperdicia: la navegación para encontrar páginas, y la reobtención de páginas que no han cambiado. El segundo ahorro depende por completo de que lastmod sea fiable, por lo que la programación de rastreo con conciencia de coste debería tratar un lastmod no verificado como una pista, no como un hecho.
La conclusión
Los sitemaps son el inventario de URLs más barato de la web: un sitio que te dice, en un formato estándar, qué quiere que se encuentre. Léelos desde robots.txt, gestiona gzip y los índices anidados, limita lo que obtienes, y úsalos primero para el descubrimiento.
Después, trata lastmod como lo hace Google: útil solo cuando se ha demostrado que es preciso para ese sitio. En un sitio que comprobamos, era simplemente la hora en que se generó el archivo. En otro, no existía. En un sitio donde se sostiene, puede reducir drásticamente la reobtención. La única manera de saber con qué tipo de sitio estás tratando es comprobarlo.
Fuentes y referencias
- Sitemaps.org, Formato XML de Sitemaps.
- Google Search Central, Crear y enviar un sitemap.
- Sitemaps leídos por Shifter el 29 de septiembre de 2026 usando el código anterior.