QQ阅读模板分析

Categories: QQ阅读
Tags: No Tags
Comments: Comments Off
Published on: 2011 年 07 月 05 日

模板的定义

QQ 阅读预先定义了一些模板,有哪些模板可以在下面数组中可见:
其中 tmp后面的第一个数据标识这个模板分几块,第二个数字标识这是分几块模板的第几套模板

这个模板在下面文件的  15004 行可见
http://rescdn.qqmail.com/rss/zh_CN/htmledition/js/reader/reader069eec.js

var 
adw=
{
1:['tmp1_1'],
2:['tmp2_1'],
3:['tmp3_1'],
4:['tmp4_1','tmp4_2','tmp4_3'],
5:['tmp5_1','tmp5_2','tmp5_3','tmp5_4','tmp5_5','tmp5_6'],
6:['tmp6_1'],
7:['tmp7_1']
}, 

这个js的文件加载比较特殊,在QQ阅读的页面

http://reader.qq.com/cgi-bin/rss_index?t=r_index&source=login&r=9c8508017c08456f036657e3e539#mag,10005/0/6 

是通过下面代码加载的:

<script>	
function loadJsFile(_aoFiles)
{
	var _oHead = document.getElementsByTagName("head")[0];
	for (var i=0, _len=_aoFiles.length; i<_len; i++)
	{
		var s = document.createElement("script");
		s.src = _aoFiles[i];
		s.charset = "GB18030";
		_oHead.appendChild(s);	
	}
}

if (top == self)
{
	loadJsFile([
		"/cgi-bin/rss_main?sid=MTOtOYx56MMzN9&t=reader_data.js&s=mag&r=388&init=true&update=1", 
		"http://rescdn.qqmail.com/rss/zh_CN/htmledition/js/reader/reader069eec.js"	
	]);
}
else
{
	//for webqq2
	document.write('<script src="/cgi-bin/rss_main?sid=MTOtOYx56MMzN9&t=reader_data.js&s=mag&r=464&init=true&update=1"></scr'+'ipt>');
	document.write('<script src="http://rescdn.qqmail.com/rss/zh_CN/htmledition/js/reader/reader069eec.js"></scr'+'ipt>');
}
</script>

每套模板的样式文件我们可以在对应的 qboard 开头的CSS中定义,不同宽度的屏幕是不同的css:

<script>
	gbISbigScreen = false;
	if(screen.width>1279&&screen.height>899){
		document.write('<link rel="stylesheet" type="text/css" href="http://rescdn.qqmail.com/rss/zh_CN/htmledition/style/reader/r_bigscreen02aad7.css" />');
		document.write('<link rel="stylesheet" type="text/css" href="http://rescdn.qqmail.com/rss/zh_CN/htmledition/style/reader/qboard_bigscreen02aad7.css" />');
		gbISbigScreen = true;
	}
	else
	{
		document.write('<link rel="stylesheet" type="text/css" href="http://rescdn.qqmail.com/rss/zh_CN/htmledition/style/reader/qboard02aad7.css" />');
	}
	if (top != self) {document.write('<link rel="stylesheet" type="text/css" href="http://rescdn.qqmail.com/rss/zh_CN/htmledition/style/reader/r_webqq02aad7.css" />')} 
</script>

以模板3_1 为例,,它的样式如下: tmp3 这里的三标识他内部有三个区块, box0,box1,box2 分别就是这三个区块:

每个区块都可能有 图(articleimg )也可能有内容(singlecontent )。

/* 模板3_1 b */
.tmp3_1 .box0 {width:600px; border-right:1px solid #D9D9D9; height:535px; overflow:hidden; float:left;}
.tmp3_1 .box0 .singlecontent {margin:0 10px 0 0; height:530px; overflow:hidden;}
.tmp3_1 .box0 .articleimg {width:590px; height:330px; overflow:hidden;}
.tmp3_1 .box0 .articleimg img {width:590px}

.tmp3_1 .box1 {width:469px; height:265px; border-bottom:1px solid #D9D9D9; overflow:hidden;  float:left;}
.tmp3_1 .box1 .singlecontent {margin:0 0 10px 10px; height:235px; overflow:hidden;}
.tmp3_1 .box1 .articleimg {width:250px; height:180px; overflow:hidden; margin-right:10px; float:left;}
.tmp3_1 .box1 .articleimg img {width:250px}

.tmp3_1 .box2 {width:469px; height:269px; overflow:hidden;  float:left;}
.tmp3_1 .box2 .singlecontent {margin:10px 0 0 10px;  height:235px; overflow:hidden;}
.tmp3_1 .box2 .articleimg {width:250px; height:180px; overflow:hidden; margin-right:10px; float:left;}
.tmp3_1 .box2 .articleimg img {width:250px}

获取数据

image

这个入口页的数据是通过下面的网址获得的。它返回的是一个 json 数据

http://reader.qq.com/cgi-bin/rss_main?sid=MTOtOYwpx56MMzN9&t=reader_data.js&s=mag&r=222&init=true&update=1

 

image

这个页面的数据是通过下面网址获得的数据,返回的数据也是 json 格式的,注意这里一次性取了30篇文章的摘要等列表信息。

30篇文章最终会被分成7页

这些数据中包含文章的标题、摘要,包含的图片(数量地址尺寸等), 视频,音乐,评论分享等。

http://reader.qq.com/cgi-bin/rss_list?r=13098493385&pagetype=mag&page=0&perpage=30&mode=digest&cache=save&id=10005&sid=MTOtOYwpxMMzN9&t=reader_data.js&s=art&resp_charset=UTF8

image

最终内容页,是通过下面网址获得的数据,注意,这里一次性获得了30篇文章。

http://reader.qq.com/cgi-bin/rss_list?r=13098433171&pagetype=mag&page=0&perpage=30&mode=detail&cache=load&id=10005&sid=MTOOYwpx56MMzN9&t=reader_data.js&s=art&resp_charset=UTF8

模板匹配算法

前面提到, 从服务器端下载30篇文章的信息, 然后分成7页。

那么第一页一共几篇文章,第二页一共几篇文章是如何算的呢?

 

  • 先假设我们取的数据可以分7页。混淆后代码的 bac 这个变量记录这个信息
  • 我们开始遍历下载下来的文章(应该是在30篇以内的,含30).我们根据一定算法计算累计文章的权重,一旦权重合计超过270,就分页。这样,我们就可以知道每一页应该放几篇文章,分别是哪几篇文章。这个算法的代码如下:代码我增加了一下注释,标明权重的算法。
while(gF<aQ&&gV<bac)
{
   var bsV=Number(ve[gF].split("_").join("").substring(ve[gF].length-5),10);
   var dF=aOO[gF];

   if(dF.unread==1)
   {
      alS=true;
   }

   var aKc=0;
   if(dF.images&&dF.images.width>qg)
   {
     // 有图片,且图片宽度大于 150, 则权重加50
     // qg 是常量, 150 ,在外部定义
     bYg=true;
     aKc+=50;
   }
   else
   {
      // 没有图,权重 20
      aKc+=20;
   }
   RR+=aKc;

   // 标题,正文最大长度
   var aex=Math.max(
      dF.title.length+dF.content.length,
      dF.root?(dF.root.title.length+dF.root.content.length):0,
      dF.webpage?(dF.webpage.title.length+dF.webpage.content.length):0
   );

   var aPl;
   if(aex>1000)
   {
      // 如果总内容长度超过 1000 ,权重 加 30 
      aPl=30;
   }
   else
   {
      // 如果总内容长度没有超过 1000, 权重加 10
      aPl=10;
   }
   RR+=aPl;

   gV=gF+1-Np;

   var bGl=adw[gV].length;

   // 初始权重
   !aby[gV]&&(aby[gV]=0);
   var bkx=(bGl-aby[gV])*70;
   RR+=bkx;

   // 从 文章编号字符串中提取的数字,限定40以内 加在权重上
   // 编号的最后下划线部分
   bsV%=40;
   RR+=bsV;



   gF++;

   // 累计权重超过 270, 需要分页
   if(RR>270)
        break;

   // 初始权重只应该被加一次
   RR-=bkx;
}
  • 我们把分页逻辑存入 OV 这个混淆过的变量中。后面的显示,以及实际是分了几页,都是基于这个对象。
  • 一页显示几篇文章,就限定了该页可用的模板数。然后我们根据一个简单的算法,就可以算出该用哪个模板。如下代码:
// 我们使用服务器端返回的文章编号的最后三位数字跟这个区块的模板数的模来确定我们要用的模板
acm=OV[i].articles[0].split("_").join("");
EZ=adw[eQ][Number(acm.substring(acm.length-3),10)%adw[eQ].length];

参考文章:

flipboard简单分析

http://weiye.info/blog/2010/09/flipboard-implement-research/

Comments are closed.

Welcome , today is 星期四, 2017 年 03 月 30 日