Hello World
Spiga

自己动手生成评论RSS

2009-06-04 11:11 by 老赵, 25580 visits

最近博客园讨论气氛热烈,有价值的评论也层出不穷。有时候我们会很希望订阅某篇文章的评论RSS,只可惜博客园目前没有这个功能。对于注册用户来说,我们可以通过点击评论框下方的“订阅回复”链接,这样就会在出现新评论的时候收到邮件。可惜匿名用户,只得不断刷新才能关注最近讨论到什么地方了。不过我们是什么人?我们是程序员,这点障碍对我们来说应该是在简单不过的小事了。自己搭一个站点,获取页面数据,分析HTML,输出为RSS,就这么简单。

老赵为此作了一个最最简单的示例,可以订阅http://jeffreyzhao.cnblogs.com上任意一篇文章的评论。由于只是简单的个人工具程序,所以完全不考虑性能、伸缩性、扩展性,容错性,也抛弃任何的单元测试,依赖注入等“最佳实践”。总之一句话,怎么容易怎么来。

这个示例由两部分组成,第一部分是个静态HTML页面,根据文章URL生成并转向至其RSS链接。寥寥数行HTML和JavaScript:

<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>博客园RSS</title>
    <script language="javascript" type="text/javascript">
        function goToCommentRss(url) {
            window.location = "CommentRss.ashx?url=" + encodeURIComponent(url);
        }
    </script>
</head>
<body>
    <textarea id="url" cols="50" rows="10"></textarea><br />
    <input type="button" value="Comment RSS"
        onclick="goToCommentRss(document.getElementById('url').value)" />
</body>
</html>

CommentRss.ashx将为我们输出评论的RSS。它的代码如下:

public class CommentRss : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        string url = context.Request.QueryString["url"];

        WebClient webClient = new WebClient();
        webClient.Encoding = Encoding.UTF8;
        string html = webClient.DownloadString(url);

        context.Response.ContentType = "text/xml";
        context.Response.ContentEncoding = Encoding.UTF8;

        SyndicationFeed feed = GetRssFeed(url, html);
        Rss20FeedFormatter rssFormatter = new Rss20FeedFormatter(feed);
        XmlWriter rssWriter = XmlWriter.Create(context.Response.Output);
        rssFormatter.WriteTo(rssWriter);
        rssWriter.Close();
    }

    private static SyndicationFeed GetRssFeed(string url, string html)
    {
        ...
    }

    public bool IsReusable { get { return false; } }
}

其实.NET框架已经为我们准备了太多太多有用的工具,我们只需要将它们拼接起来即可。例如有了WebClient类,三行代码便可下载到页面的HTML。然后我们通过GetRssFeed方法来获得一个SyndicationFeed对象,再通过Rss20FeedFormatter输出。SyndicationFeed和Rss20FeedFormatter都是.NET 3.5中自带的类库,放在System.ServiceModel.dll程序集中的System.ServiceModel.Syndication命名空间里,可以方便读取或生成Atom 1.0或RSS 2.0格式的XML为我们所用。更多信息可以参考InfoQ中文站的这篇报道:WCF的Web编程模型资源

GetRssReed的关键在于分析HTML字符串,老赵在这里使用了正则表达式匹配出每条评论的标题、URL、时间、用户和内容。然后构造出一个SyndicationFeed对象就再简单不过了。可惜的是,博客园不同模板的HTML不同,因此老赵的这个示例只支持现在用的这个模板。您可以自己改造,例如为CommentRss.ashx增加一个新的参数,用于指名HTML的解析方式,便可以用于多个模板了。

这个示例使用起来也非常简单,您可以将其编译或部署在本地的IIS上,打开Default.html页面,将文章的URL复制进去,如《老赵谈IL(2)》一文的URL:

粘贴URL链接

点击按钮,便会链接至RSS页。于是在IE中便会展示为:

评论RSS

此时您只要把URL放入本地的RSS阅读器即可。因为程序部署在您的机器上,因此您无法使用Google Reader等工具进行订阅。如果您有条件的话,把它们放到虚拟空间等地方即可。由于您的程序只为您一个人服务,因此不会占用大量资源,目前的写法也足够了。

我们是程序员。自己动手,丰衣足食。

 

点此下载示例

Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名赵劼(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言

Add your comment

38 条回复

  1. AlexLiu
    *.*.*.*
    链接

    AlexLiu 2009-06-04 11:12:00

    难得在赵老师的前排慢慢看。

  2. 青羽
    *.*.*.*
    链接

    青羽 2009-06-04 11:14:00

    @AlexLiu
    是啊~~

  3. James.Ying
    *.*.*.*
    链接

    James.Ying 2009-06-04 11:20:00

    顶~不错的东东,收藏之

  4. oec2003
    *.*.*.*
    链接

    oec2003 2009-06-04 11:23:00

    收藏了

  5. jowo
    *.*.*.*
    链接

    jowo 2009-06-04 11:27:00

    有意思,老赵就是点子多

  6. coolxlc
    *.*.*.*
    链接

    coolxlc 2009-06-04 11:36:00

    赵老师 太有才了

  7. OwnWaterloo
    *.*.*.*
    链接

    OwnWaterloo 2009-06-04 11:49:00

    谢谢谢谢~~~
    我也想过要做……
    但是…… 你知道…… C++就写点console的还适合, 要真做什么东西是很麻烦的 ……

  8. 韦恩卑鄙
    *.*.*.*
    链接

    韦恩卑鄙 2009-06-04 11:53:00

    你是坏人

  9. Haozes
    *.*.*.*
    链接

    Haozes 2009-06-04 12:01:00

    Rss20FeedFormatter
    .NET3.5把读取RSS的玩意都集成上去了....汗啊.连解析XML都省了

  10. 老赵
    admin
    链接

    老赵 2009-06-04 12:04:00

    --引用--------------------------------------------------
    韦恩卑鄙: 你是坏人
    --------------------------------------------------------
    谁让你刚好连续发了几篇,嘿嘿

  11. 老赵
    admin
    链接

    老赵 2009-06-04 12:05:00

    @OwnWaterloo
    CLI/C++调用.net类库还是很容易的阿

  12. 汉子进墙[未注册用户]
    *.*.*.*
    链接

    汉子进墙[未注册用户] 2009-06-04 12:16:00

    楼主干脆做个多人版本,服务广大程序员。一个人的需求,有时候是千千万万人的需求。

  13. OwnWaterloo
    *.*.*.*
    链接

    OwnWaterloo 2009-06-04 12:28:00

    @Jeffrey Zhao
    如果这样, 我觉得还是直接使用C#更好。
    我对C#并不排斥, 而且很有爱~~~
    就是没什么时间学.Net的库 ……

    web开发相关的很多东西也都不了解。
    比如rss整个机制是怎样运作起来的…… 目前就只能用用而已……
    再比如, 这个"订阅",

    到底是"轮询":

    for (;;) {
    GetWebContent // 获取网页的内容
    DiffAndSend // 比较, 有差别时通知订阅者
    Sleep // 休息一会
    }


    还是"通知":?

    void OnPublish() {
    DiffAndSend // 比较, 有差别时通知订阅者
    }

    Register( OnPushish ) // 再某个地方,注册一个
    如果有变化, 会调用 OnPublish。
    有什么地方可以提供这样的注册么?
    更重要的是,如果有Register,从这个层面上看,它确实是通知,而不是轮询。
    但Register本身是通过轮询,还是通知?
    它会不会是自己通过轮询,造成通知这一假象?


    这些东西都不了解 …… 所以没法下手 ……


    从这一点上来说, 如果注册cnblogs用户, 用邮件订阅, 应该是通知了。
    通知的时机很容易得到, 评论者点提交的时候, 就可以给订阅者发邮件了。
    好像还是这样效率比较高。
    为什么cnblogs、cppblog这些不做在一起呢 …………………………
    郁闷………………

  14. 不是我不想说[未注册用户]
    *.*.*.*
    链接

    不是我不想说[未注册用户] 2009-06-04 12:34:00

    老赵难得写一篇带有example下载的文章,顶起来~~哈哈

  15. 老赵
    admin
    链接

    老赵 2009-06-04 13:18:00

    @OwnWaterloo
    这个例子很简单的……不需要了解这么多……

  16. 老赵
    admin
    链接

    老赵 2009-06-04 13:20:00

    --引用--------------------------------------------------
    汉子进墙: 楼主干脆做个多人版本,服务广大程序员。一个人的需求,有时候是千千万万人的需求。
    --------------------------------------------------------
    还是需要的朋友自己动手丰衣足食吧,或者让dudu先加上这个功能。

  17. Yin.Pu@CQUSoft
    *.*.*.*
    链接

    Yin.Pu@CQUSoft 2009-06-04 15:41:00

    --引用--------------------------------------------------
    Jeffrey Zhao: --引用--------------------------------------------------

    汉子进墙: 楼主干脆做个多人版本,服务广大程序员。一个人的需求,有时候是千千万万人的需求。

    --------------------------------------------------------

    还是需要的朋友自己动手丰衣足食吧,或者让dudu先加上这个功能。
    --------------------------------------------------------
    号召大家都做一个自己的版本,选出好的用到CNBLOG中。

  18. 张蒙蒙
    *.*.*.*
    链接

    张蒙蒙 2009-06-04 23:24:00

    楼主记得你有一个评书的系列,怎么没下文了呢,期待中

  19. 0000——0000[未注册用户]
    *.*.*.*
    链接

    0000——0000[未注册用户] 2009-06-05 13:31:00

    这个东东太实用了,支持~~

  20. 差距[未注册用户]
    *.*.*.*
    链接

    差距[未注册用户] 2009-06-05 13:37:00

    就这么几行代码就可以看出与赵的差距实在太大了,以后得多挤挤海绵了

  21. 朱燚:-)
    *.*.*.*
    链接

    朱燚:-) 2009-06-05 22:57:00

    老赵属于找博客园的茬说.Net的事儿啊,我直接用左边栏的订阅最新回复.

  22. 老赵
    admin
    链接

    老赵 2009-06-06 00:01:00

    @朱燚:-)
    hmmm……

  23. Jinspet
    *.*.*.*
    链接

    Jinspet 2009-06-06 15:25:00

    深入浅出ASP.NET AJAX 系列的WebCast是你讲的吧?我的AJAX入门视频呢,谢谢赵老师,以后多关注您的博客O(∩_∩)O~

  24. CowboyRyan
    *.*.*.*
    链接

    CowboyRyan 2009-06-08 13:07:00

    同样是程序员,差距在于代码行数。~

  25. 温景良(Jason)
    *.*.*.*
    链接

    温景良(Jason) 2009-07-07 22:37:00

    呵呵

  26. Dnnmix
    *.*.*.*
    链接

    Dnnmix 2009-07-26 09:30:00

    有创意, 给了我一些提示, 有些网站的feed只是给些内容概述, 用这个方法读取全文也不成问题了,谢谢咯

  27. 缘分★星空
    *.*.*.*
    链接

    缘分★星空 2009-08-15 15:24:00

    挺好啊只是SyndicationFeed和Rss20FeedFormatter都是.NET 3.5中自带的类库,.net 2.0就得自己写代码了

  28. 老赵
    admin
    链接

    老赵 2009-08-15 15:32:00

    @缘分★星空
    我忘了是装一个.NET 3.0就行了,还是一定要装.NET 3.5。如果是服务器端程序这些应该都不是问题吧,呵呵。
    如果客户端是.NET 2.0,那么可以使用开源类库,RSS.NET。

  29. Ame
    *.*.*.*
    链接

    Ame 2009-08-17 09:04:00

    学习。。。

  30. hdl253
    *.*.*.*
    链接

    hdl253 2009-08-25 13:17:00

    遨游浏览器显示不正常,查找原因中。。。。

  31. 老赵
    admin
    链接

    老赵 2009-08-25 13:20:00

    @hdl253
    什么不正常?

  32. hdl253[未注册用户]
    *.*.*.*
    链接

    hdl253[未注册用户] 2009-09-11 10:53:00

    @Jeffrey Zhao

    遨游浏览器中显示的是源代码

  33. 老赵
    admin
    链接

    老赵 2009-09-11 10:59:00

    @hdl253
    这是给RSS阅读器看的,不是给浏览器看得,IE或FireFox自带RSS阅读功能,Chrome就没有。

  34. Yeemio
    *.*.*.*
    链接

    Yeemio 2009-11-05 17:17:00

    第一次了解RSS是个什么东西。。

  35. mrxliu
    *.*.*.*
    链接

    mrxliu 2010-01-24 10:50:00

    尝试下,嘿嘿。

  36. mrxliu
    *.*.*.*
    链接

    mrxliu 2010-01-24 10:52:00

    好像 chrome 没有效果!

  37. 老赵
    admin
    链接

    老赵 2010-01-24 13:27:00

    @mrxliu
    这个结果你应该知道其中原因吧.

  38. mrxliu
    *.*.*.*
    链接

    mrxliu 2010-01-24 15:29:00

    @Jeffrey Zhao
    其实我是来测试 RSS 效果的。哈哈!

发表回复

登录 / 登录并记住我 ,登陆后便可删除或修改已发表的评论 (请注意保留评论内容)

昵称:(必填)

邮箱:(必填,仅用于Gavatar

主页:(可选)

评论内容(大于5个字符):

  1. Your Name yyyy-MM-dd HH:mm:ss

使用Live Messenger联系我