11 дек. 2009 г.

Django RSS для Яндекс новостей

Не секрет, что контриб syndication в django умеет делать RSS ленты, и делает это очень правильно. Но вот беда, Яндексу для его новостей нужны не просто RSS 2.0 ленты, а RSS 2.0 с добавлением тэга yandex:full-text, да ещё и в кодировке windows-1251.

Завелосипедить эту досадную оплошность можно следующим образом (естественно, не только им, но именно в споре рождается истина, так что жду комментарии):


# in urls:

   (r'^yandex.xml$''text.views.yandex_rss'),





# in views:



def yandex_rss(request):

    from news.models import New

    output = {

        'news': New.objects.filter(rubrics__pk=11).order_by('-published').select_related()[:15],

    }

    from django.template.loader import render_to_string

    rendered = render_to_string('yandex.html', output).encode('cp1251')

    return HttpResponse(rendered, mimetype='application/rss+xml; Charset=windows-1251')



# yandex.html:



<?xml version="1.0" encoding="windows-1251"?>

<rss version="2.0"

     xmlns="http://backend.userland.com/rss2"

     xmlns:yandex="http://news.yandex.ru">

    <channel>

        <title>вИшиме.ру</title>

        <link>http://vishime.ru/</link>

        <description>Последние новости с вИшиме.ру</description>

        <lastBuildDate>{% now "r" %}</lastBuildDate>

        <image>

            <url>http://vishime.ru/media/favicon.ico</url>

            <title>вИшиме.ру</title>

            <link>http://vishime.ru/</link>

        </image>

        {% for new in news %}

        <item>

            <title>{{ new.title }}</title>

            <link>http://vishime.ru{{ new.get_absolute_url }}</link>

            <description>{% if new.lead %}{{ new.lead|striptags|safe }}{% else %}{{ new.text.text|striptags|truncatewords:"20"|safe}}{% endif %}</description>

            <author>{% if new.author %}{{ new.author }}{% else %}вИшиме.ру{% endif %}</author>

            <category>{{ new.rubrics.get }}</category>

            <pubDate>{{ new.published|date:'r' }}</pubDate>

            <yandex:full-text>{{ new.text.text|striptags|safe }}</yandex:full-text>

        </item>

        {% endfor %}

    </channel>

</rss>


Пример с вИшиме.ру, но внимание (!), эту ленту ещё не приняли в яндекс новости, так что приведенные куски кода ничего не гарантируют.

Ещё раз, я понимаю, что нужно такие вещи писать по другому (раз уж есть syndication).

8 комментариев:

res комментирует...

Не понятно требование насчет windows-1251. Юникод же более универсальный.

Попроси добавить этот RSS в Рамблер-Новости. Он схаваеся нормально.

Ivan Markeev комментирует...

Согласен, не ясно почему Яндекс требует win-1251, но это данность. Для сайта http://russned.ru именно так.

За ссылку спасибо!

Unknown комментирует...

Может просто наследоваться от django.utils.feedgenerator.SyndicationFeed ( django.utils.feedgenerator.Rss201rev2Feed)?
У них есть метод item_attributes, который добавляет
атрибут к тэгу item.

Ivan Markeev комментирует...

Это логично, но я не придумал, как побороть метод write, чтоб он отдавал windows 1251

res комментирует...

На Рамблере добавлено:
http://news.rambler.ru/Russia/r/4664898/
http://news.rambler.ru/Russia/r/4664727/

Рекомендую убрать в урлах картинок кириллицу, тогда Рамблер сможет их показывать в новостных сниппетах.
Новости с картинками лучше кликаются.

А если добавить картинки (до 200x200 будет достаточно) в RSS, то робот не будет ходить за ними лишний раз на страницу новости.

Ivan Markeev комментирует...

Большое Вам спасибо, за советы и поддержку!

res комментирует...

Не за что )
Региональные источники очень важны.
Жаль, пока они далеки по обьемами качеству от центральных и их перепечатчиков.

Следить можно тут:
http://news.rambler.ru/rss/Tumen

Или тут:
http://news.rambler.ru/Tumen

Unknown комментирует...

Возможно тема устарела, Яндекс более не требует cp1251, хотя в их примерах он остался. Решил задачу более правильным способом (ссылка на запись в блоге): http://web4y.ru/entries/django-proekt-i-yandeksnovosti/