Карта сайта отображает иерархическую структуру интернет ресурса. Создаётся как для пользователей, так и робота поисковых систем.
Принято считать, что на небольших сайтах карта ненужна, ибо все html страницы умещаются на первом уровне ссылок(начиная с главной страницы), но не стоит пренебрегать seo-принципом индексации страниц и для удобства пользователей даже в этом случае. Почему так происходит? Робот проходит несколько уровней вложенности, слишком "глубоко" по сайту он не забирается, для этого и существуют sitemap, которые помогают ему напрямую заходить на интернет страницу и начинать копать с неё. Примерно так выглядит проходимость поискового робота, где после 3-ого уровня начинается неизвестный туман:
Содержание:
XML-теги для карты сайта (Sitemap) google, яндекс
Для поисковых систем важно, чтобы карта сайта соответствовала стандартам. Определимся с XML-тегами для последующего написания кода.
Обязательные тэги:
urlset xmlns - указывающий стандарт протокола
url - обозначающий родительский тэг для каждой записи
loc - отображающий URL-адрес страницы
Рекомендуемые тэги:
lastmod - хранит дату последнего изменения страницы в формате W3C Datetime, например, 2021-09-01T17:47:37+00:00
priority - добавляет приоритет URL для страницы по отношению к другим. Указывается в диапазоне от 0 до 1 с шагом 0,1, по умолчанию устанавливается 0,5. Вы указываете роботу, какие страницы необходимо просканировать в первую очередь.
changefreq - отображает параметр вероятности обновления интернет страницы. Тэг changefreq принимает следующие значения:
- Always - всегда
- Hourly - ежечасно
- Daily - ежедневно
- Weekly - еженедельно
- Monthly - ежемесячно
- Yearly – ежегодно
- Never - никогда
Пример карты сайта(Sitemap)
Кодирование символов URL
В XML Sitemap используется кодировка UTF-8. Для распознавания некоторых символов в URL роботом, необходимо обработать перед выводом ссылку, заменив(Без пробелов):
Символ | Расшифровка | Мнемоника |
& | Амперсанд | & amp; |
' | Одинарные кавычки | & apos; |
" | Двойные кавычки | & quot; |
> | Больше | & gt; |
< | Меньше | & lt; |
Замена в строке URL в коде с помощью replace(Без пробелов):
siteMapUrl = “https://studiowildfox.com/articles?page=2&size=5”;
siteMapUrl = siteMapUrl.replace("&", “& amp;”);
siteMapUrl = siteMapUrl.replace("'", “& apos;”);
siteMapUrl = siteMapUrl.replace("\"", “& quot;”);
siteMapUrl = siteMapUrl.replace(">", “& gt;”);
siteMapUrl = siteMapUrl.replace("<", “& lt;”);
Sitemap на фреймворке Spring Boot
Учитывайте нюанс, в примерах я использую IDE Intellij idea.
Для формирования карты сайта, предлагаю создать новый каталог в проекте и назвать его sitemap, для вашего личного удобства.
Подключите зависимости в файл pom.xml:
- jaxb-api
- jaxb-core
- jaxb-impl
*Если не сейчас, то в конечном итоге для развертывания сайта вам пригодится jaxb.
В каталоге создайте следующие файлы:
- package-info.java – файл создается путем нажатия правой кнопкой мыши по каталогу sitemap -> New -> package-info.java
Файл, необходимый для замены @XmlRootElement(name = "urlset") на @XmlRootElement (name = "urlset", namespace = "http://www.sitemaps.org/ schemas/sitemap/0.9")
В package-info.java добавьте java код:
@XmlSchema(
namespace="http://www.sitemaps.org/schemas/sitemap/0.9",
elementFormDefault=XmlNsForm.QUALIFIED)
package com.wildfoxstudio.config.sitemap;
import javax.xml.bind.annotation.*;
Код в package-info.java исправляет проблемы отображения пространства имен ns2 в XML файле:
Пространство имен ns2 удалится, оставив urlset.
- XmlUrl – класс создания тэгов url
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.Date;
@XmlAccessorType(value = XmlAccessType.NONE)
@XmlRootElement(name = "url")
public class XmlUrl {
public enum Priority {
HIGH("1.0"), MEDIUM("0.5"), LOW("0.2");
private String value;
Priority(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
public enum Changefreq {
ALWAYS("always"), HOURLY("hourly"),
DAILY("daily"), WEEKLY("weekly"),
MONTHLY("monthly"), YEARLY("yearly"),
NEVER("never");
private String value;
Changefreq(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
@XmlElement
private String loc;
@XmlElement
private String lastmod = new Date().toString();
@XmlElement
private String changefreq = "weekly";
@XmlElement
private String priority;
public XmlUrl() {
}
public XmlUrl(String loc, String lastmod, Changefreq changefreq, Priority priority) {
this.loc = loc;
this.priority = priority.getValue();
this.changefreq = changefreq.getValue();
this.lastmod = lastmod;
}
public String getLoc() {
return loc;
}
public String getPriority() {
return priority;
}
public String getChangefreq() {
return changefreq;
}
public String getLastmod() {
return lastmod;
}
}
- XmlUrlSet – класс сбора в XML тэг urlset
import javax.xml.bind.annotation.*;
import java.util.ArrayList;
import java.util.Collection;
@XmlAccessorType(value = XmlAccessType.NONE)
@XmlRootElement(name = "urlset", namespace = "http://www.sitemaps.org/schemas/sitemap/0.9")
public class XmlUrlSet {
@XmlElements({@XmlElement(name = "url", type = XmlUrl.class)})
private Collection xmlUrls = new ArrayList();
public void addUrl(XmlUrl xmlUrl) {
xmlUrls.add(xmlUrl);
}
public Collection getXmlUrls() {
return xmlUrls;
}
}
- SitemapController – контроллер для вывода страницы карты сайта
В контроллере находится логика вывода ваших страниц сайта. Привожу пример стандартного вывода страницы, на вашем проекте необходимо будет сформировать более сложные алгоритмы вывода. Добавил код получения и вывода для html страниц в функции lastModifiedDate.
@Controller
public class SitemapController {
private String URLHOST = “studiowildfox.com”;
@RequestMapping(value = "/sitemap.xml", method = RequestMethod.GET)
@ResponseBody
public XmlUrlSet main() {
XmlUrlSet xmlUrlSet = new XmlUrlSet();
create(xmlUrlSet, "/login", XmlUrl.Priority.HIGH, XmlUrl.Changefreq.WEEKLY);
return xmlUrlSet;
}
private void create(XmlUrlSet xmlUrlSet, String link, XmlUrl.Priority priority, XmlUrl.Changefreq changefreq) throws IOException, ParseException {
//Получаем информацию о последнем обновлении страницы в lastmod
//Логика вывода последнего обновления страницы может отличаться
String lastmod = lastModifiedDate(https + URLHOST + link);
if (!lastmod.equals("Last-Modified not returned")) {
lastmod = lastmod.replace(" ", "T");
lastmod = lastmod.substring(0, lastmod.length() - 2) + ":" + lastmod.substring(lastmod.length() - 2);
} else {
lastmod = "";
}
xmlUrlSet.addUrl(new XmlUrl("https://" + URLHOST + link, lastmod, changefreq, priority));
}
}
private String lastModifiedDate(String strURL) throws IOException, ParseException {
URL url = new URL(strURL);
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.setRequestMethod("HEAD");
httpConnection.connect();
long lastModified = httpConnection.getLastModified();
httpConnection.disconnect();
if (lastModified != 0) {
SimpleDateFormat formatForDateNow = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ", new Locale("en"));
formatForDateNow.setTimeZone(TimeZone.getTimeZone("GMT"));
return formatForDateNow.format(new Date(lastModified));
} else {
return "Last-Modified not returned";
}
}
В случае использования примера как эталон, то для корректной работы lastModifiedDate, не забудьте добавить строку кода response.addHeader("Last-Modified", вашаЛогикаВыводаДаты) в каждый из контроллеров, например в ArticleController:
@Controller
@RequestMapping("/article_pages")
public class ArticleController {
@GetMapping
public String article(Model model,
HttpServletResponse response) throws ParseException {
response.addHeader("Last-Modified", myFunctionForGiveDate);
return "article-page";
}
}