2008-09-24

Bug Fixed! 文章和回應連結錯亂的問題

我們知道 Blogger 的系統一直有在調整,不管是解 Bug、還是新增功能,原則上都是一直往好的方向前進。不過系統一調整,對 Blogger 的 Hack 來說都是一種挑戰,如果 Hack 的 Code 沒寫好,系統調整完某些功能就會開始不正常。從官方開發者的 Blogger Developer Network 的部落格新聞看來,系統最近調整的重點是 Feed (Atom or RSS) 的資料擴充和標準化,基本上應該是「無痛」的擴充才是,結果調整完我一堆透過 Feed 抓取資料內容當作模組的功能開始不正常,主要的現象是:連結的網址不正確了,跑去查了一下 Code、又翻了 Google Data API 的 Spec,都看不出有什麼異狀,後來 Search 了半天,總算找到原因,而且也找到了解決的辦法。

稍微解釋一下問題點好了(不會寫程式的這段可以跳過)。我有很多 Hack,都是透過 JSON、去抓取 Feed 的資料內容,然後再一個一個 Parse 到我需要的變數裡,串成我要的東西。在「網址連結」(link) 這個資料結構裡,基本上不是只有一個連結,而是一個陣列,之前這個陣列裡都只有一個元素,就是文章的網址,因此我在寫 Code 的時候沒想太多,當我需要文章網址的時候,就直接呼叫 link[0].href。問題來了,這次系統調整完,這個陣列裡變成不只一筆資料啊,而且關鍵是,原來我要的網址資料,被移到陣列的「最後一筆」去了,link[0] 不但不是我要的,這「最後一筆」還不知道會是那一筆哩(Comment 是 link[2] 、Post 是 link[4])~就算我又 Hard-code 特定一筆,根據這篇 Blogger Data API 討論區的這篇文章,負責開發的 RD 還說,「資料順序並不是規格裡有硬性規定的」,所以就算報 Bug 給官方要求修改,一則不知道什麼時候會改回來(或是改成怎樣),二則還不一定會被接受,所以 Hard-code 不是解決問題的辦法,看來還是要想其他方式解決。後來我查了我自己的所有模組,ㄟ?還是有模組不受此調整影響的耶!查了一下內容,喔~雖然「順序」會變,但文章網址的「屬性」不會變啊!從這篇文章提到 Feed 元素的資料結構得知,每個 link 元件有很多個屬性,像是 href、rel 和 type,一般我們取用的都是 href,而文章網址有一個確定屬性,就是 rel = "alternate" (至於為什麼,請查 W3C 的文件)。知道這個條件問題就好解決啦!只要我們找出 link 這個陣列裡如果 rel 的值是 alternate 的話,那筆 link 的 href 就是我們要的啦!

根據以上的發現,要做的調整也很簡單,多三行判斷檢查就行了。原先的程式大多像是這樣(以「最新文章」模組的程式為例):

var link = Post.link[0].href;

我修改後多了檢查,確定是原文網址才可以:

var j = 0;
while (j < Post.link.length && Post.link[j].rel != "alternate")
  j++;
var link = Post.link[j].href;

再舉個例子好了(因為用「最新回應」這個模組的人看來最多),原先程式那一行是這樣的:

var link = Comment.link[0].href;

依照以上的原則修改後,變成:

var j = 0;
while (j < Comment.link.length && Comment.link[j].rel != "alternate")
  j++;
var link = Comment.link[j].href;

最小修改、只多三行(含一個 while 迴圈檢查),這樣就能確定網址是對的啦~即便哪天 Blogger 又調整了 link 這個陣列裡資料的順序,也不會再影響到 Hack 的運作了。

在找問題翻規格的過程中,我發現搞 Hack 的王道,是直接用 Blogger Data API 裡的 Javascript Client Library,只要 include 該 library 的網址,就可以用 Google 自訂的方法來取得 Feed 資料,像是如果要抓標題,不需要什麼 title.$t,直接呼叫 getTitle() 就行啦(函式規格文件在這邊),當然,這個 API 會不會調整也很難講啦,但我想至少 Google 會兼顧這些 API 的正確性吧,閒來無事的話再玩玩看好了~

以下整理這個問題會牽扯到我的相關 Blogger Hack 連結,如果你也有用過以下的玩意,記得順手修正一下,才不會不正常。原文的程式碼我都修改過了,如果看得懂以上原理,建議可以自己動手改改看,而局部修改的原則就是先找「我的原始碼裡」 var j = 0; 這一行開始,把後面幾行蓋掉「你程式碼裡」像是 xxx.link[0].href 的那一行,如果懶得找的就直接重貼一次程式碼也行。

結合發表文章的日曆模組 (Feed Calendar)
「最新回應」模組 (Recent Comments)
首頁即時可展開的留言回應 (Comment Toggling) (這個沒有 Source Code,請自行查看我的網頁原始碼)
最新文章模組「終極版」
最新文章的加強版:其他的最新文章 (Other Recent Posts)
應用 JSON 實現「最新文章」、「最新回應」和「Blog 聯播」

除了以上模組,如果發現有修正無效、引發其他狀況的 Hack,也歡迎回報。

註:像是和「回應」有相關的 Hack,有人刻意拿掉我像是 .replace("#c", "#comment-") 這個部份,之所以這樣寫當然是有原因的!因為 Blogger 的 comment feed 裡的 link 值一直有問題,明明是某個人的回應連結,文章網址後面接的應該是網址加上該人留言的錨點 (就是 # 後面那個 ID),Blogger 的格式是 #comment-ID,可是連結卻總誤植為 #cID,所以我才「好心」把它取代成正確的,如果哪天 Blogger 找到這個 Bug 並且修好的話,才有必要拿掉(當然不改也行,還是會連結到正確文章,只是不會自動跳到留言者的那個留言,要自己翻...)。看來,我應該也去和官方「反應」一下,難道都沒有人發現有問題嗎?

註 2:以上修正 commment- 的問題經 LVCHEN 提醒後發現是舊樣板才有的問題,我調整過了,看來新的樣板都是以 #cID 作為連結,因此「預設」應該是不用去修正,我也把它從程式碼裡拿掉了。

回應: 15

nobody 提到...

Thanks Abin,我已經改完了,終於可以正確顯示,我的程式功力還要多加強,哈哈。

匿名 提到...

不好意思..
我實在是看不懂程式
但我用的是
http://chagg.blogspot.com/2007/07/blogger-pixnet.html
裡面的
http://chagg0924.googlepages.com/rc.js
我喜歡他的格式
只是那篇文章的主人好像沒有在經營blog了
看了你的這篇
研究半天我還是不會弄
不知道可不可以請你幫我看看怎麼修改呢
謝謝...

LVCHEN 提到...

雖然我不確定問題在哪裡,但在我的站上,留言的連結的確是#cID,我記得很久以前好像也有人反映過,但好像得到已經修正的回應...

所以看起來 #cID 確實是正確的連結,但不知道是模板還是伺服器的問題,才會造成#comment-ID 為留言連結的錯誤。

貴方用尋找 rel 尋找連結的方式的確很好,對於這個留言外掛來說是很適用,只是由於我的外掛需要的連結種類很多,有些 rel 物件竟然還有重複,例如檢查文章標題時就有兩個 rel 物件的值都是 replies,還必須同時檢查 type 物件才能找到需要的連結。

非常感謝你提出的這個方法,我已經應用在我的外掛裡,雖然花了許多時間修改,希望這樣可以一勞永逸的應付 Blogger API 下次的改版。

黑色童話 提到...

Abin兄
感謝你的教學,我的部落格已順利修正最新文章功能

fishbowl 提到...

終於得救了,非常感謝!一次統統解決了。

Hudson Gao 提到...

今天上來點突然發現錯亂,來看之後我也改好了,真的很感謝您!

Abin 提到...

To lvchen:
感謝您的提醒,我的 Todo-list 上就有一項「找出為什麼要 replace #cID 成 #comment-ID 的原因」,我看了您的 Blog 狀況,又另外開一個測試的 Blog 檢查,您說的沒錯,新的 Blog 裡 #cID 才是正確的。但我三個舊的 Blog 程式碼裡,都還是用 #comment-ID 這樣的格式。
我看了一下,發現「早期」的 Blog 樣板裡 Blogger 並沒有每篇留言連結和 anchor 的變數,因此樣板裡必須自己組合,將 Post URL 和 ID 串起來變成連結,該格式也拿來當作 anchor,這時候,串的過程裡樣板塞進了 comment- 這玩意。
我看了新的 Blog 樣板,裡面多了兩個變數,像是 data:comment.anchorName、data:comment.url,有這兩個玩意就不用自己串啦!但我樣板還是以前自己串的 code,套用新版的 feed 就出錯啦~所以才要手動 replace 修正。
感謝您的提醒,終於得以發現和解決這個問題~

csyin 提到...

感謝Abin的分享, 我的也改好了.

炸機瑞 提到...

謝謝你的用心,我的部落格中於正常了!

Davin Chao 提到...

感謝Abin兄....
所有不正常的部份,終於都修改好了!

小笠 提到...

謝謝Abin 大大真的很厲害
把問題一勞永逸的解決掉

PEI 提到...

Yay for Abin!
非常感謝站長的辛勞與分享,幫了我這個看不懂程式又愛玩blog的傢伙很大的忙!\^O^/

GG 提到...

求助,这篇文章的http://ggq.blogspot.com/2007/02/blogger-30ajax.html

的js脚本怎么改啊?似乎真的失效不能用了。

就是这个脚本http://ggpi.googlecode.com/files/ajaxlabels.js

帮忙看看,狂谢~~那个英文作者已经很长时间不更新了,我也不懂js脚本,你的文章看得我一头雾水……

CLHSU 提到...

謝謝Abin, 我的也改好了, 有你真好!

Che HUANG 提到...

前陣子也是發現問題,不過一直沒有找解決方法,結果又找回當初從您這修改的網頁,沒想到您已經有解決方式了,真是太感謝啦。

張貼留言

歡迎留言或發表意見,不過要理性不做人身攻擊。匿名的朋友得到回應的速度會比較慢喔~
發問相關的禮貌和規矩請先參考這篇文章,不當留言、和本文無關的回應可能會被直接刪除無視喔!