首页 > 代码库 > php 获取优酷视频的真实地址(2014.6月新算法)
php 获取优酷视频的真实地址(2014.6月新算法)
上个礼拜发现优酷改版了,各种过滤优酷广告的插件都失效了,于是我百度了一下(谷歌也不能用了)发现优酷改算法了,在ckplayer论坛发现有人在6月25号发了个php 的优酷代理文件,下载下来发现,能用但只能获取mp4格式的视频地址,而且php还加密了,没办法查看源码,后来通过微盾解密发现其中的源码,结合以前自己写的一个优酷视频解析类。。。。
感谢 3shi大大 具体分析请见 3shi大大的文章 优酷视频真实地址解析 (当然现在不能用了,主要看分析)
ps. 新算法是从别人那里解密出来的所以有可能存在错误,当然也没有注释,不过我试了几个视频都可以解析。
下面是源码:
文件名为:youku.class.php
1 <?php 2 3 class Youku { 4 5 const USER_AGENT = "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36"; 6 const REFERER = "http://www.youku.com"; 7 const FORM_ENCODE = "GBK"; 8 const TO_ENCODE = "UTF-8"; 9 private static $base = "http://v.youku.com/player/getPlaylist/VideoIDS/"; 10 private static $source = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/\\:._-1234567890"; 11 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‘; 12 private static $str = ‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/‘; 13 14 public static function parse($url){ 15 preg_match("#id\_([\w=]+)#", $url, $matches); //id里可以有=号 16 if (empty($matches)){ 17 $html = self::_cget($url); 18 preg_match("#videoId2\s*=\s*\‘(\w+)\‘#", $html, $matches); 19 if(!$matches) return false; 20 } 21 //根据you vid 获取相应的视频地址 22 return self::_getYouku(trim($matches[1])); 23 } 24 /** 25 * [_cget curl获取数据] 26 * @param [type] $url [url地址] 27 * @param boolean $convert [是否转换编码] 28 * @param integer $timeout [超时时间] 29 * @return [type] [description] 30 */ 31 public static function _cget($url,$convert=false,$timeout=10){ 32 $ch=curl_init($url); 33 curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); 34 curl_setopt($ch,CURLOPT_TIMEOUT,$timeout); 35 curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout); 36 curl_setopt($ch,CURLOPT_USERAGENT,self::USER_AGENT); 37 curl_setopt($ch,CURLOPT_REFERER,self::REFERER); 38 curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1); //跟随301跳转 39 curl_setopt($ch,CURLOPT_AUTOREFERER,1); //自动设置referer 40 $res=curl_exec($ch); 41 curl_close($ch); 42 if($convert){ 43 $res=mb_convert_encoding($res,self::TO_ENCODE,self::FORM_ENCODE); 44 } 45 return $res; 46 } 47 48 //start 获得优酷视频需要用到的方法 49 private static function getSid(){ 50 $sid = time().(mt_rand(0,9000)+10000); 51 return $sid; 52 } 53 54 private static function getKey($key1,$key2){ 55 $a = hexdec($key1); 56 $b = $a ^0xA55AA5A5; 57 $b = dechex($b); 58 return $key2.$b; 59 } 60 61 private static function getFileid($fileId,$seed){ 62 $mixed = self::getMixString($seed); 63 $ids = explode("*",rtrim($fileId,‘*‘)); //去掉末尾的*号分割为数组 64 $realId = ""; 65 for ($i=0;$i<count($ids);$i++){ 66 $idx = $ids[$i]; 67 $realId .= substr($mixed,$idx,1); 68 } 69 return $realId; 70 } 71 72 private static function getMixString($seed){ 73 $mixed = ""; 74 $source = self::$source; 75 $len = strlen($source); 76 for($i=0;$i<$len;$i++){ 77 $seed = ($seed * 211 + 30031)%65536; 78 $index = ($seed / 65536 * strlen($source)); 79 $c = substr($source,$index,1); 80 $mixed .= $c; 81 $source = str_replace($c,"",$source); 82 } 83 return $mixed; 84 } 85 86 private static function yk_d($a){ 87 if (!$a) { 88 return ‘‘; 89 } 90 $f = strlen($a); 91 $b = 0; 92 $str = self::$str; 93 for ($c = ‘‘; $b < $f;) { 94 $e = self::charCodeAt($a, $b++) & 255; 95 if ($b == $f) { 96 $c .= self::charAt($str, $e >> 2); 97 $c .= self::charAt($str, ($e & 3) << 4); 98 $c .= ‘==‘; 99 break;100 }101 $g = self::charCodeAt($a, $b++);102 if ($b == $f) {103 $c .= self::charAt($str, $e >> 2);104 $c .= self::charAt($str, ($e & 3) << 4 | ($g & 240) >> 4);105 $c .= self::charAt($str, ($g & 15) << 2);106 $c .= ‘=‘;107 break;108 }109 $h = self::charCodeAt($a, $b++);110 $c .= self::charAt($str, $e >> 2);111 $c .= self::charAt($str, ($e & 3) << 4 | ($g & 240) >> 4);112 $c .= self::charAt($str, ($g & 15) << 2 | ($h & 192) >> 6);113 $c .= self::charAt($str, $h & 63);114 }115 return $c;116 }117 private static function yk_na($a){118 if (!$a) {119 return ‘‘;120 }121 122 $h = explode(‘,‘, self::$sz);123 $i = strlen($a);124 $f = 0;125 for ($e = ‘‘; $f < $i;) {126 do {127 $c = $h[self::charCodeAt($a, $f++) & 255];128 } while ($f < $i && -1 == $c);129 if (-1 == $c) {130 break;131 }132 do {133 $b = $h[self::charCodeAt($a, $f++) & 255];134 } while ($f < $i && -1 == $b);135 if (-1 == $b) {136 break;137 }138 $e .= self::fromCharCode($c << 2 | ($b & 48) >> 4);139 do {140 $c = self::charCodeAt($a, $f++) & 255;141 if (61 == $c) {142 return $e;143 }144 $c = $h[$c];145 } while ($f < $i && -1 == $c);146 if (-1 == $c) {147 break;148 }149 $e .= self::fromCharCode(($b & 15) << 4 | ($c & 60) >> 2);150 do {151 $b = self::charCodeAt($a, $f++) & 255;152 if (61 == $b) {153 return $e;154 }155 $b = $h[$b];156 } while ($f < $i && -1 == $b);157 if (-1 == $b) {158 break;159 }160 $e .= self::fromCharCode(($c & 3) << 6 | $b);161 }162 return $e;163 }164 private static function yk_e($a, $c){165 for ($f = 0, $i, $e = ‘‘, $h = 0; 256 > $h; $h++) {166 $b[$h] = $h;167 }168 for ($h = 0; 256 > $h; $h++) {169 $f = (($f + $b[$h]) + self::charCodeAt($a, $h % strlen($a))) % 256;170 $i = $b[$h];171 $b[$h] = $b[$f];172 $b[$f] = $i;173 }174 for ($q = ($f = ($h = 0)); $q < strlen($c); $q++) {175 $h = ($h + 1) % 256;176 $f = ($f + $b[$h]) % 256;177 $i = $b[$h];178 $b[$h] = $b[$f];179 $b[$f] = $i;180 $e .= self::fromCharCode(self::charCodeAt($c, $q) ^ $b[($b[$h] + $b[$f]) % 256]);181 }182 return $e;183 }184 185 private static function fromCharCode($codes){186 if (is_scalar($codes)) {187 $codes = func_get_args();188 }189 $str = ‘‘;190 foreach ($codes as $code) {191 $str .= chr($code);192 }193 return $str;194 }195 private static function charCodeAt($str, $index){196 static $charCode = array();197 $key = md5($str);198 $index = $index + 1;199 if (isset($charCode[$key])) {200 return $charCode[$key][$index];201 }202 $charCode[$key] = unpack(‘C*‘, $str);203 return $charCode[$key][$index];204 }205 206 private static function charAt($str, $index = 0){207 return substr($str, $index, 1);208 }209 210 211 /**212 * [_getYouku description]213 * @param [type] $vid [视频id]214 * @return [type] [description]215 */216 public static function _getYouku($vid){217 //$link = "http://v.youku.com/player/getPlayList/VideoIDS/{$vid}/Pf/4"; //获取视频信息json 有些视频获取不全(土豆网的 火影忍者)218 $blink = self::$base.$vid;219 $link = $blink."/Pf/4/ctype/12/ev/1";220 $retval = self::_cget($link);221 $bretval = self::_cget($blink);222 if ($retval) {223 $rs = json_decode($retval, true);224 $brs = json_decode($bretval, true);225 if(!empty($rs[‘data‘][0][‘error‘])){226 return false; //有错误返回false227 }228 $data = array();229 $streamtypes = $rs[‘data‘][0][‘streamtypes‘]; //可以输出的视频清晰度230 $streamfileids = $rs[‘data‘][0][‘streamfileids‘];231 $seed = $rs[‘data‘][0][‘seed‘];232 $segs = $rs[‘data‘][0][‘segs‘];233 $ip = $rs[‘data‘][0][‘ip‘];234 $bsegs = $brs[‘data‘][0][‘segs‘];235 list($sid, $token) = explode(‘_‘, self::yk_e(‘becaf9be‘, self::yk_na($rs[‘data‘][0][‘ep‘])));236 foreach ($segs as $key=>$val) {237 if(in_array($key,$streamtypes)){238 foreach($val as $k=> $v){239 $no = strtoupper(dechex($v[‘no‘])); //转换为16进制 大写240 if(strlen($no) == 1){241 $no ="0".$no; //no 为每段视频序号242 }243 //构建视频地址K值244 $_k = $v[‘k‘];245 if ((!$_k || $_k == ‘‘) || $_k == ‘-1‘) {246 $_k = $bsegs[$key][$k][‘k‘];247 }248 $fileId = self::getFileid($streamfileids[$key],$seed);249 $fileId = substr($fileId,0,8).$no.substr($fileId,10);250 $ep = urlencode(iconv(‘gbk‘, ‘UTF-8‘, self::yk_d(self::yk_e(‘bf7e5f01‘, ((($sid . ‘_‘) . $fileId) . ‘_‘) . $token))));251 //判断后缀类型 、获得后缀252 $typeArray = array("flv"=>"flv","mp4"=>"mp4","hd2"=>"flv","3gphd"=>"mp4","3gp"=>"flv","hd3"=>"flv");253 //判断视频清晰度 254 $sharpness = array("flv"=>"normal","flvhd"=>"normal","mp4"=>"high","hd2"=>"super","3gphd"=>"high","3gp"=>"normal","hd3"=>"original"); //清晰度 数组255 $fileType = $typeArray[$key];256 $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;;257 }258 }259 }260 //返回 图片 标题 链接 时长 视频地址261 $data[‘img‘] = $rs[‘data‘][0][‘logo‘];262 $data[‘title‘] = $rs[‘data‘][0][‘title‘];263 $data[‘seconds‘] = $rs[‘data‘][0][‘seconds‘];264 return $data;265 } else {266 return false;267 }268 }269 //end 获得优酷视频需要用到的方法270 }
引入这个类就可以使用: 输出一个带有各种清晰度的 视频url 的数组。
1 require "youku.class.php";2 $url = "http://v.youku.com/v_show/id_XNzM1NjQ0Mzgw.html";3 $data = Youku::parse($url);4 print_r($data);
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。