使用nodejs解析优酷,奇艺视频源地址

项目地址

这个项目通过一个优酷或者爱奇艺的视频地址,最终可以得到视频的下载地址

这个项目的想法是来源:https://github.com/keygle/parseVideo

因为自己要用到优酷和奇艺,所以就测试了这两个,测试结果是优酷的可以使用,爱奇艺的已经失效。

经过研究爱奇艺的视频页面的http请求,以及反编译视频播放器,找到它的下载地址,自己做了一个pr,现在该项目作者已经merge了。

这是一个php工程,所以自己用node把这个工程里面解析优酷和爱奇艺的方法重写了下

说明:

var video = require('./index');

video('http://www.iqiyi.com/v_19rrnbyreg.html','MP4',function(err,data){
    console.log(data);
});

第一个参数是视频地址(必填),第二参数是返回的视频格式(选填,只针对爱奇艺),第三个参数回掉函数(必填)

最终取到的爱奇艺的flv格式地址如下:

http://data.video.qiyi.com/f3060e76a71fedac773d327734e723f2/videos/v0/20141023/7b/b5/96c5fa7650168e97c445f976b0b5b68f.f4v?ran=1000&qyid=08ca8cb480c0384cb5d3db068161f44f&qypid=321778500_11&retry=1

是这样的,下载地址需要请求上面这个地址得到:

{
    "t": "CT|ShangHai-101.81.48.14",
    "s": "1",
    "z": "hengyang3_ct",
    "h": "0",
    "l": "http://220.170.79.37/videos/v0/20141221/38/e6/4be4e1cad4374d3447be144397366ff8.f4v?key=8f5bdcd17a8765c&ran=1000&qyid=08ca8cb480c0384cb5d3db068161f44f&qypid=335764500_11&retry=1&uuid=6551300e-5497c256-36",
    "e": "0"
}

返回结果中的l是真正的下载地址,而这个地址失效时间非常短,故返回的是上面的地址,如果最终取到的下载地址失效,再次请求返回的这个地址即可.

ps:爱奇艺的结果不是很稳定,有时解析出来的地址无法播放,解决办法只能多解析几次,测试发现有时取到的视频的ip地址是不通了,估计是奇艺的服务器的问题

分析优酷的下载地址可以参考这篇文章

这里说下分析爱奇艺的思路:

1.分析mp4或者m3u8,方法都一样,只是有一个参数不一样

因为pc上播放的视频都是flv格式的,所以你只能用移动设备做这个工作了,用iphone真机或者模拟器,配合safari使用,可以在safari上面调试页面,随便选一个视频页面,找到页面上的

<script>eval(function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1;};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p;}('z 1h(e,n,t,a,r,o){z i(e,n){F((e>>1)+(n>>1)<<1)+(1&e)+(1&n)}z c(e,n,t,a){e>0&&5>e?t>=0?p<<6>n?(a=[a[3],i(a[1],(x=i(i(a[0],[a[1]&a[2]|~a[1]&a[3],a[3]&a[1]|~a[3]&a[2],a[1]^a[2]^a[3],a[2]^(a[1]|~a[3])][y=t>>4]),i(j(m(t+1))*N|0,B[[t,5*t+1,3*t+5,7*t][y]%16+(n++>>>6)])))<<(y=[7,12,17,22,5,9,14,20,4,11,16,23,6,10,15,21][4*y+t%4])|x>>>1f-y),a[1],a[2]],P&n?c(e,n,P&n,a):(A=[i(a[0],A[0]),i(a[1],A[1]),i(a[2],A[2]),i(a[3],A[3])],c(e,n+1U,P&n,A))):(B=[],p=""):C?c(12,n,0,"1X"):c(13,n,0,"24"):e>6&&10>e?(e=X(1c(a)),t<e.K?(B[n>>2]|=e.19(t++)<<8*(n%4),c(9,++n,t,M)):(d(1Y.2a(26))&&(B[n>>2]|=1<<(n%4<<3)+7),B[p=(n+8>>6<<4)+14]=n<<3,c(3,0,0,A))):e>11&&15>e&&(t<(a.K<<1)/5?(B[n>>2]|=(2n(a.2m(10*(t>>2),10),10)>>(3-(3&t)<<3)&1r^(a.K<<1)/5-t++)<<((3&n++)<<3),c(14,n,t,a)):c(7,n,0,M))}z d(e){F"1o"!=1k G[e]}q u=18.1j,h=18.1w,s=G.1F;(1b===s||-1b===s)&&(u=u>h?h:u);q f=G.1d;u=H.V(u/f);q w=H.V(G.1G/f),b=H.V(G.1J/f),v=u-b-w,g=L(w+"N"+v),l="",N=1n,j=H.1l,m=H.1m,p="";d("1H")&&(p=Q.1I,p&&p.1L("1M.1K")>=0||(l+=L("1z"))),l+=d("1A")?(l?"N":"")+L("1x"):"";q C=n,M=e,T=7,k={},R=(1C 1B).1E();k.J=(n?o+""+r:R-T)+"",M=O(L(M)),k.J=O(L(C?k.J+a+""+t:k.J));q x,y,A=[x=1D,y=-1y,~x,~y],B=[],D=z(){1a(p=X(1c(k.J)),y=0;y<p.K;)B[y>>2]|=p.19(y)<<8*(y++%4);1a(c(1,y,-1,B),x=0;1f>x;)p+=(A[x>>3]>>4*(1^7&x++)&15).Y(16);F p},E=z(){q e="z%1t%28%29%20%1v%20%1s%1p%1q%20%1u",n="1N";F"2c"2f Q.2g.2h&&(n=O(2e.2b.Y())===e?"2j":"2d"),n};Z(n){q I={};F I.1g=D,I.1i=E,I.d=R,I}q S=D();Z(S.K>4){q U="";U+=Q.2i+";"+G.1d+";&2o="+R,U=2l(U);q W={};F W.1T="1S",W.1V=S,W.1P=U,l&&(W.1W=l),g&&(W.25=g),W.t=R-7,W.1e=E(),W}}z 1Z(e,n,t,a){q r=1h("",!0,a,t,n,e),o="27",i={};F i.1Q="1R",i.1O=r.1g(o,!0),i.2k=r.d-7,i.1e=r.1i(),i}',62,149,'||||||||||||||||||||||||||var|||||||||function||||||return|window|Math||cache|length|btoa||_|escape|63|document|||||round||atob|toString|if|||||||||screen|charCodeAt|for|90|unescape|devicePixelRatio|__jsT|32|md|weorjjigh|jc|height|typeof|abs|sin|4294967296|undefined|20code|5D|255|5Bnative|20javaEnabled|7D|7B|width|BOL|271733879|UCW|_0|Date|new|1732584193|getTime|orientation|screenTop|ucweb|referrer|outerHeight|com|indexOf|baidu|null|__sigC|__refI|__cliT|h5|d846d0c32d664d32b6b54ea48997a589|src|960|sc|qd_jsin|1330848328159996040014666388890612187513113019274921193194001265062984|String|weorjjighly|||||03603482862038069294069554231005389970290678182205184924421910467011111731869494|qd_wsz|81|jfakmkafklw23321f4ea32459|||fromCharCode|javaEnabled|WebkitAppearance|sijsc|navigator|in|documentElement|style|URL|sgve|__ctmM|encodeURIComponent|substr|parseInt|tim'.split('|'),0,{}));/*v20150304*/</script>

这段js是客户端加密的一个方法,它的作用是生成请求视频信息的参数,虽然它是结果混淆了,我们可以反混淆把这段js解析出来,整个解析的过程,这个函数很重要,其余只要监视网络请求,就可以获得最终的视频请求url。具体可以查看我的github

2.分析flv

我的做法是反编译爱奇艺的flash播放器,然后配合http请求,分析反编译后的代码,找到加密方法。