管理JAE代码的Git工具安装汉化

作者:matrix 发布时间:2014年8月31日星期日 分类:零零星星

放在jae的代码修改的时候使用git方便很多,由于没有接触过git,这里记录一些。

以win8-64bit为例:

安装工具

msysgit[Git-1.9.4-preview20140611]

Tortoisegit-64bit

Tortoisegit-64bit中文语言包

汉化步骤

安装完这仨文件后重启。

右击资源管理器任意空白位置,选择 TortoiseGit -> Settings

选择 Tortoisegit -> Settings

 

从右侧语言设置中,选择简体中文。

选择简体中文

参考:http://www.freehao123.com/jae-git/

php源码_优酷视频解析_更新

作者:matrix 发布时间:2014年8月23日星期六 分类:兼容并蓄

优酷的算法到6月份就变了,以前的优酷解析源码也早就失效。

获取视频信息的接口:

http://v.youku.com/player/getPlayList/VideoIDS/{$youku_ID}/ctype/12/ev/1
标清测试:

方法一.

通过优酷的m38u文件匹配到视频源,主要是获取m3u8地址麻烦

http://v.youku.com/player/getM3U8/vid/{ $id} /type/ {$type}这种优酷的m3u8地址在7月份的时候还能用,到这个月就成403错误没法访问。

后来找到了新的m38u地址:

http://pl.youku.com/playlist/m3u8?vid=XNTc5NDcwMjI4&type=mp4&ep={$ep}&sid={$sid}&token={$tk}&ctype=12&ev=1&oip={$oip}

麻烦的是多出来的ep等一趴拉参数,很扯拐。

还好有github项目的相关的源码,这里修改整理下[python]:

# -*- coding: utf-8 -*-
import os
import re
import sys
import json
import gzip
import base64
import time
from urllib import request, parse
def get_response(url, faker = False):
    if faker:
        response = request.urlopen(request.Request(url, headers = fake_headers), None)
    else:
        response = request.urlopen(url)
    data = response.read()
    if response.info().get('Content-Encoding') == 'gzip':
        data = ungzip(data)
    elif response.info().get('Content-Encoding') == 'deflate':
        data = undeflate(data)
    response.data = data
    return response
# DEPRECATED in favor of get_content()
def get_html(url, encoding = None, faker = False):
    content = get_response(url, faker).data
    return str(content, 'utf-8', 'ignore')
def generate_ep(vid, ep):
    f_code_1 = 'becaf9be'
    f_code_2 = 'bf7e5f01'
    def trans_e(a, c):
        f = h = 0
        b = list(range(256))
        result = ''
        while h < 256:
            f = (f + b[h] + ord(a[h % len(a)])) % 256
            b[h], b[f] = b[f], b[h]
            h += 1
        q = f = h = 0
        while q < len(c):
            h = (h + 1) % 256
            f = (f + b[h]) % 256
            b[h], b[f] = b[f], b[h]
            if isinstance(c[q], int):
                result += chr(c[q] ^ b[(b[h] + b[f]) % 256])
            else:
                result += chr(ord(c[q]) ^ b[(b[h] + b[f]) % 256])
            q += 1
        return result
    e_code = trans_e(f_code_1, base64.b64decode(ep))
    sid, token = e_code.split('_')
    new_ep = trans_e(f_code_2, '%s_%s_%s' % (sid, vid, token))
    return base64.b64encode(bytes(new_ep, 'latin')), sid, token
    #return base64.b64encode(new_ep)
def de_m3u8(vid):
        url = 'http://v.youku.com/player/getPlayList/VideoIDS/%s/Pf/4/ctype/12/ev/1' % vid
        meta = json.loads(get_html(url))
        if not meta['data']:
                print ('[Failed] Video not found.')
                sys.exit() # 退出程序
        metadata0 = meta['data'][0]
        title = metadata0['title']
        ep = metadata0['ep']
        ip = metadata0['ip']
        vid2 = metadata0['videoid']
        data = generate_ep(vid2,ep);
       # m3u8url = 'http://pl.youku.com/playlist/m3u8?vid=%s&type=mp4&ep=%s&sid=%s&token=%s&ctype=12&ev=1&oip=%s' % (vid,data[0],data[1],data[2],ip)
        m3u8_query = parse.urlencode(dict(
            ctype=12,
            ep=data[0],
            ev=1,
            keyframe=1,
            oip=ip,
            sid=data[1],
            token=data[2],
            ts=int(time.time()),
            type='mp4',
            vid=vid2,
        ))
        m3u8_url = 'http://pl.youku.com/playlist/m3u8?' + m3u8_query
        return m3u8_url;
v = 'XNjc1MDI4Nzg0'#优酷视频ID
print(get_html(de_m3u8(v)))#返回m3u8内容

说明:python的相关代码我只是DIY了,原创来自:
https://github.com/tacy/plugin.video.youkuvideo/blob/master/addon.py
https://github.com/soimort/you-get/blob/develop/src/you_get/extractors/youku.py

php源码_优酷视频解析_更新

 

执行上面的python得到如图,明显m3u8的视频源就是这些,只是不要后面的ts_参数。

之后再慢慢改成php代码,封装成类:

class youku_m3u8
{
    public static function curl($url, $carry_header = true, $REFERER_ = 0, $add_arry_header = 0)
    {
        $ch = curl_init($url);
        if ($carry_header)
        {
            curl_setopt($ch, CURLOPT_HTTPHEADER, array('User-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36'));
        }
        if ($add_arry_header)
        {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $add_arry_header);
        }
        if ($REFERER_)
        {
            curl_setopt($ch, CURLOPT_REFERER, $REFERER_);
        }
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $get_url = curl_exec($ch);
        curl_close($ch);
        return $get_url;
    }
    public static function charCodeAt($str, $index)
    {
        $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];
    }
    public static function charAt($str, $index = 0)
    {
        return substr($str, $index, 1);
    }
    public static function fromCharCode($codes)
    {
        if (is_scalar($codes))
        {
            $codes = func_get_args();
        }
        $str = '';
        foreach ($codes as $code)
        {
            $str .= chr($code);
        }
        return $str;
    }
    public 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;
    }
    public static function yk_d($a)
    {
        $str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
        if (!$a)
        {
            return '';
        }
        $f = strlen($a);
        $b = 0;
        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;
    }
    public static function get_m3u8_url($youku_ID, $type = 'flv')
    {
        $video_info = self::curl('http://v.youku.com/player/getPlayList/VideoIDS/' . $youku_ID . '/ctype/12/ev/1');
        $obj = json_decode($video_info);
        $vid = $obj->data[0]->videoid;
        $oip = $obj->data[0]->ip;
        $epdata = $obj->data[0]->ep;
        $youku_m3u8 = self::_calc_ep2($vid, $epdata);
        $m3u8_url = 'http://pl.youku.com/playlist/m3u8?vid=' . $vid . '&type=' . $type . '&ep=' . urlencode($youku_m3u8['ep']) . '&token=' . $youku_m3u8['token'] . '&ctype=12&ev=1&oip=' . $oip . '&sid=' . $youku_m3u8['sid'];
        return $m3u8_url;
    }
    public static function _calc_ep2($vid, $ep)
    {
        $e_code = self::yk_e('becaf9be', base64_decode($ep));
        $s_t = explode('_', $e_code);
        $sid = $s_t[0];
        $token = $s_t[1];
        // $new_ep = trans_e('bf7e5f01', '%s_%s_%s' % ($sid.$vid.$token));
        $new_ep = self::yk_e('bf7e5f01', $sid . '_' . $vid . '_' . $token);
        $new_ep = base64_encode($new_ep); //可以换作下面代码 
        // $new_ep = iconv('gbk', 'UTF-8', self::yk_d($new_ep));
        return array('ep' => $new_ep,
            'token' => $token,
            'sid' => $sid,
            );
    }
}

说明:调用函数youku_m3u8::get_m3u8_url('XNjc1MDI4Nzg0')就能得到m3u8地址

方法二.

像之前一样解密优酷算法,按照新的URL拼接。

这里有深渊戮影的新算法[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 (emptyempty($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(!emptyempty($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  获得优酷视频需要用到的方法
}

说明:调用Youku::parse('http://v.youku.com/v_show/id_XNzM4ODk0ODcy.html')就能得到所有地址。

php源码下载:

方法一的:http://pan.baidu.com/s/1qWEzanM
方法二:http://pan.baidu.com/s/1bnxU439

参考:

3shi天下

php 获取优酷视频的真实地址(2014.6月新算法)

plugin.video.youkuvideo

you-get