воскресенье, 31 января 2010 г.

Django: Яндекс RSS

Привет коллеги, которые пишут свои реализации RSS специально для Яндекса.
Приведенный код также добавляет в syndication возможность создавать элементы с CDATA

from django.contrib.syndication.feeds import Feed
from django.utils.xmlutils import SimplerXMLGenerator
from django.utils.feedgenerator import Rss201rev2Feed


class SXG(SimplerXMLGenerator):
    def addQuickElementCDATA(self, name, contents=None, attrs=None):
        if attrs is None: attrs = {}
        self.startElement(name, attrs)
        if contents is not None:
            self._write('<![CDATA['+contents+']]>')
        self.endElement(name)
        

class Rss(Rss201rev2Feed):
    def write(self, outfile, encoding):
        handler = SXG(outfile, encoding)
        handler.startDocument()
        handler.startElement(u"rss", self.rss_attributes())
        handler.startElement(u"channel", self.root_attributes())
        self.add_root_elements(handler)
        self.write_items(handler)
        self.endChannelElement(handler)
        handler.endElement(u"rss")
    
    def add_item_elements(self, handler, item):
        if item['description'] is not None:
            handler.addQuickElementCDATA(u'description', item['description'])
            item['description'] = None
        super(Rss, self).add_item_elements(handler, item)


class RssYandex(Rss):
    def rss_attributes(self):
        attrs = super(RssYandex, self).rss_attributes()
        attrs.update({'xmlns':'http://backend.userland.com/rss2', 'xmlns:yandex':'http://news.yandex.ru'})
        return attrs
    
    def add_item_elements(self, handler, item):
        if item['fulltext'] is not None:
            handler.addQuickElementCDATA(u'yandex:full-text', item['fulltext'])
        super(RssYandex, self).add_item_elements(handler, item)


пример использования:
class MyFeed(Feed):
    feed_type = RssYandex

    def item_extra_kwargs(self, item):
        return {'fulltext':item.body.rendered}


и не забываем про любимую Яндексом кодировку:
def feed(request, url):
    try:
        slug, param = url.split('/',1)
    except ValueError:
        slug, param = url, ''
    
    f = MyFeed(slug, request).get_feed(param)
    
    response = HttpResponse(mimetype=f.mime_type)
    f.write(response, 'windows-1251')
    return response


если вам не нужна поддержка CDATA, то можно обойтись малой кровью
from django.utils.feedgenerator import Rss201rev2Feed

class RssYandex(Rss201rev2Feed):
    def rss_attributes(self):
        attrs = super(RssYandex, self).rss_attributes()
        attrs.update({'xmlns':'http://backend.userland.com/rss2', 'xmlns:yandex':'http://news.yandex.ru'})
        return attrs
    
    def add_item_elements(self, handler, item):
        if item['fulltext'] is not None:
            handler.addQuickElement(u'yandex:full-text', item['fulltext'])
        super(RssYandex, self).add_item_elements(handler, item)

2 комментария:

  1. Grand merci! Респект и прочее в таком же духе!
    Яндекс - вещь на редкость не благодарная в плане РСС, так что Ваше решение весьма кстати.
    Спасибо!

    ОтветитьУдалить
  2. Фарид, взял за основу Ваш способ, но без windows-1251 (Яндекс более не требует) и добавил теги yandex:logo
    Результат можете посмотреть в моей записи: http://web4y.ru/entries/django-proekt-i-yandeksnovosti/

    ОтветитьУдалить