php 获取优酷视频的真实地址(2014.6月新算法)
上个礼拜发现优酷改版了,各种过滤优酷广告的插件都失效了,于是我百度了一下(谷歌也不能用了)发现优酷改算法了,在ckplayer论坛发现有人在6月25号发了个php 的优酷代理文件,下载下来发现,能用但只能获取mp4格式的视频地址,而且php还加密了,没办法查看源码,后来通过微盾解密发现其中的源码,结合以前自己写的一个优酷视频解析类。。。。
感谢 3shi大大 具体分析请见 3shi大大的文章 优酷视频真实地址解析 (当然现在不能用了,主要看分析)
ps. 新算法是从别人那里解密出来的所以有可能存在错误,当然也没有注释,不过我试了几个视频都可以解析。
下面是源码:
文件名为:youku.class.php
<?php class Youku { const USER_AGENT = "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36";
const REFERER = "http://www.youku.com";
const FORM_ENCODE = "GBK";
const TO_ENCODE = "UTF-8";
private static $base = "http://v.youku.com/player/getPlaylist/VideoIDS/";
private static $source = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/\\:._-1234567890";
private static $sz = '-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1';
private static $str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; public static function parse($url){
preg_match("#id\_([\w=]+)#", $url, $matches); //id里可以有=号
if (empty($matches)){
$html = self::_cget($url);
preg_match("#videoId2\s*=\s*\'(\w+)\'#", $html, $matches);
if(!$matches) return false;
}
//根据you vid 获取相应的视频地址
return self::_getYouku(trim($matches[1]));
}
/**
* [_cget curl获取数据]
* @param [type] $url [url地址]
* @param boolean $convert [是否转换编码]
* @param integer $timeout [超时时间]
* @return [type] [description]
*/
public static function _cget($url,$convert=false,$timeout=10){
$ch=curl_init($url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_TIMEOUT,$timeout);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
curl_setopt($ch,CURLOPT_USERAGENT,self::USER_AGENT);
curl_setopt($ch,CURLOPT_REFERER,self::REFERER);
curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1); //跟随301跳转
curl_setopt($ch,CURLOPT_AUTOREFERER,1); //自动设置referer
$res=curl_exec($ch);
curl_close($ch);
if($convert){
$res=mb_convert_encoding($res,self::TO_ENCODE,self::FORM_ENCODE);
}
return $res;
} //start 获得优酷视频需要用到的方法
private static function getSid(){
$sid = time().(mt_rand(0,9000)+10000);
return $sid;
} private static function getKey($key1,$key2){
$a = hexdec($key1);
$b = $a ^0xA55AA5A5;
$b = dechex($b);
return $key2.$b;
} private static function getFileid($fileId,$seed){
$mixed = self::getMixString($seed);
$ids = explode("*",rtrim($fileId,'*')); //去掉末尾的*号分割为数组
$realId = "";
for ($i=0;$i<count($ids);$i++){
$idx = $ids[$i];
$realId .= substr($mixed,$idx,1);
}
return $realId;
} private static function getMixString($seed){
$mixed = "";
$source = self::$source;
$len = strlen($source);
for($i=0;$i<$len;$i++){
$seed = ($seed * 211 + 30031)%65536;
$index = ($seed / 65536 * strlen($source));
$c = substr($source,$index,1);
$mixed .= $c;
$source = str_replace($c,"",$source);
}
return $mixed;
} private static function yk_d($a){
if (!$a) {
return '';
}
$f = strlen($a);
$b = 0;
$str = self::$str;
for ($c = ''; $b < $f;) {
$e = self::charCodeAt($a, $b++) & 255;
if ($b == $f) {
$c .= self::charAt($str, $e >> 2);
$c .= self::charAt($str, ($e & 3) << 4);
$c .= '==';
break;
}
$g = self::charCodeAt($a, $b++);
if ($b == $f) {
$c .= self::charAt($str, $e >> 2);
$c .= self::charAt($str, ($e & 3) << 4 | ($g & 240) >> 4);
$c .= self::charAt($str, ($g & 15) << 2);
$c .= '=';
break;
}
$h = self::charCodeAt($a, $b++);
$c .= self::charAt($str, $e >> 2);
$c .= self::charAt($str, ($e & 3) << 4 | ($g & 240) >> 4);
$c .= self::charAt($str, ($g & 15) << 2 | ($h & 192) >> 6);
$c .= self::charAt($str, $h & 63);
}
return $c;
}
private static function yk_na($a){
if (!$a) {
return '';
} $h = explode(',', self::$sz);
$i = strlen($a);
$f = 0;
for ($e = ''; $f < $i;) {
do {
$c = $h[self::charCodeAt($a, $f++) & 255];
} while ($f < $i && -1 == $c);
if (-1 == $c) {
break;
}
do {
$b = $h[self::charCodeAt($a, $f++) & 255];
} while ($f < $i && -1 == $b);
if (-1 == $b) {
break;
}
$e .= self::fromCharCode($c << 2 | ($b & 48) >> 4);
do {
$c = self::charCodeAt($a, $f++) & 255;
if (61 == $c) {
return $e;
}
$c = $h[$c];
} while ($f < $i && -1 == $c);
if (-1 == $c) {
break;
}
$e .= self::fromCharCode(($b & 15) << 4 | ($c & 60) >> 2);
do {
$b = self::charCodeAt($a, $f++) & 255;
if (61 == $b) {
return $e;
}
$b = $h[$b];
} while ($f < $i && -1 == $b);
if (-1 == $b) {
break;
}
$e .= self::fromCharCode(($c & 3) << 6 | $b);
}
return $e;
}
private static function yk_e($a, $c){
for ($f = 0, $i, $e = '', $h = 0; 256 > $h; $h++) {
$b[$h] = $h;
}
for ($h = 0; 256 > $h; $h++) {
$f = (($f + $b[$h]) + self::charCodeAt($a, $h % strlen($a))) % 256;
$i = $b[$h];
$b[$h] = $b[$f];
$b[$f] = $i;
}
for ($q = ($f = ($h = 0)); $q < strlen($c); $q++) {
$h = ($h + 1) % 256;
$f = ($f + $b[$h]) % 256;
$i = $b[$h];
$b[$h] = $b[$f];
$b[$f] = $i;
$e .= self::fromCharCode(self::charCodeAt($c, $q) ^ $b[($b[$h] + $b[$f]) % 256]);
}
return $e;
} private static function fromCharCode($codes){
if (is_scalar($codes)) {
$codes = func_get_args();
}
$str = '';
foreach ($codes as $code) {
$str .= chr($code);
}
return $str;
}
private static function charCodeAt($str, $index){
static $charCode = array();
$key = md5($str);
$index = $index + 1;
if (isset($charCode[$key])) {
return $charCode[$key][$index];
}
$charCode[$key] = unpack('C*', $str);
return $charCode[$key][$index];
} private static function charAt($str, $index = 0){
return substr($str, $index, 1);
} /**
* [_getYouku description]
* @param [type] $vid [视频id]
* @return [type] [description]
*/
public static function _getYouku($vid){
//$link = "http://v.youku.com/player/getPlayList/VideoIDS/{$vid}/Pf/4"; //获取视频信息json 有些视频获取不全(土豆网的 火影忍者)
$blink = self::$base.$vid;
$link = $blink."/Pf/4/ctype/12/ev/1";
$retval = self::_cget($link);
$bretval = self::_cget($blink);
if ($retval) {
$rs = json_decode($retval, true);
$brs = json_decode($bretval, true);
if(!empty($rs['data'][0]['error'])){
return false; //有错误返回false
}
$data = array();
$streamtypes = $rs['data'][0]['streamtypes']; //可以输出的视频清晰度
$streamfileids = $rs['data'][0]['streamfileids'];
$seed = $rs['data'][0]['seed'];
$segs = $rs['data'][0]['segs'];
$ip = $rs['data'][0]['ip'];
$bsegs = $brs['data'][0]['segs'];
list($sid, $token) = explode('_', self::yk_e('becaf9be', self::yk_na($rs['data'][0]['ep'])));
foreach ($segs as $key=>$val) {
if(in_array($key,$streamtypes)){
foreach($val as $k=> $v){
$no = strtoupper(dechex($v['no'])); //转换为16进制 大写
if(strlen($no) == 1){
$no ="0".$no; //no 为每段视频序号
}
//构建视频地址K值
$_k = $v['k'];
if ((!$_k || $_k == '') || $_k == '-1') {
$_k = $bsegs[$key][$k]['k'];
}
$fileId = self::getFileid($streamfileids[$key],$seed);
$fileId = substr($fileId,0,8).$no.substr($fileId,10);
$ep = urlencode(iconv('gbk', 'UTF-8', self::yk_d(self::yk_e('bf7e5f01', ((($sid . '_') . $fileId) . '_') . $token))));
//判断后缀类型 、获得后缀
$typeArray = array("flv"=>"flv","mp4"=>"mp4","hd2"=>"flv","3gphd"=>"mp4","3gp"=>"flv","hd3"=>"flv");
//判断视频清晰度
$sharpness = array("flv"=>"normal","flvhd"=>"normal","mp4"=>"high","hd2"=>"super","3gphd"=>"high","3gp"=>"normal","hd3"=>"original"); //清晰度 数组
$fileType = $typeArray[$key];
$data[$sharpness[$key]][$k] = "http://k.youku.com/player/getFlvPath/sid/".$sid."_00/st/{$fileType}/fileid/".$fileId."?K=".$_k."&hd=1&myp=0&ts=".((((($v['seconds'].'&ypp=0&ctype=12&ev=1&token=').$token).'&oip=').$ip).'&ep=').$ep;;
}
}
}
//返回 图片 标题 链接 时长 视频地址
$data['img'] = $rs['data'][0]['logo'];
$data['title'] = $rs['data'][0]['title'];
$data['seconds'] = $rs['data'][0]['seconds'];
return $data;
} else {
return false;
}
}
//end 获得优酷视频需要用到的方法
}
引入这个类就可以使用: 输出一个带有各种清晰度的 视频url 的数组。
require "youku.class.php";
$url = "http://v.youku.com/v_show/id_XNzM1NjQ0Mzgw.html";
$data = Youku::parse($url);
print_r($data);
php 获取优酷视频的真实地址(2014.6月新算法)的更多相关文章
- 【API】获取优酷视频信息接口
序: 自己的网站中需要接入一个视频模块,虚拟主机的空间小所以只能引用第三方的链接.感觉国内优酷好不错,所以查了一下优酷的接口. 0x00: 先去优酷API开放中心申请一个开 ...
- python3自动下载优酷视频小程序
我们一般都在优酷里看一些好玩的视频,有时候看到精彩的就想下载到本地保存起来留作纪念,在win下可以用维棠等软件下载,但苦了用linux的孩子们.尽管chrome和firefox的一些插件可以下载,但有 ...
- 使用Vitamio打造自己的Android万能播放器(5)——在线播放(播放优酷视频)
前言 为了保证每周一篇的进度,又由于Vitamio新版本没有发布, 决定推迟本地播放的一些功能(截图.视频时间.尺寸等),跳过直接写在线播放部分的章节.从Vitamio的介绍可以看得出,其支持http ...
- JavaScript使用DeviceOne开发实战(四)仿优酷视频应用
开发之前需要考虑系统的差异性,比如ios手机没有回退键,所以在开发时一定要考虑二级界面需要有回退键,否则ios的手机就会陷入到这个页面出不去了.安卓系统有回退键,针对这个情况需要要求用户在3秒钟之内连 ...
- JSP页面怎样导入优酷视频
我在做的一个项目里面,应客户要求.要导入视频.然后我再考虑,视频是直接放在本地数据库的话,那么肯定会出现数据视频读取反应慢. 那么,就能够把视频先传到优酷上面,然后再直接应用优酷视频上的html代码, ...
- fedora23的firefox不能播放优酷视频?
安装了多次 firefox的 flash player插件, 也设置了 /usr/lib/mozilla/plugins/libflashplayer.so的权限为777, 而且所有者 也是root. ...
- 关于ubuntu14.04LTS 64位 播放优酷视频
起因:chrome无法播放优酷视频,然后换firefox发现居然没有装flash 插件. 解释:关于chrome在网上看到了不少说法,说chrome新版本的不支持adobe flash之类的,但是这些 ...
- 网页中引用优酷视频去广告自动播放代码[xyytit]
很多时候需要在网站中加入视频,可视频太大放自己服务器上太占空间,可以把视频上传到优酷网上,这样节省了空间,打开速度方面也会有不少提升.下面教大家如何引用自动播放的优酷视频.把下面的代码加在你网页适当位 ...
- 怎样获取优酷站内视频的MP4格式地址,嵌入到手机页面播放
最近的有关项目需要使用video标签播放视频,并且视频的路径src是优酷里面的视频,所以需要得到优酷里面的mp4路径才能播放. 但是在网上查了下资料,看到优酷的播放格式是一个m3u8文件,如图所示: ...
随机推荐
- iOS进行单元测试OCUnit+xctool
单元测试 什么是单元测试 wiki解释 简单说来就是为你的方法多专门写一个测试函数.以保证你的方法在不停的修改开发中.保持正确.如果出错,第一时间让你知道,这样从最小单位开始监控来保证软件的质量. 我 ...
- ios编程规范
允许使用较长的描述尽量不要使用缩写,而是将完整的意思写出来.源于代码的维护可能会被不同文化背景的programmer阅读 适当的命名前缀,比如给变量,协议等,不要给方法加前缀 方法命名规则一般以小写字 ...
- 【GLSL教程】(九)其他说明 【转】
http://blog.csdn.net/racehorse/article/details/6664775 法线矩阵 在很多顶点shader中都用到了gl_NormalMatrix.这里将介绍这个矩 ...
- GLSL逐像素光照 【转】
转载:http://blog.csdn.net/hgl868/article/details/7872414 逐像素的方向光(Directional Light per Pixel) 这一节将把前面的 ...
- Netty通过心跳保持长链接
Netty自带心跳检测功能,IdleStateHandler,客户端在写空闲时主动发起心跳请求,服务器接受到心跳请求后给出一个心跳响应.当客户端在一定时间范围内不能够给出响应则断开链接. public ...
- HashSet和SortSet对比--c#学习笔记
微软在 .NET 3.5 新增了一个 HashSet 类,在 .NET 4 新增了一个 SortedSet 类. .NET Collection 函数库的 HashSet.SortedSet 这两个泛 ...
- mysql rpm安装,以及修改charset
http://my.oschina.net/u/1156660/blog/343154?fromerr=tmDGGiDL 修改charset: http://stackoverflow.com/que ...
- vue2.0 watch 详解
vue官网解释: 一个对象,键是需要观察的表达式,值是对应回调函数.值也可以是方法名,或者包含选项的对象.Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个属性. 也就是 ...
- C# DateTime和String(转)
http://www.cnblogs.com/Pickuper/articles/2058880.html C#语言之“string格式的日期时间字符串转为DateTime类型”的方法 方法一:Con ...
- SpringBoot学习之启动方式
1.通过@SpringBootAppliction注解类启动 启动方法:找到注解类->鼠标右键->run as-> java application. 2 通过maven启动Spri ...