zoukankan      html  css  js  c++  java
  • 落网的音乐很好听的,你造么?不能下载啊,怎么破?

    本人比较喜欢听音乐,尤其是上下班路上,由于公司离住的地方不远,走着上班也就40分钟,喜欢边走边听音乐,听惯了那种流行音乐,总有点泛滥的感觉,于是到处扒拉那种不一样的听歌软件(什么酷狗,酷我,虾米,咪咕之类的就不算了),找到一些比较符合自己口味的,像LavaRadio,落网 http://www.luoo.net/。第一次用落网的感觉是,哇,这个小清新居然整理了这么多优质音乐,他每一期提供的音乐风格各有不同,总有那么点让人期待的感觉,后来,后来就一直用落网了....

    不过让人遗憾的是,落网的音乐不能下载,上班路上安可没有那么多的流量,虽说用落网的客户端也可以听缓存的音乐,不过断网的情况下效果还是不理想。于是就想办法折腾落网的音乐,发现一个Chrome插件:声海盗,这货可以下载落网的音乐,用过后,感觉效果还是不太好,比如下载的音乐全是01.MP3这样的,而且必须得播放时才能下载,不是很方便。

    实在抵挡不住那么好的音乐的诱惑,决定自己开发个小工具来下载落网的音乐,用着方便就行了,这么想也就这么做了,刚好最近学习Nodejs,就拿Nodejs来开发了。

    开工前的准备

    分析了落网的页面源代码,发现最后的脚本中有个播放列表的数组(窃喜),那么开发思路就有了,这样就可以很方便拿到他的播放列表了,然后根据播放列表的信息去下载MP3就可以了。他的列表代码这这样滴:

    <script>
    try{
        var volPlaylist = [{"id":"11999","title":"u4e16u754cu662fu5757u5fe7u4f24u7684u77f3u5934","artist":"u6cbcu6cfd","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。

    感觉不错?那就点个推荐吧。

  • 相关阅读:
    主流浏览器标签默认样式一览
    为什么要清除默认样式?
    php 的空间命名以及对对象的相关操作,扩展到对数据库的相关函数
    js string
    js基础
    ubuntu-desktop
    php 时期相关函数
    字符串,验证码
    function 相关
    ubuntu_soft相关安装
  • 原文地址:https://www.cnblogs.com/jasondan/p/luoo-down.html
Copyright © 2011-2022 走看看