Парсинг sitemap: как обойти карту сайта перед сбором данных

Зачем начинать сбор с sitemap.xml: разбор индексных карт, выбор нужных URL и экономия на обходе сайта перед парсингом.

КP
Команда Parsing.agency
Сбор данных под задачи бизнеса
Опубликовано: 9 апреля 2025

Sitemap (карта сайта) — это XML-файл со списком URL сайта, который владелец отдаёт поисковым системам и краулерам. Для задач сбора данных карта сайта бесценна: вместо того чтобы слепо обходить ссылки со страницы на страницу, вы получаете готовый перечень адресов, часто с датой последнего изменения и приоритетом. Поэтому парсинг sitemap обычно идёт первым шагом перед парсингом HTML. Эта статья продолжает наш обзор форматов документов; поскольку sitemap — частный случай XML, общие приёмы работы с деревом описаны в статье про парсинг XML.

Структура файла

Стандартный sitemap описан схемой sitemaps.org. Каждый URL — это элемент <url> с обязательным <loc> и необязательными <lastmod>, <changefreq>, <priority>.

xml
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://example.com/product/101</loc>
    <lastmod>2026-05-12</lastmod>
    <priority>0.8</priority>
  </url>
  <url>
    <loc>https://example.com/product/102</loc>
    <lastmod>2026-06-01</lastmod>
  </url>
</urlset>

Важная деталь — пространство имён http://www.sitemaps.org/schemas/sitemap/0.9. Из-за него «наивный» поиск тега loc без учёта namespace вернёт пустоту; это самая частая ошибка при разборе карт (подробнее о namespaces — в статье про XML).

Sitemap index и вложенные карты

На крупных сайтах один файл не вмещает все ссылки (лимит — 50 000 URL или 50 МБ), поэтому используется индекс карт — файл со ссылками на другие sitemap. Корневой элемент здесь <sitemapindex>, а внутри — <sitemap> с вложенными <loc>.

xml
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <sitemap><loc>https://example.com/sitemap-products.xml</loc></sitemap>
  <sitemap><loc>https://example.com/sitemap-articles.xml.gz</loc></sitemap>
</sitemapindex>

Поэтому надёжный парсер должен быть рекурсивным: сначала прочитать индекс, затем по очереди скачать и разобрать каждую вложенную карту. Обратите внимание, что вложенные файлы часто отдаются в gzip (.xml.gz) — их нужно распаковывать на лету.

Где искать карту

Адрес карты обычно лежит в robots.txt в строке Sitemap:. Если её там нет, проверяют стандартные пути /sitemap.xml и /sitemap_index.xml. Начинать стоит именно с robots.txt — это самый надёжный способ узнать актуальное расположение.

Python

Самый прозрачный путь — скачать файл и разобрать его как обычный XML через lxml, не забыв про namespace и рекурсию по индексу.

python
import gzip
import requests
from lxml import etree

NS = {"sm": "http://www.sitemaps.org/schemas/sitemap/0.9"}

def fetch(url):
    data = requests.get(url, timeout=30).content
    if url.endswith(".gz"):
        data = gzip.decompress(data)
    return etree.fromstring(data)

def parse_sitemap(url, urls=None):
    urls = urls if urls is not None else []
    root = fetch(url)
    # если это индекс — спускаемся во вложенные карты
    for loc in root.xpath("//sm:sitemap/sm:loc/text()", namespaces=NS):
        parse_sitemap(loc.strip(), urls)
    # обычные ссылки
    for loc in root.xpath("//sm:url/sm:loc/text()", namespaces=NS):
        urls.append(loc.strip())
    return urls

links = parse_sitemap("https://example.com/sitemap.xml")
print(len(links), "URL найдено")

Если не хочется писать рекурсию и обработку gzip вручную, есть специализированная библиотека ultimate-sitemap-parser: она сама находит карту, обходит индексы и отдаёт плоский список страниц.

python
from usp.tree import sitemap_tree_for_homepage

tree = sitemap_tree_for_homepage("https://example.com/")
for page in tree.all_pages():
    print(page.url, page.last_modified)

JavaScript / Node.js

В Node карту удобно разбирать связкой fetch и fast-xml-parser (тем же, что используется для XML).

javascript
const { XMLParser } = require("fast-xml-parser");

async function parseSitemap(url) {
  const xml = await (await fetch(url)).text();
  const parser = new XMLParser();
  const doc = parser.parse(xml);

  if (doc.sitemapindex) {
    const maps = [].concat(doc.sitemapindex.sitemap);
    const all = [];
    for (const m of maps) all.push(...await parseSitemap(m.loc));
    return all;
  }
  return [].concat(doc.urlset.url).map((u) => u.loc);
}

parseSitemap("https://example.com/sitemap.xml").then((urls) =>
  console.log(urls.length)
);

Что делать с датами обновления

Поле <lastmod> — главная причина любить карты сайта. Сравнивая его со временем предыдущего обхода, можно скачивать только изменившиеся страницы и не нагружать сайт лишними запросами. Это превращает разовый парсинг в эффективный регулярный мониторинг: вы обходите не весь сайт, а только дельту. Учтите, что lastmod заполняется не всегда и не всегда честно, поэтому его стоит использовать как подсказку, а не абсолютную истину.

После того как список URL собран, начинается собственно извлечение данных со страниц — это уже задача парсинга HTML. Если нужно регулярно обходить большой сайт с индексной картой, gzip и фильтрацией по дате — мы настроим парсинг под ключ, включая расписание и выгрузку результата в нужный вам формат, например CSV или Excel.