搜索七里香,所有格式
http://mp3.baidu.com/m?f=ms&tn=baidump3&ct=134217728&lf=&rn=&word=%C6%DF%C0%EF%CF%E3&lm=-1 第一页
http://mp3.baidu.com/m?z=0&cl=3&ct=134217728&sn=&lm=-1&cm=1&sc=1&bu=&rn=30&tn=baidump3&word=%C6%DF%C0%EF%CF%E3&pn=30 第二页
http://mp3.baidu.com/m?z=0&cl=3&ct=134217728&sn=&lm=-1&cm=1&sc=1&bu=&rn=30&tn=baidump3&word=%C6%DF%C0%EF%CF%E3&pn=60 第三页
http://mp3.baidu.com/m?z=0&cl=3&ct=134217728&sn=&lm=-1&cm=1&sc=1&bu=&rn=30&tn=baidump3&word=%C6%DF%C0%EF%CF%E3&pn=90 第四页
http://mp3.baidu.com/m?z=0&cl=3&ct=134217728&sn=&lm=-1&cm=1&sc=1&bu=&rn=30&tn=baidump3&word=%C6%DF%C0%EF%CF%E3&pn=720 最后页 30首
搜索七里香,mp3格式
http://mp3.baidu.com/m?f=ms&tn=baidump3&ct=134217728&lf=&rn=&word=%C6%DF%C0%EF%CF%E3&lm=0 第一页
http://mp3.baidu.com/m?z=0&cl=3&ct=134217728&sn=&lm=0&cm=1&sc=1&bu=&rn=30&tn=baidump3&word=%C6%DF%C0%EF%CF%E3&pn=30 第二页
http://mp3.baidu.com/m?z=0&cl=3&ct=134217728&sn=&lm=0&cm=1&sc=1&bu=&rn=30&tn=baidump3&word=%C6%DF%C0%EF%CF%E3&pn=630 最后页7首
搜索七里香,rm格式
http://mp3.baidu.com/m?f=ms&tn=baidump3&ct=134217728&lf=&rn=&word=%C6%DF%C0%EF%CF%E3&lm=1 第一页
http://mp3.baidu.com/m?z=0&cl=3&ct=134217728&sn=&lm=1&cm=1&sc=1&bu=&rn=30&tn=baidump3&word=%C6%DF%C0%EF%CF%E3&pn=30 最后页,17首
搜索七里香,wma格式
http://mp3.baidu.com/m?f=ms&tn=baidump3&ct=134217728&lf=&rn=&word=%C6%DF%C0%EF%CF%E3&lm=2 第一页
http://mp3.baidu.com/m?z=0&cl=3&ct=134217728&sn=&lm=2&cm=1&sc=1&bu=&rn=30&tn=baidump3&word=%C6%DF%C0%EF%CF%E3&pn=30 第二页
http://mp3.baidu.com/m?z=0&cl=3&ct=134217728&sn=&lm=2&cm=1&sc=1&bu=&rn=30&tn=baidump3&word=%C6%DF%C0%EF%CF%E3&pn=240 最后页 13首
搜索七里香,其它格式
http://mp3.baidu.com/m?f=ms&tn=baidump3&ct=134217728&lf=&rn=&word=%C6%DF%C0%EF%CF%E3&lm=32767 第一页
http://mp3.baidu.com/m?z=0&cl=3&ct=134217728&sn=&lm=32767&cm=1&sc=1&bu=&rn=30&tn=baidump3&word=%C6%DF%C0%EF%CF%E3&pn=30 第二页
http://mp3.baidu.com/m?z=0&cl=3&ct=134217728&sn=&lm=32767&cm=1&sc=1&bu=&rn=30&tn=baidump3&word=%C6%DF%C0%EF%CF%E3&pn=240 最后页 4首
上面的链接中,“%C6%DF%C0%EF%CF%E3”是中文“七里香”的6个字节的十六进制编码,可以用“七里香”代替。稍微观察一下就可以发现,“http://mp3.baidu.com/m?f=ms&tn=baidump3&ct=134217728&lf=&rn=&word=歌曲名&lm=格式”就是搜索歌曲第一个结果页面URL,格式有-1(所有格式),0(mp3格式),1(rm格式),2(wma格式),32767(其它格式)5种。我没有把歌词搜索,视频搜索,铃声搜索包括在内,他们跟歌曲搜索的差异太大了。“http://mp3.baidu.com/m?z=0&cl=3&ct=134217728&sn=&lm=格式&cm=1&sc=1&bu=&rn=30&tn=baidump3&word=歌曲名&pn=起始数量N”是搜索第N/30+1页,格式意义同搜索第一页的情况。
对照网页查看一下其源码,可以发现搜索结果页面中的每首歌曲是这样的形式的存在的
<tr>
<td class=tdn>1</td>
<td class=d><a href="http://202.108.23.172/m?ct=134217728&tn=baidusg,借口 &word=mp3,http://ddos.8833168.cn/wmp3/周杰伦/7hryDjU$.mp3,,[%C6%DF%C0%EF%CF%E3]&si=%BD%E8%BF%DA;;%D6%DC%BD%DC%C2%D7;;3708;;3708&lm=16777216" title="请点击左键!来源网址: http://ddos.8833168.cn/ 请参照百度权利声明使用" οnclick="return ow(event,this)" target="_blank">借口 </a></td>
<td><a href="http://mp3.baidu.com/singerlist/%D6%DC%BD%DC%C2%D7.html" target="_blank">周杰伦</a> <a href="http://mp3.baidu.com/singerlist/.html" target="_blank"></a> <a href="http://mp3.baidu.com/singerlist/.html" target="_blank"></a> </td>
<td class=al><a href="http://mp3.baidu.com/albumlist/%D6%DC%BD%DC%C2%D7;;;;;;%C6%DF%C0%EF%CF%E3.html" target="_blank"><font style=color:#e10900>七里香</font></a> </td>
<td><a href="http://box.zhangmen.baidu.com/m?gate=1&ct=134217728&tn=baidumt,借口 &word=mp3,http://ddos.8833168.cn/wmp3/周杰伦/7hryDjU$.mp3,,[%C6%DF%C0%EF%CF%E3]&si=%BD%E8%BF%DA;;%D6%DC%BD%DC%C2%D7;;3708;;3708&lm=16777216" οnclick="return ot(event,this,'3708')">试听</a> </td>
<td><a href="http://mp3.baidu.com/m?tn=baidump3lyric&word=%D6%DC%BD%DC%C2%D7+%BD%E8%BF%DA&ct=150994944&lm=-1&lf=3" target="_blank">歌词</a> </td>
<td> <a name="ls" href="http://mp3.baidu.com/tr?url=http://ad.cn.doubleclick.net/clk;140266405;20620248;r?http://www.12530.com/main/all/subscribe/index/0/qd001/bd0092/1/0/0/null/--------------------------------------2560.html&sn=1" οnclick="return or(event,this);">铃声</a> </td>
<td>3.9 M</td>
<td>mp3</td>
<td class=spd><img src="http://img.baidu.com/img/mp3/d9.gif%22%3E%3C/td>
</tr>
以下是分析结果:
“<td class=tdn>1</td>”:歌曲的序号,每个下载页都不一样的,从1开始递增。我们分析页面中的歌曲就靠这个字符串了。利用一个循环读出所有歌曲下载页,知道查找“<td class=tdn>N</td>”不到为止。
“http://202.108.23.172/m?ct=134217728&tn=baidusg,借口 &word=mp3,http://ddos.8833168.cn/wmp3/周杰伦/7hryDjU$.mp3,,[%C6%DF%C0%EF%CF%E3]&si=%BD%E8%BF%DA;;%D6%DC%BD%DC%C2%D7;;3708;;3708&lm=16777216”:这个URL就是带下载链接的页面。
“target="_blank">借口 </a”:“借口”是歌曲的名字,有时搜索结果会有误,比如我搜索“七里香”就出来“借口”,可能是把“七里香”当专辑名了吧,而“借口”是这张专辑的一首歌。所以可以通过检查这里来确定是否下载。
“<td>3.9 M</td>”:音乐文件的尺寸,一般来说wma有2M以上,Mp3为4M左右。太小的话歌曲不完整。
“ <td>mp3</td>”:歌曲的类型。
打开http://202.108.23.172/m?ct=134217728&tn=baidusg,借口 &word=mp3,http://ddos.8833168.cn/wmp3/周杰伦/7hryDjU$.mp3,,[%C6%DF%C0%EF%CF%E3]&si=%BD%E8%BF%DA;;%D6%DC%BD%DC%C2%D7;;3708;;3708&lm=16777216这个页面,查看其源码看到:
<div style="padding:30px 0px 0px 40px;">
歌曲名:<a href="http://ddos.8833168.cn/wmp3/周杰伦/借口.mp3">借口 ...</a><br>
<li class="li" style="margin-top:2px;">请点击此链接:</li>
傻瓜都知道了“http://ddos.8833168.cn/wmp3/周杰伦/借口.mp3”就是下载地址。左边的“歌曲名”和右边的“请点击此链接”是识别它的最明显方式。
了解这些后,不打开浏览器搜索歌曲就容易做了,只要你懂得如何在自己的程序中获取web页面源码。获取页面源码可以用WebBrowser,也可以用速度更快更轻巧的IdHttp组件(Indy套件的一个成员)。使用TIdHttp获取页面的方法是:
src:=IdHttpObj.Get('www.163.com');
获取页面之后就是利用分析所得到的特征字符串来查找下载链接了。我很笨,不会列举页面的超链接啊,图片啊,表格啊,按钮啊什么的。我采用的是最原始的办法:字符串处理函数。Pos和Copy就够用了。
下面是我的代码,由于是练习玩。写得很不严谨哈。而且没有注释(我认为上面讲得已经很清楚了)。唯一需要说的是,http://202.108.23.172/m?ct=134217728&tn=baidusg,借口 &word=mp3,http://ddos.8833168.cn/wmp3/周杰伦/7hryDjU$.mp3,,[%C6%DF%C0%EF%CF%E3]&si=%BD%E8%BF%DA;;%D6%DC%BD%DC%C2%D7;;3708;;3708&lm=16777216这种URL中含有2个ASCII码为32的控制字符。这两个字符在“&word=”的前面,我们要把它们换成%20(就是32的十六进制码),否则用IdHttp是抓不到页面的。我只是做了最简单抓下载链接的功能。
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ComCtrls, FileDownLoadThread, UrlMon, IdBaseComponent,
IdComponent, IdTCPConnection, IdTCPClient,
IdHTTP,StrUtils;
type
TMusicType = (mtAll =- 1 ,mtMp3 = 0 ,mtRm = 1 ,mtWma = 2 ,mtOther = 32767 );
TMusicInfo = record
Name:string;
DownUrl:string;
Size: Real;
end ;
TFrmMain = class( TForm )
ProgBar: TProgressBar;
edtFileURL: TLabeledEdit;
edtFilePath: TLabeledEdit;
Label1: TLabel;
btnStart: TButton;
btnCancel: TButton;
edtMusicName: TLabeledEdit;
btnSearch: TButton;
rgType: TRadioGroup;
IdHTTP: TIdHTTP;
lstResult: TListBox;
procedure FormCreate( Sender: TObject );
procedure btnStartClick( Sender: TObject );
procedure DownProgress( Sender: TFileDownLoadThread; Progress, ProgressMax: Cardinal );
procedure DownComplete( Sender: TFileDownLoadThread );
procedure DownFail( Sender: TFileDownLoadThread; Reason: LongInt );
procedure btnCancelClick( Sender: TObject );
procedure FormDestroy( Sender: TObject );
procedure btnSearchClick( Sender: TObject );
function SearchMusic(mName:string;mType:TMusicType):string;
procedure GetMusic(ResultUrl:string);
procedure lstResultClick(Sender: TObject);
private
FSearchResult:string;
public
{ Public declarations }
end ;
var
FrmMain: TFrmMain;
AThread: TFileDownLoadThread;
implementation
{ $R *.dfm }
const
ModelURL = ' http://mp3.baidu.com/m?f=ms&rn=&tn=baidump3&ct=134217728&word=%s&lm=%d ' ;
procedure TFrmMain.btnCancelClick( Sender: TObject );
begin
if AThread <> nil then
begin
AThread.Terminate;
AThread.WaitFor;
FreeAndNil( AThread );
end ;
end ;
procedure TFrmMain.btnSearchClick( Sender: TObject );
var
MusicType:TMusicType;
begin
if rgType.ItemIndex < 4 then
MusicType: = TMusicType(rgType.ItemIndex - 1 )
else
MusicType: = mtOther;
try
FSearchResult: = SearchMusic(edtMusicName.Text,MusicType);
GetMusic(FSearchResult);
except
FSearchResult: = '' ;
ShowMessage( ' search failed ' );
end ;
end ;
procedure TFrmMain.btnStartClick( Sender: TObject );
var
SaveFileName: string;
begin
if AThread = nil then
AThread : = TFileDownLoadThread.Create( edtFileURL.Text, edtFilePath.Text, DownProgress, DownComplete, DownFail );
end ;
procedure TFrmMain.DownComplete( Sender: TFileDownLoadThread );
begin
ShowMessage( ' 下载完成 ' );
end ;
procedure TFrmMain.DownFail( Sender: TFileDownLoadThread; Reason: Integer );
begin
OutputDebugString( PAnsiChar( Format( ' Down Fail,Reason:%s ' , [ IntToHex( Reason, 8 ) ] ) ) );
end ;
procedure UpdateProgressBar( Progress, Max: Cardinal );
begin
if Max > 0 then
FrmMain.ProgBar.Position : = ( Progress * FrmMain.ProgBar.Max ) div Max;
end ;
procedure TFrmMain.DownProgress( Sender: TFileDownLoadThread; Progress, ProgressMax: Cardinal );
begin
UpdateProgressBar( Progress, ProgressMax );
end ;
procedure TFrmMain.FormCreate( Sender: TObject );
begin
AThread : = nil ;
rgType.ItemIndex: =- 1 ;
end ;
procedure TFrmMain.FormDestroy( Sender: TObject );
begin
btnCancelClick( nil );
end ;
function GetMusicDownLoadURL(ADownPage:string):string;
const
str = ' 歌曲名:<a href=" ' ;
var
I,J:Integer;
begin
I: = Pos(str,ADownPage);
J: = PosEx( ' "> ' ,ADownPage,I + Length(str));
Result: = Copy(ADownPage,I + Length(str),J - I - Length(Str));
end ;
procedure TFrmMain.GetMusic(ResultUrl: string);
const
CharStr = ' <td class=tdn>%d</td> ' ;
CharStr2 = ' href=" ' ;
CharStr3 = ' title="请点击左键!来源网址 ' ;
var
L,I,J:Integer;
DownPage:string;
FirstPart,SecondPart:string;
begin
lstResult.Clear;
L: = 1 ;
while True do
begin
I: = Pos( Format(CharStr,[L]),ResultUrl);
if I <= 0 then Break;
I: = I + Length(CharStr);
I: = PosEx(CharStr2,ResultUrl,I) + Length(CharStr2);
J: = PosEx(CharStr3,ResultUrl,I);
DownPage: = Trim(Copy(ResultUrl,I,J - I));
SetLength(DownPage,Length(DownPage) - 1 );
I: = Pos( ' &word= ' ,DownPage);
FirstPart: = Copy(DownPage, 1 ,I - 3 );
SecondPart: = Copy(DownPage,I,Length(DownPage) - I + 1 );
DownPage: = FirstPart + ' %20%20 ' + SecondPart;
try
lstResult.Items.Add(GetMusicDownLoadURL(Self.IdHTTP.Get(DownPage)));
except
end ;
Inc(L);
end ;
if lstResult.Count = 0 then
ShowMessage( ' 没有找到歌曲! ' );
end ;
procedure TFrmMain.lstResultClick(Sender: TObject);
begin
if lstResult.ItemIndex <>- 1 then
edtFileURL.Text: = lstResult.Items[lstResult.ItemIndex];
end ;
function TFrmMain.SearchMusic(mName: string; mType: TMusicType): string;
var
AUrl:string;
begin
AUrl: = Format(ModelURL,[mName,Ord(mType)]);
Result: = Self.IdHTTP.Get(AUrl);
end ;
end .