JSON 應用(2):最新迴響的標題
分類:
部落格
自從 blogger.com 的新版發佈以來,最另人詬病的就是若是有加入一個新網頁元素(Page Elements),選擇資訊提供(Feed)的時候,加入是最新迴響的 Feed(http://xxxxx.blogspot.com/feeds/comments/summary) 更新的速度很慢,甚至要到幾個小時之譜,這對來部落格留言的人不是很能接受的。
因為 blogger.com 之前的舊版是利用轉成靜態網頁的方式,但新版就不是這樣的模式,增加了很大的彈性,但是這對於資料的同步與 Cache 是很大的考驗,所以其實也不能責怪他們。
若改成用 Javascript 的模式去抓 JSON 格式的 Feed 來顯示,可以解決上述的問題,因為資料是在客戶端電腦去抓取 Feed 回來顯示。可是問題又來了,這個 Feed 的格式居然沒有原文章的標題,這個對寫很多文章的人來說是個很大的困擾,往往要點入後才知道這些人是在哪篇文章留言的!所以,我想了幾個辦法如下:
- 先抓取 comments 的 feed,內有標題的網址,然後利用搜尋的方法去 blogsearch.google.com 取回標題
- 先抓取 comments 的 feed,內有標題的網址,然後再抓取 posts 的 feed 兩個去比對
- 先抓取 comments 的 feed,內有標題的網址,再抓取藉由 comments 發佈到 gmail 信箱然後轉發到另一個部落格的 posts feed 去比對網址,取回標題。
分析以上作法的風險,我決定採用最麻煩的第三種作法。
- blogsearch 的效能不可預知,新文章可能搜尋不到,舊文章可能搜不到,或者標題更改也不一定會更新。
- 看起來是完美的作法,但是萬一有人在很舊很舊的文章留言, posts 的 feed 一次最多只能抓取 99 則,若比對不到的話,可能還要抓第二次第三次,很浪費連線的資訊傳送。
- 去比對最新 comments 的 feed 雖然可行,可是中間經過兩個SMTP(gmail)的轉寄,未來格式轉變,或是被誤認為 SPAM 也是很容易出問題。
我很懶的剪圖做說明,就簡單的把第三種方法的設定方式描述如下,有問題的人麻煩在詢問就好。
- 在原部落格A的控制主頁(Dashboard) → 設定(Settings) → 意見(Comments) → 意見通知地址 (Comment Notification Address) 打入一個為了最新迴響而開設的gmail 信箱(C@gmail.com)
- 開一個新的部落格B,然後在控制主頁(Dashboard) → 設定(Settings) → 電子郵件(Email) → Mail-to-Blogger 地址 Mail-to-Blogger Address 自行設定一組地址(account.D@blogger.com) 然後下方的 發佈(Publish) 要打勾勾
- 進入 (C@gmail.com) 的信箱收信匣(Web版) → 設定(Settings) → 轉寄和 POP 轉寄內收郵件的副本至輸入上個步驟的 account.D@blogger.com
- 在部落格A隨便留個言,然後打開部落格B看看是否留言有變成一篇新的文章,若有的話再進行下一個步驟。
- 在部落格A的控制主頁(Dashboard) → 範本(Template) → 網頁元素(Page Elements) → 新增網頁元素(Add a New Page Elements) → HTML/Javascript 然後把下面的原始碼貼上,就大功告成了,不過寄得把紅字的網址要打對。
<div id="divrc">下載中...</div>
<script>
var g_szAuthorsLink=new Array();
var g_szTitle= new Array();
var g_szOrgLink = new Array();
var g_iIndex=0;
var g_iShowCount=5;
function a_comprc(a,b){
order= Date.parse(a.published.$t.replace(/^(\d{4})-(\d{2})-(\d{2})T([0-9:]*)([.0-9]*)(.)(.*)$/,
'$1/$2/$3 $4 GMT')) - Date.parse(b.published.$t.replace(/^(\d{4})-(\d{2})-(\d{2})T([0-9:]*)([.0-9]*)(.)(.*)$/,
'$1/$2/$3 $4 GMT'));
return 0-order;
}
function a_rc(json)
{
g_entry = json.feed.entry.sort(a_comprc);
}
function a_FindTitle(json,orgLink)
{
var ret= orgLink;
for (var ii=0,rc; rc= json.feed.entry[ii]; ii++)
{
var content=rc.content.$t;
var index=content.indexOf(orgLink);
if (index>0)
{
var iBegin=index+orgLink.length+2;
var content2= content.substring(iBegin,content.length);
var iEnd = content2.indexOf('</a>');
if (iEnd >0)
ret=content2.substring(0,iEnd);
break;
}
}
return ret;
}
function a_FindIndex(json,orgLink)
{
var ij=0;
for (ij=0; ij < g_iIndex; ij++)
{
if (orgLink==g_szOrgLink[ij])
return ij;
}
g_szOrgLink[ij]=orgLink;
g_szTitle[ij]= a_FindTitle(json,orgLink);
g_szAuthorsLink[ij]='◎';
g_iIndex ++;
return ij;
}
function b_rc(json)
{
for (var i=0,post; post = g_entry[i]; i++)
{
var content = post.title.$t;
var link = post.link[0].href;
var iFind = link.indexOf('#');
var orgLink= link;
if (iFind>0)
orgLink = link.substring(0,iFind);
var index = a_FindIndex(json,orgLink);
if (index>= g_iShowCount)
{
g_iIndex--;
break;
}
var auther= post.author[0].name.$t;
var timestamp=post.published.$t.substr(0,10) + ' ' +post.published.$t.substr(11,5);
g_szAuthorsLink[index] += '<a href="' + link + '" title="' + timestamp + ':' + content + '">' + auther + '</a>«';
}
var temp = '<ul id="feedItemListDisplay">';
for (var j=0; j< g_iIndex; j++)
{
temp += '<li><a href="' + g_szOrgLink[j] + '">' + g_szTitle[j] + '</a><br/>' + g_szAuthorsLink[j] + '</li>';
}
temp+="</ul>";
document.getElementById("divrc").innerHTML = temp;
}
</script>
<script src="http://部落格A網址/feeds/comments/summary?alt=json-in-script&callback=a_rc" type="text/javascript"></script>
<script src="http://部落格B網址/feeds/posts/full?alt=json-in-script&callback=b_rc" type="text/javascript"></script>
至於實際的效果,就看左邊的《最新迴響》就是了。
2007.1.11 更新
上面這個方法,email 轉發文章到部落格B 被 blogger.com 擋掉了,他們認為是 spam。所以我改用了方法2. 其實程式碼是差不多,也做成一個元件送給大家使用,使用方法如下:
<script>g_szBlogDomain='xxxxx.blogspot.com'; </script>
<script src="http://js.writers.idv.tw/rc.js"></script>
2008.9.23 更新
今天不知道怎樣,json 輸出的格式改了,我把程式更新在 rc3.js
<script>g_szBlogDomain='xxxxx.blogspot.com'; </script>
<script src="http://js.writers.idv.tw/rc3.js"></script>
2008.9.24 更新
我把原來程式加入 rel 這個值的判斷,所以用原來的 rc.js 也可以了!

總共有35個迴響
Cool
很棒的解決方式,找時間要來裝裝看。
上面這個方法,email 轉發文章到部落格B 被 blogger.com 擋掉了,他們認為是 spam。所以我改用了方法2. 其實程式碼是差不多,也做成一個元件送給大家使用,使用方法如下:
<script>g_szBlogDomain='xxxxx.blogspot.com'; </script>
<script src="http://js.writers.idv.tw/rc.js"></script>
天啊,我找了半個月的程式出現了... 第三個想法真妙哪。
前兩天想自己動手寫,我本來想的是用 xmlhttprequest 抓網頁下來解出 title,不過你的想法速度應該快上 n 倍。
大感謝
Hi,
因為想讓顯示版面更符需求一點,希望你不介意我把程式抓回去修改,改完正式上線後會貼篇文章註明出處的 :)
柏強,歡迎拿回去修改。
找到一個以 postid 取得單篇文章 json 的方法:http://www2.blogger.com/feeds/{blogId}/posts/summary/{postId}?alt=json-in-script
例如 http://www2.blogger.com/feeds/5918579739413557982/posts/summary/5099559220264953311
不過我還沒有實際去做相應的程式,這好像應該用 httprequest 動態取回比較好?.. mmm
總之先提供您這項資訊 :)
柏強
1. postid 的網址用下面這個可能好一點
http://部落格網址/feeds/posts/summary/{postid}?alt=json-in-script
若是用這種方法也不錯,只是有個缺點,若要顯示10個最新迴響,而且分別在不同文章回應,就要去抓10次的標題,有點耗費資源!
2. 我個人覺得 json 比較好用,因為是瀏覽器透過 http 的協定去取回資料,而 httprequest 是利用瀏覽器內建的元件去取用,不知道有無最佳化過,這部份非同步的程式碼需要跑 javascript 才會去取資料,而 json 雖然也是 javascript 的語法,可是取資料的時候並沒有經過語言的解譯就去取資料了。
3. 至於你問為什麼要排序,是因為blogger 的原始排序方式是依據更新的時間,而不是文章的時間,這個例子是以最新迴響的時間,應該並不需要排序,就是正確的。若是顯示最新文章,一定要排序才是對的。
喔喔排序我了解了。
我也覺得 JSON 比較好用,不過不了解除了 xmlhttprequest 之外怎麼動態取回某網址的資料。(每次都硬塞個 document.write([script]...[/script]) 進去?)
多謝說明~
柏強,對的,就是用 document.write......
不過,這樣就跟用 XMLHttpRequest 的效果一樣了,呵呵!
抱歉,請問所以方法3是不能用了嗎?我自己試結果是失敗的。
沒想到要弄個最新的回應也這麼花工夫啊……
感謝水瓶子啊
原來的迴響佔了好多邊欄位置
現在變的好清爽
謝謝 ^^
請問水瓶子:
您所說的改使用方法二
那兩行程式碼,我要放在我的blog哪邊呢?謝謝
真是不好意思,我已經嘗試出來了
您好:
不知道什麼原因
今天看blog的時候,《最新迴響》那邊始終show不出來
的確有幾天有問題,但我沒時間查,現在已經正常。
你好
謝謝提供好用的功能
但我使用了方法二的程式碼
最新迴響的地方卻一直是"下載中"
重新整理了好幾次都沒用
請問可能是出了什麼問題?
謝謝解答
麻煩您把使用的部落格網址給我,我來查看看。
你好我是16樓
今天最新回應還是一直"下載中"
很頭痛啊...
http://8020rule.blogspot.com/
順便問一下
因為想用自己的欄位名稱
所以想要把《最新迴響》隱藏
請問要如何修改
非常謝謝
給樓上的 fox,我想下面這段貼上去就可以了。
<script>g_szBlogDomain='8020rule.blogspot.com'; var g_szHead='';</script><script src="http://js.writers.idv.tw/rc.js"></script>
謝謝水瓶子^^
現在回應終於出來了
非常完美XD
我好像也有跟fox一樣的問題耶
都是出現下載中...
可以請瓶子幫我?
謝謝^^
to hidelensman 以及其他留言的朋友:
要協助的請留下您的部落格網址(測試站台也可以),我可以去看看幫你 debug,我不是神,馬上可以判讀您的問題。
http://hidelensman.blogspot.com
謝謝水瓶子^^
我發現水瓶子真的好厲害耶...
很多文章對我這blogger初學者都很有幫助
有空會多來跟水瓶子請教的^^
再次謝謝:)
樓上這位 hidelensman 大哥,您的 feed設定開關沒有打開,請到主控台(Dashboard)→設定(Setting)→網站提供(Site Feed)→進階模式(Advanced Mode) 把前兩個 Feed 打開
謝謝水瓶子>///<
我在修改您的 code 時有幾個問題。
Blogger 的comment RSS or JSON feed 好像並沒有留言者的網站連結或是 e-mail 資訊,在留言者暱稱加的連結好像怪怪的,Anyway 會連到文章的網頁,那不是多此一舉嗎?
希望您有看懂我在說什麼><...
還有用 JSON-in-script 的方式處理 JSON 是相當方便的,還可以避掉本地端無法開啟外部資源的問題,但是似乎在送到 function 處理 JOSN 的同時,並沒有辦法向外傳出參數,即使是利用全域變數(global),也沒有辦法,但是,不同的 JSON-in-script 呼叫卻可以直接使用 function 裡的變數,即使他們是在不同的 function 與不同的 callback。
請問您對這有什麼看法,如果我要從 JSON-in-script 的呼叫中傳參數到其他的function (與json-in-script callback 用的function 沒關係),有什麼好辦法嗎?
您可以 e-mail 給我,我的e-mail 是 lvchen.blog@m2k.com.tw
謝謝您的回答。
花了一個下午,勉強解決了問題。
成果就在我的站上。
雖然還沒有得到您的解答,但總之還是要謝謝您的 CODE 給我的靈感。
LVCHEN,你已經克服了,恭喜!有關大於99篇的文章,其實還是有解決方法,只是很耗IE的效能及頻寬,再去讀下一個99篇文章的標題來比對就可以了,只是很懶得再寫程式了。
還有一個解決的方式,若你到那篇文章去重新發佈一下文章,有機會會在 RSS 上出現,這樣就可以抓到標題了,不過並不太適用很久很久以前的文章,我也不知道為什麼,我想應該是 blogger.com 資料庫的儲存方式問題吧!這個就不深究了
有關你對於為何作者要連結到網頁的這個問題,應該可以發現連結後面有個 #123456789 的號碼,而留言的地方多了 <a name=#123456789> 的這個 HTML tag 就是可以快速的指到留言者的地方,只是這樣,沒有別的作用。你可能要改一下 template 才能配合的天衣無縫
謝謝你的回答
我還想試試能不能讓這個看似普通的功能得到更大的擴充。
但我的確遇到一些困難...
不知道您對 jQuery 熟不熟,如果有這方面的問題可以請教你嗎?
您好,我從您的最新迴響得到很多 IDEA,也寫了一個屬於自己的最新迴響 widget,這幾天我想要發表出來,先給您通知ㄧ聲,希望您有空能看一看,順便給我ㄧ些意見。
我的 blog 有範例,porject 的 Homepagey 在 http://code.google.com/p/lvchen-recentcomments/
在此再對您說聲謝謝。
謝謝大大
已用您的方案
謝謝
大大,想請問妳一下,因為我本身不會任何網路語言,
但是又很想把樣板更換,http://www.fresheezy.com/請問這網站的樣板,該怎麼套用呢??能幫幫我嗎?
我跟32樓的大大有同樣的困擾>"<
我是用wordperss,然後想用fresheezy的樣板更換,可是下載下來以後不知道要怎麼弄到wordpress上
只是想問問看
如果水瓶子不方便也沒關係
先謝過囉
附上我的e-mail:
uperkids@hotmail.com
^^
感謝你的更新解決了我的問題!
無意間得知這個地方
感覺真棒,謝謝大大的研究
讓我這個對程式語言不懂的人
可以如願地加入訪客的回應
感謝^_^
給予迴響