加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

挖掘视频网站【优酷】上被截断的视频的地址--002

发布时间:2020-12-14 03:52:41 所属栏目:大数据 来源:网络整理
导读:上一篇博客(这里)寻找视频地址的时候,有些细节没有弄很清楚,这两天继续弄,发现原来路径里边的sid是个随机生成数,不需要找它。对于k值,现在的是服务器直接返回来的,而里边也有通过返回的json里边的key1计算获得: PlayListProxy.as文件里边: param1.k

上一篇博客(这里)寻找视频地址的时候,有些细节没有弄很清楚,这两天继续弄,发现原来路径里边的sid是个随机生成数,不需要找它。对于k值,现在的是服务器直接返回来的,而里边也有通过返回的json里边的key1计算获得:

PlayListProxy.as文件里边:

param1.key1 = (Number("0x" + param2.key1) ^ Number("0xA55AA5A5")).toString(16);

而关键之处是就剩下了那个fileid,这是我从它的播放器里边找到的源码:

        private function parseMainData(param1:PlayListData,param2:Object) : void
        {
            var _loc_5:String = null;//临时变量
            var _loc_9:String = null;//临时变量
            var _loc_10:String = null;//flvmp4分段视频信息
            var _loc_11:Object = null;//streamfileids
            var _loc_12:String = null;
            var _loc_13:Array = null;
            var _loc_14:RandomProxy = null;
            var _loc_15:Dictionary = null;//segs里边几种视频类型的数据
            var _loc_16:String = null;//视频类型
            var _loc_17:int = 0;//临时变量,长度计数用
            var _loc_18:String = null;
            var _loc_19:Array = null;//存放视频数据
            var _loc_20:String = null;
            var _loc_21:Object = null;//临时变量
            var _loc_22:VideoSegmentData = null;//视频数据:no,size.type,seconds,k值
            if (param1 == null || param2 == null)
            {
                return;
            }
            param1.drm = param2.drm;
            param1.rtmp = param2.rtmp;
            param1.ct = param2.ct;
            param1.show = this.parseShowData(param2.show);
            param1.programList = this.parseProgramListData(param2.list,param2.list_pre,param2.list_next);
            param1.dvdinfo = this.parseDVDData(param2.dvd);
            param1.trial = this.pareseTrialData(param2.trial);
            param1.caption = this.parseCaptionData(param2.dvd);
            param1.threeD = this.parseThreeDData(param2.dvd);
            param1.tt = param2.tt;
            param1.ct = param2.ct;
            param1.cs = param2.cs;
            param1.logo = param2.logo;
            param1.seed = Number(param2.seed);
            param1.tags = param2.tags;
            param1.categories = param2.categories;
            param1.videoId = String(param2.videoid);
            param1.vidEncoded = param2.vidEncoded;
            param1.userName = param2.username;
            param1.userId = param2.userid;
            param1.title = unescape(param2.title);
            param1.key1 = (Number("0x" + param2.key1) ^ Number("0xA55AA5A5")).toString(16);
            param1.key2 = param2.key2;
            param1.seconds = Number(param2.seconds);
            if (param2.sourceVid != null)
            {
                param1.sourceVid = Number(param2.sourceVid);
            }
            param1.streamFileIds = param2.streamfileids;
            param1.segs = param2.segs;
            param1.streamSizes = param2.streamsizes;
            param1.streamTypes = param2.streamtypes;
            param1.error = param2.error;
            param1.errorlink = param2.link;
            param1.up = param2.up;
            param1.down = param2.down;
            if (param2.lastpoint)
            {
                param1.lastpoint = Number(param2.lastpoint);
            }
            param1.token = param2.ts ? (param2.ts) : ("");
            var _loc_3:* = new HashCash();
            param1.hashcash = _loc_3.getHashCash(param1.token + "o");
            param1.tokenup = param2.tsup ? (param2.tsup) : ("");
            param1.hashcashup = _loc_3.getHashCash(param1.tokenup);
            param1.currentLang = "";
            if (param1.dvdinfo && param1.dvdinfo.audioLangs.length > 1)
            {
                _loc_17 = 0;
                while (_loc_17 < param1.dvdinfo.audioLangs.length)
                {
                    
                    if (param1.vidEncoded == param1.dvdinfo.audioLangs[_loc_17].vid || param1.videoId == param1.dvdinfo.audioLangs[_loc_17].vid)
                    {
                        param1.currentLang = param1.dvdinfo.audioLangs[_loc_17].lang;
                        param1.currentLangID = param1.dvdinfo.audioLangs[_loc_17].langid;
                    }
                    _loc_17++;
                }
            }
            var _loc_4:Array = [];//视频类型
            for (_loc_5 in param2.streamfileids)
            {
                if (!this.isValidType(_loc_5))
                {
                    continue;
                }
                _loc_4.push(_loc_5);
            }
            param1.typeArr = _loc_4;
            this._playListData.fileType = _loc_4[0];
            if (_loc_4.length > 1)
            {
            }
            var _loc_6:Number = 0;
            var _loc_7:* = Number.MAX_VALUE;
            var _loc_8:* = param2.segs;
            for (_loc_9 in _loc_8)
            {
                
                if (_loc_9 == "flv" || _loc_9 == "mp4" || _loc_9 == "flvhd" || _loc_9 == "hd2" || _loc_9 == "hd3")
                {
                    _loc_6 = 0;
                    for (_loc_18 in _loc_8[_loc_9])
                    {
                        
                        _loc_6 = _loc_6 + Number(_loc_8[_loc_9][_loc_18].seconds);
                    }
                    if (_loc_6 < _loc_7)
                    {
                        _loc_7 = _loc_6;
                    }
                }
            }
            param1.totalTime = _loc_7;
            _loc_10 = "";
            _loc_11 = param2.streamfileids;
            for (_loc_12 in _loc_11)
            {
                
                if (_loc_12 == param1.fileType)
                {
                    _loc_10 = _loc_11[_loc_12];
                    break;
                }
            }
            _loc_13 = [];
            _loc_14 = new RandomProxy(param1.seed);
            _loc_15 = new Dictionary();
            for (_loc_16 in param2.segs)
            {
                if (!this.isValidType(_loc_16))
                {
                    continue;
                }
                _loc_19 = [];
                
                //_loc_16   --   flv
                //_loc_16   --   mp4
                //_loc_20   --   0,1,2,3
                for (_loc_20 in param2.segs[_loc_16])
                {
                    _loc_21 = param2.segs[_loc_16][_loc_20];
                    _loc_22 = new VideoSegmentData();
                    _loc_22.no = _loc_21.no;
                    _loc_22.size = _loc_21.size;
                    _loc_22.seconds = _loc_21.seconds;
                    if (_loc_21.k)
                    {
                        _loc_22.key = _loc_21.k;
                    }
                    //streamfileids,mp4/flv,i,RandomProxy(param1.seed)
                    _loc_22.fileId = this.getFileId(_loc_11,_loc_16,int(_loc_20),_loc_14);
                    _loc_22.type = _loc_16;
                    _loc_19.push(_loc_22);
                }
                _loc_15[_loc_16] = _loc_19;
            }
            param1.videoSegmentsDic = _loc_15;
            param1.watermarks = param2.streamlogos;
            if (param2.hasOwnProperty("paike"))
            {
                param1.paike = param2.paike as Boolean;
            }
            else
            {
                param1.paike = false;
            }
            if (param2.hasOwnProperty("share"))
            {
                param1.share = param2.share as Boolean;
            }
            else
            {
                param1.share = false;
            }
            param1.previews = this.parsePreviews(param2.preview);
            return;
        }// end function
里边的注释是我理解的备注,目前很疑惑的是这个:

_loc_22.fileId = this.getFileId(_loc_11,_loc_14);

知道它是计算fileId的关键代码,但是RandomProxy是什么结构的有人知道吗?为什么怎么搜索都找不到呢?

getFileId函数代码:

//streamfileids,RandomProxy(param1.seed)
        private function getFileId(param1:Object,param2:String,param3:int,param4:RandomProxy) : String
        {
            var _loc_6:String = null;//mp4/flv
            var _loc_5:String = "";//"66*59*66*66*66*9*66*30*66*66*57*66*53*47*47*67*11*3..........
            for (_loc_6 in param1)
            {
                if (_loc_6 == param2)
                {
                    _loc_5 = param1[_loc_6];
                    break;
                }
            }
            if (_loc_5 == "")
            {
                return "";
            }
            var _loc_7:String = "";
            var _loc_8:* = param4.cg_fun(_loc_5);
            var _loc_9:* = param4.cg_fun(_loc_5).slice(0,8);
            var _loc_10:* = int(param3);
            var _loc_11:* = int(param3).toString(16);
            if (int(param3).toString(16).length == 1)
            {
                _loc_11 = "0" + _loc_11;
            }
            _loc_11 = _loc_11.toUpperCase();
            var _loc_12:* = _loc_8.slice(10,_loc_8.length);
            _loc_7 = _loc_9 + _loc_11 + _loc_12;
            return _loc_7;
        }// end function
关键部分就是这个随机的函数cg_fun()是干什么的。

比如fileid是:0300080400510C15B61CF004ED56DCBD905FF1-B527-63DA-87D3-6C0D90F804E1

很显然,_loc_9得到的是前边8位,_loc_11得到的是中间两位,而_loc_12是通过函数cg_fun()得到的那个字符串出去前边被替换的10位的剩余字符串。

所有的核心就剩下这个函数了,一时间找不到办法解决,之后查了一下其他人做的方法,那些几乎都是以前的早起版本,但是现在依然可以用:

?最新的优酷真实下载地址解析 http://blog.csdn.net/feige2008/article/details/8198434?

优酷视频真实地址解析?http://blog.csdn.net/amor2006/article/details/7055902


记录一个获取fileid的脚本代码:

import time
import random
import math
def createSid():
    nowTime = int(time.time() *1000)
    random1 = random.randint(1000,1998)
    random2 = random.randint(1000,9999)
    return "%d%d%d" %(nowTime,random1,random2)

def getFileIDMixString(seed):
    mixed=[]
    source=list("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/:._-1234567890")
    seed=float(seed)
    for i in range(len(source)):
        seed = (seed * 211 + 30031 ) % 65536
        index = math.floor(seed /65536 *len(source))
        mixed.append(source[int(index)])
        source.remove(source[int(index)])
    #return ''.join(mixed)
    return mixed

def getFileId(fileId,seed):
    mixed=getFileIDMixString(seed)
    ids=fileId.split('*')
    realId=[]
    for ch in ids:
        realId.append(mixed[int(ch)])
    return ''.join(realId)
if __name__ == '__main__':
    #print createSid()
    print getFileIDMixString(4528)
    fileId='49*48*49*49*49*12*49*5*49*49*1*42*49*16*42*1*32*11*42*16*55*49*49*5*63*38*1*11*38*16*32*38*19*49*1*55*55*42*64*32*1*2*23*64*11*48*38*15*64*12*23*38*48*64*11*16*49*38*19*49*55*12*49*5*63*42'
    seed=2034
    print getFileId(fileId,seed)

整体的源码:

test.html ?使用的时候使用IE浏览器,其他的还在研究中

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
  <head>
    <title>JSON</title>
  </head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  
  <script type="text/javascript">
   var xmlhttp;
   var message="";
   
   //本源码只能在IE浏览器或者IE模式下可以使用,因为ActiveXObject有足够的权限,而XMLHttpRequest不能跨域请求json

   //创建http 请求的对象
       function createxmlhttpRequest() {
            try {
                xmlhttp = new ActiveXObject("Msxml2.xmlhttp");
            } catch (e) {
                try {
                    xmlhttp = new ActiveXObject("Microsoft.xmlhttp");
                } catch (e2) {
                    xmlhttp = false;
                }
            }
            if (!xmlhttp && typeof XMLHttpRequest  != "udefined") {
                try {
					xmlhttp = new XMLHttpRequest ();
					} catch (e2) {
                    xmlhttp = false;
                }
            }
        }
		
	//工具函数,删除一个字符串指定位置的字符
	function remove(str,index)
	{
		if(str == null)
			return null;
		if(index < 0)
			return str;
		if(index < str.length)
		{
			str=str.substring(0,index)+str.substring(index+1);
			return str;
		}
		else
		{
			return null;
		}
	}
		

	//通过seed计算得到解密的“种子”
	function getFileIDMixString(_seed)
	{
		var	mixed			= [];
		var source			= "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/:._-1234567890";
		var seed			= parseFloat(_seed)+0.00;
		
		
		var source_length = source.length;
		for(var i = 0 ; i < source_length ; i ++)
		{
			seed		= (seed * 211 + 30031) % 65536;
			var index	= Math.floor(seed /65536 * (source.length));
			index		= parseInt(index);
			mixed[i]	= source.charAt(index);
			
			source = remove(source,index);
		}
		
		return mixed;
	}
	
	//通过上边的解密种子,将fileid解密
	function getFileId(fileId,seed)
	{
		var mixed	= getFileIDMixString(seed);
		var ids		= fileId.split('*');
		var realId	= [];
		
		for(var i = 0 ; i < ids.length ; i ++)
		{
			if(ids[i] == "")break
			realId[i] = mixed[ids[i]];
		}
		
		return realId;
	}
	

    function getInfo()
    {
		createxmlhttpRequest();
		try {
		
		//实验方法:
		//找到一个优酷视频的链接:   http://v.youku.com/v_show/id_XMjQwOTM4NDQ4.html
		//将id后边的XMjQwOTM4NDQ4取出,连接成字符串:   http://v.youku.com/player/getPlayList/VideoIDS/XMjQwOTM4NDQ4
			xmlhttp.open("get","http://v.youku.com/player/getPlayList/VideoIDS/XMjQwOTM4NDQ4",false);
			xmlhttp.onreadystatechange = returnInfo;
			xmlhttp.send(null);
		}
		catch(e)
		{
		}
    }

	//回调函数,处理传回来的json
    function returnInfo()
    {
		if(xmlhttp.readyState == 4)
		{
			var info = xmlhttp.responseText;
			eval("var json= " + info);
			
			var seed			= "";
			var title			= "";
			var streamtypes		= [];
			var streamfileids	= [];
			var segs			= [];
			var	mixed			= [];
			var FileId			= [];
			var video			= [];
			var videorealurl	= [];
			
			seed			= json.data[0].seed;
			document.getElementById("seed").innerHTML = "随机种子: "+seed;//显示此时的随机种子
			mixed = getFileIDMixString(seed);
			
			title			+= json.data[0].title;
			document.getElementById("title").innerHTML = "视频名字: "+title+"<br/>";//显示当前播放视频的名字
			
			
			streamtypes		= json.data[0].streamtypes;
			
			document.getElementById("streamtypes").innerHTML	= "视频格式: ";
			document.getElementById("streamfileids").innerHTML	= "加密的stream id: <br/>";
			document.getElementById("FileId").innerHTML			= "解密的stream id: <br/>";
			document.getElementById("video").innerHTML = "视频加密的K值:<br/>";
			
			for(var i = 0 ; i < streamtypes.length ; i ++)
			{
				streamfileids[i]	= json.data[0].streamfileids[""+streamtypes[i]];
				
				document.getElementById("streamtypes").innerHTML +=" "+streamtypes[i];//显示当前视频可以选择的种类
				document.getElementById("streamfileids").innerHTML+=streamtypes[i]+": "+streamfileids[i]+"<br/>";//显示当前视频加密后的stream id
				
				FileId[i] = getFileId(streamfileids[i],seed);
				var temp_fileid = "";
				for(var j = 0 ; j < FileId[i].length ; j ++)
				{
					temp_fileid += FileId[i][j];
				}
				FileId[i] = temp_fileid;
				document.getElementById("FileId").innerHTML += streamtypes[i]+": FileId: "+FileId[i]+"<br/>";//显示当前播放视频的名字
				
				document.getElementById("video").innerHTML += streamtypes[i]+" :<br/>";
				segs	= json.data[0].segs[""+streamtypes[i]];
				var url	= [];
				for(var j = 0 ; j < segs.length ; j ++)
				{
					document.getElementById("video").innerHTML += segs[j].k+"<br/>";//显示当前播放视频的名字
					//http://f.youku.com/player/getFlvPath/sid/138846963736713671615_00/st/flv/fileid/
					url[j] = "http://f.youku.com/player/getFlvPath/sid/00_00/st/";//基本路径
					url[j]+= streamtypes[i];//视频类型
					temp_fileid = FileId[i];
					if(j < 16)
						temp_fileid = temp_fileid.substring(0,8)+"0"+parseInt(j).toString(16)+temp_fileid.substring(10);
					else
						temp_fileid = temp_fileid.substring(0,8)+parseInt(j).toString(16)+temp_fileid.substring(10);
					
					url[j]+= "/fileid/"+temp_fileid;//增加file的id
					url[j]+= "?K="+segs[j].k;//增加K值验证
					document.getElementById("videorealurl").innerHTML += 
						j+": <a href=""+url[j]+"">"+url[j]+"</a><br/>";//显示当前播放视频的名字
				}
				videorealurl[i] = url;
			}
		}
    }
  </script>
  <body>
  
  <br/><br/>
  <h2 style="color: red;">JSON</h2>
  <br/>
  <input type="button" value="JSON" onclick="getInfo()" />
   <table>
    <tr><td><div id="test"></div></td></tr>
	<tr><td><div id="seed"></div></td></tr>
	<tr><td><span id="title"><span></td></tr>
	<tr><td><span id="streamtypes"><span></td></tr>
	<tr><td><span id="streamfileids"><span></td></tr>
	<tr><td><span id="FileIDMixString"><span></td></tr>
	<tr><td><span id="FileId"><span></td></tr>
	<tr><td><span id="video"><span></td></tr>
	<tr><td><span id="videorealurl"><span></td></tr>
   </table>
  </body>
</html>
实验结果:

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读