您的位置:首页 > 其它

Blog外挂之:妙用del.icio.us实现“站内相关文章”

2007-04-26 17:36 561 查看
Blog外挂之:妙用del.icio.us实现站内相关文章

By 刘未鹏(pongba)
C++的罗浮宫(http://blog.csdn.net/pongba)

先说明一下,其实这个方法是跟Blog无关的,只要支持插入javascript代码的blog都可以使用。

废话少说,翠花,上图片先:

图片截取自:月光博客




图片截取自:ThinkingParallel









是不是很眼馋这些功能?站内相关文章文章排行文章评价文章相关tags,以及全局tags

所有这些功能的最大好处不是漂亮,而是实用。其实用之处在于能够增加blog的粘着度。一般来说如果是一个简陋的blog,如果别人从一个文章链接跳到你的blog上看了一篇文章,那么很可能看完就走了,但如果能在文章的正下方跟着显示相关文章的话,粘着度就会得到大大的提高。相关文章其实就是简单的关联挖掘,而后者是所有网上营销类网站的最大法宝之一(有人见过不用“读(买)过…的人也读(买)过…”的网上书店吗?)。

可惜的是,除了很少一些独立blog具有这个功能之外,国内外的博客系统目前基本都没有这个功能,似乎就连最好的免费blog系统wordpress也还没有增加这个功能。

CSDN blog 06年的时候还有过一阵子的“相关文章”栏的,如图:



可后来广告栏上去了,相关文章栏消失了。不过CSDN blog的广告栏还算是做得蛮有心的,首先不像live space的广告栏那样不尊重用户,弄一个花花绿绿还闪啊闪的Flash大摇大摆的放在blog主页的正上方,跟人家把脑白金广告贴到你家门匾上一样,丑就不说了,太影响阅读情绪。Donews曾经仿效了一次,结果被群起而讨伐之,只好又灰溜溜改回去。其实BSP运营不容易大家也都有数,像新浪blog这样的毕竟在少数。所以放点广告大家也能理解,但所谓盗亦有道,放广告也要讲技巧。我最欣赏的就是Gmail的广告投放,根据email的内容进行关联挖掘,投放最可能对你有用的广告,这甚至已经不能算是一种广告,简直是双赢了。而且文字广告不那么扎眼,较之图片广告看起来要舒服很多;这也是我抛弃hotmail和yahoo mail的原因。CSDN blog的广告栏总算比较人道,不乱投垃圾,不乱放图片,也用上了关联挖掘;但之所以提这个广告栏,最重要的一点还是它很有用,待会你就会知道。

再来说06年还在的那个“相关文章”栏,我不大清楚CSDN为何把这个栏目撤掉,这是个能增加blog粘着度的功能。但最重要的一点是,原先CSDN blog上的“相关文章”栏的“相关”是指全站的相关文章。而不是你自己blog上的相关文章。这就让人很不爽,并不是说全站相关不好,只是应该再增加一个“本站相关文章”才是。

那是不是就没办法了?老大们都是程序员吧,程序员会干嘛?不,不是指泡MM,是编码。所以现在不管怎样,我们还是需要自己实现一个“站内相关文章”功能出来。

我对web开发基本可以说是七窍通了六窍,以前没写过一行Javascript代码,没写过一个网页。大一的时候玩过一阵子flash,早已全还掉了。但web盲归web盲,要实现这个功能,大致思路还是可以想出来的。

CSDN blog不知道有没有开放获取文章tag以及根据tag获取文章的JSON接口,就算开放了也要精确到个人blog才行,就算精确到了个人blog也还有修改tag不方便等问题。所以不管怎样,依赖CSDN blog开放接口是不大可能了。

上次写到如何用del.icio.us给blog加上tags,那个比较简单,只要用del.icio.us现成的tagrolls功能即可。这次仍然还是用del.icio.us的功能,不过这次del.icio.us没有提供现成的功能,要自己根据它开放的JSON接口来实现。

实现耗了一些时间,没办法,谁叫俺不是web开发出身呢?只好乖乖拉出犀牛书,架上google,“边搜索边编程”:)

“本站相关文章”1.0
忙活了几个小时,总算搞定了一个1.0版,顺便也了解了一下JSONdel.icio.us的开发接口,还学了不少javascript。总算也有点了解为什么有那么多人鼓吹动态语言了——上手很快,很直观灵活。另外感觉反射特性(reflection)对web开发实在是很重要。

1.0版实现的效果如下





为什么这个“本站相关文章”会出现在“特别推荐”的上面,等会解释。先来说说这个实现的问题。

我假设你已经像上篇里面说的,将你blog上的所有文章链接导入到一个专门的del.icio.us帐号上了,比如我的。这样一来这个del.icio.us帐号便存储了你的blog上所有文章及其所属tags的信息,这些信息已经足够用了,关键是怎么提取出来。

在最初实现这个功能的时候,本想用URL feed来获取当前url(document.URL)的相关信息,然后从其中抽取出相关的tags,然后再使用posts feed来获取与这些tag相关的posts,便大功告成。

谁知道算盘打得响当当的,实现起来就处处问题了,首先的问题就是URL feed只能获取一个url在del.icio.us全站上的tags,而且还是top tags,如果你的文章被别人save得不多,那么就算你给它加了十个tag,最后返回的tag集合也有可能是空的,因为它返回的是top tags。我不知道del.icio.us是怎么计算top tags的,可能有一个最少被save数目加一个百分比,但无论如何,这个办法是没法获取到你给你的一篇文章加上的所有tags的。没法获取其所有tags,便没法很好地获取与其相关的文章了。

硬着头皮试了一下,能获取到的tags极少,而且还可能是人家标的,不是你自己标的。只好放弃,另辟他径。

一拍脑袋方才想起,del.icio.us的posts feed是能够获取所有posts的详细信息的,获取到的是一个数组,其中每个元素都是一个posts的相关信息集合,后者包括它的链接标题注释tags。这下问题不就结了?只要遍历一下这个数组,把当前文章url往里面一个个的比,直到找到代表当前文章的那个JSON对象,提取其中的tags。然后用这些tags再往里面作一次相关搜索,搜索出相关的JSON对象,提取出他们的标题和链接,done!

目前的版本(2.0+)采用的也正是这个办法。

改进
现在的问题是“相关搜索”如何做。我们知道,一篇文章可能有多个tags,那么怎么判定另一篇文章是和它相关的呢?一个最简单的办法是取该文章的第一个tag(这依赖于你在导入文章链接的时候将其第一个tag设为tag),然后找出所有包含该tag的其它文章。这个办法是可行的,也是上面展示的1.0版采用的办法。

但这个办法有一个大问题,就是它依赖于你对任意一篇文章所设的第一个tag必须是最能反映这篇文章内容的tag,不够自动化,我们平常给文章设tags的时候一般都是松散的,哪考虑那么多,结果为此就要去del.icio.us上调整tag顺序,很麻烦。此外的一个问题是,和该文章亲缘关系较远的文章就显示不出来了。比如一篇boost源码剖析,它既属于boost又属于GP,还属于C++。那如果选”boost”为它的tag,那么就只能显示含”boost” tag的文章了,如果这些文章较少,只有聊聊几篇,而这时你想退而求其次显示一些GP的怎么办呢?

另一个问题是1.0版的选择相关文章的算法是从头到尾遍历的,而你选出来的相关文章数目又必须设一个上限,否则遇到大类的时候就会拉出长长一串来,不好看,噪音也太大。这就导致一些比较久远的文章可能总是不会被选到,你可能不希望看到这种情况,因为文章年代久远并不一定代表它就不好看了:-) 这个问题易于解决,只要引入一个随机选择过程即可——先找出所有相关的文章,然后随机选取maxSize个(maxSize是你的“本站相关文章”框的大小限制)。

亲缘关系的判定则要麻烦一些。如果不依赖于用户指定第一个tag为tag的话,又该如何判定一个tag跟当前文章的主题亲缘关系有多紧密呢?

理想的设想应该是这样的,对于一篇特定的文章,我们想首先找出最能反映它的主题的tag,然后找出所有包含该tag的所有其它文章,显示出来。如果这时候还没达到maxSize个,我们就选一个tag,接着显示,以此类推…

那么,如何判定一个tag与特定文章的“相关性”便成了最大的问题。以上的问题就是2.0要解决的问题了。

“本站相关文章”2.0
2.0判断tag相关性依赖于一个简单的观察:即在与一个文章有关的多个tag中,那些总体被使用最少的tag一般就是最specific的,次少的则是次specific的,以此类推。这是因为我们平常对一篇文章分类的时候一般是树状的,越往树顶去的tag越大,同时也越。而越往枝叶部分去的tag越小,也越specific。所以,如果将一篇文章的所有tags按从小到大排序,那么遍历过去就基本相当于在tag-tree上从叶节点往根节点移动的过程。

基于这个想法修改了一些代码。效果不错,如下

这是一篇《读古龙的岁月》系列文章的相关文章列表:



注意,显示在最上面的是关联最紧密的tag和文章,然后亲缘关系逐步疏远。直到满12篇(我设的上限(maxSize)是12)为止。此外,我把通过同一个tag找到的相关文章分了组,并在前面加上了该组的tag,这样使得结构更分明,信噪比也更大一些

一个要注意的小问题是要避免不同组之间显示的文章的重复。

“本站相关文章”2.1
“本站相关文章”2.1主要添加了一个小功能,就是显示“本文相关tags”,如图:



此外2.1的另一个小修正就是当别人从一个comments链接打开一篇文章的时候能够正确处理。因为这时document.URL并不是你收藏的那个URL,而是后面加上了”#comments”,于是你就得把这个尾巴去掉才行。

为什么链接放在“特别推荐”广告栏的上方
简单的答案是“找不到其它合适的地方好放”。如果你查看一下你的CSDN blog的页面源代码,你会发现有”id”属性的div不是很多。其实最理想的地方是紧跟在你发表的文章的结尾另起一行,但因为发表文章的div块没有id,而通过编号来定位的方法又过于fragile,所以只好退而求其次。

广告栏的div是有id的,名为”csdn_zhaig_ad_yahoo”,之所以有id是因为CSDN本身也要用javascript往这个div里面写内容,所以不妨“复用”一下这个div,把我们的内容也写到里面。幸运的是,这个div的位置刚刚好在文章的正下方。呵呵,希望CSDN不会修改广告栏div的位置,否则只好往comments那个div里面写了:-)

其实不写在这个div里面也可以,你可以写到侧边栏上,不过这在用户行为学上不是最佳的,别人看你文章的时候可能只会一路往下扫着看,一般不会去注意侧边栏的。

CSDN Blogjavascript代码
在写javascript代码的时候也顺便看了一下CSDN Blog本身是如何填充那个广告div的,结果吓了一跳:

document.getElementById("csdn_zhaig_ad_yahoo").innerHTML=outhtml;

幸好main那个div比rightmenu那个div加载得早,而我们的javascript代码放在rightmenu里面。这要是反过来,我们辛辛苦苦写的内容就得生生给覆盖掉了。

其实直接修改innerHTML的这种方式并不是最佳的写页面方式(也不是最厚道的:P。再看看这个:

document.write('<script language = "JavaScript1.1" src='+str+"><//script>");

汗,好大一个document.write。这是最不推荐使用的写方式了,而且还是直接写HTML代码…

俺虽然土,只接触web编程一下午,犀牛书基本从索引翻起,那也是知道应该用:

var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', calledURL);

ct. appendChild (script);

这种方式,不硬编码,不出现raw string,杀人不见血,实在是居家旅行,必备之良药…

应用到非CSDN Blog
其实这个方法是跟Blog无关的,只要支持插入javascript代码的blog都可以使用,当然,另一个前提是你得找到能够插入相关文章链接的div才行,比如CSDN Blog就比较厚道,刚好提供了一个广告div:-) 不过你可别像上面给出的代码那样直接写innerHTML,don’t be evil:-) 把人家广告覆盖掉了也不够厚道是不是?人家对你厚道你总得投桃报李吧:P

总结
我们借助del.icio.us的社会化书签功能和开放JSON接口实现了一个非常酷非常有用的“本站相关文章”系统,这个系统可以移植到任何支持插入javascript代码的blog,并且非常灵活,只依赖于del.icio.us。其唯一的弱点是当前del.icio.us的posts feed目前只支持最多获取100个post。如果哪位老大blog上的文章实在太多的话,有两个权宜之计,一是“精选”一下你的好文章收藏到del.icio.us上,如果“精选”之后精品实在还是太多的话,呵呵,那就只好再申请一个del.icio.us帐号,获取两个帐号内的posts然后合起来了。什么?还是不够?你新闻blog啊,靠。

用到的工具
犀牛书第五版(都做完了才知道第五版已经出了,汗)
Firebug,做web开发的不知道firebug就好比做C++的不知道gcc,做java的不晓得Eclipse,做.NET的不清楚Visual Studio,做程序员的不知道吃饭…
Komodo,新兴的web开发全能型IDE,正如巨蜥一般酷(国外的程序员社群似乎有动物情节,python, camel,整个一动物庄园。O’Reilly出书更是如此,不知道的还以为是动物饲养指南)。此外Komodo还带了javascript调试插件,跟firefox结合,非常酷。

Further Work
没办法,paper看多了的结果,总要画蛇添足来一个Further Work:-) 发挥你的想像力吧,比如:

如何添加文章评价(rating)系统。
如何添加“收藏到del.icio.us”。

如何添加“文章排行”。






代码
干嘛?不会自己到页面里面刮啊?提醒一下,用firebug。在侧边(公告)栏的一开始。一共三个javascript项目。前两个是通过JSON来获取del.icio.us上的post集合和tag集合的,最后一个里面就是实现代码了,约300行(别担心速度问题,就一点文本而已,除非你上不了国外网站而且还假定任何浏览你blog的人也上不了),文章里就不直接帖了。用到你自己的blog上需要改三个地方:

<script type="text/javascript" src="http://del.icio.us/feeds/json/pongbablog?count=100"></script>

<script type="text/javascript" src="http://del.icio.us/feeds/json/tags/pongbablog?count=100&sort=count"></script>

把两处pongbablog改成你自己在del.icio.us上的帐号名。

此外代码中还有两处地方用到了’http://del.icio.us/pongbablog/’这个字符串,相应改之。(好吧好吧,我DRY了,不过只有两处,就懒得提取出来了:))

/*
get available div to use
*/
function GetAvailDiv()
{
return document.getElementById('csdn_zhaig_ad_yahoo');
}

把这个函数改成你自己的,获取可放东西的容器的函数。CSDN bloggers就不用改了。

还不会?留下mail吧,CSDN blog没法上传文件。或留言让懂web开发的老大们帮你解决也行。


P.S google bookmarks原则上也可以用来实现同样的功能,但似乎它没有开放API。此外也可以考虑用CSDN tag自身内的数据,有兴趣的可以去挖一下CSDN blog嵌在页面内的javascript代码,看它们是怎么获取数据的。

P.S 可别小看了粘着度,更别小看了“相关文章”,前一阵子我用google-analytics观察了一下blog的访问统计,结合blog后台自带的访问统计,发现加上del.icio.us的tagrolls之后,通过右侧tagrolls访问的链接出现了不少。而且,普通blog系统的分类导航能力极弱,大家平时看blog都有感觉,像g9老大的《负暄琐话》这么好的blog,上面有大量过往的好文章,但因为好文章太多了,想找到自己要找的好文章就很难,从“文章分类”找太慢,因为这个分类极其粗糙,而且很难控制一篇文章所属分类(需要重新编辑文章)。上次我要找一篇关于javascript的文章就查了半天,痛苦。tag的细粒度分类刚好填补这个空缺。而“相关文章”则是一个微型的push系统。当你看到一篇好文章的时候自然会想要看看同一作者还写了哪些有关的好文章,这时候再好不过的就是相关文章们自动出现在你的眼皮子底下了。往往这时候,导航能力就显得很重要,一般我们都是在文章里面直接加相关link来手动实现,一来十分不方便(比如最近我试着组织了《boost源码剖析》《C++0x漫谈》两个系列,要想使其中每篇都链到系列目录,必须修改每篇已经发表的文章,非常痛苦。而有了tag和相关文章功能之后,不用自己动手,往del.icio.us上一放就搞定了,比如《读古龙的岁月》系列就是这样,你会发现:根本不用登录到blog后台,就可以完全实现相关文章的组织
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: