本文配套源碼
最近博客園討論氣氛熱烈,有價值的評論也層出不窮。有時候我們會很希望訂閱某篇文章的評論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的解析方式,便可以用於多個模板了。