HanDs
NO.2

[Delphi文章] 听音乐网歌曲地址及Delphi实现自动刺探 





学习中请遵循国家相关法律法规,黑客不作恶。没有网络安全就没有国家安全

本站需要登陆后才能查看


后来弄了个支持中文的。




【文章标题】: 手动分析一听音乐网歌曲下载地址及Delphi实现自动刺探
【文章作者】: BeyondMe
【作者邮箱】: [email protected]
【作者主页】: http://hi.baidu.com/beyond0769
【软件名称】: http://www.1ting.com
【下载地址】: http://www.1ting.com
【作者声明】: 绝对原创,如有雷同,纯属偶合。
--------------------------------------------------------------------------------
【 前   言 】: BeyondMe 又回来了,我说我不会离开UpK的,我还想继续在UPK混精华,希望版主们多多抬举 ^_^
此外有个要求,不要把我的文章移动到其它版块,我只需要呆在【我的起点】,因为我自认为自己是Newbie。

【详细过程】
  
   关于嗅探网页地址的软件N多,使用也非常方便,比如傲游的“网页嗅探器”功能就非常好用。
   这篇文章只是简单介绍一下如何手动分析国内知名在线试听网“一听音乐”http://www.1ting.com的歌曲的真实下载地址。
   这篇文章启发于“看雪”论坛里的某篇类似文章,有兴趣的可以去查询对比。
  
  
   分析依据:希望能通过在线播放时的地址来分析出该曲目的所有其它信息,包括:歌曲名,歌手,专辑,下载地址,甚至歌词等。
  
   分析过程:
  
   第一步:观察播放时的地址格式,留间有用信息。
   播放时有两种状态,要么单曲播放,要么多曲目连播,分别是以下两种格式,做个例子。
   单曲播放:http://www.1ting.com/player/9b/player_151572.html
   多曲连播:http://www.1ting.com/p_144658_14 ... _144291_144283.html
  
   很明显,URL后面的数字是曲目的身份标识ID。希望能通过这些ID来获得对应曲目的所有信息。
  
   第二步:通过ID获得曲目信息。这是最关键的一步.
   曲目的信息估计是保存在网站数据库或其它文件,不会直接提供一个绝对地址在源代码里,于是尝试分析这个网站如何分析ID对应
   曲目信息的原理。这里就提示我们把目光锁定在提交播放地址时网站会调用哪些 javascript 脚本去读取信息了。
  
   于是在播放器的页面上点右键“查看源文件”,Ctrl+F 搜索 '.js'后缀。可查得有几个 .js 被调用:
  1.    <script type="text/javascript" src="/v5/r4/js/jquery-1.3.2.min.js"></script>
  2.    <script type="text/javascript" src="/v5/r4/player/js/jquery.player.js"></script>
  3.    <script type="text/javascript" src="/v5/r4/player/js/lightbox.js"></script>
  4.    <script type="text/javascript" src="/v5/r4/player/js/share.js"></script>
  5.    <script type='text/javascript' src='/v5/js/m.js'></script>
复制代码
一个一个下载下来看看。(方法是提交 http://www.1ting.com 加上scr后面引号里的串)
   经过查看,发现 http://www.1ting.com/v5/r4/player/js/jquery.player.js 里面有一些好东西。
   还是用 记事本打开 然后复制到 word 里容易看一些。居然有28页那么长,那不看死人???
  
   耐心点可以看到一些有用东西: 虽然根本没有学过 JavaScript 语言,却能大体上看得懂这个js在做些什么。
   留意有用东西:
  
   Word里的第1页:
  1.   
  2.       },mt = ['http://f.dongmuzhi.com',//真实下载地址的基址!!!
  3.                'http://nonie.dongmuzhi.com:8082'];
复制代码
第2页:
  1.       a.fields={'song-id':0,'singer-name':1,
  2.                    'singer-url':2,'song-name':3,
  3.                    'song-url':4,'album-name':5,
  4.                    'album-url':6,'song-media':7,
  5.                    'album-cover':8};//这不是曲目的所有信息的字段名吗??
复制代码
第10页:
  1.       a.datasources = {
  2.              'history':function(){
  3.                return '/json2010_'+yiting.ed.get().join('_')+'.js'; //曲目的信息保存在此,最最重要的家伙。
  4.              },
复制代码
第26页
  1.       $('#jlrc_url').attr('src','http://www.1ting.com/lrc'+b+'.html');//类似于歌词的下载地址
复制代码
……
  
   当然可能还有其它有用信息,有兴趣自己去找。
   关键定位无疑在第10页那个保存曲目信息的.js地址了。
   即 http://www.1ting.com 加上 /json2010_ 加上曲目的ID 再加上 .js
  
   比如前面提到我的比较喜欢的BEYOND早期第一首曲:
   单曲播放:http://www.1ting.com/player/9b/player_151572.html
   ID是 151572
   则保存其曲目信息的地址在:http://www.1ting.com/json2010_151572.js
  
   提交后得到返回信息如下:http://f.dongmuzhi.com/
  
   window.callback([["151572","Beyond","http:\/\/www.1ting.com\/singer\/70\/singer_1751.html","Dead Romance (Part\u2161)","http:\/\/www.1ting.com\/player\/9b\/player_151572.html","\u518d\u89c1\u7406\u60f3","http:\/\/www.1ting.com\/album\/65\/album_11220.html","\/zzzzfuck520\/2007eMay\/05h_Beyond\/5.wma","http:\/\/img.1ting.com\/images\/special\/38\/s150_59d644e6ddaf593407239013271eb008.jpg"]])

   一切尽在意料当中。
  
   整理得到:
   第1个参数是:歌曲ID
   第2个参数是:歌手名
   第3个参数是:歌手介绍地址
   第4个参数是:歌曲名
   第5个参数是:播放页面地址
   第6个参数是:专辑名
   第7个参数是:专辑地址
   第8个参数是:歌曲下载地址
   第9个参数是:专辑封面图
  
   第三步:处理曲目信息得到最终想到的数据:
  
   要得到这个地址的真实下载地址很简单的事了。提交“基址”+ 第8个参数。(当然要把\号去掉,否则无法解析)
   比如上述曲目的真实地址为:http://f.dongmuzhi.com/zzzzfuck520/2007eMay/05h_Beyond/5.wma
   放到迅雷里马上可以下载了。OK
  
  
   ========================================
  
   网站的曲目查询过程小结如下:
   1、提交播放地址(含ID号的URL)
   2、通过"/v5/r4/player/js/jquery.player.js"获得曲目的信息文件 http://www.1ting.com/json2010_ ID.js,以及其它歌词等信息。
   3、把相关信息提交播放器进行播放。
  
   当然上述只是一个非常粗略的过程,其中还有一些加密,查询过程,次要,略过。
  
   =======================================
  
   知道了原理,不妨用 Delphi 写一个下载地址刺探工具。详细实现过程如下,看注释。
  1.    unit Unit1;
  2.   
  3.    interface
  4.   
  5.    uses
  6.    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7.    Dialogs, StdCtrls, ComCtrls, Menus, WinInet, ExtCtrls, ShellAPI, Clipbrd;
  8.   
  9.    type
  10.    TForm1 = class(TForm)
  11.       Button1: TButton;
  12.       EditURL: TEdit;
  13.       LV: TListView;
  14.       SB: TStatusBar;
  15.       Label1: TLabel;
  16.       Pop: TPopupMenu;
  17.       mTTPlayer: TMenuItem;
  18.       mIE: TMenuItem;
  19.       mCopySongURL: TMenuItem;
  20.       N1: TMenuItem;
  21.       mMediaPlay1: TMenuItem;
  22.       N2: TMenuItem;
  23.       mCopyAll: TMenuItem;
  24.       procedure Button1Click(Sender: TObject);
  25.       procedure LVMouseDown(Sender: TObject; Button: TMouseButton;
  26.              Shift: TShiftState; X, Y: Integer);
  27.       procedure mCopySongURLClick(Sender: TObject);
  28.       procedure mIEClick(Sender: TObject);
  29.       procedure mTTPlayerClick(Sender: TObject);
  30.       procedure mMediaPlay1Click(Sender: TObject);
  31.       procedure mCopyAllClick(Sender: TObject);
  32.    private
  33.       { Private declarations }
  34.       function GetSongInfoJsURL(ID: string): string;
  35.       //过滤'\'号
  36.       function DelSlash(Str: string): string;
  37.   
  38.    public
  39.       { Public declarations }
  40.    end;
  41.   
  42.    var
  43.    Form1: TForm1;
  44.    iINDEX: Integer; //当前被选中的条目。
  45.   
  46.    implementation
  47.   
  48.    {$R *.dfm}
  49.   
  50.    {读取指定URL的源代码内容}
  51.    function GetWebPage(const Url: string): string;
  52.    var
  53.    Session, HttpFile: HINTERNET;
  54.    szSizeBuffer: Pointer;
  55.    dwLengthSizeBuffer: DWord;
  56.    dwReserved: DWord;
  57.    dwFileSize: DWord;
  58.    dwBytesRead: DWord;
  59.    Contents: PChar;
  60.    begin
  61.    Session := InternetOpen('', 0, nil, nil, 0); ///初始化WININET.DLL
  62.    HttpFile := InternetOpenUrl(Session, PChar(Url), nil, 0, 0, 0); //连接服务器并读取数据
  63.    dwLengthSizeBuffer := 1024;
  64.    HttpQueryInfo(HttpFile, 5, szSizeBuffer, dwLengthSizeBuffer, dwReserved); //得到页面信息
  65.    GetMem(Contents, dwFileSize); //开辟内存
  66.    InternetReadFile(HttpFile, Contents, dwFileSize, dwBytesRead); //读取文件
  67.    InternetCloseHandle(HttpFile); //释放HttpFile资源
  68.    InternetCloseHandle(Session); //释放Session资源
  69.    Result := StrPas(Contents);
  70.    FreeMem(Contents); //释放
  71.    end;
  72.   
  73.    //核心过程,通过播放地址来读取曲目相关的信息以及下载地址
  74.    procedure TForm1.Button1Click(Sender: TObject);
  75.    var
  76.    PlayURL: string;
  77.    AChar: Char;
  78.    I, J, K: Integer;
  79.    index: Integer; //当前处理的曲目序号
  80.    iLen: Integer; //播放URL的长度、
  81.    ID: string;
  82.    strSongInfo: string; //歌曲所有信息字符串
  83.    iPos: array[1..18] of Integer; //保存strSongInfo中含有"号的位置 。
  84.    strSong, strAlbum, strSinger, strSongURL: string;
  85.    begin
  86.    Button1.Enabled := False;
  87.    PlayURL := EditURL.Text;
  88.    iLen := Length(PlayURL);
  89.    if iLen <= 0 then Exit;
  90.    if Pos('www.1ting.com', PlayURL) <= 0 then
  91.    begin
  92.       SB.Panels[1].Text := '抱歉!只支持对"一听音乐"(www.1ting.com)的地址刺探,请重新输入。';
  93.       Beep();
  94.       Exit;
  95.    end;
  96.    ID := '';
  97.    index := 0;
  98.    try
  99.       for I := (iLen - 5) downto 1 do
  100.       begin
  101.              AChar := PlayURL[I];
  102.              Application.ProcessMessages;
  103.              LV.Update;
  104.              if (AChar <> '_') then Insert(AChar, ID, 0)
  105.              else
  106.              begin
  107.                //获得一个ID之后马上联网读取相关信息并显示到ListView中。
  108.                SB.Panels[1].Text := '正在读取ID为' + ID + '的曲目信息.....';
  109.                strSongInfo := GetWebPage(GetSongInfoJsURL(ID));
  110.                K := 0; //初始化K
  111.                for J := 1 to Length(strSongInfo) do
  112.                begin
  113.                   if strSongInfo[J] = '"' then
  114.                   begin
  115.                          inc(K);
  116.                          iPos[K] := J; //获得" 号的序数
  117.                   end;
  118.                end;
  119.                //歌曲名:
  120.                strSong := Copy(strSongInfo, iPos[7] + 1, iPos[8] - iPos[7] - 1);
  121.                //歌手:
  122.                strSinger := Copy(strSongInfo, iPos[3] + 1, iPos[4] - iPos[3] - 1);
  123.                //专辑
  124.                strAlbum := Copy(strSongInfo, iPos[11] + 1, iPos[12] - iPos[11] - 1);
  125.                //下载地址:
  126.                strSongURL := Copy(strSongInfo, iPos[15] + 1, iPos[16] - iPos[15] - 1);
  127.                with LV.Items.Insert(0) do //添加到ListView列表中。
  128.                begin
  129.                   Caption := ID; //添加标题。
  130.                   SubItems.Add(DelSlash(strSong));
  131.                   SubItems.Add(DelSlash(strSinger));
  132.                   SubItems.Add(DelSlash(strAlbum));
  133.                   SubItems.Add(DelSlash('http://f.dongmuzhi.com' + DelSlash(strSongURL)));
  134.                end;
  135.                inc(index);
  136.                ID := '';
  137.                Continue;
  138.              end;
  139.       end;
  140.    finally
  141.       SB.Panels[1].Text := '搜索完成,共找到' + IntToStr(index) + '条曲目';
  142.       Button1.Enabled := True;
  143.    end;
  144.    end;
  145.   
  146.    //弹出右键菜单
  147.    procedure TForm1.LVMouseDown(Sender: TObject; Button: TMouseButton;
  148.    Shift: TShiftState; X, Y: Integer);
  149.    var
  150.    pt: TPoint;
  151.    begin
  152.    if (Button = mbRight) and (LV.SelCount = 1) then
  153.    begin
  154.       Windows.GetCursorPos(pt);
  155.       if LV.Selected <> nil then iINDEX := LV.Selected.index;
  156.       Pop.Popup(pt.X, pt.Y);
  157.    end;
  158.    end;
  159.   
  160.   
  161.   
  162.    //根据ID获得对应 js 信息地址:
  163.    function TForm1.GetSongInfoJsURL(ID: string): string;
  164.    begin
  165.    Result := 'http://www.1ting.com/json2010_' + ID + '.js';
  166.    end;
  167.   
  168.   
  169.    //去掉曲目信息里的\号
  170.    function TForm1.DelSlash(Str: string): string;
  171.    var
  172.    I: Integer;
  173.    begin
  174.    Result := '';
  175.    for I := 1 to Length(Str) do
  176.    begin
  177.       if Str[I] = '\' then Continue;
  178.       Result := Result + Str[I];
  179.    end;
  180.    end;
  181.   
  182.    procedure TForm1.mIEClick(Sender: TObject);
  183.    begin
  184.    ShellExecute(0, '', 'IEXPLORE', PChar(LV.Items[iINDEX].SubItems.Strings[3]), nil, SW_MINIMIZE)
  185.    end;
  186.   
  187.    procedure TForm1.mTTPlayerClick(Sender: TObject);
  188.    begin
  189.    ShellExecute(0, '', 'TTPlayer', PChar(LV.Items[iINDEX].SubItems.Strings[3]), nil, SW_SHOW)
  190.    end;
  191.   
  192.    procedure TForm1.mMediaPlay1Click(Sender: TObject);
  193.    begin
  194.    ShellExecute(0, '', 'MediaPlay', PChar(LV.Items[iINDEX].SubItems.Strings[3]), nil, SW_SHOW)
  195.    end;
  196.   
  197.   
  198.    {复制指定列表到剪贴板}
  199.    procedure TForm1.mCopySongURLClick(Sender: TObject);
  200.    begin
  201.    clipboard.Clear;
  202.    clipboard.AsText := LV.Items[iINDEX].SubItems.Strings[3];
  203.    end;
  204.   
  205.    {复制指定列表到剪贴板}
  206.    procedure TForm1.mCopyAllClick(Sender: TObject);
  207.    begin
  208.    clipboard.Clear;
  209.    clipboard.AsText := LV.Items[iINDEX].Caption + ' ' + LV.Items[iINDEX].SubItems.CommaText;
  210.    end;
  211.   
  212.    end.

==================================
  
   写在最后:
  
   这个Delphi实现过程只是以粗糙的算法简单地复述了网站获得网址的过程。明显还有不少需要改进的地方
  
   1、程序简单使用单线程,速度慢,可能会因网速慢出现假死状态。有兴趣的网友把它改成多线程的吧。
   2、程序没有做过多的异常捕获,胡乱地输一些网址进去会导致出错退出。
      本程序没有过多考虑这个转换,大家去完善。而且上述代码不支持中文编码,但这个问题已经被解决。到 http://www.unpack.cn/viewthread.php?tid=45432 详见。

  


学习中请遵守法律法规,本网站内容均来自于互联网,本网站不负担法律责任
音乐网 歌曲 地址 D el ph i 实现 自动 刺探
#1楼
发帖时间:2016-7-9   |   查看数:0   |   回复数:0
游客组