视频网站通用的播放原理比较简单:
打开页面首先load一个播放器,然后播放器根据
一定的条件向后台请求flv文件并播放。
youku网防止用户下载的几个措施
1 动态创建flv播放器,防止用查看源代码的方式分析其播放器。
2 flv文件分割,将一个较长的文件分割成每段大约为7分钟的几段,其地址不同,甚至有可能在不同的服务器上。
3 动态生成flv文件地址,并且地址有时间限制,过时失效。
这是我目前所知最为费尽心思的加密方式,这方面比tudou作的好。
典型的youku播放地址是这样的:
http://v.youku.com/v_show/id_XMTgzMTg1ODQ=.html
大体上这个页面应该是不存在的,youku应该有一个类似SessionFilter的东西对这些请求地址进行过滤并动态生成页面,当然由于效率原因可能对一些请求频率高的页面进行缓存,这都不在我们讨论范围之内,这里重点是,如果我们的猜想是正确的,youku必然是通过这个地址地址来决定播放的视频,我们应该能够看出 ‘id_XMTgzMTg1ODQ=’这一段应该是与这个视频的id相关的。也就是说,youku应该对每个视频有一个唯一的id,可以通过这个id来找到对应的视频。
不过地址中的这个id是加密的,在页面源文件中搜索:XMTgzMTg1ODQ=
可以找到:
var videoId = '4579646';
var videoId2= 'XMTgzMTg1ODQ=';
我们找到了加密前后的videoid。
我们前面说的播放器通用的播放原理的youku版就是:
1 输入地址
2 根据地址生成页面,load播放器,并且获得播放文件id
3 将id传给播放器,播放器根据视频id获取视频地址。我们前面说的youku视频已被分割,所以这里获取的应该是该视频对应的列表地址。
下面要做的工作是分析flv播放器如何根据id来找到视频的:
使用firebug分析页面,
有这样一个请求:
http://v.youku.com/player/getPlayList/VideoIDS/4579646/version/5/source/video/password/?ran=8639&n=3
这是典型的REST架构阿,其 response如下:
{"data":[{"tt":"0","ct":"c","cs":"2043|2053","logo":"http:\/\/vimg15.youku.com\/11270F1F4647B1CFAEC63F0051AE550CE7D610-8E8B-4C0D-58CB-D44E6653E344"
,"seed":9054,"tags":["\u5927\u72ec\u88c1\u8005","\u6b27\u7f8e\u7535\u5f71","\u5353\u522b\u6797"],"categories"
:"96","streamsizes":{"flv":"291427815"},"streamfileids":{"flv":"56*14*14*7*56*15*1*8*56*56*13*7*64*1
*50*15*57*54*14*64*15*16*56*56*54*1*46*16*54*54*7*16*54*64*56*14*8*61*40*9*7*56*13*40*14*61*64*15*40
*9*10*15*57*40*50*7*10*1*50*46*64*61*56*16*61*14*"},"videoid":"4579646","segs":{"flv":[{"no":"0","size"
:"12756561","seconds":"395"},{"no":"1","size":"12588606","seconds":"396"},{"no":"2","size":"12575477"
,"seconds":"395"},{"no":"3","size":"12589273","seconds":"395"},{"no":"4","size":"12426491","seconds"
:"395"},{"no":"5","size":"12543093","seconds":"395"},{"no":"6","size":"12419380","seconds":"395"},{"no"
:"7","size":"12642058","seconds":"395"},{"no":"8","size":"12560630","seconds":"395"},{"no":"9","size"
:"12754471","seconds":"396"},{"no":"10","size":"12345040","seconds":"395"},{"no":"11","size":"12642647"
,"seconds":"395"},{"no":"12","size":"12685996","seconds":"395"},{"no":"13","size":"12678854","seconds"
:"395"},{"no":"14","size":"12562234","seconds":"395"},{"no":"15","size":"12537914","seconds":"395"},
{"no":"16","size":"12685755","seconds":"395"},{"no":"17","size":"12371695","seconds":"396"},{"no":"18"
,"size":"11860130","seconds":"395"},{"no":"19","size":"13183528","seconds":"394"},{"no":"20","size":"11896514"
,"seconds":"394"},{"no":"21","size":"11055722","seconds":"394"},{"no":"22","size":"12370008","seconds"
:"393"},{"no":"23","size":"5036383","seconds":"171"}]},"fileid":"56*14*14*7*56*15*1*8*56*56*13*7*64*1
*50*15*57*54*14*64*15*16*56*56*54*1*46*16*54*54*7*16*54*64*56*14*8*61*40*9*7*56*13*40*14*61*64*15*40
*9*10*15*57*40*50*7*10*1*50*46*64*61*56*16*61*14*","username":"pk\u6b27\u7f8e\u7535\u5f71","userid":"5353045"
,"title":"\u5927\u72ec\u88c1\u8005","key1":"bd7ed169","key2":"2f67ce4b4901bd2f","seconds":"9271.00","streamtypes"
:["flv"]}],"user":{"id":0}}
这是个JSON对象,指明了播放列表的相关信息。
streamsizes 指明该视频总的大小。
segs对象指明了该视频被分成了22个视频段落,以及每个视频的长度和大小。
与视频地址相关的重要变量为seed,fileid,key1和key2。我们下面细说。
先说下一个请求
http://f.youku.com/player/getFlvPath/sid/122873056861916199103_00/st/flv/fileid/02270F180047B1CF952BFE0051AE557E5B0286-3704-26BF-3DF9-C7D1CAB60E62?K=b4cf663c8307abcb14f9fc6
点击这个链接,浏览器会返回给你一个flv文件,这就是我们需要的文件,那么这个请求地址是如何构造得到的呢?
你点击这个链接可能会提示页面不存在,这是youku的地址时效机制起作用--这个地址已经超时啦。