爬取美拍视频网址

1)博主最近想写一个类似小视频的webApp项目

爬取美拍的时候发现竟然找不到video标签,这样就影响了我获取视频地址啊
仔细看看网页源码发现发现原来视频地址藏在元素身上了

image.png

但是这个视频地址是加密了的?怎么办?看看美拍的请求,发现解密方法藏在js中,也就是说 解密是靠前端解密的

 var d = a("jquery")
      , e = a("support")
      , f = a("constants")
      , g = a("base64")
      , h = "substring"
      , i = "split"
      , j = "replace"
      , k = "substr";
    b.decodeMp4 = {
        getHex: function(a) {
            return {
                str: a[h](4),
                hex: a[h](0, 4)[i]("").reverse().join("")
            }
        },
        getDec: function(a) {
            var b = parseInt(a, 16).toString();
            return {
                pre: b[h](0, 2)[i](""),
                tail: b[h](2)[i]("")
            }
        },
        substr: function(a, b) {
            var c = a[h](0, b[0])
              , d = a[k](b[0], b[1]);
            return c + a[h](b[0])[j](d, "")
        },
        getPos: function(a, b) {
            return b[0] = a.length - b[0] - b[1],
            b
        },
        decode: function(a) {
            var b = this.getHex(a)
              , c = this.getDec(b.hex)
              , d = this[k](b.str, c.pre);
            return g.atob(this[k](d, this.getPos(d, c.tail)))
        }
    };

后期经过加工改造

;(function(base64){
        var substring='substring',
            split='split',
            reverse='reverse',
            join='join',
            toString='toString',
            substr='substr',
            replace='replace',
            fn={
            getHex: function(str) {//获取前4位标记数字
                return {
                    str: str[substring](4),//排除前4位字符串
                    hex: str[substring](0, 4)[split]("")[reverse]()[join]("")//前4位倒序
                }
            },
            getDec: function(str) {//获取混淆字符位置坐标
                str = parseInt(str, 16)[toString]();//前4位倒序的16进制
                //str[substring](0, 2)[split]("");
                return {
                    pre: str[substring](0, 2)[split](""),//前面坐标
                    tail: str[substring](2)[split]("")//后面坐标
                }
            },
            delStr: function(str, pos) {//混淆的字符抽取
                var s = str[substring](0, pos[0]),
                    del = str[substr](pos[0], pos[1]);//需替换的字符
                return s + str[substring](pos[0])[replace](del, "");//返回替换完成后的base64字符串
            },
            getPos: function(str, pos) {
                return [str.length - pos[0] - pos[1],pos[1]];
            },
            decode: function(str) {//解密
                var sh = this.getHex(str),//获取前4位标记数字
                    pos = this.getDec(sh.hex),//获取混淆位置坐标
                    d = this.delStr(sh.str, pos.pre);//前面混淆的字符抽取
                    d=this.delStr(d, this.getPos(d, pos.tail));
                return decodeURIComponent(escape(this.atob(d)));//base64转成utf-8(兼容中文)  atob
            },
            encode:function(str){//加密
                var base64=this.btoa(unescape(encodeURIComponent(str))),//转换成base64格式
                    random=this.getRanNum(base64),//获取16进制是4位数的随机字符
                    pos = this.getDec(random);//获取混淆位置坐标
                base64 = this.addStr(base64, pos);//插入混淆字符
                //console.log(random,pos)
                return random[toString]()[split]("")[reverse]()[join]("")+base64;
            },
            addStr: function(str, pos) {//混淆的字符插入
                var r1=this.getRanStr(pos.pre[1]),//获取随机字符串(前)
                    r2=this.getRanStr(pos.tail[1]),//获取随机字符串(后)
                    pre=this.insertStr(str,r1,pos.pre[0]),//插入随机字符串(前)
                    tail=pre.length - pos.tail[0];
                str=this.insertStr(pre,r2,tail);//插入随机字符串(后)
                return str;
            },
            atob:function(src){//解密
                //用一个数组来存放解码后的字符。
                var str=new Array();
                var ch1, ch2, ch3, ch4;
                var pos=0;
                //过滤非法字符,并去掉'='。
                src=src.replace(/[^A-Za-z0-9\+\/]/g, '');
                //decode the source string in partition of per four characters.
                while(pos+4<=src.length){
                  ch1=this.deKey[src.charCodeAt(pos++)];
                  ch2=this.deKey[src.charCodeAt(pos++)];
                  ch3=this.deKey[src.charCodeAt(pos++)];
                  ch4=this.deKey[src.charCodeAt(pos++)];
                  str.push(String.fromCharCode(
                    (ch1<<2&0xff)+(ch2>>4), (ch2<<4&0xff)+(ch3>>2), (ch3<<6&0xff)+ch4));
                }
                //给剩下的字符进行解码。
                if(pos+1>4), (ch2<<4&0xff)+(ch3>>2)));
                  }else{
                    str.push(String.fromCharCode((ch1<<2&0xff)+(ch2>>4)));
                  }
                }
                //组合各解码后的字符,连成一个字符串。
                return str.join('');
            },
            btoa:function(src){//加密
                //用一个数组来存放编码后的字符,效率比用字符串相加高很多。
                var str=new Array();
                var ch1, ch2, ch3;
                var pos=0;
                //每三个字符进行编码。
                while(pos+3<=src.length){
                  ch1=src.charCodeAt(pos++);
                  ch2=src.charCodeAt(pos++);
                  ch3=src.charCodeAt(pos++);
                  str.push(this.enKey.charAt(ch1>>2), this.enKey.charAt(((ch1<<4)+(ch2>>4))&0x3f));
                  str.push(this.enKey.charAt(((ch2<<2)+(ch3>>6))&0x3f), this.enKey.charAt(ch3&0x3f));
                }
                //给剩下的字符进行编码。
                if(pos>2));
                  if(pos>4))&0x3f));
                    str.push(this.enKey.charAt(ch2<<2&0x3f), '=');
                  }else{
                    str.push(this.enKey.charAt(ch1<<4&0x3f), '==');
                  }
                }
                //组合各编码后的字符,连成一个字符串。
                return str.join('');
            },
            insertStr:function(str,addstr,pos){//往指定位置插入字符串
                return str[substring](0,pos)+addstr+str[substring](pos);
            },
            getRanNum:function(str){//获取16进制是4位数的4位随机字符
                var ranArr=[];
                ;(function(){
                    var n='',
                        length=str.length;
                    /** 4101开始16进制是4位数 **/
                    for(var i=4101;i<=9999;i++){//找出所有符合要求的16进制4位数
                        n=i[toString](16);//10转成16
                        if(length>=8&&!(Math.floor(i/100)%10===0||i%10===0)&&n.length===4){
                        //正常的base64编码长度大于8才前后加混淆字符
                            //console.log(i,n);
                            if(Math.floor(i/1000)<=length/2&&Math.floor(i%100/10)<=length/2){//混淆位置不能大于长度一半
                                ranArr.push(n);
                            }
                        }else if(i%100===0&&n.length===4){//只在前面插入混淆字符
                            if(Math.floor(i/1000)<=length){//混淆位置不能大于长度
                                ranArr.push(n);
                            }
                        }
                    }
                }());
                var length=ranArr.length,
                    ran = Math.round(Math.random()*(length-1));
                return ranArr[ran];
            },
            enKey:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
            deKey: new Array(
                -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
            ),
            getRanStr:function(num){//获取指定个数随机字符串
                var key=this.enKey.split("");
                    length=key.length,
                    res = "";
                 for(; num-- ;) {
                     var id = Math.round(Math.random()*(length-1));
                     res += key[id];
                 }
                 return res;
            }
        }
        base64.tranCode=fn;
        window.base64=base64;
    }(window.base64||{}));

此方法包括 解密以及加密
window.base64.tranCode.decode(str) //解密

image.png

你可能感兴趣的:(爬取美拍视频网址)