Оригинал: /naklon.debilarius.ru
Автор: Егор Наклоняев

RSS - в массы, а массы...
или RSS для умственно иных.

После того, как я обнаружил в сети Интернет, что все прогрессивное человечество давно уже пользуется форматом RSS (Really Simple Syndication)  для передачи новостей, а я  прикрутил сиё дитя шкодливой мысли к сайту. Потом еще к одному... И ещё... В процессе прикручивания оного дитяти к разным сайтам, я столкнулся с некими проблемами, которые мне пришлось решать, чем и спешу поделиться. Итак, по порядку... 

Главное, ради чего пользователи ходят в Интернет - это информация. Причём та стадия, когда первичным вопросом стояла публикация информации уже давно пройдена - сейчас только ленивый не публикуется, теперь основным вопросом стоит систематизация информации и обмен ею в автоматическим режиме. Проблема автоматизации ставит другую проблему - проблему стандартизации. Дело в том, что, например, новостные ленты на разных сайтах настолько отличаются по оформлению и расположению, что отбирать их и обрабатывать можно только вручную. Как известно, лень - двигатель прогресса. Для решения этой задачи был придуман формат обмена информацией на базе языка разметки XML. Данный формат носит название RSS. В формате RSS 2.0, о котором я, собственно, и хочу рассказать, он означает Really Simple Syndication, а изначально он назывался RDF Site Summary, где RDF означает Resource Definition Framework. Таким образом, абревиатура RSS на настоящий момент обозначает два совершенно различных формата. Не будем вдаваться в историю, как это получилось - интересующихся отсылаю к статье "RSS - осознанная необходимость", -  а рассмотрим как нам со всем этим жить на примере RSS 2.0, поскольку он гораздо удобнее в программировании и ручном формировании, чем его младшие братья. Многие сайты транслируют свою информацию в RSS, в том числе каждая страница LiveJournal. Эти каналы доступны по адресам http://www.livejournal.com/users/______/data/rss,  где подчеркивание - никнейм пользователя. Как получать эту информацию с помощью программ-агрегаторов, я уже писал, только замечу, что на данный момент я пользуюсь другим агрегатором - NewzCrawler. На этом я останавливаться в этой заметке не буду. Поговорим о том, как собственными руками сделать себе RSS канал и наслаждаться морально глядя на дело рук своих. 

Начнём ab ovo. Что из себя представляет формат RSS в самом минимальном виде, видно из приведенного ниже примера:

Естественно, что в таком виде он никому и даром не нужен, но не спешите, это только присказка, сказка вся впереди. Итак, что мы имеем с гуся? Первая строчка говорит нам о том, что это язык разметки XML и кодировка текста внутри windows-1251. Конечно, наиболее правильным было бы использовать UTF-8, как это рекомендуется в документации к XML, но поскольку допускаются любые стандартные кодировки, не будем мудрствовать лукаво и возмем кодировку, используемую для документов нашего сайта. Возможна также кодировка koi8-r или любая другая по Вашему выбору.

Вторая строчка это открывающий тэг <rss>, который содержит служебную информацию. Данную информацию не трогайте и пишите без изменений. В конце примера мы видим закрывающий тэг </rss>. Внутри тэга <rss> вложен тэг <channel>, состоящего из обязательных непустых  элементов: <title>,<link> и <description>. Данные об этих элементах сведены в таблицу:

Элемент Описание Пример
title Название вашего канала. Именно по данному названию и будут ссылаться на Ваш ресурс. Если Вы это делаете для своего вебсайта - просто впишите название своего сайта. <title>Портал Егора Наклоняева</title>
link Ссылка на сайт, соответствующий данному каналу <link>http://naklon.debilarius.ru/</link>
description        Краткое описание канала. <description>Сайт Егора Наклоняева и Сигизмунда Траха - людоведов и душелюбов. Сайт посвящен наклону, его пропаганде и практическому применению</description>

Теперь, о необязательных элементах.

Элемент Описание Пример
language Язык, на котором Вы пишите. Скорее всего - русский. Перечень языков, определенных W3C, доступен  здесь. <language>ru</language>
copyright Авторские права на канал. NB! Должно быть на английском языке. <copyright>Copyright 2003, Egor Naklonyaeff</copyright>
managingEditor Адрес электронной почты редактора данного канала <managingEditor>chyduskam@debilarius.ru (Egor Naklonyaeff)</managingEditor>
webMaster Адрес электронной почты администратора сайта. <webMaster>chyduskam@debilarius.ru (Egor Naklonyaeff)</webMaster>
pubDate Дата публикации данного канала, т.е. дата и время последней публикации канала. Если Ваш канал обновляется раз в сутки, то вне зависимости от того менялось или нет содержимое дату следует изменить. Должно обязательно соответствовать стандарту RFC 822, за исключением того, что год может состоять как из двух символов, так и из четырех. Но лучше из четырех. Стандарт RFC 822 допускает вместо GMT ставить временную зону. Например, для Москвы она будет +0300. Пример см. ниже. В принципе, данный элемент - бесполезная для обывателя вещь. <pubDate>Sat, 20 Dec 2003 00:00:01 GMT</pubDate>
lastBuildDate Дата последнего изменения содержимого. <lastBuildDate>Sat, 20 Dec 2003 00:00:01 +0300</lastBuildDate>
category Описывает категорию, к которой принадлежит канал. Описание см. ниже в элементе <item>. Скорее всего этот элемент Вам не понадобится.
generator Строка, описывающая программу, которая использовалась для создания файла. При создании вручную совершенно не нужна. <generator>notepad.exe</generator>
docs Ссылка на документацию, описывающую формат данного RSS файла. Справочная информация для удобства Ваших пользователей. Нужно использовать приведенную справа в графе "пример" ссылку, или вообще не использовать этот элемент. <docs>http://blogs.law.harvard.edu/tech/rss</docs>
cloud Нечто из области автоматики и телемеханики. Вам это скорее всего не понадобится. Но на всякий случай знайте, что прочитать об этом можно здесь.

 

<cloud domain="rpc.sys.com" port="80" path="/RPC2" registerProcedure="pingMe" protocol="soap"/>
ttl Указание для программ-агрегаторов сколько секунд нужно хранить канал в кэше переж тем как обновить его очередной раз. Большинство протестируемых мною агрегаторов игнорируют данный параметр, поэтому можно и не заморачиваться <ttl>600</ttl>
image Описывает картинку GIF, JPEG или PNG, которая может показываться агрегаторами для данного канала. Состоит из трех основных и трех дополнительных элементов.

К основным элементам относятся:
<url> ссылка на картинку. Обычно, это пресловутые кнопки 88х31 сайтов, а LiveJournal, например, сюда помещает так называемый "userpic".
<title> - краткое описание картинки, соответствует ALT атрибуту HTML тэга <img>. Обычно, соответствует названию Вашего сайта.
<link> - ссылка на то, куда мы попадем ткнув в картинку. Обычно соответствует главной странице Вашего сайта.

К необязательным элементам относятся:
<width> и <height> - размер картинки в пикселях. Ширина и высота, соответственно.  Максимальная ширина 144, по умолчанию - 88. Максимальная высота 400, по умолчанию 31.
<description>  - содержание атрибута TITLE элемента <a> для данной картинки. Или, говоря простым языком, всплывающая подсказка, которая возникнет при наведении мышью на картинку.

<image>
    <url>http://naklon.debilarius.ru/images/naklon.gif</url> 
    <title>Портал Егора Наклоняева</title> 
    <link>http://naklon.debilarius.ru/</link> 
    <width>88</width> 
    <height>31</height> 
</image>
rating Некий PICS rating. Я так и не понял, зачем это нужно обывателю.
textInput Позволяет описать поле ввода текста. Состоит из четырех обязательных подэлементов.
<title> - Название кнопки "Submit" в области ввода текста.
<description> - Описание в  области ввода текста.
<name> - Название текстового объекта. Служит для скриптов.
<link> - ссылка на CGI скрипт, обрабатывающего текст введенный в поле ввода. Большинство агрегаторов игнорирует данный элемент. Позволяет создать посковую системку или еще какую-нибудь ерунду.
skipHours Говорим агрегаторам, в какое время мы их не хотим видеть.
skipDays Говорим агрегаторам по каким дням нас не беспокоить.

С описанием заголовка канала на этом закончили. Теперь разберемся собственно с элементом <item>. Каждый элемент <item> - это отдельная статейка или краткая аннотация на статью и ссылка на полную версию статьи. Канал может содержать любое число элементов этого типа, но не старайтесь поместить весь сайт в канал. Вполне достаточно 5-10 последних поступлений. Все вложенные элементы <item> необязательные, но хотя бы один из элементов <title> или <description> должны быть.

Элементы <item>

Элемент Описание Пример
title Название заметки <title>RSS - в массы, а массы... или RSS для умственно иных</title>
link The URL of the item. <link>http://naklon.debilarius.ru/texts/sleep/rss.htm</link>
description      Аннотация или полная заметка <description>После того, как я обнаружил в сети Интернет, что все прогрессивное человечество давно уже пользуется форматом RSS для передачи новостей, а я прикрутил сиё дитя шкодливой мысли к сайту. В процессе прикручивания оного дитяти я столкнулся с некими проблемами, которые мне пришлось решать, чем и спешу поделиться. Итак, по порядку...</description>
author Адрес электронной почты автора заметки.  <author>chyduskam@debilarius.ru (Egor Naklonyeff)</author>
category Позволяет описать категорию данного раздела. Содержит необязательный атрибут domain, используемый для категоризации. <category domain="http://naklon.debilarius.ru/texts/sleep/">Маразм</category>
comments Ссылка на страницу, позволяющаю писать комментарии к данной заметке. <comments>http://naklon.debilarius.ru/forum/thread.php?group=debilarius.naklon</comments>
enclosure Описывает медиа-объект. Содержит три обязательных атрибута. url - адрес, где находится,  lengh - размер в байтах, type - MIME тип.  Как этим пользоваться можно посмотреть здесь. <enclosure url="http://www.scripting.com/mp3s/weatherReportSuite.mp3" length="12216320" type="audio/mpeg" />
guid Строка, однозначно идентифицирующая данную заметку. NB! Если этот элемент используется он должен быть уникальным. Может содержать атрибут isPermaLink="true" , если это уникальная ссылка на соответствующий ресурс. По умолчанию - "true". <guid isPermaLink="true>http://naklon.debilarius.ru/texts/sleep/rss.htm#v2</guid>
pubDate Дата публикации документа. О формате смотрите выше. Если содержит дату в будущем, агрегаторы не должны её показывать. <pubDate>Sat, 20 Dec 2003 00:00:01 +0300</pubDate>
source Ссылка на канал, с которого пришла данная новость, если оное имело место. Содержит один обязательный атрибут url , ссылающийся на источник. <source url="http://naklon.debilarius.ru/rss/">Портал Егора Наклоняева</source>

Ну, а теперь собираем всё вместе. Вставка выделена жирным шрифтом.

<item>
<title>RSS - в массы, а массы... или RSS для умственно иных</title>
<link>http://naklon.debilarius.ru/texts/sleep/rss.htm</link>
<description>После того, как я обнаружил в сети Интернет, что все прогрессивное человечество давно уже пользуется форматом RSS для передачи новостей, а я прикрутилсиё дитя шкодливой мысли к сайту. В процессе прикручивания оного дитяти я столкнулся с некими проблемами, которые мне пришлось решать, чем и спешу поделиться. Итак, по порядку...</description>
<author>chyduskam@debilarius.ru (Egor Naklonyeff)</author>
<category domain="http://naklon.debilarius.ru/texts/sleep/">Маразм</category>
<comments>http://naklon.debilarius.ru/forum/thread.php?group=debilarius.naklon</comments>
<guid isPermaLink="true>http://naklon.debilarius.ru/texts/sleep/rss.htm</guid>
<pubDate>Sat, 20 Dec 2003 00:00:01 +0300</pubDate>
</item>

Если мы делаем  RSS вручную, то теперь при появлении очередной новости мы просто добавляем её в фаил, стирая по мере необходимости старые. В принципе, без разницы куда добавлять очередной блок, но красивее когда он идёт в обратном хронологическом порядке. Например:

Следует напомнить, что если вы хотите использовать в формате XML, допустим, в элементе <description> тэги HTML, то согласно стандарту, правильно будет или заменить везде открывающую и закрывающую скобки на &lt; &gt;, а кавычки на &quot; либо использовать специальные скобки:

Лично я предпочитаю второй вариант. Теперь записываем полученный файл, например, как rss.xml (расширение очень важно!). После чего  выкладываем оный на Ваш сайт и пытаемся проверить его. Проверить Ваш RSS можно (и нужно) по данной ссылке:  http://feedvalidator.org/ - введите адрес Вашего файла и нажмите кнопку "Validate". После чего действуйте по обстоятельствам. Если всё нормально, то осталось только порадовать весь окружающий мир фактом, что у Вас есть RSS. Делается это тремя способами. Во-первых, на главную страницу, содержащую новости, мы помещаем в заголовок страницы ссылку на RSS файл. В моём случае, это выглядит так:

<link rel="alternate" type="application/rss+xml" title="RSS" href="http://naklon.debilarius.ru/rss/" >

Измените атрибут href  и будет Вам счастье.

 Во-вторых, можно поставить модные кнопки на сайт. Такую:  XML icon и даже такую: Тыц! . Вторая кнопка служит для автоматической подписки на новости в UserLand и некоторых других программах, поддерживающих этот способ. Ссылка у второй кнопки выглядит следующим хитрым образом: http://127.0.0.1:5335/system/pages/subscriptions?url=http://naklon.debilarius.ru/rss/. Если у Вас не установлена необходимая программа ничего криминального не произойдет. Сообщит об ошибке и всё. Понятно, что у себя на сайте адрес url следует поменять на Ваш собственный. Есть еще другие кнопки, не менее жизнеутверждающие, но они менее распространены.
Ну, и третий способ, это  зарегистрировать свой RSS на сайте-каталоге данных ресурсов и ждать у моря погоды. Этим способом, конечно, брезговать не стоит, но всё-таки основными остаются первые два.


Теперь о программировании этого всего на PHP в динамическом режиме. Думаю, что человеку знакомому с азами PHP сделать вывод файла в описанном формате не представляется сложным, задачка тривиальнейшая, но есть одно "но". Дело в том, что надо правильно сформировать заголовки. Поскольку агрегаторы могут обращаться к Вашему ресурсу достаточно часто, неплохо чтобы они получали отлуп, если никаких изменений на сайте нету. Для этого в HTTP-заголовке прописываются следующие вещи:

header("Content-type: text/xml");
header("Last-Modified: $MypubDate");
header("Etag: \"$MyETAG\"");

Оставлю на Ваше усмотрение формирование элемента Etag. Я, лично, использую timestamp самой свежей новости плюс некую служебную информацию. Но, возможно, до выдачи вышеперечисленного может и не дойти, поскольку сперва надо проверить заголовки вызова и в случае, если у нас ничего не изменилось вернуть код ошибки HTTP 304 Not Modified. Фрагмент кода, осуществляющего проверки, приведен ниже. 

$headers = getallheaders();
if(isset($headers["If-None-Match"])) {
    if ($headers["If-None-Match"] == $MyETAG) {
        header("HTTP/1.1 304 Not Modified");
        exit;
    }
}
else {
if(isset($headers["If-Modified-Since"])) {
    if ($headers["If-Modified-Since"] == $MyGMTtime) {
    header("HTTP/1.1 304 Not Modified");
    exit;
}}}

Обратите внимание: все даты в заголовках HTTP должны формироваться только в соответствии со стандартом RFC 1123. Корректный формат даты, соответсвующий данному стандарту, можно получить, например, следующим образом: $MyGMTtime=gmdate("D, d M Y H:i:s", $mytime)." GMT";

Вот, примерно, и всё что я могу доложить по данному вопросу. Если Вы заметите какую либо неточность, или Вам покажется что я недостаточно полно осветил тему - адрес моей электронной почты справа внизу страницы. 

Sapienti Sat.

Могу еще добавить для любознательных:

Дополнительная литература:

Стандарт RSS 2.0

Extending RSS 2.0 With Namespaces