Blog外挂之:热门文章与导航栏

By 刘未鹏

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

还是看图说话:-)

图一:导航栏

图二:热门文章

导航栏的实现很容易:往main和header之间塞入一个div,往div里面写入所有的分类链接即可。

分类的获取有几个办法,一是把分类链接也收藏到del.icio.us上,这样就可以用JSON协议获取到所有分类(见上篇文章——《Blog外挂之:妙用del.icio.us实现“站内相关文章”》)。二是直接获取侧边栏上的分类列表。dodo的blog上用的就是这个办法,但这个办法太脆弱,因为分类的那个ul没有id,所以用getElementById就行不通了。只能依赖于对那个ul的顺序的掌握,先getElementById(‘rightmenu’)获得rightmenu的引用,然后再对后者getElementsByTagName(‘ul’)获得其中所有的ul容器的数组,然后基于对页面代码的观察从这个数组中取出对应于分类菜单的ul。这个办法的问题在于如果我们不小心在公告栏加入了新的ul,或者能生成ul的js代码,就会破坏分类那个ul所在的序号。另一方面,把分类链接收藏到del.icio.us上是个较好的选择,但del.icio.us帐号的空间有限,目前你最多能获取100个post,还是别浪费在分类上的好。用另一个del.icio.us帐号的办法又会增加一个http请求。想想还是不要杀鸡用牛刀了。于是结果使用的是brute force,直接把分类链接及标题硬编码到代码中了:-)反正分类的修改也并不频繁。比如我的分类之前都快一年没改动了。

导航栏实现的主要代码如下:

function insertTopMenuDiv()

{

var topMenuDiv = document.createElement('div');

topMenuDiv.setAttribute('id', 'topMenu');

var main = document.getElementById('main');

main.parentNode.insertBefore(topMenuDiv, main);

return topMenuDiv;

}

function appendNavigatorBar()

{

var topMenuDiv = insertTopMenuDiv();

var categoryList = getCategoryList();

var html = '';

for(var i = 0; i < categoryList.length; ++i){

html += '<a href = "' + categoryList[i].url + '" class = "tab ';

if(GetThisURL() != categoryList[i].url)

html += 'tabUnselected">';

else

html += 'tabSelected">';

html += categoryList[i].title;

html += '</a>';

}

document.getElementById('topMenu').innerHTML = html;

}

getCategoryList你自己写。目的是获取分类列表。我用的是硬编码。

CSS调整

导航栏就这样插入到main和header之间是不行的,需要调整格式。往后台定制CSS栏加入代码调整其位置,我的是:

#topMenu {

position:absolute;

top: 78px;

padding-left: 20px;

}

#topMenu a:hover {

background: #0044BB none repeat scroll 0%;

color: #FFFFFF;

text-decoration: none;

}

.tabUnselected {

border-left:1px solid #CCCCCC;

border-right:1px solid #CCCCCC;

}

.tab {

margin:0em 0em 0em 0.25em;

padding:2px;

font-size: 12pt ;

}

.tabSelected {

border-left:1px solid #CCCCCC;

border-right:1px solid #CCCCCC;

}

最重要的就是topMenu的位置。我定的是离顶部78px。你自己用firebug调节吧。tabSelected和tabUnselected的CSS一样是因为原本的效果不能在IE和firefox下统一,只好暂时就这样了。Web设计达人自己调整就是了:-)俺是程序员,只能朴素一点,用左右两条线分隔了。

热门文章的实现也不算复杂。最关键的问题是如何获取相应文章的评论数。我原本想通过blog的rss文件获得,观察rss文件会发现里面包含了每篇文章的评论数。等等,我说了每篇文章吗?唉,其实只有聊聊十几篇而已,所以没法对整个blog上的所有文章进行排名了。不过rss可以用来实现最近更新。

图三:最近更新

Anyway,那如何获取评论数呢?我们知道每篇文章的URL(从del.icio.us上获得的),问题转化为如何从URL到评论数。CSDN blog对文章的评论数是动态加载的:

图四:加载中

图五:加载完毕

既然是动态加载的,那么必然有办法获取对应文章的评论数。偷窥一下页面代码:

图六:评论加载代码(一)

可见,每篇文章的postFoot处都有一个js调用,调用AddFeedbackCountStack将该文章的一个ID添加一下,这个ID其实就是文章URL的最后一部分。从数字大小猜测它应该是服务器上的文章编号,1601519,也就是第一百多万篇文章。随便找篇03年的文章,你会发现那时候CSDN blog系统上只有一万多篇文章。

为了节省HTTP请求,CSDN blog的页面加载过程中并非每遇到一个“评论数(…)”框都发起一次http调用获取相应文章的评论数,而是用刚才你看到的AddFeedbackCountStack先将该文章的ID保存起来,等到最后一并获取所有的评论数:

图七:评论加载代码(二)

LoadFeedbackCount做了两件事情:先使用一路保存下来的文章ID列表来获取一个评论数列表。然后将评论数一一填充到相应的“评论数(…)”框中。如果一篇文章的ID为1234那么其评论数框的span id就是FeedbackCount_1234。见图六。

AddFeedbackCountStack和LoadFeedbackCount的代码在LoadFeedbackCount.js中。自己看它是怎么发起http请求获取评论数的吧。

最后需要注意的一点是,无论ID列表里面文章的顺序如何,返回的评论数列表总是对应于ID从大到小来排列的。也就是说如果你给出的ID列表为“ID2,ID 1 ” ,假定ID2 < ID1,即第二篇文章发得较早,那么返回的评论数仍然还是feedbackCountForID1,feedbackCountForID2。所以如果del.icio.us上的文章收藏并非按从早到晚严格顺序排的,那得先sort一下,然后建立ID列表。

知道了如何获取评论数就好办了,有了URL列表,有了相应的评论数。排名那就太简单了。

最热门文章排行的主要代码如下:

var getFeedbackCountReq;

var myBlogPosts = [];

var hotPostsContainer;

function showHotPosts(ct)

{

hotPostsContainer = ct;

for(i = 0; i < Delicious.posts.length; ++i){

myBlogPosts.push(

{url:Delicious.posts[i].u,

id:urlToId(Delicious.posts[i].u),

title:Delicious.posts[i].d, feedbackCount:0}

);

}

myBlogPosts.sort(compareById);

var idList = '';

for(i = 0; i < myBlogPosts.length; ++i){

idList += myBlogPosts[i].id + ',';

}

getFeedbackCountReq = HTTP.newRequest();

getFeedbackCountReq.onreadystatechange =

handleGetFeedbackCountReq;

getFeedbackCountReq.open('GET',

'/NewCount.aspx?FeedbackCountStack=' + idList);

getFeedbackCountReq.send(null);

}

function handleGetFeedbackCountReq()

{

if(getFeedbackCountReq.readyState==4){

if(getFeedbackCountReq.status==200){

handleGetFeedbackCountReq2(

getFeedbackCountReq.responseText);

}

}

}

function handleGetFeedbackCountReq2(feedbackStr)

{

var feedbackList = feedbackStr.split(',');

var i;

for(i = 0; i < myBlogPosts.length; ++i){

myBlogPosts[i].feedbackCount = feedbackList[i];

}

myBlogPosts.sort(compareByFeedbackCount);

var title = document.createElement('h3');

title.appendChild(document.createTextNode('本blog评论最多文章'));

hotPostsContainer.appendChild(title);

var NGList =

['http://blog.csdn.net/pongba/archive/ 2004/08/26 /84978.aspx',

'http://blog.csdn.net/pongba/archive/ 2004/11/26 /195052.aspx',

'http://blog.csdn.net/pongba/archive/ 2004/11/26 /195075.aspx'];

var maxNumHotPosts = 12 + NGList.length;

if(myBlogPosts.length < maxNumHotPosts)

maxNumHotPosts = myBlogPosts.length;

var ul = document.createElement('ul');

ul.setAttribute('id', 'my_hot_posts');

for(i = 0; i < maxNumHotPosts; ++i){

if(IsIn(myBlogPosts[i].url, NGList))continue;

var li = document.createElement('li');

var a = document.createElement('a');

a.setAttribute('href', myBlogPosts[i].url);

a.appendChild(document.createTextNode(myBlogPosts[i].title

+ '(' + myBlogPosts[i].feedbackCount + ')'));

li.appendChild(a);

ul.appendChild(li);

}

hotPostsContainer.appendChild(ul);

}

function compareByFeedbackCount(post1, post2)

{

return post2.feedbackCount - post1.feedbackCount;

}

function compareById(post1, post2){

return post2.id - post1.id;

}

其中NGList是排除在外的文章列表。如果你blog上也有一些你觉得价值不大的口水文章也可以排除一下:-)

Further Work

按评论数排行是最平凡的热门文章排行方式。揉合进点击率,tag等信息会是一个不错的选择。但似乎点击率没法获取,tag信息倒是有,但目前也没想到较好的利用办法。Tag越小文章越特殊是一个观察,但未必特殊的文章就一定重要。所以如果要加入文章的重要性,还不如直接利用del.icio.us手动收藏重要性文章。

转载于:https://my.oschina.net/abcijkxyz/blog/720602

Blog外挂之:热门文章与导航栏相关推荐

  1. Blog外挂之:文章置顶

    Blog外挂之:文章置顶 By 刘未鹏(pongba) C++的罗浮宫(http://blog.csdn.net/pongba) 许多朋友想要文章置顶的功能.比如博客园的这个样子: 图片截自爆牙齿的b ...

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

    Blog外挂之:妙用del.icio.us实现"站内相关文章" By 刘未鹏(pongba) C++的罗浮宫(http://blog.csdn.net/pongba) 先说明一下, ...

  3. Android ActionBar完全解析,使用官方推荐的最佳导航栏(下) .

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/25466665 本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工 ...

  4. React Native 的顶部导航栏和底部导航栏目

    说来也是惭愧,本来关于底部导航栏,我已经写过一篇博客,只不过那篇更偏向于入门一些,当时一实现功能之后就迫不及待的分享给大家了.地址在这儿:http://blog.csdn.net/LJFPHP/art ...

  5. Android ActionBar完全解析,使用官方推荐的最佳导航栏(下)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/25466665 本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工 ...

  6. 移动端也能兼容的web页面制作2:导航栏、背景图片设置

    [ 导读 ] MDBootstrap 是基于 Vue.js 开发的一套前端框架,拥有美观大气的界面效果,友好的交互体验,更棒的是对于移动端也有很好的兼容性.先给大家看下演示 demo 的运行,后面将围 ...

  7. 使用Bootstrap制作导航栏

    废话不多说,直接上代码. <body ><!--若采用浮动,则需要加style="padding-top: 60px;"--><nav class=& ...

  8. 用js实现导航栏shoufang效果_【读者投稿】用Github+docsify,我花了半天就搭好了个人博客...

    前言 "作为一个真正的码农,不能没有自己的个人博客",这是我说的.惭愧的是,入行两年多了都没搞起来,这让我一度怀疑自己是个假程序员.昨天终于克服了心里的"犹豫" ...

  9. 红橙Darren视频笔记 builder设计模式 navigationbar 导航栏第二版

    1.builder设计模式简介 builder的实际应用的典型案例有AlertDialog和OKHttp 例如 // AlertDialogAlertDialog alertDialog = new ...

最新文章

  1. 判断人工智能是否可信的“四把尺子”
  2. ajax入门实例代码,AJAX、AJAX实例及AJAX源代码
  3. 使用TensorRT和Jetson TX1 / TX2部署深度学习推理网络和深度视觉原语的指南 学习五
  4. ThinkPHP验证码类
  5. 浅谈format格式化输出
  6. Docker 容器从入门到Devops实践
  7. CNN: TensorFlow 1.14.0 更新
  8. 【网络配置】双网卡访问
  9. 关于NOR FLASH地址左右移的问题
  10. 基于Java+SpringBoot+vue+element实现家具购物销售网站详细设计和实现
  11. 小程序开发配置接口域名提示:不在以下 request 合法域名列表中,请参考文档
  12. mysql最小费用最大流问题_最小费用最大流问题
  13. mysql 设置 0、1 用什么数据类型_什么是MySQL数据库?看这一篇干货文章就够了!...
  14. iperf 安卓 灌包命令_iperf工具测速
  15. android铃声总结
  16. 句法结构分析:基于PCFG的基本分析方法
  17. 驾驶员理论考试系统的设计与实现(论文+源码)_kaic
  18. Excel如何对合并单元格数据进行排序
  19. 路由器使用Caddy搭建Webdav服务
  20. 【巨人的肩膀上制造世界】——1——Unity3D实用插件之地形插件Gaia,高质高效搭建你的地形,全中文教程!

热门文章

  1. 机械设计基础知识点总结
  2. html下拉框里怎么打出间距,CSS下拉菜单间距
  3. ALBRECHT密钻夹头SK30 2-14mm A92
  4. mysql创建供应商标_mysql 建数据库
  5. Qt实现中国象棋:(四)棋子绘制的实现
  6. 视频教程-SAP ABAP 开发入门-其他
  7. Zulip 2.0.0 发布,功能强大的群组聊天软件
  8. Artisteer 3.1
  9. 算法设计与分析 实验五 算法综合实验
  10. php学习笔记——学习路线图记录