首页
社区
课程
招聘
7
[原创]杀鸡焉用牛刀,再探好听音乐网
发表于: 2009-6-26 13:53 13085

[原创]杀鸡焉用牛刀,再探好听音乐网

2009-6-26 13:53
13085

看了破船兄的文章【原创】好听音乐网 -- 歌曲下载分析流程及程序的编写,我也来写一个。破船的代码是智慧型的,我来个猛士型的。。

打开好听音乐网的首页,随便点一首歌来听,出现了播放界面,同时音乐也出来了,这时查看源文件,容易发现如下关键代码

1
2
3
4
5
6
7
8
9
10
11
12
13
           if("undefined"==typeof(UUAuthCode)|| UUAuthCode==null)  UUAuthCode="";
    else UUAuthCode="?"+UUAuthCode;
        [COLOR="red"] urlht = "/21z/0/daodaidq090508/1/8f4257328b24c8d0_5.wma"+[/COLOR]UUAuthCode;
}
seto();
 
[COLOR="Red"]var url='http://wma.haoting.com';[/COLOR]
 
document.writeln("<object id=\"mPlayer\" width=365 height=62");
document.writeln(" classid=\"CLSID:6BF52A52-394A-11D3-B153-00C04F79FAA6\" type=application\/x-oleobject standby=\"Loading Windows Media Player ");
document.writeln("");
document.writeln("components...\">");
document.writeln("             <param name=\"URL\[COLOR="red"]" value='"+url+""+urlht+"'[/COLOR]>");

[注意]看雪招聘,专注安全领域的专业人才平台!

上传的附件:
收藏
免费 7
支持
分享
赞赏记录
参与人
雪币
留言
时间
Youlor
为你点赞~
2024-2-18 00:07
伟叔叔
为你点赞~
2024-1-4 03:18
QinBeast
为你点赞~
2023-11-22 00:17
shinratensei
为你点赞~
2023-10-5 00:03
PLEBFE
为你点赞~
2023-10-2 00:13
心游尘世外
为你点赞~
2023-9-21 00:10
飘零丶
为你点赞~
2023-9-12 00:17
最新回复 (15)
雪    币: 1708
活跃值: (586)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
3
原文有误,以 /21z/ 做为特征码并不能保证 100%找到下载地址,应该改为用 .wma 做为特征码,应该修改为
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
[color=#0000D0]for[/color] ([color=#0000D0]UINT[/color] i = 0; i < FileSize.u.LowPart; i++)
        {
 
            [color=#0000D0]if[/color] ((*lpByte == '.')           [color=#008000]//判断是不是找到了特征代码[/color]
                && (*(lpByte + 1) == 'w')
                && (*(lpByte + 2) == 'm')
                && (*(lpByte + 3) == 'a'))
            {
     
                [color=#0000D0]for[/color] (;;)
                {
                     
                    lpByte -= 1;
 
                    [color=#0000D0]if[/color] (*(lpByte - 1) == '[color=#808080]"')  //退回到左边的引号开始的地方[/color]
                    {
                         
                        [color=#0000D0]for[/color] ([color=#0000D0]UINT[/color] j = 0; ; j++)
                        {
                            szBuffer[j] = *lpByte;
                             
                            [color=#0000D0]if[/color] (*(++lpByte) == '[color=#808080]"') //判断是不是已经到尽头了[/color]
                            {
                                [color=#0000D0]break[/color];
                            }
 
                        }
 
                        [color=#0000D0]break[/color];
                    }
 
                     
                }
 
                [color=#0000D0]break[/color];
            }
 
            lpByte += 1;
        }
]
给大家带来不便,对不起了。。
上传的附件:
2009-6-26 16:13
0
雪    币: 168
活跃值: (152)
能力值: ( LV11,RANK:180 )
在线值:
发帖
回帖
粉丝
4
收益了,嘿嘿。
我没有仔细的看他的JS代码,没有找到这样的代码,不过看了同学你的文章以后,仔细看了一下我的程序,才发现,我的程序也存在问题的。


urlht = "/21z/0/daodaidq090508/1/8f4257328b24c8d0_5.wma"+UUAuthCode;

这里的“UUAuthCode”起到了一定的防止下载的作用。

很佩服LZ的学习精神,共同努力吧,嘿嘿
2009-6-27 11:16
0
雪    币: 1708
活跃值: (586)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
5
破船通过分析js的方法能获取很多有用信息,对于我等懒人,本来想拿来改改就用的, 但是在使用过程中还是发现了一个小问题,在分析到一个页面的时候,出现了乱码。。

反正源码已经有了,改改就行了,但是分析js实在是。。俺小菜目前的水平还不会,干脆还是直接读它的源文件吧,通过分析源文件,我们已经知道,真实的下载地址就是 url + urlht urlht 每首歌都不一样,而且url也不是一个固定值,在这里又要对不起大家了,之前我一直认为它是一个固定值,就没有把它分析出来。发现了这个问题,只要修改分析引擎就可以达到我们的要求了,当然也可以分析出歌曲名,歌手,和所属专辑。在这里我只分析了它的下载地址并且封装在了GetHaoTingWMAPath这个函数里,对于我们来说,这个才是最重要的。修改后的代码如下:
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
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
[color=#0000D0]BOOL[/color] [color=#0000D0]WINAPI[/color] GetHaoTingWMAPath([color=#0000D0]char[/color] * lpFullPath[color=#008000]/*指向存放下载地址的缓冲区指针*/[/color], [color=#0000D0]LPCTSTR[/color] lpURL[color=#008000]/*播放音乐的页面*/[/color], [color=#0000D0]LPCTSTR[/color] lpFileName[color=#008000]/*存放源文件的临时文件,会在文件关闭后被自动删除*/[/color])
{
  [color=#0000D0]char[/color] szBuffer[256];
 
  [color=#FF0000]memset[/color](szBuffer, 0, [color=#0000D0]sizeof[/color]([color=#0000D0]char[/color]) * 256);
 
  [color=#0000D0]if[/color] ([color=#0000D0]S_OK[/color] == [b][color=#000080]URLDownloadToFile[/color][/b]([color=#0000D0]NULL[/color],
    lpURL,
    lpFileName,
    0,
    [color=#0000D0]NULL[/color]))
  {
    [color=#0000D0]HANDLE[/color] hFile = [b][color=#000080]CreateFile[/color][/b](lpFileName,
      GENERIC_READ,
      FILE_SHARE_READ,
      [color=#0000D0]NULL[/color], OPEN_EXISTING,
      FILE_FLAG_DELETE_ON_CLOSE,
      [color=#0000D0]NULL[/color]);
     
         
    [color=#0000D0]if[/color] (INVALID_HANDLE_VALUE == hFile)
    {
      hFile = [color=#0000D0]NULL[/color];
      [color=#0000D0]return[/color] [color=#0000D0]FALSE[/color];
    }
 
    LARGE_INTEGER FileSize = {0};
 
    [b][color=#000080]GetFileSizeEx[/color][/b](hFile, &FileSize);
     
    [color=#0000D0]HANDLE[/color] hMemFile = [b][color=#000080]CreateFileMapping[/color][/b](hFile, [color=#0000D0]NULL[/color], PAGE_READONLY, 0, 0, [color=#0000D0]NULL[/color]);
 
    [color=#0000D0]if[/color] (INVALID_HANDLE_VALUE == hMemFile)
    {
      hMemFile = [color=#0000D0]NULL[/color];
      [color=#0000D0]return[/color] [color=#0000D0]FALSE[/color];
    }
 
    [color=#0000D0]LPBYTE[/color] lpByte = ([color=#0000D0]LPBYTE[/color])[b][color=#000080]MapViewOfFile[/color][/b](hMemFile, FILE_MAP_READ, 0, 0, 0);
 
    [color=#0000D0]for[/color] ([color=#0000D0]UINT[/color] i = 0; i < FileSize.u.LowPart; i++)
    {
 
      [color=#0000D0]if[/color] ((*lpByte == '.')           [color=#008000]//判断是不是找到了特征代码[/color]
        && (*(lpByte + 1) == 'w')
        && (*(lpByte + 2) == 'm')
        && (*(lpByte + 3) == 'a'))
      {
   
        [color=#0000D0]for[/color] (;;)
        {
           
          lpByte -= 1;
 
          [color=#0000D0]if[/color] (*(lpByte - 1) == '[color=#808080]"')[/color]
          {
             
            [color=#0000D0]for[/color] ([color=#0000D0]UINT[/color] j = 0; ; j++)
            {
              szBuffer[j] = *lpByte;
               
              [color=#0000D0]if[/color] ((*lpByte == 'a')
                && (*(lpByte - 1) == 'm')
                && (*(lpByte - 2) == 'w')
                && (*(lpByte - 3) == '.'))
              {
                [color=#0000D0]break[/color];
              }
 
              lpByte += 1;
 
            }
 
            [color=#0000D0]break[/color];
          }
 
           
        }
         
        [color=#0000D0]for[/color] ([color=#0000D0]UINT[/color] k = 0; ; k++)
        {
           
 
          [color=#0000D0]if[/color] ((*lpByte == 'h')
            && (*(lpByte + 1) == 'a')
            && (*(lpByte + 2) == 'o')
            && (*(lpByte + 3) == 't')
            && (*(lpByte + 4) == 'i')
            && (*(lpByte + 5) == 'n')
            && (*(lpByte + 6) == 'g')
            && (*(lpByte + 7) == '.')
            && (*(lpByte + 8) == 'c')
            && (*(lpByte + 9) == 'o')
            && (*(lpByte + 10) == 'm'))
          {
             
            [color=#0000D0]for[/color] (;;)
            {
              lpByte -= 1;
 
              [color=#0000D0]if[/color] ((*(lpByte - 1) == '\''))
              {
               
                [color=#0000D0]for[/color] ([color=#0000D0]UINT[/color] l = 0; ; l++)
                {
                  lpFullPath[l] = *lpByte;
 
                  [color=#0000D0]if[/color] ((*lpByte == 'm')
                    && (*(lpByte - 1) == 'o')
                    && (*(lpByte - 2) == 'c')
                    && (*(lpByte - 3) == '.'))
                  {
                    [color=#0000D0]break[/color];
                  }
 
                  lpByte += 1;
                }
 
                [color=#0000D0]break[/color];
              }
 
            }
             
            [color=#0000D0]break[/color];
          }
 
          lpByte += 1;
 
        }
 
        [color=#0000D0]break[/color];
      }
 
      lpByte += 1;
    }
     
    [b][color=#000080]UnmapViewOfFile[/color][/b](([color=#0000D0]LPVOID[/color])lpByte);
 
    [b][color=#000080]CloseHandle[/color][/b](hMemFile);
    [b][color=#000080]CloseHandle[/color][/b](hFile);
     
    lstrcatA(lpFullPath, szBuffer);
 
    [color=#0000D0]return[/color] [color=#0000D0]TRUE[/color];
 
  }
 
  [color=#0000D0]return[/color] [color=#0000D0]FALSE[/color];
 
}

为了方便,我写了个GUI界面来查看效果:

附件里是我写的Demo程序,我试过很多页面,都可以读出来。破船的那个程序有一个缺点,就是分析起来太久了,对于批量分析不太适用。。。

PS:
刚刚编辑完帖子,就发现破船回复了。。我写的这个分析引擎貌似它的防下载没有作用,因为我只读到.wma就不再读了,它后面是什么内容都不用管了...
上传的附件:
2009-6-27 11:33
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
这个用正则表达式很好做的
用脚本比如python等做的话会简单很多
2009-6-27 18:54
0
雪    币: 168
活跃值: (152)
能力值: ( LV11,RANK:180 )
在线值:
发帖
回帖
粉丝
7
很好很强大,嘿嘿。
我的程序写出来就发上来了,问题肯定很多啦,嘿嘿。
一个功能有好多的实现方法,多多交流,相互学习进步吧。

再次感谢cntrump 的指教^
2009-6-27 18:59
0
雪    币: 168
活跃值: (152)
能力值: ( LV11,RANK:180 )
在线值:
发帖
回帖
粉丝
8
至于乱码的问题,我也不清楚问题出在哪里,估计是我获取JS代码的函数没有做判断导致的。
至于慢,是因为我网络环境比较差,我加了Sleep等待。嘿嘿,去掉就可以了。
2009-6-27 19:06
0
雪    币: 1708
活跃值: (586)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
9
之前我一直都是实现单首播放时的歌曲路径获取,一直没有实现获取多曲播放页面时的音乐路径,实在不想留下这个遗憾,今天就一鼓作气把它拿下
首先在好听音乐网上选定几首歌曲连续播放,打开播放页面查看源文件,可以发现
1
2
3
4
5
6
7
8
var strstr = document.location.search;
var arrtmp = strstr.substr(1,strstr.length).split("&");
var qString = new Array();
for(iii=0;iii < arrtmp.length;iii++){
    var tmpStr2 = arrtmp[iii].split("=");
    if(tmpStr2[0]=="id")    document.write("<script src=\"../musicjs/"+(qString[iii]=tmpStr2[1])+".js\"><\/script>");  
    else break;
}

上面的这段代码意思是把地址中的歌曲ID分离出来,再和../musicjs/这个字符串连接,末尾再加上.js组成一个新的路径,这是一个相对路径,必需把把它转换为绝对的网址我们才能下载这个js文件.从../musicjs/这个字符串我们可以知道,这个目录是相对于网站的根目录的,可以轻易知道完整的URL就是http://www.haoting.com/musicjs/[id].js,从这里我们也可以知道,每个歌曲对应唯一个js,而且是以歌曲ID作为区分的,对于单曲播放也是一样,到底是不是这样?我们可以这样验证,随机输入一个ID做为歌曲的ID来下载相应的js是不是是可以呢?我构造了一个简单的地址http://www.haoting.com/musicjs/1.js,果然弹出来了我想要文件下载对话框。OK,Let's go!打开这个js文件,里面的内容不多
1
2
3
4
5
6
var url_1="/ahn/a/adu/1/1.wma";
var music_1="Andy";
var singer_1="阿杜(A-Du)";
var nclassid_1=2;
var specialid_1="31a616e6816d20fc";
var specialName_1="天黑";

我们需要的信息全部在里面了,有wma的地址(相对地址),歌曲名字,歌手名字,所属专辑
有了wma的相对地址,怎么获取到完整地址呢?再打开连播时的网页,查看源文件。可以发现:
1
2
3
4
5
6
7
8
9
10
    <div id="playlist">正在读取列表,请稍后.....(如果很长时间未读出,请按“F5”刷新)</div>
    <div id="gj_2"><span id="url"><a href="#" class="abuts1" id="bg_fs">分享</a></span><a href="#" id="bg_sc_lb" class="abuts1">收藏列表</a><span id="MusicGeCi"><a href="#" class="abuts1" id="bg_gc">歌词</a></span>
      <div id="gj_bf"><input id="loop" type="checkbox" onclick='changeClassName(this,document.getElementById("dxhs"),"hs");loopp();' /><label for="loop" id="dxhs" onmousemove='this.className="hs"' onmouseout='if(!document.getElementById("loop").checked) this.className=""'>单曲循环</label> <input  type="checkbox" value="" id="ran" onclick='changeClassName(this,document.getElementById("sjbs"),"hs");ran();' /><label for="ran" id="sjbs" onmousemove='this.className="hs"' onmouseout='if(!document.getElementById("ran").checked) this.className=""'>随机播放</label></div>
  </div></div>
  <div id="right"><div id="diange"></div><div id="wmusicad"></div></div>
<div id="foot"></div>
</div>
</body>
<SCRIPT language="JavaScript" src="[COLOR="Red"]/js/lianbosy.js[/COLOR]"></SCRIPT>
</html>

加红的部分就是存放有关键信息的js文件,OK我们把它下载回来,可以看到如下内容:
1
2
3
4
5
6
7
8
var STAND_STR = "/19z/",
STAND_STR2 = "/20z/",
STAND_STR3 = "/21z/",
STAND_STR4 = "/22z/";
 
if(url.indexOf(STAND_STR)==-1 && url.indexOf(STAND_STR2)==-1 && url.indexOf(STAND_STR3)==-1 && url.indexOf(STAND_STR4)==-1)    
                               ht = "http://ow.haoting.com";
else                                               ht = "http://wma.haoting.com";

没错它的wma服务器就只有2个,哪首歌曲存放在哪个服务器上的判断条件也给出来了,就是判断前5个字符,如果符合要求就用http://wma.haoting.com,否则用另外一个.现在煮饭用的锅碗瓢盆都已经有了,就差一把烈火了,我们只要通过分析音乐播放页面的地址,从中找到歌曲ID,再从相应的JS文件中分析出下载地址,歌曲名,歌手名,所属专辑。就大功告成了,这个方法对好听音乐网站上的所有歌曲适用。
Now is Code time !........
要是连代码一起贴出来,整个帖子就太长了,直接上个效果图

源码和程序都在附件里提供了,加了个把下载地址导出为下载列表的功能,可以用迅雷导入来实现批量下载。
Good luck !
上传的附件:
2009-6-28 16:17
0
雪    币: 168
活跃值: (152)
能力值: ( LV11,RANK:180 )
在线值:
发帖
回帖
粉丝
10
过来支持一下。
再膜拜下LZ的学习精神~~~~
2009-6-28 22:36
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
谢谢大牛,
2009-6-29 09:49
0
雪    币: 205
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
LZ可真是穷追不舍啊。只是将原来破船的程序稍微改进了下 其实原理是一样的
2009-6-30 22:10
0
雪    币: 1708
活跃值: (586)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
13
我其实没有看破船的代码,只看了他的分析网站的那段,是同一原理的不同实现而已
2009-6-30 22:52
0
雪    币: 411
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
不错。谢谢LZ哦。
2009-7-1 10:22
0
雪    币: 284
活跃值: (106)
能力值: ( LV9,RANK:160 )
在线值:
发帖
回帖
粉丝
15
我实现的是这样的,用CString实现,简单快捷,而且屡试不爽:
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
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
UINT WINAPI WorkThread(LPVOID  Param)// need a point
{ THREADDATA * data=(THREADDATA * )Param;
  CString Url=L"http://haoting.com/musicjs/";
  int len=data->ID.GetLength();//ID就是歌曲ID了
 Url+=data->ID;
  Url+=L".js";
  //OutputDebugString(Url.GetBuffer(0));
  if(data->ID.IsEmpty())
   return 0;
HINTERNET Internet=::InternetOpen(L"DownloadMulic",INTERNET_OPEN_TYPE_DIRECT
,NULL,NULL,0);
if(Internet==0)
{OutputDebugStringA("open Internet failed\n");
   return 0;
}
HINTERNET hUrl=::InternetOpenUrl(Internet,Url,NULL,0,INTERNET_FLAG_RELOAD,0);
if(hUrl==NULL)
{   OutputDebugString(L"打开URL失败!");
    InternetCloseHandle(Internet);
    return 0;
}
PVOID buffer=malloc(1024);
memset(buffer,0,1024);
DWORD ret=0;
if(!::InternetReadFile(hUrl,buffer,1024,&ret))
{
    InternetCloseHandle(hUrl);
    InternetCloseHandle(Internet);
    return 0;
}
CString ALL,Temp=L"http://wma.haoting.com";
WCHAR * widechar=new WCHAR[1024];
MultiByteToWideChar(CP_ACP,0,(char*)buffer,strlen((char*)buffer),widechar,1024);
ALL=widechar;
//AfxMessageBox(ALL);
int Pos=0;
Temp+=ALL.Right(ALL.GetLength()-ALL.Find(L"url_")-6-len);
ALL=Temp;
Temp=Temp.Left(Temp.Find(L"\";"));
data->Dlg->m_List.SetItemText(data->Index,4,Temp);//地址
Temp.Empty();
//OutputDebugString(ALL.GetBuffer(0));
Temp=ALL.Right(ALL.GetLength()-ALL.Find(L"music")-8-len);
ALL.Empty();
ALL=Temp;
Temp=Temp.Left(Temp.Find(L"\";"));
data->Dlg->m_List.SetItemText(data->Index,1,Temp);//歌名
Temp.Empty();
Temp=ALL.Right(ALL.GetLength()-ALL.Find(L"singer")-9-len);
ALL.Empty();
ALL=Temp;
Temp=Temp.Left(Temp.Find(L"\";"));
data->Dlg->m_List.SetItemText(data->Index,2,Temp);//歌手
Temp.Empty();
Temp=ALL.Right(ALL.GetLength()-ALL.Find(L"specialName")-14-len);
ALL.Empty();
ALL=Temp;
Temp=Temp.Left(Temp.Find(L"\";"));
data->Dlg->m_List.SetItemText(data->Index,3,Temp);//专辑
Temp.Empty();
CString FileName;
FileName=data->Dlg ->m_FolderPath;
FileName+=L"\\";
Temp=data->Dlg->m_List.GetItemText(data->Index,1);
FileName+=Temp;
Temp.Empty();
Temp=data->Dlg->m_List.GetItemText(data->Index,4);
Temp=Temp.Right(4);
FileName+=Temp;
data->Dlg->DownLoadToFileW(0,NULL,0,data->Dlg->m_List.GetItemText(data->Index,4).GetBuffer(),FileName.GetBuffer(0));//直接下载一起搞定,多线程socket下载,速度和迅雷一样快
delete widechar;
int pos=data->Dlg->m_Progress.GetPos()+1;
data->Dlg ->m_Progress.SetPos(pos);
free(buffer);
return 1;
2009-7-1 22:10
0
雪    币: 220
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
sdk 里没有MFC的类用。。。
2009-7-2 10:35
0
雪    币: 104
活跃值: (31)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
  学习 ~~
2009-8-9 23:43
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册