PHP: пишем простой генератор файла sitemap.xml
Современному сайту мало иметь RSS-канал, а нужна ещё и карта сайта Sitemap.
Обычно достаточно простейшего её формата с тегами вида
<url> <loc>http://example.com/page.php</loc> </url>
чтобы поисковики начали нормально индексировать Ваш сайт а не формировать у себя в базах его заведомо ошибочную структуру, как делает тот же "Яндекс".
Яше достаточно один раз найти на сайте <a href="www.chtoto.com">...</a> вместо <a href="http://www.chtoto.com">...</a>, чтобы он на годы решил, что www.chtoto.com - это вложенный раздел Вашего сайта и с упорством дятла пытался его индексировать :) Порой создаются тысячи и тысячи линков на несуществующие страницы, а время обхода сайта поисковиком становится настолько большим, что начинает подтормаживать сервер.
В Сети полно онлайн-генераторов для sitemap.xml
, к сожалению, все они довольно медленные, с ограничениями по количеству страниц и не "заточены" под Ваш сайт, реальную структуру которого знаете только Вы, как его создатель.
Мне бывает проще написать подобный генератор под конкретный сайт, что я сейчас и сделаю в этой заметке.
Напишем PHP-скрипт для формирования простейшего, но вполне корректного файла sitemap.xml
. Будем исходить из типовой ситуации, реализованной, в том числе, в этом блоге:
- в структуре сайта должны быть отражены данные, выдаваемые несколькими скриптами (например, скрипт для выдачи одной страницы, скрипт для выдачи списка записей, содержащих определённый тег и т.д.);
- страницы различаются между собой по некоему идентификатору записи, переданному параметром URL-адреса (например, http://yoursite.com/index.php?id=1, http://yoursite.com/index.php?id=2 и т.д.);
- эти идентификаторы можно получить запросом из поля некоторой таблицы базы.
Как и для любых отлаживаемых в процессе написания скриптов, включим из кода настройку
error_reporting(E_ALL);
, чтобы видеть все предупреждения и сообщения о возможных проблемах.
Затем определим с помощью констант данные для работы с MySQLi (надеюсь, вы на него тоже перешли) и файлом:
MAP_URL
- главный URL вашего сайта, с "/" в конце;MAP_HEAD
- секция заголовка XML-файла, сюда же можно включить ссылки на статические страницы, которые обязательно должны присутствовать в карте, например:<url> <loc>http://blog.kislenko.net/index.php</loc> </url>
и так далее;
MAP_FOOT
- секция, завершающая XML-файл, у нас это просто закрывающий тег;$map_scripts
- массив массивов, состоящий из записей видаarray ('name'=>'URL страницы', 'table'=>'имя таблицы', 'field'=>'имя поля идентификатора записи')
У меня для этого блога получилось просто
$map_scripts = array ( //Имя файла - Таблица - Имя поля идентификатора array ('name'=>'tag.php', 'table'=>'tags', 'field'=>'id'), array ('name'=>'show.php', 'table'=>'notes', 'field'=>'id') );
То есть, URL-адреса страниц здесь вписаны относительные и они будут "прицепляться" к MAP_URL
.
Остальной код хорошо виден из прилагаемого листинга. Файл с ним достаточно настроить "под себя" и скопировать в корень сайта,
он запишет полученный файл sitemap.xml
и покажет его в многострочном текстовом поле <textarea>
.
<!DOCTYPE html> <html> <head> <meta charset="windows-1251"> <title>sitemap.xml</title> </head> <body> <?php error_reporting(E_ALL); //Данные для работы с MySQLi define ('DB_HOST','localhost'); //хост define ('DB_LOGIN','root'); //логин define ('DB_PASS',''); //пароль define ('DB_NAME','blognot'); //имя БД define ('DB_CODEPAGE','cp1251'); //кодовая страница БД //Данные для генерации XML define ('MAP_URL','http://blog.kislenko.net/'); //общий URL, с '/' В конце! define ('MAP_HEAD','<?xml version="1.0" encoding="UTF-8"?> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"> <url> <loc>http://blog.kislenko.net/index.php</loc> </url> <url> <loc>http://blog.kislenko.net/help.php</loc> </url> <url> <loc>http://blog.kislenko.net/search.php</loc> </url> <url> <loc>http://blog.kislenko.net/mail.php</loc> </url> <url> <loc>http://blog.kislenko.net/rss.php</loc> </url> <url> <loc>http://blog.kislenko.net/stat.php</loc> </url> <url> <loc>http://blog.kislenko.net/alltags.php</loc> </url> <url> <loc>http://blog.kislenko.net/allcomments.php</loc> </url>'); //header файла sitemap.xml define ('MAP_FOOT','</urlset>'); //footer файла sitemap.xml $map_scripts = array ( //Имя файла - Таблица - Имя поля идентификатора array ('name'=>'tag.php', 'table'=>'tags', 'field'=>'id'), array ('name'=>'show.php', 'table'=>'notes', 'field'=>'id') ); //Выполняемый код: $link=mysqli_connect(DB_HOST, DB_LOGIN, DB_PASS, DB_NAME); if (mysqli_connect_errno()) { printf ("Не удалось подключиться: %s\n", mysqli_connect_error()); exit (); } if (!mysqli_set_charset($link, DB_CODEPAGE)) { printf ("Ошибка при загрузке набора символов: ".DB_CODEPAGE.": %s\n", mysqli_error($link)); exit (); } $n = count($map_scripts); $str = ''; for ($i=0; $i<$n; $i++) { $map = $map_scripts[$i]; $sql = 'select '.$map['field'].' from '.$map['table'].' order by '.$map['field'].' asc'; $result=mysqli_query($link,$sql); if ($result and mysqli_num_rows($result)) { while ($row=mysqli_fetch_assoc ($result)) { $str .= "\n<url> <loc>".MAP_URL.$map['name']."?".$map['field']."=".$row[$map['field']]."</loc> </url>"; } mysqli_free_result ($result); } else { $msg = mysqli_error ($link); printf ("Получено 0 строк по запросу: $sql, сообщение: %s<br>\n",(empty($msg)?'нет':$msg)); } } $result_str = ''.MAP_HEAD.$str."\n".MAP_FOOT; @file_put_contents ('sitemap.xml',$result_str); echo '<textarea rows="32" cols="140">'.$result_str.'</textarea>'; mysqli_close ($link); ?> </body></html>
Примечания.
1. В HTML-обрамлении страницы у меня на момент написания скрипта была указана ещё кодировка Windows-1251, но в теге XML
я указываю Юникод (UTF-8). Это работает, поскольку содержимое файла - только ссылки латиницей. При необходимости поменяйте на utf-8 кодировку страницы со скриптом и её указание в теге meta charset
.
2. Для скорости из текста запроса $sql
вполне можно убрать сортировку
.' order by '.$map['field'].' asc'
25.12.2017, 17:13 [8033 просмотра]