V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
jacy
V2EX  ›  编程

研究虾米高品质歌曲地址,遇到问题,编解码高手来看看

  •  
  •   jacy · 2013-08-02 22:37:58 +08:00 · 4323 次点击
    这是一个创建于 4126 天前的主题,其中的信息可能已经有所发展或是发生改变。
    通过对在线播放器抓包,发现播放器首先发送这个:
    http://www.xiami.com/song/gethqsong/sid/歌曲id
    会返回一段json数据,比如:
    {"status":1,"location":"8h2fmFfmxu4wMVVzVBtFiihTgcP9EYRq2Rlt%l.%IqhRU84gVjIOp2ec28S%HtJDts9Wm%F.oFdV5jqomIfI%I3mxmh4TESg%kxFG2A3i%GzYeFo5ZyLu5%.a2u1g4wtECOTp2"}
    然后就下载歌曲了,地址是:
    http://m3.file.xiami.com/h/hGufTI8d4z1mgqSVTYgxch0e4uPRHjSFw49UtqgotwE8Jo0MY4DmkZCVRgtIxyOVqVsfFLTz2j9IGupVRIW%2BlOmI
    可以肯定地址是根据location中算出来的,但是没看出是怎样编码的,如果不是常用的,那么还得反编译播放器的swf文件了。
    发到这看看有人能否解出。
    另外即使同一个歌曲每次的数据和地址都会变化,但是老的地址在一定时间内还是可以访问下载到的。
    第 1 条附言  ·  2013-08-04 12:03:12 +08:00
    已经自己解决了
    http://v2ex.com/t/77863
    大家可以试试,可下载320kpbs的mp3。
    7 条回复    1970-01-01 08:00:00 +08:00
    jacy
        1
    jacy  
    OP
       2013-08-02 22:42:45 +08:00
    长的英文不会自动换行啊-_-||
    双击复制下来,粘贴到回复框看完整的数据
    jacy
        2
    jacy  
    OP
       2013-08-02 22:57:19 +08:00
    经过反编译,确实不是常用编码,是虾米自己的算法,找到as文件了,不太会,谁翻译一下

    package xiami
    {
    import com.adobe.serialization.json.*;
    import flash.events.*;
    import flash.net.*;

    public class HQlocationDecode extends EventDispatcher
    {
    private var _url:String;
    private var _isHQ:Boolean;
    private static const getHQlocationUrl:String = "http://www.xiami.com/song/gethqsong/sid/";
    private static const getTrylocationUrl:String = "http://www.xiami.com/song/gethqsong";

    public function HQlocationDecode()
    {
    return;
    }// end function

    public function getTryLoation(param1:int, param2:String = null, param3:int = 0) : void
    {
    var _loc_4:* = new URLRequest(getTrylocationUrl);
    var _loc_5:* = new URLVariables();
    new URLVariables().sid = param1;
    _loc_5.type = param2;
    _loc_5.typeId = param3;
    _loc_4.data = _loc_5;
    var _loc_6:* = new URLLoader();
    new URLLoader().addEventListener(Event.COMPLETE, this.loadCompleteHandler);
    _loc_6.addEventListener(IOErrorEvent.IO_ERROR, this.errorHandler);
    _loc_6.load(_loc_4);
    return;
    }// end function

    public function getHQLocation(param1:int, param2:String = null, param3:int = 0) : void
    {
    var _loc_4:* = new URLRequest(getHQlocationUrl + param1);
    var _loc_5:* = new URLLoader();
    new URLLoader().addEventListener(Event.COMPLETE, this.loadCompleteHandler);
    _loc_5.addEventListener(IOErrorEvent.IO_ERROR, this.errorHandler);
    _loc_5.load(_loc_4);
    return;
    }// end function

    private function loadCompleteHandler(event:Event) : void
    {
    var _loc_4:* = undefined;
    var _loc_2:* = event.target.data;
    var _loc_3:* = JSON.decode(_loc_2).status;
    if (_loc_3 == 1)
    {
    this._isHQ = true;
    _loc_4 = JSON.decode(_loc_2).location;
    this._url = this.getLocation(_loc_4);
    }
    else
    {
    this._isHQ = false;
    this._url = null;
    }
    dispatchEvent(new Event(Event.COMPLETE));
    return;
    }// end function

    private function errorHandler(event:Event) : void
    {
    this._isHQ = false;
    dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR));
    return;
    }// end function

    public function get url() : String
    {
    return this._url;
    }// end function

    public function get isHQ() : Boolean
    {
    return this._isHQ;
    }// end function

    public function getLocation(param1:String) : String
    {
    var _loc_10:* = undefined;
    var _loc_2:* = Number(param1.charAt(0));
    var _loc_3:* = param1.substring(1);
    var _loc_4:* = Math.floor(_loc_3.length / _loc_2);
    var _loc_5:* = _loc_3.length % _loc_2;
    var _loc_6:* = new Array();
    var _loc_7:* = 0;
    while (_loc_7 < _loc_5)
    {

    if (_loc_6[_loc_7] == undefined)
    {
    _loc_6[_loc_7] = "";
    }
    _loc_6[_loc_7] = _loc_3.substr((_loc_4 + 1) * _loc_7, (_loc_4 + 1));
    _loc_7 = _loc_7 + 1;
    }
    _loc_7 = _loc_5;
    while (_loc_7 < _loc_2)
    {

    _loc_6[_loc_7] = _loc_3.substr(_loc_4 * (_loc_7 - _loc_5) + (_loc_4 + 1) * _loc_5, _loc_4);
    _loc_7 = _loc_7 + 1;
    }
    var _loc_8:* = "";
    _loc_7 = 0;
    while (_loc_7 < _loc_6[0].length)
    {

    _loc_10 = 0;
    while (_loc_10 < _loc_6.length)
    {

    _loc_8 = _loc_8 + _loc_6[_loc_10].charAt(_loc_7);
    _loc_10 = _loc_10 + 1;
    }
    _loc_7 = _loc_7 + 1;
    }
    _loc_8 = unescape(_loc_8);
    var _loc_9:* = "";
    _loc_7 = 0;
    while (_loc_7 < _loc_8.length)
    {

    if (_loc_8.charAt(_loc_7) == "^")
    {
    _loc_9 = _loc_9 + "0";
    }
    else
    {
    _loc_9 = _loc_9 + _loc_8.charAt(_loc_7);
    }
    _loc_7 = _loc_7 + 1;
    }
    _loc_9 = _loc_9.replace("+", " ");
    return _loc_9;
    }// end function

    }
    }
    PeterD
        3
    PeterD  
       2013-08-03 16:32:52 +08:00
    dndx
        4
    dndx  
       2013-08-03 16:45:04 +08:00
    pubby
        5
    pubby  
       2013-08-03 16:56:12 +08:00
    还好了,算法是固定的,改写成你需要的语言就可以解码了。

    以前破解百度指数算法的时候,他是每几小时随机变化的加解密算法,而且编译在swf文件里面。当时不得不对照《ActionScript Virtual Machine 2 (AVM2) Overview》写了个简单的ABC(ActionScript Byte Code)模拟器来解码 :(
    jjplay
        6
    jjplay  
       2013-08-03 17:00:11 +08:00
    很早 算不上研究,找到了3L 那人的文章,最终下载的还是低品质的~
    jacy
        7
    jacy  
    OP
       2013-08-04 12:01:33 +08:00
    晕哦,谢了,不过你们回复太慢了,我已经自己做好了
    http://v2ex.com/t/77863
    可以下载高品质哦
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3485 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 11:17 · PVG 19:17 · LAX 03:17 · JFK 06:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.