java多執行緒抓取鈴聲多多官網的鈴聲數據
一直想练习下java多线程抓取数据。
有天被我发现,铃声多多的官网(http://www.shoujiduoduo.com/main/)有大量的数据。
通过观察他们前端获取铃声数据的ajax
http://www.shoujiduoduo.com/ringweb/ringweb.php?type=getlist&listid={类别ID}&page={分页页码}
很容易就能发现通过改变 listId和page就能从服务器获取铃声的json数据, 通过解析json数据,
可以看到都带有{"hasmore":1,"curpage":1}这样子的指示,通过判断hasmore的值,决定是否进行下一页的抓取。
但是通过上面这个链接返回的json中不带有铃声的下载地址
很快就可以发现,点击页面的“下载”会看到
通过下面的请求,就可以获取铃声的下载地址了
http://www.shoujiduoduo.com/ringweb/ringweb.php?type=geturl&act=down&rid={铃声ID}
所以,他们的数据是很容易被偷的。于是我就开始...
源码已经发在github上。如果感兴趣的童鞋可以查看
github:https://github.com/yongbo000/DuoduoAudioRobot
上代码:
<pre class="brush:java;">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发生错误,已自动停止。当前page为 %2$d";public static String STATUS_MSG = "开始抓取数据,当前listId: %1$d,当前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; /** * 构造函数 * @param listId 菜单ID * @param page 开始页码 * @param endPage 结束页码 * */ public DuoduoRingRobotClient(int listId, int beginPage, int endPage) {this.listId = listId;this.page = beginPage;this.endPage = endPage;this.dbHelper = new DbHelper();} /** * 构造函数 * @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(",]", "]"));}/** * 发起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字符串转化成Ring对象,并存入txt中 * @param json Json字符串 * */public void ringParse(String json) {Ring ring = null;JsonElement element = new JsonParser().parse(json);JsonArray array = element.getAsJsonArray();// 遍历数组Iterator<JsonElement> it = array.iterator(); Gson gson = new Gson();while (it.hasNext() && !errorFlag) {JsonElement e = it.next();// JsonElement转换为JavaBean对象ring = gson.fromJson(e, Ring.class);ring.setDownUrl(getRingDownUrl(ring.getId()));if(isAvailableRing(ring)) {System.out.println(ring.toString()); //可选择写入数据库还是写入文本//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();}}}/** * 写入数据库 * @param ring 一个Ring的实例 * */ 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("该页数据写入完成"));}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;} /** * 判断当前Ring是否满足条件。当Ring的name大于50个字符或是duration为小数则不符合条件,将被剔除。 * @param ring 当前Ring对象实例 * */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多執行緒抓取鈴聲多多官網的鈴聲數據相关文章请关注PHP中文网!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

Java中volatile關鍵字的作用及應用場景詳解一、volatile關鍵字的作用在Java中,volatile關鍵字用來識別一個變數在多個執行緒之間可見,即保證可見性。具體來說,當一個變數被宣告為volatile時,任何對該變數的修改都會立即被其他執行緒所知曉。二、volatile關鍵字的應用程式場景狀態標誌volatile關鍵字適用於一些狀態標誌的場景,例如一

Java開發中,文件讀取是一個非常常見且重要的操作。隨著業務的成長,文件的大小和數量也不斷增加。為了提高檔案讀取的速度,我們可以採用多執行緒的方式來並行讀取檔案。本文將介紹如何在Java開發中最佳化檔案讀取多執行緒加速效能。首先,在進行檔案讀取前,我們需要先確定檔案的大小和數量。根據檔案的大小和數量,我們可以合理地設定線程的數量。過多的執行緒數量可能會導致資源浪費,

多執行緒環境下異常處理的要點:捕捉異常:每個執行緒使用try-catch區塊捕捉異常。處理異常:在catch區塊中列印錯誤訊息或執行錯誤處理邏輯。終止執行緒:無法復原時,呼叫Thread.stop()終止執行緒。 UncaughtExceptionHandler:處理未捕獲異常,需要實作該介面並指定給執行緒。實戰案例:線程池中的異常處理,使用UncaughtExceptionHandler來處理未捕獲異常。

探索Java多執行緒的工作原理和特點引言:在現代電腦系統中,多執行緒已成為一種常見的並發處理方式。 Java作為一門強大的程式語言,提供了豐富的多執行緒機制,讓程式設計師可以更好地利用電腦的多核心處理器、提高程式運作效率。本文將探索Java多執行緒的工作原理和特點,並透過具體的程式碼範例來說明。一、多線程的基本概念多線程是指在一個程式中同時執行多個線程,每個線程處理不同

Java多執行緒效能最佳化指南提供了五個關鍵最佳化點:減少執行緒建立和銷毀開銷避免不當的鎖爭用使用非阻塞資料結構利用Happens-Before關係考慮無鎖並行演算法

多執行緒偵錯技術解答:1.多執行緒程式碼除錯的挑戰:執行緒之間的互動導致複雜且難以追蹤的行為。 2.Java多執行緒偵錯技術:逐行調試執行緒轉儲(jstack)監視器進入和退出事件執行緒本地變數3.實戰案例:使用執行緒轉儲發現死鎖,使用監視器事件確定死鎖原因。 4.結論:Java提供的多執行緒偵錯技術可以有效解決與執行緒安全、死鎖和爭用相關的問題。

Java是一種廣泛應用於現代軟體開發的程式語言,其多執行緒程式設計能力也是其最大的優點之一。然而,由於多執行緒帶來的並發存取問題,Java中常常會出現多執行緒安全性問題。其中,java.lang.ThreadDeath就是一個典型的多執行緒安全問題。本文將介紹java.lang.ThreadDeath的原因以及解決方法。一、java.lang.ThreadDeath的原因

Java並發鎖機制可確保多執行緒環境下,共享資源僅由一個執行緒存取。其類型包括悲觀鎖(獲取鎖再存取)和樂觀鎖(訪問後檢查衝突)。 Java提供了ReentrantLock(互斥鎖)、Semaphore(信號量)和ReadWriteLock(讀寫鎖)等內建並發鎖類別。使用這些鎖可以確保共享資源的執行緒安全訪問,如確保多個執行緒同時訪問共享變數counter時僅有一個執行緒更新其值。
