Muitos crawlers descobrem páginas da forma cara: buscam uma página, extraem seus links, colocam na fila, repetem. Funciona, mas gasta a maior parte do orçamento em navegação, listagens e páginas que você já viu, e ainda assim pode deixar passar páginas que nada aponta.
Muitos sites publicam de propósito uma lista de suas URLs. Sitemaps XML existem para que mecanismos de busca encontrem páginas de forma eficiente, e o mesmo arquivo diz a uma equipe de dados o que existe em um site, como está organizado e, às vezes, o que mudou recentemente. Este guia cobre como encontrar e ler sitemaps corretamente, e por que o campo mais útil neles, lastmod, precisa ser verificado antes de você confiar nele. Verificamos em dois sites reais, e falhou de duas formas diferentes.
Principais conclusões
- Um sitemap lista até 50.000 URLs por arquivo, e um índice de sitemap pode listar até 50.000 sitemaps, então até sites muito grandes podem publicar um inventário completo.
- Sitemaps geralmente são declarados no robots.txt com uma linha
Sitemap:; verifique isso antes de tentar adivinhar um local. lastmodé o campo que poderia economizar mais buscas, e é o menos confiável. O Google diz que usalastmodapenas se ele for “consistente e verificavelmente” preciso.- Em nossa verificação, o sitemap de notícias de um grande veículo de notícias deu a mesma marca de tempo a todas as entradas, o momento em que o arquivo foi gerado. Um grande arquivo de documentos publicou mais de 10.000 URLs sem nenhum
lastmod. - Use sitemaps para descoberta, verifique o
lastmodpor site antes de programar tarefas com base nele, e mantenha o crawling por links como rede de segurança.
O que o protocolo permite
O protocolo de sitemaps é curto e vale a pena conhecer com precisão:
| Regra | Detalhe |
|---|---|
| Limites de tamanho | ”não mais que 50.000 URLs” e “não maior que 50MB (52.428.800 bytes)” por arquivo de sitemap, sem compressão |
| Índices de sitemap | Um arquivo listando outros sitemaps, com os mesmos limites de 50.000 entradas e 50MB |
| Compressão | Os arquivos podem ser comprimidos com gzip, desde que estejam dentro do limite uma vez descomprimidos |
lastmod | Opcional, no formato W3C Datetime, que pode ser apenas uma data, como YYYY-MM-DD |
| Descoberta | Uma linha Sitemap: no robots.txt; um site pode listar várias |
Dois campos opcionais que você verá, changefreq e priority, podem ser ignorados. O Google diz claramente que “ignora os valores de <priority> e <changefreq>”, e há pouca razão para qualquer outra parte confiar neles também.
Sites de notícias frequentemente publicam um sitemap de notícias separado cobrindo apenas artigos recentes, com campos extras como uma data de publicação. Esses sitemaps são pequenos, regenerados com frequência e muito úteis para monitorar conteúdo recente.
Lendo sitemaps corretamente
Um leitor robusto precisa fazer quatro coisas: encontrar os sitemaps a partir do robots.txt, lidar com gzip, seguir índices de sitemap recursivamente e converter lastmod em algo comparável. Ele também deve limitar quantos arquivos busca, já que um índice pode apontar para milhares deles.
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}
O percorredor do índice visita os sitemaps filhos dos mais recentes para os mais antigos quando o índice fornece datas, então uma execução limitada lê primeiro as partes mais recentemente atualizadas de um site grande. Dois detalhes estão ali por segurança. Um sitemap é uma entrada não confiável vinda do servidor de outra pessoa, então o código o analisa com defusedxml, que recusa os truques de entidade que podem fazer com que analisadores XML padrão expandam um arquivo pequeno em gigabytes, e limita tanto o download quanto o tamanho descomprimido ao limite de 50MB do protocolo, então um arquivo comprimido não pode se expandir sem limite. O parâmetro opener permite rotear requisições através de um proxy quando você precisa ver uma versão específica de mercado de um site, a mesma abordagem usada para qualquer outra busca.
Confie no lastmod apenas depois de verificá-lo
lastmod promete exatamente o que a coleta incremental precisa: uma lista do que mudou desde a última execução. Se fosse confiável em todos os lugares, um crawler poderia buscar apenas as páginas alteradas e ignorar todo o resto. Não é confiável em todos os lugares, e nossos dois sites de teste mostram ambas as falhas comuns.
Falha um: lastmod é o horário de geração. Lemos o sitemap de notícias de um grande veículo de notícias. Todas as entradas datadas traziam um de dois carimbos de tempo, com um segundo de diferença: o momento em que o arquivo foi gerado, não o momento em que cada artigo mudou. Filtrar por “mudou nas últimas seis horas” retornou todas as URLs do arquivo. Usado ingenuamente, esse lastmod acionaria uma nova busca de tudo, toda vez.
Falha dois: nenhum lastmod. Lemos o sitemap de um grande arquivo de documentos técnicos. Ele listava 10.236 URLs, e nenhuma trazia um lastmod. Isso é uma fonte de descoberta perfeitamente boa e nenhuma ajuda para decidir o que buscar novamente.
É por isso que a própria orientação do Google diz que ele usa lastmod apenas “se for consistente e verificavelmente (por exemplo, comparando com a última modificação da página) preciso”, e por isso você deve aplicar o mesmo teste você mesmo. Antes de programar tarefas com base no lastmod de um site:
- Verifique a dispersão. Se a maioria das entradas compartilha um mesmo carimbo de tempo, ou os valores acompanham o horário de geração do arquivo, o campo não está descrevendo mudanças de página.
- Faça amostragem e compare. Busque uma amostra de páginas e compare o
lastmodcom um sinal independente, como o própriodateModifiedda página em dados estruturados ou uma impressão digital de conteúdo. Como extrairdateModifiedé abordado em pare de analisar HTML, e como comparar conteúdo sem se afogar em ruído em detecção de mudanças em escala. - Pontue o site. Registre, por site, com que frequência o
lastmodmudou quando o conteúdo mudou, e com que frequência o conteúdo mudou quando olastmodnão mudou. Uselastmodpara agendamento apenas em sites que passarem no teste, e continue verificando, porque o gerador de sitemap de um site pode mudar sem aviso.
Onde os sitemaps se encaixam em um pipeline de coleta
Sitemaps são mais fortes como a primeira etapa, não a única:
- Descoberta. Um sitemap fornece o inventário diretamente, incluindo páginas pouco vinculadas. Para sites de catálogo e conteúdo, é frequentemente a lista de URLs mais completa disponível.
- Segmentação. Sitemaps são comumente divididos por tipo de conteúdo ou seção, como produtos, categorias, artigos e vídeos. A divisão mostra como um site está organizado antes de você buscar uma única página.
- Coleta incremental, em sites cujo
lastmodpassa nas verificações acima, e via sitemaps de notícias para artigos recentes. - Verificações de cobertura. Comparar o que seu crawler encontrou com o que o sitemap lista mostra o que está faltando.
Mantenha o crawling baseado em links como rede de segurança. Sitemaps podem estar desatualizados, incompletos ou deliberadamente limitados ao que um site quer indexado. E respeite o robots.txt do site para as páginas em si: uma URL aparecer em um sitemap é um convite para os mecanismos de busca a indexá-la, não uma renúncia a qualquer outra coisa que o site tenha solicitado, como abordado em robots.txt, opt-outs de IA e sinais de reserva.
Usados dessa forma, sitemaps cortam o orçamento de busca nos dois lugares em que geralmente é desperdiçado: navegar para encontrar páginas, e buscar novamente páginas que não mudaram. A segunda economia depende inteiramente de o lastmod ser confiável, motivo pelo qual agendamento de crawl consciente de custo deveria tratar um lastmod não verificado como uma pista, não como um fato.
Conclusão
Sitemaps são o inventário de URLs mais barato da web: um site dizendo a você, em um formato padrão, o que quer que seja encontrado. Leia-os a partir do robots.txt, lide com gzip e índices aninhados, limite o que busca, e use-os primeiro para descoberta.
Depois trate o lastmod da mesma forma que o Google trata: útil apenas quando foi demonstrado que é preciso para aquele site. Em um site que verificamos, era apenas o horário em que o arquivo foi gerado. Em outro, ele não existia. Em um site em que se mantém confiável, pode reduzir drasticamente as buscas repetidas. A única forma de saber com que tipo de site você está lidando é verificar.
Fontes e referências
- Sitemaps.org, Formato XML de Sitemaps.
- Google Search Central, Criar e enviar um sitemap.
- Sitemaps lidos pela Shifter em 29 de setembro de 2026 usando o código acima.