MP3网站的歌曲都采用了不同的加密方法,直接从页面的源文件中是找不到其 MP3的网址的。以下有两个public class都可独立运行,只要将其构造方法更名为main方法就可以了,同时还需要在给出的JAVA源代码中找到“//播放或下载代码...”这一行,将 其改为“Thread.sleep(1000)"延时,否则同一IP频繁的连接会遭服务器拒绝或引发服务器的防恶意搜索保护。
1.获取百度新歌MP3真实地址
百度新歌的网址是http://xinge.baidu.com/,打开该页面后用查看源文件,搜索“{sid:”,会看到这样的文本:
其中:“sid:”后面是歌曲连接、“al:”后是唱片集、“ti:”后面是歌曲标题、“si:”后面是歌手。
源代码如下:
/*
* XingeBaidu.java - 获取'百度新歌'的MP3真实网址
*/
package jmp123.player;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.HttpURLConnection;
public class XingeBaidu {
public XingeBaidu() {
String strLine;
int beginIndex, endIndex, idx;
System.out.println("连接到百度新歌\n");
try {
URL url = new URL("http://xinge.baidu.com/");
HttpURLConnection objHttp = (HttpURLConnection) url.openConnection();
objHttp.setRequestProperty("User-Agent", "mozilla/5.0");
objHttp.setRequestProperty("Connection", "Keep-Alive");
InputStream objIS = objHttp.getInputStream();
BufferedReader objReader = new BufferedReader(new InputStreamReader(objIS));
while ((strLine = objReader.readLine()) != null) {
if ((beginIndex = strLine.indexOf("{sid:")) != -1) {
if ((idx = strLine.indexOf("al:")) != -1
&& (endIndex = strLine.indexOf("',ti")) != -1
&& idx + 4 < endIndex)
System.out.printf("[唱片集:%s] ",strLine.substring(idx+4,endIndex));
if ((idx = strLine.indexOf("ti:")) != -1
&& (endIndex = strLine.indexOf("',si")) != -1
&& idx + 4 < endIndex)
System.out.printf("%s", strLine.substring(idx + 4,endIndex));
if ((idx = strLine.indexOf("si:")) != -1
&& (endIndex = strLine.indexOf("',cp")) != -1
&& idx + 4 < endIndex)
System.out.printf(" [歌手:%s]",strLine.substring(idx+4,endIndex));
System.out.printf("\n");
if ((endIndex = strLine.indexOf(".mp3")) != -1) {
strLine = strLine.substring(beginIndex + 6, endIndex + 4);
getMP3URL("http://xinge.baidu.com/wgns/url/" + strLine);
}
}
}
} catch (Exception e) {
// e.printStackTrace();
}
}
private void getMP3URL(String surl) throws Exception {
String strLine;
URL url = new URL(surl);
HttpURLConnection objHttp = (HttpURLConnection) url.openConnection();
objHttp.setRequestProperty("User-Agent", "mozilla/5.0");
InputStream objIS = objHttp.getInputStream();
BufferedReader objReader = new BufferedReader(new InputStreamReader(objIS));
if ((strLine = objReader.readLine()) != null) {
strLine = "http://xinge.baidu.com" + strLine;
System.out.println(strLine); //打印查找到的MP3的真实网址
//播放或下载的代码...
}
objHttp.disconnect();
objHttp = null;
objReader.close();
objReader = null;
url = null;
}
}
2.获取搜狗新歌Top100的MP3真实网址
用上面的方法不能获取搜狗新歌100的MP3真实网址,原因可能是其服务 器有更严格的限制,防止用上面的方法去恶意搜索。前两天调试代码时连接上去,接收到的页面源文件中提示输入验证码,所以就不能用程序去解析其MP3网址 了,晕,接连两天都不行,不知道是前两天调试程序连接频繁搜的太猛了还是别的什么原因,触发了网站的防恶意搜索保护。
源代码如下,自己对比一下,就能琢磨出与第一种方法有什么不同了。总的步骤是一样的,仍是两步:
/*
* SogouNewTop.java - 获取'搜狗音乐新歌TOP100'的MP3真实网址
*/
package jmp123.player;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.Socket;
/**
* 创建、发送HTTP请求头
*/
class MySocket {
private String strReferer;
private Socket socket;
private PrintWriter pwOut;
BufferedReader brIn;
public MySocket(String strReferer) {
this.strReferer = strReferer;
}
public void create(String surl) {
int beginIndex, endIndex, iPort = 80;
String strHost = surl.substring(7);
endIndex = strHost.indexOf("/");
String strPath = strHost.substring(endIndex);
strHost = strHost.substring(0, endIndex);
if( (beginIndex = strHost.indexOf(":")) != -1) {
if(endIndex - beginIndex > 1)
iPort = Integer.parseInt(strHost.substring(beginIndex+1, endIndex));
strHost = strHost.substring(0, beginIndex);
}
try {
socket = new Socket(strHost, iPort);
pwOut = new PrintWriter(socket.getOutputStream(), true);
// 构建HTTP请求头
pwOut.println("GET " + strPath + " HTTP/1.1");
pwOut.println("Host:" + strHost);
pwOut.println("Referer:" + strReferer);
pwOut.println("Accept:*/*");
pwOut.println("User-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322)");
pwOut.println("Connection: Keep-Alive");
pwOut.println();
// 调用socket.getInputStream方法时才发送HTTP请求头
brIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
System.out.println("创建套接字/输入流错误。");
System.exit(1);
}
}
public BufferedReader getBufferedReader() {
return brIn;
}
public void close() {
try {
brIn.close();
pwOut.close();
socket.close();
} catch (IOException e) {
System.out.println("关闭套接字错误。");
System.exit(1);
}
}
}
/**
* 解析搜狗音乐新歌TOP100页面获取MP3真实网址。
*/
public class SogouNewTop {
private static final String strReferer = "http://music.sogou.com/song/newtop_1.html";
private MySocket htmlSocket = new MySocket(strReferer);
private MySocket urlSocket = new MySocket(strReferer);
/*
* 查找页面的歌曲链接
*/
public SogouNewTop() throws Exception {
System.out.println("连接到搜狗音乐新歌TOP100\n");
String strline = "";
htmlSocket.create(strReferer);
BufferedReader brIn = htmlSocket.getBufferedReader();
int beginIndex, endIndex;
while ((strline = brIn.readLine()) != null) {
// 1.查找歌曲名(可省略)
if ((beginIndex = strline.indexOf("consume=phb_song")) != -1 ) {
strline = strline.substring(beginIndex);
if ((beginIndex = strline.indexOf(">")) != -1
&& (endIndex = strline.indexOf("<")) != -1) {
strline = strline.substring(beginIndex+1, endIndex);
System.out.println("[歌曲名] " + strline);
}
continue;
}
// 2.查找歌曲链接
if ((beginIndex = strline.indexOf("οnclick=\"window.open(")) != -1
&& (beginIndex = strline.indexOf("http://mp3.sogou.com/down.so")) != -1
&& (endIndex = strline.indexOf("',")) != -1) {
strline = strline.substring(beginIndex, endIndex);
getMP3URL(strline);
}
}
htmlSocket.close();
}
/**
* 分析歌曲链接找到其真实网址
*/
private void getMP3URL(String surl) throws Exception {
String strline = "";
urlSocket.create(surl);
BufferedReader brIn = urlSocket.getBufferedReader();
int beginIndex, endIndex;
while ((strline = brIn.readLine()) != null) {
if ((beginIndex = strline.indexOf("http://")) != -1
&& (endIndex = strline.indexOf(".mp3")) != -1) {
strline = strline.substring(beginIndex, endIndex + 4);
System.out.println(strline); //打印MP3的真实地址
//播放或下载的代码放这......;
break;
}
}
urlSocket.close();
}
}
MP3网站的加密方法经常变更,到目前为止这种方法可用,不能保证一直可用。应用示例到http://jmp123.sf.net/ 下载最新的程序(zip压缩包),程序用法见其中的readme.txt。