БлогNot. PHP: пишем простой генератор файла sitemap.xml

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 просмотра]


теги: php textprocessing вебдезигн форматы яндекс xml поиск

К этой статье пока нет комментариев, Ваш будет первым