前兩天上新浪,看到新浪 RSS 頻道開通,不容易啊,等了這么久。
我的目標是做一個簡單的portlet,每次讀取新浪的RSS站點顯示最新的新聞條目。
花了一個下午,去sourceforge和google 上搜索 opensource 的 java rss lib,還真有不少(順便提一下,sourceforget的搜索真的很爛)。簡單過濾以后,覺得以下三個類庫比較有搞頭。Rome 、rssutils和rsslib4j。具體的評測如下:
一. Rome
Rome 是
java.net 上的一個開源項目,現在的版本是0.5。為什么叫Rome呢,按它的介紹上的說法,有個“條條大路通羅馬”的意思,有些RSS的意味。Rome可能是 sun 公司從自己某個子項目中抽離出來的,package和類的命名就象j2sdk一樣感覺規范。功能上支持RSS的所有版本及 Atom 0.3(Atom是和RSS類似的一種內容聚合的方式)。Rome 本身是提供API和功能實現,其下獨立出一個 rome-fetcher 項目,專門用來讀取RSS內容。正和我意啊。
參照 fetcher 上的范例,解析 RSS 相當簡單,代碼片斷如下:
FeedFetcher fetcher = new HttpURLFeedFetcher();
SyndFeed feed = fetcher.retrieveFeed(feedUrl);
System.out.println(feedUrl + " has a title: " + new String(feed.getTitle().getBytes("iso8859-1"), "utf-8") + " and contains " + feed.getEntries().size() + " entries.");
for (Iterator iter = feed.getEntries().iterator(); iter.hasNext(); ) {
SyndEntry entry = (SyndEntry) iter.next();
System.out.println("<a href=" + entry.getLink() + ">" + entry.getTitle() + "</a>[" + entry.getPublishedDate() + "]");
}
為什么用 new String(feed.getTitle().getBytes("iso8859-1"), "utf-8") 進行轉碼,是因為Rome來解析
新浪新聞 RSS的時候試圖從 URLConnection 的 header 中得到編碼信息,否則總是用 iso8859-1。而新浪的RSS response header 中不包含編碼信息,所以要做一番轉碼。另外還有就是 entry.getPubDate() 也將返回null,因為Rome 用多種pattern 去試圖解析時間信息,新浪的時間格式還是符合RFC822的,但是Rome 使用SimpleDateFormat 來解析時間,它忘記了一點,就是 SimpleDateFormat的解析是關聯于 Locale 的,所以由于我本地locale是China,SimpleDateFormat的parse方法解析不出英文的時間字符。以上代碼前加 Locale.setDefault(Locale.Englisth) 可以搞定,但總覺得不爽。
如果也不想轉碼的話,Rome 還提供了一個 XmlReader 的類,通過分析 header 和 xml 內容推斷 encoding,修改 HttpURLFeedFetcher 的源碼 :
// 改變 InputStreamReader , 換用 XmlReader
//InputStreamReader reader = new InputStreamReader(is, ResponseHandler.getCharacterEncoding(connection));
XmlReader reader = new XmlReader(connection);
SyndFeedInput input = new SyndFeedInput();
SyndFeed feed = input.build(reader);
那么中文不用轉碼也能正確顯示了,不過修改源碼后我再解析
百度新聞 RSS 的時候,底層的JDOM卻會抱錯說xml 格式不正確。也許Rome的開發者也遇到過這樣的問題,所以才沒有使用 XmlReader。
二. rssutils
它是一個工具包,sun 的 develope站點上有文章
RSS Utilities: A Tutorial 專門介紹用taglib 顯示RSS內容,附帶的可以下載這個工具包,但我從網上搜索不到它的出處,自然也無法看到它的源碼。但從反編譯的代碼來看,也是sun公司內部高手所做,設計精巧,代碼簡練。實現一個handler,用sax的方式解析xml內容,handler內部用反射和javabean的機制構造RSS元素對象并賦值。代碼片斷如下:
RssParser parser = new RssParserImpl();
Rss rss = parser.parse(new URL(url));
System.out.println(rss.getChannel().getTitle());
for (Iterator iter = rss.getChannel().getItems().iterator(); iter.hasNext();) {
Item item = (Item)iter.next();
System.out.println("<a href=" + item.getLink() + "</a>" + item.getTitle() + " " + item.getPubDate());
}
如上所示,代碼也是相當簡單,沒有轉碼的需求,時間也正確顯示(因為根本沒做分析,當字符串直接返回)。但是該工具包并非真正對外公布,代碼中有些不嚴謹的地方,如System.out的輸出,很不爽。而且如果 RSS 的 xml內容如果缺少部分不常用元素 ,它也會printStackTrace一大串,服了它了。另外還有一個大問題,就是當我用它解析 百度新聞 的時候,直接就報錯:org.xml.sax.SAXParseException: 字符轉換錯誤:“Unconvertible UTF-8 character beginning with 0xb0”。網上查了查,可能是 java 修改過的 UTF-8 和標準 UTF-8 些微不兼容導致。詳情參看
Java 平臺中的增補字符 一文。
三. rsslib4j
rsslib4j 是 sourceforget 上的項目,主頁是
http://sourceforge.net/projects/rsslib4j,現在最新的版本是0.2,才0.2,可是開發狀態卻已經是穩定產品化了。同樣支持所有RSS版本。
rsslib4j 解析 RSS 的方式和 rssutils 一樣,我看了看源碼,設計比較簡單,代碼可讀性一般,大量使用if。代碼片斷如下:
RSSHandler hand = new RSSHandler();
RSSParser.parseXmlFile(new URL(url), hand, false);
RSSChannel ch = hand.getRSSChannel();
System.out.println(ch.toString());
LinkedList lst = hand.getRSSChannel().getItems();
for (int i = 0; i < lst.size(); i++) {
RSSItem itm = (RSSItem) lst.get(i);
System.out.println(itm.toString());
}
看起來也是相當清晰易懂,執行結果也和rssutils一樣,不過用它來解析 百度新聞 卻不會出現 rssutils 的utf-8編碼錯誤,真是奇怪,兩者都是調JAXP的 SAXParser 。不過它的代碼也有bug,不能解析出 channel 的一些信息,查看源碼,有點簡單邏輯錯誤,修正后解決。想寫封email給項目開發者可惜英文不行,通過cvs去commit一下也嫌麻煩,作罷。
總結
Rome:
優 - 1)可擴展性好,有前途。2)功能強大,除了用來解析RSS,還可以聚合和構造RSS。
劣 - 1)兼容性待加強,2)綁定jdom。為什么不喜歡 jdom呢,因為它api 老變,還很絕,搞得不兼容。
rssutils:
優 - 1)代碼設計精妙,值得學習。2)附帶 taglib 實現,直接可在 jsp 中應用。
劣 - 1)沒有源碼。 2)兼容性有待加強。 3)功能較弱,只能用來解析RSS,沒有聚合和構造RSS功能。
rsslib4j:
優 - 1)簡單有效,體積小。2)兼容性不錯。
劣 - 1)有小bug。2)功能較弱,只能用來解析RSS,沒有聚合和構造RSS功能。
編輯選擇: rsslib4j
我只用來讀讀新浪新聞,rsslib4j 夠用就好,不過要自己修改和編譯源碼。
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=282333
posted @
2008-01-31 00:23 wangxlyy 閱讀(356) |
評論 (0) |
編輯 收藏