技巧:使用 Universal Feed Parser 驾驭 RSS

当人们忽视了标准时,工具可以节约时间

Comments

XML 到处都有标准,但让每个人都照规矩行事并不是一件容易的事。Web 以蔑视 HTML 和 XHTML 标准的网页而出名,这也是造成很多受到广泛关注的问题的缘由。W3C 的 Dave Raggett 开发了颇受欢迎的工具 Tidy(请参阅 参考资料)来挽救这种局面,它将“标签汤”(粗心和结构错误的 HTML)转化成结构良好的 XHTML。RSS 是另一个理论标准被混乱的现实打破的例子。更糟的是,RSS 存在很多相互竞争的标准,有一些相差甚大。沿着 Raggett 的思路,Mark Pilgrim 开发了 Universal Feed Parser,用他的话来说就是“极端自由的 RSS 解析器”。但 Universal Feed Parser 的功能不止于此,引用文档中的说法:

Universal Feed Parser 是一个下载和解析连锁消息包的 Python 模块。它可以处理 RSS 0.90、Netscape RSS 0.91、Userland RSS 0.91、RSS 0.92、RSS 0.93、RSS 0.94、RSS 1.0、RSS 2.0、Atom 和 CDF 消息包。

从这个列表就可以看出人们为何把 RSS 和混乱联系在一起。Atom(请参阅 我最近撰写的相关文章)本来希望给 RSS 一个全新的面貌,但实际上仅仅增加了一种选择。所幸的是,Universal Feed Parser 吸收了大家所能设想到的各种消息包格式,包括那些宣称遵循某种 RSS 标准但又有细微不同的消息包。本文给出的示例代码利用 Universal Feed Parser 能够处理各种 RSS 消息包。

简单的消息包列表程序

清单 1 示范了 Universal Feed Parser 的用法,它从给定的 URL 读入 RSS 并在控制台上显示消息包中的基本信息。

清单 1. 在标准输出中显示消息包信息
import sys
import feedparser
#List of uples (label, property-tag, truncation)
COMMON_CHANNEL_PROPERTIES = [
    ('Channel title:', 'title', None),
    ('Channel description:', 'description', 100),
    ('Channel URL:', 'link', None),
]
COMMON_ITEM_PROPERTIES = [
    ('Item title:', 'title', None),
    ('Item description:', 'description', 100),
    ('Item URL:', 'link', None),
]
INDENT = u' '*4
def feedinfo(url, output=sys.stdout):
    """
    Read an RSS or Atom feed from the given URL and output a feed
    report with all the key data
    """
    feed_data = feedparser.parse(url)
    channel, items = feed_data.feed, feed_data.entries
    #Display core feed data
    for label, prop, trunc in COMMON_CHANNEL_PROPERTIES:
        value = channel[prop]
        if trunc:
            value = value[:trunc] + u'...'
        print >> output, label, value
    print >> output
    print >> output, "Feed items:"
    for item in items:
        for label, prop, trunc in COMMON_ITEM_PROPERTIES:
            value = item[prop]
            if trunc:
                value = value[:trunc] + u'...'
            print >> output, INDENT, label, value
        print >> output, INDENT, u'---'
    return
if __name__ == "__main__":
    url = sys.argv[1]
    feedinfo(url)

清单 COMMON_CHANNEL_PROPERTIESCOMMON_ITEM_PROPERTIES 定义了频道和特别关注的每个条目的属性。Use Universal Feed Parser 尝试使用最常见的名称提供对最常用属性的访问,而不考虑不同 RSS 版本间的差异。清单 1 列出的条目名称适用于 Universal Feed Parser 所能识别的任何格式的任何消息包。工具文档中有一节题为“Content Normalization”,讨论了如何处理源格式术语的差异。 feedinfo 是主函数,负责接收 URL 和可选的输出流(类似文件的对象),默认输出流为系统输出(控制台)。 feedparser.parse 是惟一需要知道的 Universal Feed Parser API。它在一个数据结构中返回所有的消息包数据,可以像嵌套对象那样访问这种数据结构,或者像嵌套词典那样访问(如果愿意的话)。比如,可以使用 feed_data.feedfeed_data.['feed'] 访问顶层频道或者消息包属性。

剩下的代码打印顶层消息包的细节和每个条目。它提供了有限的格式化特性,比如将很长的属性值缩减到给定的字符数(由 COMMON_CHANNEL_PROPERTIESCOMMON_ITEM_PROPERTIES 列表中每一条的第三项决定)。注意,我在处理 Use Universal Feed Parser 的字符串时使用了 Unicode。该工具就是使用 Unicode 对象表示数据,从而很好地保证了消息包数据的国际化。但是如果您恰好对包含非 ASCII 字符的消息包运行 清单 1,那么可能在打印语句中遇到编码错误。如果出现这种情况,则需要明确使用 Python 的 Unicode 设施更小心地处理输出(可以用标准 codecs 模块中的 Unicode 编码器包装输出流)。

下面的片段是对 IBM DeveloperWorks 首页的 RSS 消息包运行 清单 1 的结果,这是一个结构良好的 RSS 2.0 消息包。为了便于查看,我添加了一些新行,并把消息包项减为两个。

清单 2. 对 RSS 消息包运行清单 1
$ python listing1.py http://www.ibm.com/developerworks/news/dw_dwtp.rss
Channel title: IBM developerWorks
Channel description: The latest content from IBM developerWorks...
Channel URL: http://www.ibm.com/developerworks/index.html?ca=drs-tp4704
Feed items:
     Item title: Meet the experts: Ric Telford on the state of autonomic
computing today
     Item description: This question and answer article features Ric
Telford, Director for Autonomic Computing at IBM. deve...
     Item URL:
http://www.ibm.com/developerworks/library/ac-telford/index.html?ca=drs-tp4704
     ---
     Item title: Lightweight RFID framework
     Item description: When administration and cost are an issue, lightweight
RFID is an interim solution...
     Item URL:
http://www.ibm.com/developerworks/library/wi-rfid/index.html?ca=drs-tp4704
     ---

结束语

我曾经多次使用 Universal Feed Parser 作为一种过滤器工具,将任意的消息包转化成 RSS 1.0。它负责最困难的那部分任务,比如应付无法预料的输入。Universal Feed Parser 的测试包给我留下了深刻的印象,它展示了 Mark Pilgrim 为处理 RSS 领域的种种古怪行为付出了多么大的努力。可能有那么一天,RSS 的创建者和用户会就某种消息包格式(比如 Atom)达成一致,但是在那遥远的一天来临之前,Universal Feed Parser 对于每个需要编写代码处理 Weblog 之类信息的人来说,都是一个不可或缺的工具。


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=XML
ArticleID=58159
ArticleTitle=技巧:使用 Universal Feed Parser 驾驭 RSS
publish-date=01012005