落網的音樂很好聽的,你造么?不能下載啊,怎么破?


本人比較喜歡聽音樂,尤其是上下班路上,由於公司離住的地方不遠,走着上班也就40分鍾,喜歡邊走邊聽音樂,聽慣了那種流行音樂,總有點泛濫的感覺,於是到處扒拉那種不一樣的聽歌軟件(什么酷狗,酷我,蝦米,咪咕之類的就不算了),找到一些比較符合自己口味的,像LavaRadio,落網 http://www.luoo.net/。第一次用落網的感覺是,哇,這個小清新居然整理了這么多優質音樂,他每一期提供的音樂風格各有不同,總有那么點讓人期待的感覺,后來,后來就一直用落網了....

不過讓人遺憾的是,落網的音樂不能下載,上班路上安可沒有那么多的流量,雖說用落網的客戶端也可以聽緩存的音樂,不過斷網的情況下效果還是不理想。於是就想辦法折騰落網的音樂,發現一個Chrome插件:聲海盜,這貨可以下載落網的音樂,用過后,感覺效果還是不太好,比如下載的音樂全是01.MP3這樣的,而且必須得播放時才能下載,不是很方便。

實在抵擋不住那么好的音樂的誘惑,決定自己開發個小工具來下載落網的音樂,用着方便就行了,這么想也就這么做了,剛好最近學習Nodejs,就拿Nodejs來開發了。

開工前的准備

分析了落網的頁面源代碼,發現最后的腳本中有個播放列表的數組(竊喜),那么開發思路就有了,這樣就可以很方便拿到他的播放列表了,然后根據播放列表的信息去下載MP3就可以了。他的列表代碼這這樣滴:

<script>
try{
    var volPlaylist = [{"id":"11999","title":"\u4e16\u754c\u662f\u5757\u5fe7\u4f24\u7684\u77f3\u5934","artist":"\u6cbc\u6cfd","album":"\u8fdc","mp3":"http:\/\/luoo.800edu.net\/low\/luoo\/radio614\/01.mp3","poster":"http:\/\/img.luoo.net\/pics\/albums\/6679\/cover.jpg_580x580.jpg","poster_small":"http:\/\/img.luoo.net\/pics\/albums\/6679\/cover.jpg_60x60.jpg"},........];
    var navid = '1';
    
}catch(e){}
......
</script>

需要解決的問題:

  • 根據期刊地址,發送http請求,從返回的html代碼中拿到這段playList代碼;
  • 下載mp3到本地,每個期刊創建一個目錄,便於組織這些音樂;
  • 讓用戶按照自己的喜好,下載自己喜歡的音樂,也就是得有個界面讓用戶去選;
  • 下載完以后干啥呢,聽唄!,還得解決下載后播放音樂的問題。

開工

針對以上問題去研究實現方案,四處奔波后(主要在npmjs上,上面有大量的第三方包),基本解決以上問題,解決方法如下:

  1. 發送Http請求的問題,這個可以直接用Nodejs自帶的http模塊,不過簡單的處理還行,復雜的處理比如下載MP3就沒有那么方便了,不過幸好有個request模塊解決了這個問題,發送請求特方便,下載文件同樣很Easy。
  2. 如何從返回的html代碼中獲取那個playlist列表呢,jsdom+jquery去提取?算了,直接分析字符串獲取吧,也不麻煩。
  3. 創建目錄啥的就不說了,直接用自帶的fs模塊去搞就行了。
  4. 弄個界面?起初想到了node-webkit,雖然用這貨雖然可以把UI做的很棒,不過有些重量級了,我還是崇尚簡潔輕量的,后來找到term-list模塊,可以直接在控制台中弄個簡單的列表選擇界面,純文本的哦,真方便。
  5. 下載音樂是需要時間的,怎么才能更友好的下載呢(提示下載進度),發現request模塊並沒有下載進度相關的信息,后來找到request-progress可以解決這個問題,然后再從界面上顯示進度,可以使用progress這個東東。
  6. 咋播放下載下來的音樂呢,簡單點就直接使用本地的播放器播放得了,那就用open模塊,可以自動調用本地app打開MP3.

萬事俱備,只欠代碼,來吧,開搞吧!

感覺講代碼什么的最頭疼了,說幾個關鍵的吧,其余的根據各模塊的官方文檔都能搞明白。

從html代碼中提取想要的信息,也就是字符串截取:

function findContent(html, key, endTag, offset) {
  var start = html.indexOf(key);
  var end = html.indexOf(endTag, start);
  return html.substring(start + key.length, end + offset);
}

然后就可以很方便的獲取播放列表了:playList = JSON.parse(findContent(html, 'var volPlaylist = ', '}];', 2));

簡化版的MP3下載代碼:

    progress(request(mp3Info.mp3))  // 請求MP3的下載地址
    .on('progress', function (state) {
      // 這里處理下載進度
    })
    .pipe(fs.createWriteStream(mp3File))    // MP3保存到本地文件
    .on('close', function (err) {
      // 這里處理下載結束
    });

結合request和request-progress模塊去下載東西還是蠻方便的,若沒有這些模塊,我不知道要寫多少代碼,向此模塊的作者致敬!

其他的全是些UI方面的東西了,也沒啥值得說的,下面大家可以去GitHub找到完整的代碼。

貼圖欣賞

程序跑起來的效果圖如下,輸入要獲取的期刊url,就可以分析出他的下載列表,然后選擇自己喜歡的音樂回車開始下載,下載完成后,再次回車就可以播放了:

luoo-down,Windowns版的截圖:

MP3下載目錄,每期的歌曲單獨存放到自己的目錄中:

問題

大家知道我們獲取播放列表是從落網的網頁源代碼中獲取的,要是哪一天落網把頁面改了,找不到播放列表了,那就妥妥的悲劇了。希望落網的程序猿們不要動那段播放列表的代碼哦。

其實這個問題可以分析他們客戶端調用的接口,接口變動總該是少的吧,他們有個Android的客戶端,可以反編譯分析下接口地址,不過會麻煩些,沒有折騰,現在這個版本能用就先用着吧。

開源

開發完成后,邊聽歌,邊調試,最后搞穩定了,差不多可以分享給大家用了,就扔到github上去了,開源分享精神必須是有滴!

GitHub項目地址:https://github.com/stanzhai/luoo-down

大家有興趣的可以加入進來一起完善哦。

總結

總結下用到的一些模塊:

var fs = require('fs')    
  , path = require('path')
  , readline = require('readline')
  , request = require('request')    // 非常方便的發送http請求
  , progress = require('request-progress')   // 處理請求進度
  , ProgressBar = require('progress')   // 控制台進度顯示
  , open = require('open')   // 使用本地應用打開文件
  , colors = require('colors')  // 控制台文本顏色  
  , List = require('term-list');  // 控制台列表菜單項

相關技術點:Nodejs網頁信息采集,文件下載及下載進度,控制台(終端)UI。

感覺不錯?那就點個推薦吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM