Giter VIP home page Giter VIP logo

rfeed's Introduction

Overview

rfeed is a library to generate RSS 2.0 feeds in Python. It's based on the work from Andrew Dalke in the PyRSS2Gen library (see the Inspiration section below for more information.)

rfeed is extensible, and in my opinion very easy to use. Besides the standard RSS 2.0 specification, it also includes iTunes support for podcast feeds.

Installation

The library is a single file rfeed.py, so you could simply copy it wherever you need it. You can also install it using the following command:

% python setup.py install

Usage

I don't think you are going to find a better reference for using the library than the test suite in tests.py. However, unit tests are sometimes hard to understand and isolated, so here is a simple example from end to end:

import datetime 
from rfeed import *

item1 = Item(
    title = "First article",
    link = "http://www.example.com/articles/1", 
    description = "This is the description of the first article",
    author = "Santiago L. Valdarrama",
    guid = Guid("http://www.example.com/articles/1"),
    pubDate = datetime.datetime(2014, 12, 29, 10, 00))

item2 = Item(
    title = "Second article",
    link = "http://www.example.com/articles/2", 
    description = "This is the description of the second article",
    author = "Santiago L. Valdarrama",
    guid = Guid("http://www.example.com/articles/2"),
    pubDate = datetime.datetime(2014, 12, 30, 14, 15))

feed = Feed(
    title = "Sample RSS Feed",
    link = "http://www.example.com/rss",
    description = "This is an example of how to use rfeed to generate an RSS 2.0 feed",
    language = "en-US",
    lastBuildDate = datetime.datetime.now(),
    items = [item1, item2])

print(feed.rss())

It's a very succinct example, but it exposes the following concepts:

  • The main object of the RSS 2.0 feed is the Feed class.
  • The Feed class supports a list of Item instances.
  • To specify the guid attribute of an item, you can use a Guid instance.
  • To get the final RSS content, you can use the rss() method of the Feed class.

Of course, there's way more than what the example above illustrates. Here is the full list of exposed classes and a brief description of each one of them:

  • Feed: This is the main class that represents the RSS 2.0 feed.
  • Item: Represents an item of a feed's channel.
  • Category: Represents one or more categories that the channel or item belongs to.
  • Cloud: Represents a web service that supports the rssCloud interface which can be implemented in HTTP-POST, XML-RPC or SOAP 1.1.
  • Image: Represents a GIF, JPEG or PNG image that can be displayed with the channel.
  • TextInput: Represents a text input box that can be displayed with the channel.
  • SkipHours: Represents a hint for aggregators telling them which hours they can skip.
  • SkipDays: Represents a hint for aggregators telling them which days they can skip.
  • Enclosure: Represents a media object that is attached to a feed's item.
  • Guid: Represents a string that uniquely identifies the item.
  • Source: Represents the RSS channel that the item came from.

(For more information about each one of these classes, you can check the official RSS 2.0 specification, and check out the rfeed.py source file.)

Extending the library

The RSS 2.0 specification is extensible, so it's rfeed. Adding extra content to your feed is very simple:

  1. Create a class that extends the Extension class.
  2. Overwite the Extension.get_namespace method to return the namespace of your extension (the one will be included in the <rss/> element of your feed.) If you don't need to add a namespace, you can simply extend the Serializable class instead.
  3. Use the Feed.add_extension() method, or the extensions array in the constructor to provide your extension.

Here is an example of extending your feed with a content:encoded element:

import datetime 
from rfeed import *

class Content(Extension):
    def get_namespace(self):
        return {"xmlns:content": "http://purl.org/rss/1.0/modules/content/"}

class ContentItem(Serializable):
    def __init__(self, content):
        Serializable.__init__(self)
        self.content = content

    def publish(self, handler):
        Serializable.publish(self, handler)
        self._write_element("content:encoded", self.content)

item = Item(
    title = "Sample article",
    link = "http://www.example.com/articles/1", 
    description = "This is the description of the first article",
    author = "Santiago L. Valdarrama",
    guid = Guid("http://www.example.com/articles/1"),
    pubDate = datetime.datetime(2014, 12, 29, 10, 00),
    extensions = [ContentItem('This is the value of the enconded content')])

feed = Feed(
    title = "Sample RSS Feed",
    link = "http://www.example.com/rss",
    description = "This is an example of how to use rfeed to generate an RSS 2.0 feed",
    language = "en-US",
    lastBuildDate = datetime.datetime.now(),
    items = [item],
    extensions = [Content()])

print(feed.rss())
  • Note that we want to add our Content instance to the list of extensions at the feed level. This way we make sure the namespace is included in the feed.
  • In this case the Content instance doesn't provide a publish method because there's nothing to add to the <channel/> element of the feed.
  • The ContentItem class extends Serializable because it doesn't need to provide a namespace (it was already provided by the Content instace.)
  • The ContentItem instance implements the publish method and uses the _write_element method to output the specific XML content.

For a more exhaustive example, check the implementation of the iTunes extension in the rfeed.py file.

iTunes Support

Podcasts are a huge medium in 2014, and iTunes is the preferred way of publishing them. This is the reason rfeed provides an extension for iTunes support. Here is an example of how to use it:

import datetime 
from rfeed import *

itunes_item = iTunesItem(
    author = "Santiago L. Valdarrama",
    image = "http://www.example.com/artwork.jpg",
    duration = "01:11:02",
    explicit = "clean",
    subtitle = "The subtitle of the podcast episode",
    summary = "Here is the summary of this specific episode")

item = Item(
    title = "Sample article",
    link = "http://www.example.com/articles/1", 
    description = "This is the description of the first article",
    author = "Santiago L. Valdarrama",
    guid = Guid("http://www.example.com/articles/1"),
    pubDate = datetime.datetime(2014, 12, 29, 10, 00),
    enclosure = Enclosure(url="http://www.example.com/articles/1.mp3", length=0, type='audio/mpeg'),
    extensions = [itunes_item])

itunes = iTunes(
    author = "Santiago L. Valdarrama",
    subtitle = "A sample podcast that will never be produced",
    summary = "This is just a fake description",
    image = "http://www.example.com/artwork.jpg",
    explicit = "clean",
    categories = iTunesCategory(name = 'Technology', subcategory = 'Software How-To'),
    owner = iTunesOwner(name = 'Santiago L. Valdarrama', email = '[email protected]'))

feed = Feed(
    title = "Sample Podcast RSS Feed",
    link = "http://www.example.com/rss",
    description = "An example of how to generate an RSS 2.0 feed",
    language = "en-US",
    lastBuildDate = datetime.datetime.now(),
    items = [item],
    extensions = [itunes])

print(feed.rss())

Inspiration

I created my own blog engine in Python for Google App Engine, thus I needed a way to generate my RSS feed. Later on, I added a podcast site that also needed an RSS feed, but this time with iTunes support.

The only help I could find was the amazing PyRSS2Gen library written by Andrew Dalke. The library is very simple, but it didn't help with the iTunes support, so I found myself modifying it to get as much as I could out of it.

At the end I didn't like what I did to the original library: it was messy all around. It wasn't the library's fault, but my own. I decided to fix the problem from scratch, by rewriting the library in a different way.

I'm not claiming this new version is better than the original. It's just different and I think a little bit easier to extend and maintain (since it comes with a suite full of unit tests). Since I needed iTunes support from the beginning, I also coded an iTunes extension for the library. Now I'm powering my blog and podcast sites with it, and I hope it serves well to anyone with similar needs.

Thanks to Andrew Dalke for writing (what I consider) the first version a long time ago. This project is based on his original work, borrowing ideas and code from it, but with enough differences that I felt it deserved a new name.

Contributing

Contributions, questions and comments are all welcome and encouraged. If you run into any problems, please submit an issue and I'll take a look. If you want to get your hands dirty and submit a pull request, even better. Also, take a look at the test suite in tests.py and tests your changes to make sure nothing else breaks. To run the tests, execute the following command:

$ python tests.py

I really appreciate anything you can contribute to the library.

License

MIT Licence

Copyright (c) 2014 Santiago Valdarrama

rfeed's People

Contributors

chrisle avatar dbeath avatar egorsmkv avatar mahdisarikhani avatar philiptrauner avatar svpino avatar tbowers avatar teunvink avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rfeed's Issues

date doesn't support timezones

Serializable._date() returns a date string with a hard-coded 'GMT' timezone representation regardless of the actual timezone of the datetime object.

Neither the RSS 2.0 Specification nor the RFC 2822 (section 5.1 SYNTAX) require a GMT/UTC value for the datetime, just that it follow the specified format.

I would suggest that instead of blindly returning 'GMT' for the timezone, either use the tzname() of the timezone aware datetime object and default to 'UTC' if it returns None, or convert any timezone aware datetime objects to UTC and then return the new value + 'UTC' as the timezone value.

Typo Error in feed example snippet

Hi,
there seems to be an typo error in Line 28 of the documentation snippet for a rss feed with rfeed.
link = "http://www.example.com/rss"
As far as i know, it should be:
link = "http://www.example.com/rss",
So with a comma at the end.
Kind regards,
Alex

Items printed as "[[...]]"

The examples provided on the main page work fine for me. However they are based on building your items up individually and then passing them into the feed.

In my case I am walking a folder structure and building an items list. I think my modification is very straight forward however when I print the rss, I end up with "<title>[[...]]</title>" instead of my actual serialized items.

   share_urls = get_urls()
    items = []
    for share_url in share_urls:
        itunes_item = iTunesItem(
            author = author,
            image = logo_url,
            explicit = "yes",
            subtitle = "Test Subtitle",
            summary = description)

        item = Item(
                title = title,
                link = homepage,
                description = description,
                author = author,
                guid = Guid(homepage),
                pubDate = datetime.datetime(2014, 12, 29, 10, 00),
                enclosure = Enclosure(url=share_url, length=0, type=''),
                extensions = [itunes_item])

        items.append(items)

    itunes = iTunes(
        author = author,
        subtitle = description,
        summary = description,
        image = logo_url,
        explicit = "yes",
        owner = iTunesOwner(name = author, email = email))

    feed = Feed(
            title = title,
            link = homepage,
            description = description,
            language = "en-US",
            lastBuildDate = datetime.datetime.now(),
            items = [ Item(items) ], # <<<--- I feel like my main issue is here but I'm not sure what I'm doing wrong
            extensions = [itunes])

    print(feed.rss())

May want to default to UTF-8 encoding

Great rewrite of PyRSS2Gen, it's made it really easy for me to add an extension for pubsubhubbub links.

I ran into a issue where I was generating feeds using aggregated content from feeds using UTF-8. The UTF-8 content was being added to the generated feed's XML, but because the charset for the feed read ISO-8859-1, the UTF-8 content wasn't being read by Firefox or Tiny Tiny RSS.

I fixed this by changing the saxutils.XMLGenerator to use UTF-8, which seems fine because UTF-8 is backwards compatible with ISO-8859-1.

Not really a big deal, but I figure that PyRSS2Gen was originally written in 2003, and a lot of feeds are using UTF-8 as default these days.

<![CDATA[...]]> tags are ignored

any content inside a tag should be unescaped, along with the enclosing tag. This tag should be available as a way to render HTML embedded in the description field.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.