上个礼拜发现优酷改版了,各种过滤优酷广告的插件都失效了,于是我百度了一下(谷歌也不能用了)发现优酷改算法了,在ckplayer论坛发现有人在6月25号发了个php 的优酷代理文件,下载下来发现,能用但只能获取mp4格式的视频地址,而且php还加密了,没办法查看源码,后来通过微盾解密发现其中的源码,结合以前自己写的一个优酷视频解析类。。。。
感谢 3shi大大 具体分析请见 3shi大大的文章 (当然现在不能用了,主要看分析)
ps. 新算法是从别人那里解密出来的所以有可能存在错误,当然也没有注释,不过我试了几个视频都可以解析。
下面是源码:
文件名为:youku.class.php
1 > 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);