java多線程抓取鈴聲多多官網(wǎng)的鈴聲數(shù)據(jù)
一直想練習(xí)下java多線程抓取數(shù)據(jù)。
有天被我發(fā)現(xiàn),鈴聲多多的官網(wǎng)(http://www.shoujiduoduo.com/main/)有大量的數(shù)據(jù)。
通過觀察他們前端獲取鈴聲數(shù)據(jù)的ajax
http://www.shoujiduoduo.com/ringweb/ringweb.php?type=getlist&listid={類別ID}&page={分頁頁碼}
很容易就能發(fā)現(xiàn)通過改變 listId和page就能從服務(wù)器獲取鈴聲的json數(shù)據(jù), 通過解析json數(shù)據(jù),
可以看到都帶有{"hasmore":1,"curpage":1}這樣子的指示,通過判斷hasmore的值,決定是否進(jìn)行下一頁的抓取。
但是通過上面這個鏈接返回的json中不帶有鈴聲的下載地址
很快就可以發(fā)現(xiàn),點(diǎn)擊頁面的“下載”會看到
通過下面的請求,就可以獲取鈴聲的下載地址了
http://www.shoujiduoduo.com/ringweb/ringweb.php?type=geturl&act=down&rid={鈴聲ID}
所以,他們的數(shù)據(jù)是很容易被偷的。于是我就開始...
源碼已經(jīng)發(fā)在github上。如果感興趣的童鞋可以查看
github:https://github.com/yongbo000/DuoduoAudioRobot
上代碼:
package me.yongbo.DuoduoRingRobot; import java.io.BufferedReader; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; import java.util.Iterator; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonParser; /* * @author yongbo_ * @created 2013/4/16 * * */ public class DuoduoRingRobotClient implements Runnable { public static String GET_RINGINFO_URL = "http://www.shoujiduoduo.com/ringweb/ringweb.php?type=getlist&listid=%1$d&page=%2$d"; public static String GET_DOWN_URL = "http://www.shoujiduoduo.com/ringweb/ringweb.php?type=geturl&act=down&rid=%1$d"; public static String ERROR_MSG = "listId為 %1$d 的Robot發(fā)生錯誤,已自動停止。當(dāng)前page為 %2$d";public static String STATUS_MSG = "開始抓取數(shù)據(jù),當(dāng)前l(fā)istId: %1$d,當(dāng)前page: %2$d"; public static String FILE_DIR = "E:/RingData/";public static String FILE_NAME = "listId=%1$d.txt";private boolean errorFlag = false;private int listId;private int page; private int endPage = -1;private int hasMore = 1; private DbHelper dbHelper; /** * 構(gòu)造函數(shù) * @param listId 菜單ID * @param page 開始頁碼 * @param endPage 結(jié)束頁碼 * */ public DuoduoRingRobotClient(int listId, int beginPage, int endPage) {this.listId = listId;this.page = beginPage;this.endPage = endPage;this.dbHelper = new DbHelper();} /** * 構(gòu)造函數(shù) * @param listId 菜單ID * @param page 開始頁碼 * */ public DuoduoRingRobotClient(int listId, int page) {this(listId, page, -1);} /** * 獲取鈴聲 * */public void getRings() {String url = String.format(GET_RINGINFO_URL, listId, page);String responseStr = httpGet(url);hasMore = getHasmore(responseStr); page = getNextPage(responseStr); ringParse(responseStr.replaceAll("\\{\"hasmore\":[0-9]*,\"curpage\":[0-9]*\\},", "").replaceAll(",]", "]"));}/** * 發(fā)起http請求 * @param webUrl 請求連接地址 * */public String httpGet(String webUrl){URL url;URLConnection conn;StringBuilder sb = new StringBuilder();String resultStr = "";try {url = new URL(webUrl);conn = url.openConnection();conn.connect();InputStream is = conn.getInputStream();InputStreamReader isr = new InputStreamReader(is);BufferedReader bufReader = new BufferedReader(isr);String lineText;while ((lineText = bufReader.readLine()) != null) {sb.append(lineText);}resultStr = sb.toString();} catch (Exception e) {errorFlag = true;//將錯誤寫入txtwriteToFile(String.format(ERROR_MSG, listId, page));}return resultStr;}/** * 將json字符串轉(zhuǎn)化成Ring對象,并存入txt中 * @param json Json字符串 * */public void ringParse(String json) {Ring ring = null;JsonElement element = new JsonParser().parse(json);JsonArray array = element.getAsJsonArray();// 遍歷數(shù)組Iterator<JsonElement> it = array.iterator(); Gson gson = new Gson();while (it.hasNext() && !errorFlag) {JsonElement e = it.next();// JsonElement轉(zhuǎn)換為JavaBean對象ring = gson.fromJson(e, Ring.class);ring.setDownUrl(getRingDownUrl(ring.getId()));if(isAvailableRing(ring)) {System.out.println(ring.toString()); //可選擇寫入數(shù)據(jù)庫還是寫入文本//writeToFile(ring.toString());writeToDatabase(ring);}}} /** * 寫入txt * @param data 字符串 * */public void writeToFile(String data) {String path = FILE_DIR + String.format(FILE_NAME, listId);File dir = new File(FILE_DIR);File file = new File(path);FileWriter fw = null;if(!dir.exists()){dir.mkdirs(); }try {if(!file.exists()){file.createNewFile();}fw = new FileWriter(file, true); fw.write(data);fw.write("\r\n");fw.flush();} catch (IOException e) { // TODO Auto-generated catch blocke.printStackTrace(); }finally {try {if(fw != null){fw.close();}} catch (IOException e) { // TODO Auto-generated catch blocke.printStackTrace();}}}/** * 寫入數(shù)據(jù)庫 * @param ring 一個Ring的實(shí)例 * */ public void writeToDatabase(Ring ring) {dbHelper.execute("addRing", ring);} @Overridepublic void run() {while(hasMore == 1 && !errorFlag){if(endPage != -1){if(page > endPage) { break; }}System.out.println(String.format(STATUS_MSG, listId, page)); getRings();System.out.println(String.format("該頁數(shù)據(jù)寫入完成"));}System.out.println("ending...");} private int getHasmore(String resultStr){Pattern p = Pattern.compile("\"hasmore\":([0-9]*),\"curpage\":([0-9]*)"); Matcher match = p.matcher(resultStr); if (match.find()) { return Integer.parseInt(match.group(1)); } return 0; } private int getNextPage(String resultStr){Pattern p = Pattern.compile("\"hasmore\":([0-9]*),\"curpage\":([0-9]*)");Matcher match = p.matcher(resultStr);if (match.find()) {return Integer.parseInt(match.group(2));}return 0;} /** * 判斷當(dāng)前Ring是否滿足條件。當(dāng)Ring的name大于50個字符或是duration為小數(shù)則不符合條件,將被剔除。 * @param ring 當(dāng)前Ring對象實(shí)例 * */private boolean isAvailableRing(Ring ring){Pattern p = Pattern.compile("^[1-9][0-9]*$"); Matcher match = p.matcher(ring.getDuration()); if(!match.find()){return false;}if(ring.getName().length() > 50 || ring.getArtist().length() > 50 || ring.getDownUrl().length() == 0){return false;}return true;} /** * 獲取鈴聲的下載地址 * @param rid 鈴聲的id * */ public String getRingDownUrl(String rid){String url = String.format(GET_DOWN_URL, rid); String responseStr = httpGet(url);return responseStr;}}
- Java模擬新浪微博登陸抓取數(shù)據(jù)
- 詳解Java實(shí)現(xiàn)多種方式的http數(shù)據(jù)抓取
- java抓取網(wǎng)頁數(shù)據(jù)示例
- java抓取網(wǎng)頁數(shù)據(jù)獲取網(wǎng)頁中所有的鏈接實(shí)例分享
- JAVA使用爬蟲抓取網(wǎng)站網(wǎng)頁內(nèi)容的方法
- java簡單網(wǎng)頁抓取的實(shí)現(xiàn)方法
- java 抓取網(wǎng)頁內(nèi)容實(shí)現(xiàn)代碼
- java在網(wǎng)頁上面抓取郵件地址的方法
- java利用url實(shí)現(xiàn)網(wǎng)頁內(nèi)容的抓取
相關(guān)文章
java如何獲取用戶登錄ip、瀏覽器信息、SessionId
這篇文章主要介紹了java如何獲取用戶登錄ip、瀏覽器信息、SessionId,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11SpringBoot整合RabbitMQ實(shí)現(xiàn)RPC遠(yuǎn)程調(diào)用功能
在分布式系統(tǒng)中,RPC(Remote?Procedure?Call)是一種常用的通信機(jī)制,它可以讓不同的節(jié)點(diǎn)之間像調(diào)用本地函數(shù)一樣進(jìn)行函數(shù)調(diào)用,隱藏了底層的網(wǎng)絡(luò)通信細(xì)節(jié),通過本教程,你可以了解RPC的基本原理以及如何使用Java實(shí)現(xiàn)一個簡單的RPC客戶端和服務(wù)端2023-06-06詳解基于Spring Boot/Spring Session/Redis的分布式Session共享解決方案
本篇文章主要介紹了詳解基于Spring Boot/Spring Session/Redis的分布式Session共享解決方案 ,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06Javascript和Java語言有什么關(guān)系?兩種語言間的異同比較
雖然Javascript與Java有緊密的聯(lián)系,但卻是兩個公司開發(fā)的不同的兩個產(chǎn)品。那么js和java有什么關(guān)系,兩種語言的不同點(diǎn)是什么呢?介于這兩個問題,小編一起給大家解答下2016-09-09Java 獲取當(dāng)前設(shè)備的 IP 地址(最新推薦)
Internet 協(xié)議 (IP) 地址可以是連接到 TCP/IP 網(wǎng)絡(luò)的每個設(shè)備的標(biāo)識符,該標(biāo)識符用于識別和定位中間通信的節(jié)點(diǎn),這篇文章主要介紹了在 Java 中獲取當(dāng)前設(shè)備的 IP 地址,需要的朋友可以參考下2023-06-06