能力值:
( LV15,RANK:670 )
3 楼
原文有误,以
/21z/ 做为特征码并不能保证 100%找到下载地址,应该改为用
.wma 做为特征码,应该修改为
[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;
} ]
给大家带来不便,对不起了。。
上传的附件:
能力值:
( LV11,RANK:180 )
4 楼
收益了,嘿嘿。
我没有仔细的看他的JS代码,没有找到这样的代码,不过看了同学你的文章以后,仔细看了一下我的程序,才发现,我的程序也存在问题的。
urlht = "/21z/0/daodaidq090508/1/8f4257328b24c8d0_5.wma"+UUAuthCode;
这里的“UUAuthCode”起到了一定的防止下载的作用。
很佩服LZ的学习精神,共同努力吧,嘿嘿
能力值:
( LV15,RANK:670 )
5 楼
破船通过分析js的方法能获取很多有用信息,对于我等懒人,本来想拿来改改就用的, 但是在使用过程中还是发现了一个小问题,在分析到一个页面的时候,出现了乱码。。
反正源码已经有了,改改就行了,但是分析js实在是。。俺小菜目前的水平还不会,干脆还是直接读它的源文件吧,通过分析源文件,我们已经知道,真实的下载地址就是
url + urlht urlht 每首歌都不一样,而且
url 也不是一个固定值,在这里又要对不起大家了,之前我一直认为它是一个固定值,就没有把它分析出来。发现了这个问题,只要修改分析引擎就可以达到我们的要求了,当然也可以分析出歌曲名,歌手,和所属专辑。在这里我只分析了它的下载地址并且封装在了GetHaoTingWMAPath这个函数里,对于我们来说,这个才是最重要的
。修改后的代码如下:
[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就不再读了,它后面是什么内容都不用管了...
上传的附件:
能力值:
( LV2,RANK:10 )
6 楼
这个用正则表达式很好做的
用脚本比如python等做的话会简单很多
能力值:
( LV11,RANK:180 )
7 楼
很好很强大,嘿嘿。
我的程序写出来就发上来了,问题肯定很多啦,嘿嘿。
一个功能有好多的实现方法,多多交流,相互学习进步吧。
再次感谢cntrump 的指教^
能力值:
( LV11,RANK:180 )
8 楼
至于乱码的问题,我也不清楚问题出在哪里,估计是我获取JS代码的函数没有做判断导致的。
至于慢,是因为我网络环境比较差,我加了Sleep等待。嘿嘿,去掉就可以了。
能力值:
( LV15,RANK:670 )
9 楼
之前我一直都是实现单首播放时的歌曲路径获取,一直没有实现获取多曲播放页面时的音乐路径,实在不想留下这个遗憾,今天就一鼓作气把它拿下
首先在好听音乐网上选定几首歌曲连续播放,打开播放页面查看源文件,可以发现
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文件,里面的内容不多
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的相对地址,怎么获取到完整地址呢?再打开连播时的网页,查看源文件。可以发现:
<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我们把它下载回来,可以看到如下内容:
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 !
上传的附件:
能力值:
( LV11,RANK:180 )
10 楼
过来支持一下。
再膜拜下LZ的学习精神~~~~
能力值:
( LV2,RANK:10 )
11 楼
谢谢大牛,
能力值:
( LV2,RANK:10 )
12 楼
LZ可真是穷追不舍啊。只是将原来破船的程序稍微改进了下 其实原理是一样的
能力值:
( LV15,RANK:670 )
13 楼
我其实没有看破船的代码,只看了他的分析网站的那段,是同一原理的不同实现而已
能力值:
( LV2,RANK:10 )
14 楼
不错。谢谢LZ哦。
能力值:
( LV9,RANK:160 )
15 楼
我实现的是这样的,用CString实现,简单快捷,而且屡试不爽:
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;
能力值:
( LV2,RANK:10 )
16 楼
sdk 里没有MFC的类用。。。
能力值:
( LV2,RANK:10 )
17 楼
学习 ~~