这些日子一直有人在问我要Magike的“相关文章”插件,大家也不理解为什么像“相关文章”用户体验这么好的东西,为什么我不放到程序中。实际上我要说的是,像blog这种个人站点如果消耗自己的资源来做相关文章实际上是得不偿失的。首先是消耗服务器资源,相关文章的匹配查询是很消耗资源的,无论你做什么样的优化都是如此。其次是准确度也有问题,如果你想让查询更加轻便那么准确度就会下降。
那么有没有比较好的解决方案呢?答案是肯定的。我们可以通过google提供的API来打造完全适合本站的文章关联服务,如果你熟悉google的API你会发现它提供了一个叫做Google Feed Ajax的API,这个API可以跨域地实现feed的调用。没错,它是跨域的,但是通常我们都说AJAX是无法跨域的,难道google有什么独门秘笈或者后门吗,其实google使用的并不是ajax技术。如果你用过jQuery,那么你肯定知道jquery里面有一个getScript的API,它在1.2.0的版本后增加了一个新特性"across domain",就是跨域。在1.2.0以前这个函数是无法实现跨域的,因为它使用的是ajax方法把js从本域中取出然后执行,而1.2.0以后它是通过在header里面把script节点动态增加进去实现跨域调用的,因为我们都知道,script标签是可以调用其它站点的js脚本的,而一旦你动态的修改了header里面的节点,浏览器就会自动去下载并执行这些资源(这是浏览器的特性决定的),这种跨域的实现颇有些hack的味道,但是的确非常可行,因为已知的浏览器都支持这种方式。
通过上面的解释,你大概可以知道google的跨域ajax实现方法,它把执行结果封装为一个js对象然后把这个url动态加载到我们浏览器的header里,我们浏览器会自己去下载这个对象,这样一次完整的异步请求就完成了。不过就算你不知道上面的东西也不要紧,因为google已经帮我们封装好了所有的应用,你所要做的就是去使用它们。
上面介绍的Google Ajax Feed API可以帮我们解决跨域调用的问题,算是为我们达到目的造了一座桥,但是我们还需要找一个地方来获取我们需要的内容(也就是相关文章)。我把目光锁定到了google blog search,原因很简单第一它够快,第二它的查询结果可以以rss feed的方式输出,这样我们就可以用Google Ajax Feed API取出查询的结果,然后将它动态地显示出来。好了,暂时收敛一下内心小小的激动,让我们来关注一下google blog search的查询字符串组成格式,这样我们就可以动态构造查询了。通过观察我们发现它的url构成是如下形式
+blogurl:www.joyqi.com&ie=utf-8&num=10&output=rss
其中xxx代表我们的查询字符串,而后面的则表示我们需要查询的网址。因此接下来我们要做的就是把xxx替换成我们需要查询的关键字,剩下的匹配工作就可以交给google了。那么如何获取我们当前文章的关键字呢,这就需要靠你的blog系统输出了,一般可以用tags代替。如果你使用的是Magike系统,那么你可以通过调用来获取当前页面的关键字。所以最后我们得到的代码就是
google.load("feeds", "1");
function initialize() {
keyword = "";
keyword = keyword.replace(",","+OR+");
keyword = encodeURI(keyword);
var feed = new google.feeds.Feed(
+ keyword + "+blogurl:www.joyqi.com&ie=utf-8&num=10&output=rss");
feed.load(function(result) {
if (!result.error) {
var container = document.getElementById("related-posts");
container.removeChild(document.getElementById("loading"));
num = 0;
for (var i = 0; i < result.feed.entries.length; i++)
{
var entry = result.feed.entries;
if(entry.link != "")
{
var li = document.createElement("li");
var a = document.createElement("a");
a.setAttribute("href",entry.link);
a.appendChild(document.createTextNode(entry.title));
li.appendChild(a);
container.appendChild(li);
num ++;
}
}
if(num == 0)
{
var li = document.createElement("li");
li.appendChild(document.createTextNode("No entries..."));
container.appendChild(li);
}
}
});
}
google.setOnLoadCallback(initialize);
google.load("feeds", "1");
function initialize() {
keyword = "";
keyword = keyword.replace(",","+OR+");
keyword = encodeURI(keyword);
var feed = new google.feeds.Feed(
"
+ keyword + "+blogurl:www.joyqi.com&ie=utf-8&num=10&output=rss");
feed.load(function(result) {
if (!result.error) {
var container = document.getElementById("related-posts");
container.removeChild(document.getElementById("loading"));
num = 0;
for (var i = 0; i < result.feed.entries.length; i++)
{
var entry = result.feed.entries;
if(entry.link != "")
{
var li = document.createElement("li");
var a = document.createElement("a");
a.setAttribute("href",entry.link);
a.appendChild(document.createTextNode(entry.title));
li.appendChild(a);
container.appendChild(li);
num ++;
}
}
if(num == 0)
{
var li = document.createElement("li");
li.appendChild(document.createTextNode("No entries..."));
container.appendChild(li);
}
}
});
}
google.setOnLoadCallback(initialize);没错,是google.cn提供的feed,因为通过对比我发现google.cn对中文blog的更新速度比较快,而且匹配也更加准确。注意,以上代码仅适用于我的页面,如果你想用到自己的blog上面还需要做一些修改。但是大体的思路就是这个样子,最后你千万别忘了在这段代码之前引用一下google API的js库,也就是
<SCRIPT src="type=text/javascript></SCRIPT>
其中key后面的是google提供的API KEY,你需要到它的网站申请,这个key只对申请的网站有效。