Пожалуй, написано немало статей на тему, зачем нужен файл Sitemap.xml, и что с ним делают поисковики. Здесь мне не хотелось бы повторяться. Поэтому просто оговоримся, что файл Sitemap представляет карту сайта, содержит перечень страниц сайта и служит для лучшей индексации ресурса поисковыми роботами вроде Yandex, Google и пр. На этом и закончим.
Конечно, для создания карты сайта всегда можно обратиться к генераторам Sitemap, благо, что в интернете существует много таких сервисов (нагуглить их по запросу «sitemap generator» не составит труда). Стоит лишь вбить адрес сайта в предлагаемое поле ввода, и для вас сгенерируется файл карты сайта Sitemap.xml по всем правилам. Сохраняете его на своем компьютере, переносите на сайт, а далее переходите в Яндекс.вебмастер и просто указываете ссылку на него. Однако, такой способ имеет ряд определённых недочётов. Во-первых, количество линков (url-ов вашего сайта), как правило, лимитируется генераторами в пределах от 500 до 1000. Т.е. для больших сайтов, с количеством страниц, превышающих тысячу, а то и несколько, такая карта сайта Sitepam.xml будет не полной. Во-вторых, если речь идет об интернет-магазине, в котором постоянно добавляются новые товары, безусловно, однажды созданная карта сайта не будет их включать. Для того, чтобы новые товары или любые изменения категорий были учтены в Sitemap.xml, нужно создать динамичный php-скрипт, который будет моделировать файл Sitemap.xml каждый раз при индексации сайта поисковиком.
Данный материал подготовлен для тех веб-разрабочиков и сео-оптимизаторов, которые стремятся зарекомендовать сайт в лучших традициях и которых уже не удовлетворяют единожды генерированные карты сайта.
Дополнительно пару слов о создании карты сайта Sitemap.xml посредством генераторов. Изучив такую карту сайта для интернет-магазина на базе osCommerce, я обнаружила ещё одну особенность. В ущерб более ценным ссылкам, таким генератором формируются линки вида:
.../ray-ban-kupit-ochki-m-61.html?sort=1a&page=1
.../ray-ban-kupit-ochki-m-61.html?sort=2d&page=1
.../ray-ban-kupit-ochki-m-61.html?sort=3a&page=1
.../ray-ban-kupit-ochki-m-61.html?sort=4a&page=1
Обратите внимание на фрагмент «?sort=1a&page=1» — эта выдержка говорит об использовании сортировки на странице. Не будем забывать, что заголовок такой страницы в разделе интернет-магазина остаётся прежним — по названию категории или производителя (бренда). Как известно, поисковики чаще всего исключают из своего поля зрения страницы с одинаковыми названиями, поэтому такой линк, по всей вероятности, окажется, скорее мусорным. Вспомним про лимит ссылок от генератора при создании карты сайта Sitemap.xml, и мы получаем картину, когда такие дубликаты заполоняют пространство Sitemap взамен более значимых путей по сайту.
С обоснованиями актуальности мало-мальски разобрались. Пора приступить к делу. Я буду создавать файл карты сайта Sitemap на PHP по аналогии с YML-файлом для трансляции товаров на Яндекс.Маркете — скриптом, подготовленным под типичный формат.
Пробежимся по основным требованиям к файлу Sitemap.xml, где рассмотрим элементы из XML-стандартов, используемые для этого . Итак, простейший Sitemap будет представлять примерно следующее:
http://www.example.com/
0.8
Как видим, здесь используется только сама ссылка, причём единственная, и один необязательный тег «priority» (указывает приоритетность страницы в спектре от 0.0 до 1.0 по отношению к другим страницам этого же сайта). Другие необязательные теги, которыми также можно применять: «lastmod» (дата последнего изменения, напр., 2012-03-05), «changefreq» (выбор периодичности изменения страницы, напр., «monthly», «weekly», «never», «always» и др.). Подробнее о XML формате файла Sitemap можно ознакомиться на этом сайте.
В нашем PHP скрипте карты сайта Sitemap создаем подключение к БД и определяем формат передачи XML:
/**************************************************
* Скрипт sitemap.php для индексации Yandex, Google и других поисковых ботов
интернет-магазина на движке osCommerce 2.3
* Дата разработки: 30 августа 2012
* Разработчик: Володина Нина
* Сайт: www.codda.ru
// Скрипт распространяется по лицензии GNU.
// Вы можете использовать скрипт на свой страх и риск. За любые ошибки разработчики отвественности не несут.
**************************************************/
header('Content-type: application/xml');
header("Content-Type: text/xml; charset=utf-8");
$kurs=$currency_value[0];
define('DB_HOST', '');//Вписать сервер бд
define('DB_USER', '');//Вписать имя пользователя
define('DB_PASS', '');//Вписать пароль
define('DB_NAME', '');//Вписать имя базы данных
$ctt = mysql_connect(DB_HOST, DB_USER, DB_PASS) or die(mysql_error());
$db = mysql_select_db(DB_NAME) or die("Ошибка базы данных");
mysql_query ("SET NAMES 'latin1'");
Т.к. таблицы хранятся в кодировке latin1, осуществляем запрос mysql с заданной кодировкой (прописано в последней строке). Я работаю с тюнингованной версией движка (чит. Тюнинг osCommerce v.2.3, или прокачка интернет-магазина для дизайнерских и seo-целей), в которой все линки (url-ы) являются seo-оптимизированными и преображаются согласно семантики. Чтобы выдавать в карте сайта Sitemap именно такие ссылки на страницы, создадим функцию «str_ru». В полевых условиях хостинга и используемого файл-менеджера, мне удобнее конвертировать знаки из cp1251 (Windows-1251) в кодировку UTF-8 (что обеспечивается iconv). Однако, если вы делаете Sitemap.php в онлайновом файл-менеджере на сайте компании хостинга, можно сразу задать редактирование файла в UTF-8. Тогда конвертировать знаки не нужно. В этом случае, к каждому символу в массиве приводим («к» => «k», «а» => «a» и т.д.). Ниже сама функция:
function str_ru($text) {
$onetit = mb_strtolower($text, 'UTF-8');
$trans = array(
addslashes(iconv('cp1251','UTF-8','к')) => "k",
addslashes(iconv('cp1251','UTF-8','а')) => "a",
addslashes(iconv('cp1251','UTF-8','б')) => "b",
addslashes(iconv('cp1251','UTF-8','в')) => "v",
addslashes(iconv('cp1251','UTF-8','г')) => "g",
addslashes(iconv('cp1251','UTF-8','д')) => "d",
addslashes(iconv('cp1251','UTF-8','е')) => "e",
addslashes(iconv('cp1251','UTF-8','ё')) => "e",
addslashes(iconv('cp1251','UTF-8','ж')) => "j",
addslashes(iconv('cp1251','UTF-8','з')) => "z",
addslashes(iconv('cp1251','UTF-8','и')) => "i",
addslashes(iconv('cp1251','UTF-8','й')) => "y",
addslashes(iconv('cp1251','UTF-8','к')) => "k",
addslashes(iconv('cp1251','UTF-8','л')) => "l",
addslashes(iconv('cp1251','UTF-8','м')) => "m",
addslashes(iconv('cp1251','UTF-8','н')) => "n",
addslashes(iconv('cp1251','UTF-8','о')) => "o",
addslashes(iconv('cp1251','UTF-8','п')) => "p",
addslashes(iconv('cp1251','UTF-8','р')) => "r",
addslashes(iconv('cp1251','UTF-8','с')) => "s",
addslashes(iconv('cp1251','UTF-8','т')) => "t",
addslashes(iconv('cp1251','UTF-8','у')) => "u",
addslashes(iconv('cp1251','UTF-8','ф')) => "f",
addslashes(iconv('cp1251','UTF-8','х')) => "h",
addslashes(iconv('cp1251','UTF-8','ц')) => "c",
addslashes(iconv('cp1251','UTF-8','ч')) => "ch",
addslashes(iconv('cp1251','UTF-8','ш')) => "sch",
addslashes(iconv('cp1251','UTF-8','щ')) => "sch",
addslashes(iconv('cp1251','UTF-8','ь')) => "",
addslashes(iconv('cp1251','UTF-8','ъ')) => "",
addslashes(iconv('cp1251','UTF-8','ы')) => "i",
addslashes(iconv('cp1251','UTF-8','э')) => "e",
addslashes(iconv('cp1251','UTF-8','э')) => "e",
addslashes(iconv('cp1251','UTF-8','ю')) => "yu",
addslashes(iconv('cp1251','UTF-8','я')) => "ya",
addslashes(iconv('cp1251','UTF-8',' ')) => "-",
" & " => "-",
"&" => "",
addslashes(iconv('cp1251','UTF-8','.')) => "_");
$content = strtr($onetit, $trans);
return urldecode($content);
}
Прописываем адрес сайта и начинаем шапку XML, открываем тег urlset:
#########################
# Начинаем генерировать XML
# переменные для заголовка
$cdate = date("Y-m-d H:i",time());
$csite = "http://staroptic.ru/";//Вписать адрес интернет-магазина
#----------------------------------------------
$yandex=<<
$csite
END;
Вручную прописываем три стандартных области сайта, такие как: Бренды (Все производители), Новинки, Скидки (Спецпредложения). Т.к. сайт, который мной оптимизировался, интернет-магазин очков STAROPTIC.RU, посвящен теме очков и очковых оправ, то используются заменённые названия файлов: kupit-ochki-brands.php (бывш. allmanufacturers.php), novie-ochki.php (бывш. products_new.php), ochki-so-skidkoy.php (бывш. specials.php). Четвертая ссылка — статьи (poleznoe-pro-ochki-t-2.html). Следует отметить, что сам движок находится в папке сайта «ochki-linzi-opravi/», и в данном скрипте наименование этого каталога будет фигурировать повсеместно.
$yandex .= "
".
$csite."ochki-linzi-opravi/kupit-ochki-brands.php
0.9
\n
".
$csite."ochki-linzi-opravi/novie-ochki.php
0.7
\n
".
$csite."ochki-linzi-opravi/ochki-so-skidkoy.php
0.7
\n
".
$csite."ochki-linzi-opravi/poleznoe-pro-ochki-t-2.html
0.5
\n";
Теперь приступим к запросам БД. Для начала, выведем все категории и подкатегории:
$arr_cats=array();
#----------------------------------------------
# выводим все подкатегории
$yandex .= "\n";
$tmp="
select
c.categories_id as categoryID, cd.categories_name as name, c.parent_id as parent
FROM
categories as c, categories_description as cd where c.categories_id = cd.categories_id AND cd.language_id=2
ORDER BY
parent, name";
$res = mysql_query($tmp);
while ($rezzzz = mysql_fetch_array($res)){
#экранируем спецсимволы
$rezzzz['name']=htmlspecialchars($rezzzz['name']);
$fftt = "\n \n" . $csite. "ochki-linzi-opravi/". str_ru($rezzzz['name'])."-c-";
if($rezzzz['parent']>0) $fftt .= $rezzzz['parent']."_";
$fftt.= $rezzzz['categoryID'].".html\n \n 0.8 \n \n";
$yandex .= $fftt;
$arr_cats[$rezzzz['categoryID']]=$rezzzz;
}
#----------------------------------------------
Теперь будем выводить все бренды:
# выводим все бренды
$arr_fact=array();
$manufacturers_query =
"select manufacturers_name as name, manufacturers_id as manufacturersID
from
manufacturers
order by name";
$factres = mysql_query($manufacturers_query);
while ($rezfact = mysql_fetch_array($factres)){
#экранируем спецсимволы
$rezfact['name']=htmlspecialchars($rezfact['name']);
$fftt_fct = "\n \n" . $csite. "ochki-linzi-opravi/". str_ru($rezfact['name'])."-kupit-ochki-m-".$rezfact['manufacturersID'].".html";
$fftt_fct.= "\n \n0.8 \n \n";
$yandex .= $fftt_fct;
$arr_fact[$rezfact['categoryID']]=$rezfact;
}
$yandex .="\n\n";
#------------------------------------
Здесь следует оговориться, что сам линк на бренды немного модернизирован. Скажем, в интернет-магазине используется две версии подачи брендов. Если в товарах (навесной) применяется исключительно название бренда (например, Ray-Ban, Prada и т.д.), то на конкретной странице, посвящённой бренду, он имеет заголовок «Купить очки Ray-Ban«, «Купить очки Prada«. Соответственно этому заголовку, были построены и ссылки, т.е. к каждой из них, после названия, помимо указания бренда (-m-*manufacturersID) приписывается ещё и знаменатель «-kupit-ochki». Т.е. вид такого человеко-понятного урла (ЧПУ) в адресной строке будет следующим:
http://staroptic.ru/ochki-linzi-opravi/ray-ban-kupit-ochki-m-61.html
Я люблю последовательность во всём, и если в заголовок страницы бренда прописывается определённая связка (в данном случае, «Купить очки …»), она должна прослеживаться и в урле.
И, наконец, переходим к выводу товаров в нашей карте сайта Sitemap.php:
#----------------------------------------------
# выводим все товары
$tmp="
select
p.products_id AS productID,
p.products_status AS in_stock,
pd.products_id,
pd.products_name AS name
FROM
products AS p,
products_description AS pd
WHERE
p.products_price>0
AND pd.products_id=p.products_id
AND p.products_status=1
AND pd.language_id=2
ORDER BY name";
$res = mysql_query($tmp);
while ($tovar = mysql_fetch_array($res)) {
$valuta="RUR";//изменить на нужную валюту
$price=$tovar[Price];
$price=intval($price);
$description=htmlspecialchars(strip_tags($tovar[brief_description]));
$tovar['name'] = htmlspecialchars($tovar['name']);
$srv = str_ru($tovar['name']);
#----------------------------------------------
$yandex.=<<
{$csite}ochki-linzi-opravi/{$srv}-p-$tovar[productID].html
0.6
END;
}
В окончание, прописываем закрытие тега urlset, а дальше начинаем вывод того, что наскриптили:
$yandex .= "";
#выводим, что нагенерили
echo $yandex;
?>
На выходе мы получили динамичный PHP-скрипт для создания файла Sitemap (карты сайта для лучшей индексации поисковиками). Наша карта сайта включает все разделы (рубрики), бренды и товары. Причём, при обновлении интернет-магазина, такие обновления будут отражаться на нашем файле.