package com.macrohard.musicbug;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.content.Context;
import android.util.Log;
// This class is not thread safe.
public class SogoMp3Fetcher implements IMp3Fetcher {
private static final String BASE_URL = "http://mp3.sogou.com/music.so?pf=mp3&query=";
private static final String SOGOU_MP3_URL = "http://mp3.sogou.com";
private static final String TAG = Debug.TAG;
private String mKeyWords;
private final String mLink;
private int mNextPage;
private boolean mDone;
private String getLink(String key) {
String reqString = null;
try {
reqString = URLEncoder.encode(key, "GB2312");
} catch (UnsupportedEncodingException e) {
reqString = URLEncoder.encode(key);
}
return BASE_URL + reqString;
}
public SogoMp3Fetcher(Context context, String keyWords) {
mKeyWords = keyWords;
mLink = getLink(mKeyWords); // Base link.
mNextPage = 1;
mDone = false;
}
private String getNextUrl() {
return mNextPage == 1 ? mLink : mLink + "&page=" + mNextPage;
}
// TODO(zyu): Rewrite the following code.
// Consider using cache?
private ArrayList<MP3Info> getListBatchByUrl(String urlStr, int limit) {
Debug.D("mp3 url = " + urlStr);
ArrayList<MP3Info> songs = new ArrayList<MP3Info>();
String httpresponse = null;
try {
URL url = new URL(urlStr);
HttpURLConnection urlConn = (HttpURLConnection) url
.openConnection();
urlConn.setRequestProperty("User-Agent",
"Apache-HttpClient/UNAVAILABLE (java 1.4)");
urlConn.setConnectTimeout(12000);
urlConn.connect();
InputStream stream = urlConn.getInputStream();
StringBuilder builder = new StringBuilder(8 * 1024);
char[] buff = new char[4096];
InputStreamReader is = new InputStreamReader(stream, "gb2312");
int len;
while ((len = is.read(buff, 0, 4096)) > 0) {
builder.append(buff, 0, len);
}
urlConn.disconnect();
httpresponse = builder.toString();
Pattern PATTERN_ROW = Pattern.compile("<tr(.*?)</tr>", Pattern.DOTALL);
Pattern PATTERN = Pattern.compile(
"<td.*?\\btitle=\"([^\"]*)\".*?" + // 1
"<td.*?\\bsinger=\"([^\"]*)\".*?" + // 2
"<td.*?\\btitle=\"([^\"]*)\".*?" + // 3
"<td.*?</td>.*?" + // Ignore
"<td.*?</td>.*?" + // Ignore
"<td.*?\'(/down.so.*?)\'.*?" + // 6
"<td.*?href=\"([^\"]*)\".*?" + // 7
"<td.*?</td>.*?" + // Ignore
"<td.*?>([^<]*)<.*?" + // 9
"<td.*?>([^<]*)<" + // 10
""
, Pattern.DOTALL);
Matcher matcherRow = PATTERN_ROW.matcher(httpresponse);
while (matcherRow.find()) {
Matcher m = PATTERN.matcher(matcherRow.group(1));
while (m.find()) {
MP3Info info = new MP3Info();
info.setName(m.group(1).trim());
info.setArtist(URLDecoder.decode(m.group(2), "gb2312").trim());
info.setAlbum(m.group(3).trim());
info.setLink(m.group(4).trim());
info.setSize(Utils.sizeFromStr(m.group(6).trim()));
songs.add(info);
}
}
} catch (Exception e) {
// ShowToastMessage("Network can not connect, please try again.");
e.printStackTrace();
return null;
}
Debug.D("songs = " + songs);
if (songs != null) {
Log.e(TAG, "song size: " + songs.size());
}
return songs;
}
// Given the link to each individual mp3, get the corresponding link by which we can actually download the music.
public String getDownloadLink(MP3Info mp3) throws Mp3FetcherException {
try {
String request = SOGOU_MP3_URL + mp3.getLink();
URL url = new URL(request);
HttpURLConnection urlConn = (HttpURLConnection)url.openConnection();
urlConn.setRequestProperty("User-Agent", "Apache-HttpClient/UNAVAILABLE (java 1.4)");
urlConn.setConnectTimeout(12000);
urlConn.connect();
InputStream stream = urlConn.getInputStream();
StringBuilder builder = new StringBuilder(8 * 1024);
char[] buff = new char[4096];
//必须在此指定编码,否则后面toString会导致乱码
InputStreamReader is = new InputStreamReader(stream,"gb2312");
int len;
while ((len = is.read(buff, 0, 4096)) > 0) {
builder.append(buff, 0, len);
}
urlConn.disconnect();
String httpresponse = builder.toString();
int linkStartPos = httpresponse.indexOf("下载歌曲\" href=\"") + "下载歌曲\" href=\"".length();
int linkEndPos = httpresponse.indexOf('>', linkStartPos)-1;
return httpresponse.substring(linkStartPos, linkEndPos);
} catch (IOException e) {
e.printStackTrace();
throw new Mp3FetcherException("Failure in getting mp3 download link: " + mp3.getLink());
}
}
/*
@Override
public void downloadMp3(MP3Info mp3, String saveFile, DefaultDownloadListener listener)
throws Mp3FetcherException {
// TODO(zyu): Use DownloadFile in feebelib.
}
*/
@Override
public ArrayList<MP3Info> getNextListBatch() throws Mp3FetcherException {
if (mDone) {
return null;
}
ArrayList<MP3Info> songs = getListBatchByUrl(getNextUrl(), -1);
if (songs != null) {
if (songs.size() == 0) {
mDone = true;
} else {
++mNextPage;
}
} else {
// Some error occurred.
}
return songs;
}
@Override
public boolean listDone() {
return mDone;
}
@Override
public void resetList() {
mDone = false;
mNextPage = 1;
}
}