刘未鹏|C++的罗浮宫

Knowledge sharing is the best reuse

刘未鹏ID:pongba
[修改头像]
703862次访问,排名42好友7人,关注者62
pongba的文章
原创 99 篇
翻译 8 篇
转载 0 篇
评论 1509 篇
刘未鹏的公告
除非特别声明,本站采用Creative Commons License许可。转载请注明作者、出处,非商业。

喜欢这个Blog的风格?见这里这里,还有这里

我的豆瓣饭否

讨论问题请到TopLanguage小组

TopLanguage

gtalk/msn(邮件请发送到gmail邮箱)

pongba@gmail.com
pp_liu@msn.com

订阅C++的罗浮宫

  • FeedSky
  • 订阅到鲜果
  • 订阅到Google
  • 订阅到抓虾
  • 订阅到BlogLines
  • XML聚合

搜索C++的罗浮宫上的内容

最新发表

    whaz going on


    饭否

    books I've translated




    最近评论
    李彬:我大一本科,也是所谓的“信息与计算科学”专业的,现在拼命学习C++,学些高代 分析之类的课,其他课实在没兴趣,我接触电脑业比较早了,前辈们的经验一定会让我少走弯路的
    pongba:@julie:
    sorry, 不知道啊:-)
    Kenny:“肯德基和麦当劳的食物中的热量早就超过了人体所需,但我们的身体系统还是照样笑纳”

    对这个,我有点话要讲:肯德基和麦当劳套餐一直比中餐馆的食物更健康——当然,这个是从统计意义上来讲的,如果有个MM进中餐馆后一直点素炒苦瓜加一碗米饭那就别说了

    我觉得你这句话写得有失水准,平时看BLOG感觉你满有深度的,但这一句可能是人云亦云得太多了吧?
    julie:请问:Viking Adult出版社在哪个城市?

    我在豆瓣上看到你读过斯蒂芬平克的思想的材料

    pongba:@bigfatsea:
    Ma和Mb只需要两相比较便至少可以扔掉一个,所以不存在复杂度问题。
    另,你的方法,包括上面列的方法,本质上都是一样的。用的都是一个关键性质。所以..
    关键是不同的思路,引领到同样的答案。
    文章分类
    收藏
    相册
    其它图片
    文章中的图片
    我的大头贴
    C++
    Andrei Alexandrescu
    Andrew Lumsdaine
    Bjarne Stroustrup
    boost
    C++ Standard Commitee
    Doug Gregor
    Hans J. Boehm
    Jaakko Jarvi
    Jeremy G. Siek
    Matthew Wilson
    newsgroups
    boost.Developer
    boost.User
    comp.lang.c++.moderated
    comp.std.c++
    TopLanguage
    Open Source
    codeplex
    Google AJAX Search API
    Google Code Prettify
    Google Web Toolkit
    MS shared source initiative
    notepad++
    STLSoft
    不认识的朋友们
    fatalerror99
    Yelz
    余晟|乱象&乱想
    刘慈欣
    姬十三
    张志强|阅微堂
    许式伟
    阮一峰
    鲍志云
    其它
    科学松鼠会
    科学美国人
    科幻世界
    认识的朋友们
    chenyufei
    duguguiyu|Venus神庙
    Joyfire
    littlestone
    lxwde
    Matrix67
    soloist
    云风
    刘江@图灵
    史晓明
    周星星
    周筠@博文视点
    孟岩
    张振
    徐宥|4G Spaces&Web 2.3
    方舟@博文视点
    李笑来|Pure Pleasure
    杨文博
    王信文|地球没有好朋友
    荣耀
    莫华枫
    袁泳(g9)|负暄琐话
    谢东升
    陈冀康@华章
    存档
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

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

    新一篇: 关于刘慈欣的若干个标题

    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的内容进行关联挖掘,投放最可能对你有用的广告,这甚至已经不能算是一种广告,简直是双赢了。而且文字广告不那么扎眼,较之图片广告看起来要舒服很多;这也是我抛弃hotmailyahoo 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.usblog加上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只能获取一个urldel.icio.us全站上的tags,而且还是top tags,如果你的文章被别人save得不多,那么就算你给它加了十个tag,最后返回的tag集合也有可能是空的,因为它返回的是top tags。我不知道del.icio.us是怎么计算top tags的,可能有一个最少被save数目加一个百分比,但无论如何,这个办法是没法获取到你给你的一篇文章加上的所有tags的。没法获取其所有tags,便没法很好地获取与其相关的文章了。

     

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

     

    一拍脑袋方才想起del.icio.usposts 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是你的“本站相关文章”框的大小限制)。

     

    亲缘关系的判定则要麻烦一些。如果不依赖于用户指定第一个tagtag的话,又该如何判定一个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那个divrightmenu那个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:-) 不过你可别像上面给出的代码那样直接写innerHTMLdon’t be evil:-) 把人家广告覆盖掉了也不够厚道是不是?人家对你厚道你总得投桃报李吧:P

     

    总结

    我们借助del.icio.us的社会化书签功能和开放JSON接口实现了一个非常酷非常有用的“本站相关文章”系统,这个系统可以移植到任何支持插入javascript代码的