Youku 视频绝对地址获取的方法详解


Posted in PHP onJune 26, 2013

前一阵子为了研究 KnLiveCommentary 而进行了一系列的关于视频站点的研究。由于KnLiveCommentary需要能够获取充足的视频源进行测试,所以我们选取了 Youku(优酷)一个比较大的视频网站来进行测试。
其实开始研究解析绝对地址也是为了研究Youku 的自带播放器,顺便去除广告什么的。后来我们就把Youku 的播放器用 ASV6 (ActionScript Viewer 6)“反编译”了一下,达到了惊人的效果。

Youku的视频采取了加密+动态的获取方式,视频地址需要访问网站动态获取,而结果则还需经过解密等操作。

$base_url = 'http://v.youku.com/player/getPlayList/VideoIDS/'; //获取视频信息的地址 基地址
$_VIDEO_ID = $_GET['vid'];  //从GET里面把Video Id提取
if($_VIDEO_ID=='')
$_VIDEO_ID = 'XMjY0ODE1MDA0'; //我比较懒,测试的时 候就固定了一个
$ch = curl_init(); //开启cURL对象
curl_setopt($ch, CURLOPT_URL, $base_url . $_VIDEO_ID);  //获取这个视频的信息的地址
curl_setopt($ch, CURLOPT_HEADER, 1);  //要 HEADER
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_REFERER, 'http://v.youku.com/v_show/id_' . $_VIDEO_ID);   //给一个假的"REFERER"
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); //把现在的浏览器User Agent传递给服务器
curl_setopt($ch, CURLOPT_NOBODY, 0);
$content = curl_exec($ch);  //执行!!!
curl_close($ch); /*下面解析*/
preg_match(‘~”seed”\s*:\s*(\d+)\s*,~iUs',$content,$seed);
preg_match(‘~\{\s*”(flv|mp4)”\s*:\s*”(.*)”\s*\}~iUs',$content,$encoded);
preg_match(‘~”key1″\s*:\s*”(.*)”\s*,~iUs',$content,$key1);
preg_match(‘~”key2″\s*:\s*”(.*)”\s*,~iUs',$content,$key2);
//从返回的JSON串中提取必要信息 seed, encoded_url, key1, key2
class decoder{
var $randomSeed = 0;
var $cg_str=”";
function __construct($seed){
$this->randomSeed = $seed;
}
function ran(){
$this->randomSeed = (($this->randomSeed * 211)+30031)%65536;
return ($this->randomSeed / 65536);// 根据旧的 Seed 计算新的Seed,并且返回一个Seed的比例位置 [0,1)
}
function cg_hun(){    //估计这个叫 “CG混”,反正ASV解的函数就是这个名字
$this->cg_str="";
$sttext = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/\:._-1234567890';   //默认字符串(最大)
$len = strlen($sttext);   //获取其长度
for($i=0;$i<$len;$i++){
$cuch = (int)($this->ran()*strlen($sttext));   //获取字符串 Seed比例 位置的字符下标
$this->cg_str.=$sttext[$cuch];   //把字母读出来
$sttext = str_replace($sttext[$cuch],”,$sttext);   //删掉这个读出来的字母(到 0 就停)
}
}
function decode($string){
$output=”";
$this->cg_hun();
$expl = explode(‘*',$string);   //把 1*23*34*45*56* 这个字符串打散
for($i=0;$i<count($expl)-1;$i++){
$output.=$this->cg_str[(int)$expl[$i]];  //获取数字位代表的 cg_hun 打乱字符串字符,自此解密完成
}
return $output;  //OK拉
}
function decode_key($key1,$key2){
$key = hexdec($key1);  //两个Key都是HEX
$key = $key ^ -1520786011; //这个原来也是个8 位HEX,后来被我用计算器算了数值,因为这样方便PhP位运算
return $key2 . dechex($key); //合成最终 Key
}
}//解密类,用这个很方便$new = new decoder((int)$seed[1]);
$fileid = $new->decode($encoded[2]);
$key = $new->decode_key($key1[1],$key2[1]);
//把数据喂进去,计算//地址载构成
$s7 = substr($fileid,10,strlen($fileid));
$s5 = substr($fileid,0,8);
$s6 = substr($fileid,6,2);
//拆开$s4 = '00′;//注意这是一个 HEX 值,即00表示视频第一个分段,01第二个 0f第十五个…依此类推$sid = time() . mt_rand(10,99) . '1000′ . mt_rand(30,80) . '00′;//获取一个随机的SID,给服务器(其实不会被检查) 
$d_ADDR = ‘http://f.youku.com/player/getFlvPath/sid/‘ . $sid . ‘_'. $s4 . ‘/st/' . $encoded[1] . ‘/fileid/' . $file_id;
echo $d_ADDR . ‘?K=' . $key;
//最后把地址输出

请注意,由于Youku 更换算法/格式上面的方法已经不能处理所有情况,我来描述下现在的流程:
1.访问http://v.youku.com/player/getPlayList/VideoIDS/[ID]
2.获得文件,同时解析”streamfileids”:{“flv”:”加密地址”,”mp4″:”加密地址”,”等等等”:”加密地址”
3.按照上面的方法破解加密地址
4.获取分段数目和K
{“mp4″:[{“no”:”0“,”size”:”18367795″,”seconds”:”421″,”k”:”281ff2875db680bb261c02ce“},{“no”:”1“,”size”:”19045091″,”seconds”:”421″,”k”:”45398cdd4aa44968261c02ce“},
……
5.合成地址,不过每个分段的K都采用上面获得的新K
PHP 相关文章推荐
PHP生成带有雪花背景的验证码
Oct 09 PHP
Dedecms V3.1 生成HTML速度的优化办法
Mar 18 PHP
Mysql中limit的用法方法详解与注意事项
Apr 19 PHP
基于PHP常用函数的用法详解
May 10 PHP
PHP程序员常见的40个陋习,你中了几个?
Nov 20 PHP
php获取字符串中各个字符出现次数的方法
Feb 23 PHP
php运行时动态创建函数的方法
Mar 16 PHP
PHP基于工厂模式实现的计算器实例
Jul 16 PHP
php版微信返回用户text输入的方法
Nov 14 PHP
利用PHP获取汉字首字母并且分组排序详解
Oct 22 PHP
ThinkPHP5.1表单令牌Token失效问题的解决
Mar 22 PHP
Thinkphp5+Redis实现商品秒杀代码实例讲解
Dec 29 PHP
解析php 版获取重定向后的地址(代码)
Jun 26 #PHP
php连接函数implode与分割explode的深入解析
Jun 26 #PHP
解析PHP正则提取或替换img标记属性
Jun 26 #PHP
php 在windows下配置虚拟目录的方法介绍
Jun 26 #PHP
关于PHP自动判断字符集并转码的详解
Jun 26 #PHP
安装apache2.2.22配置php5.4(具体操作步骤)
Jun 26 #PHP
php 批量生成html,txt文件的实现代码
Jun 26 #PHP
You might like
php生成数组的使用示例 php全组合算法
2014/01/16 PHP
php日历制作代码分享
2014/01/20 PHP
php使用for语句输出三角形的方法
2015/06/09 PHP
Yii2框架自定义验证规则操作示例
2019/02/08 PHP
JavaScript调用Activex控件的事件的实现方法
2010/04/11 Javascript
jquery下jstree简单应用 - v1.0
2011/04/14 Javascript
JavaScript调试技巧之console.log()详解
2014/03/19 Javascript
jQuery中:radio选择器用法实例
2015/01/03 Javascript
javascript的几种继承方法介绍
2016/03/22 Javascript
JQuery的Pager分页器实现代码
2016/05/03 Javascript
jquery div模态窗口的简单实例
2016/05/28 Javascript
微信小程序前端源码逻辑和工作流
2016/09/25 Javascript
获取IE浏览器Cookie信息的方法
2017/01/23 Javascript
js记录点击某个按钮的次数-刷新次数为初始状态的实例
2017/02/15 Javascript
video.js使用改变ui过程
2017/03/05 Javascript
ES6新特性一: let和const命令详解
2017/04/20 Javascript
详解Vue中一种简易路由传参办法
2017/09/15 Javascript
js+css3实现炫酷时钟
2020/08/18 Javascript
利用Python演示数型数据结构的教程
2015/04/03 Python
Python多进程原理与用法分析
2018/08/21 Python
python+selenium实现QQ邮箱自动发送功能
2019/01/23 Python
TensorFlow——Checkpoint为模型添加检查点的实例
2020/01/21 Python
pytorch实现seq2seq时对loss进行mask的方式
2020/02/18 Python
python GUI框架pyqt5 对图片进行流式布局的方法(瀑布流flowlayout)
2020/03/12 Python
详解如何将 Canvas 绘制过程转为视频
2021/01/25 HTML / CSS
美国折扣网站:jClub
2017/08/07 全球购物
Linux面试经常问的文件系统操作命令
2015/11/05 面试题
护士的自我鉴定
2014/02/07 职场文书
《蜗牛的奖杯》教后反思
2014/04/24 职场文书
2015年“七七卢沟桥事变”纪念活动总结
2015/03/24 职场文书
停电调休通知
2015/04/16 职场文书
新闻稿格式范文
2015/07/18 职场文书
学生会2016感恩节活动小结
2016/04/01 职场文书
如何理解PHP核心特性命名空间
2021/05/28 PHP
用JS实现飞机大战小游戏
2021/06/09 Javascript
Mysql使用全文索引(FullText index)的实例代码
2022/04/03 MySQL