原博文位址——初學者們爬起來啊http://blog.sina.com.cn/s/blog_49b6bc490101estr.html
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class DownLoadTalkBox {
/*算法思路:
* 1.設定url集,通路過的url不再繼續通路
* 2.設定網站的正規表達式模式
* 3.資料流中的連結分為三種情況:
* 3.1帶協定頭的可以直接通路的絕對位址
* 3.2不帶協定頭的相對位址:使用基位址加上資源位址組成絕對位址再通路
* */
private static Set<String> urlSet = new HashSet<String>();
//将map定義成treemap,友善導出的檔案時排好序的
private static Map<String,String> voiceMap = new TreeMap<String,String>();
//隻是針對本次需求,設定了音頻檔案的正規表達式,隻讓我的爬蟲抓取該音頻檔案
private static Pattern p = Pattern.compile(
"^(http://)" + "((/|.)*([a-z]*[1-9]*)+)" + ".wma $" , Pattern.CASE_INSENSITIVE);
//設定相對位址的正規表達式
private static Pattern nextPage = Pattern.compile(
"^(/Apps/Live/)" + "(/|.)*[a-zA-Z]*[1-9*]", Pattern.CASE_INSENSITIVE);
private static void getVoice(String baseUrl ,String exUrl){
//生成絕對路徑
if(baseUrl.endsWith("/") && exUrl.startsWith("/")){
baseUrl = baseUrl.substring(0, baseUrl.length()-1);
}
//這是比較糾結的地方,每次遞歸之後得到的相對路徑總是加了這麼長一段字元串
//我對網絡程式設計比較菜,不明白是什麼原因,為了避免死循環,隻要暫時将這個子串删掉
String newUrl = baseUrl + exUrl;
if(newUrl.contains("%2FApps%2FLive%2F%3Fs%3D%2FProgram%2Findex%2Fid%2F41")){
newUrl = newUrl.replace("%2FApps%2FLive%2F%3Fs%3D%2FProgram%2Findex%2Fid%2F41", "");
}
//爬過的節點就不要再爬了,不然就死循環了
if(urlSet.contains(newUrl)){
return ;
}
try {
urlSet.add(newUrl);//記錄爬過的節點
Elements links = getElements(newUrl);//調用getElements方法(這是我自己定義的方法)得到網頁中表示連結的元素集合
for(Element link: links){
//得到元素的連結内容(音頻位址) 以及 文本内容(音頻名字)
String ref = link.attr("href");
String name = link.ownText();
Matcher matcher = p.matcher(ref);
if(matcher.matches()){//如果元素的連結内容比對我們定義的音頻的正規表達式,則記錄連結内容和音頻的名字
if(!voiceMap.containsKey(ref)){
voiceMap.put(ref, name);
}
}else{//不比對的話,看看該元素連結内容符不符合相對路徑的正規表達式
if(nextPage.matcher(ref).matches()){
getVoice(baseUrl,ref);//如果這個連結内容是相對路徑,則往下爬(大家猜猜這是深度搜尋還是廣度搜尋)
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static Elements getElements(String url) throws IOException{
urlSet.add(url);
Document doc = Jsoup.connect(url).get();
return doc.select("a[href]");
}
public static void main(String[] args) {
//這個url代表,我将爬蟲放在哪裡,即讓它從哪兒開始爬。
String url = "http://t.am774.com/Apps/Live/?s=/Program/index/id/41";
getVoice(url,"");
writeTxt(voiceMap);//這個方法是後面順手加的,導出文本
}
private static void writeTxt(Map<String, String> map){
File f = new File("E:/map.txt");
OutputStream os;
Set keysSet = map.keySet();
Iterator iterator = keysSet.iterator();
try {
os = new FileOutputStream(f);
while(iterator.hasNext()){
String key = (String) iterator.next();
String name = (String) map.get(key);
String b = key + "\t" + name + "\r\n";//不是很明白\r\n和\n\r的差別,本來是用的\n\r但是text文本中出現亂碼,囧rz
System.out.print(b);
os.write(b.getBytes());
}
if(!f.exists()){
f.mkdir();
}
os.flush();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}