人生自古谁无死,留取丹心照汉青。——宋·文天祥《过零丁洋》 楠少博客 阅读文章 Eclipse下载付费音乐 楠少 2018-11-25 6666666 8888888 Eclipse Java 下载 音乐 摘要声明 本程序用到的一切资源,均来源于网络,仅作学习、交流用! 网站: 音乐下载助手 - Hwk小康 ( 网页链接 ) 所用到的相关知识: 1. Java 网络请求 2. Java 文件下载 3. Java 文件读取 会简单的网络请求以及IO流就可以KO这个小Demo了。 **目录 (Table of Contents)** [TOC] ### 声明 本程序用到的一切资源,均来源于网络,仅作学习、交流用! ### 问题引入 ![聊天记录截图](https://ae01.alicdn.com/kf/Hfd8f84239f1f48908bcc06312261bdf8p.png "聊天记录截图") 实在有点尴尬,看着他那满屏幕的歌曲文件,我替他感受到了绝望,遂动手写了个下载音乐的Java程序(当然忽视任何版权)。 接下来咱就开始! ### 正文 ##### 网站: 音乐下载助手 - Hwk小康 ( [网页链接](https://music.hwkxk.cn/ "网页链接") ) ##### 所用到的相关知识: 1. Java 网络请求 2. Java 文件下载 3. Java 文件读取 会简单的网络请求以及IO流就可以KO这个小Demo了。 #### 开始: 首先不是我自己写的站、接口什么的不知道有没有(反正我没找着)所以就只能抓取网页源码进行操作咯。 支持QQ音乐、网易云音乐、酷狗音乐、酷我音乐等音乐源。 个人建议 使用 QQ音乐源,理由是版权多、质量好。 ### 代码 首先,请求过程中需要用到一些歌曲的信息,这里把它封装成一个`JavaBean`: ```java package top.nanshaobit.demo.music; /** * 歌曲实体 单首 * */ public class Bean { /** * 歌名 */ public String name; /** * 歌手 */ public String artist; /** * 歌曲链接 */ public String url; } ``` 部分工具类: ```java /** * 流转字符串 * @param inputStream * @return * @throws Exception */ private static String byte2String(InputStream inputStream) { String result = ""; try { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024 * 6]; int length = 0; while ((length = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, length); outputStream.flush(); } result = new String(outputStream.toByteArray(), "utf-8"); outputStream.close(); } catch (Exception e) { System.out.println(getTime() + "-------------------------------"); System.out.println(getTime() + "------------网络出错-------------"); System.out.println(getTime() + "-------------------------------"); } return result; } /** * url获取返回结果 * * @param url * @return */ private static String url2String(String url) { HttpURLConnection conn; String result = "0"; try { URL _url = new URL(url); conn = (HttpURLConnection) _url.openConnection(); conn.setConnectTimeout(6000); int code = conn.getResponseCode(); if (code == 200) { InputStream inputStream = conn.getInputStream(); result = byte2String(inputStream); } else { System.out.println(getTime() + "-------------------------------"); System.out.println(getTime() + "------------网络出错-------------"); System.out.println(getTime() + "-------------------------------"); return "0"; } } catch (Exception e) { System.out.println(getTime() + "-------------------------------"); System.out.println(getTime() + "------------网络出错-------------"); System.out.println(getTime() + "-------------------------------"); } return result; } ``` 支持多平台,为了防止输入时的大意导致错误,这里把他们写作常量。 ```java public static final String QQ = "qq"; public static final String WANG_YI_YUN = "wy"; public static final String KU_WO = "kuwo"; public static final String KU_GOU = "kg"; ``` 搜一个试试: ![搜索结果截图](https://ae01.alicdn.com/kf/Hcc2f9b65acfb4e7e9ff0de3e5cf64bd2L.png "搜索结果截图") 可以看到,URL是以get的方式请求的。搜索数据是以列表的形式展现的,由于没有接口,咱就自己扒源码抓取吧。 HTML代码看着很乱,好在有段代码特别清晰,而且正是我们想要的,那是一段JS代码块: ```javascript <script> const ap1 = new APlayer({ element: document.getElementById('player1'), mini: false, autoplay: false, fixed: false, lrcType: 3, mutex: true, listFolded: false, theme: '#E94C4C', audio: [ { name: '真的爱你', artist: 'BEYOND', url: 'http://dl.stream.qqmusic.qq.com/M500004Gyue33FERTT.mp3?vkey=380B7AEB4C51A503219277CD9B6C9E64746FD902F49FF1C8171107F0BD7512FCE9A62E4612B92E725FB64C62717C3C68C078772293180B93&guid=594132158&uid=123456&fromtag=30', pic: 'http://imgcache.qq.com/music/photo/mid_album_300/C/s/000eOgmK1fN8Cs.jpg' , lrc: 'http://music.hwkxk.cn/lrc.php?id=004Gyue33FERTT&source=tencent' },{ name: '不再犹豫', artist: 'BEYOND', url: 'http://dl.stream.qqmusic.qq.com/M5000033N6Jr4DvOl9.mp3?vkey=380B7AEB4C51A503219277CD9B6C9E64746FD902F49FF1C8171107F0BD7512FCE9A62E4612B92E725FB64C62717C3C68C078772293180B93&guid=594132158&uid=123456&fromtag=30', pic: 'http://imgcache.qq.com/music/photo/mid_album_300/R/m/001Gikfw1MiLRm.jpg' , lrc: 'http://music.hwkxk.cn/lrc.php?id=0033N6Jr4DvOl9&source=tencent' }, /***省略部分***/ { name: '高温派对', artist: 'BEYOND', url: 'http://dl.stream.qqmusic.qq.com/M5000008DPzP3ANhn8.mp3?vkey=380B7AEB4C51A503219277CD9B6C9E64746FD902F49FF1C8171107F0BD7512FCE9A62E4612B92E725FB64C62717C3C68C078772293180B93&guid=594132158&uid=123456&fromtag=30', pic: 'http://imgcache.qq.com/music/photo/mid_album_300/E/h/002XSb5j2bTyEh.jpg' , lrc: 'http://music.hwkxk.cn/lrc.php?id=0008DPzP3ANhn8&source=tencent' }, ] }); jQuery(document).ready(function($){ $('.scroll_t').click(function(){$('html,body').animate({scrollTop: '0px'}, 800);}); $('.scroll_b').click(function(){$('html,body').animate({scrollTop: document.body.clientHeight+'px'}, 800);}); }); $(document).ready(function(){ $("ul.scroll li").hover(function() { $(this).find("div").stop() .animate({right: "0", opacity:1}, "fast") .css("display","block") }, function() { $(this).find("div").stop() .animate({right: "0", opacity: 0}, "fast") }); }); </script> ``` 还是比较规范的,那咱就直接正则提取一下就行了。 ```java /** * 获取实体集合 * * @param json * @return */ private static ArrayList<Bean> getBeansByJson(String json) { ArrayList<String> name = new ArrayList<String>(); Pattern pName = Pattern.compile("name:[\\s]+#([^#]+)"); Matcher mName = pName.matcher(json); while (mName.find()) { name.add(mName.group(1)); } ArrayList<String> artist = new ArrayList<String>(); Pattern pArtist = Pattern.compile("artist:[\\s]+#([^#]+)"); Matcher mArtist = pArtist.matcher(json); while (mArtist.find()) { artist.add(mArtist.group(1)); } ArrayList<String> url = new ArrayList<String>(); Pattern pUrl = Pattern.compile("url:[\\s]+#([^#]+)"); Matcher mUrl = pUrl.matcher(json); while (mUrl.find()) { url.add(mUrl.group(1)); } ArrayList<Bean> beans = new ArrayList<Bean>(); for (int index = 0; index < name.size(); index++) { Bean bean = new Bean(); bean.name = name.get(index); bean.artist = artist.get(index); bean.url = url.get(index); beans.add(bean); } return beans; } ``` 这就把歌曲的部分重要信息给提取出来了。 然后就可以根据歌曲的url下载后依据歌手名、歌曲名去命名、保存了。 ```java /** * 下载音乐 * * @param Name * @param musicPath */ private static void download(String musicUrl, String path) { // 重要:网站ssl证书有问题,切换到普通连接 musicUrl = musicUrl.replace("https", "http"); // 获取扩展名 // String[] name = musicUrl.split("\\?")[0].split("\\."); // String kzm = name[name.length - 1]; String kzm = "mp3"; path += "." + kzm; // System.out.println(musicUrl); System.out.println(getTime() + "正在下载: " + path); File f = new File(path); if (f.exists()) { System.out.println(getTime() + "已存在的歌曲: " + path); return; } try { URL url = new URL(musicUrl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(6000); int code = conn.getResponseCode(); if (code != 200) { System.err.println(getTime() + "歌曲: " + path + " 下载失败!********************"); return; } DataInputStream in = new DataInputStream(conn.getInputStream()); DataOutputStream out = new DataOutputStream(new FileOutputStream(path)); byte[] buffer = new byte[1024 * 2]; int count = 0; System.out.println(getTime() + "* * * * * * * * * * * * * * * * * * * * * * "); while ((count = in.read(buffer)) > 0) { out.write(buffer, 0, count); } out.close(); in.close(); } catch (Exception e) { System.out.println(getTime() + "-------------------------------"); System.out.println(getTime() + "------------网络出错-------------"); System.out.println(getTime() + "-------------------------------"); } System.out.println(getTime() + "文件: " + path + " 下载成功!"); } ``` 基本流程就是这样,也可以封装点功能,比如: - 根据歌手名下载 - 默认下载第一页 - 自定义下载几首 - 根据歌曲名下载 - 默认下载搜索结果第一首 - 下载文件较大的一首 - 根据文件下载(歌手名) - (同上) 根据文件下载(歌曲名) - (同上) ![自定义函数](https://ae01.alicdn.com/kf/Hc7c9f374c61546fc898b9f77f6f9529bg.png "自定义函数") #### 跑一下,效果预览: ![运行截图](https://ae01.alicdn.com/kf/H8305c21d99224101a24d32402ca28e59S.png "运行截图") ![文件下载截图](https://ae01.alicdn.com/kf/H8431f31483b84cb9932f6fbaabd15465w.png "文件下载截图") #### 至此,结束。 ### 体会 任何作品都是源于一个创意、一个想法,然后去思考如何实现,整个过程是怎么样的,想好就去写代码吧,不要浪费了好不容易出来的Demo。 只要你做了,就会有收获、不言结果。 #### 没有任何的努力,会被辜负! --马老师(芜湖大司马) ### END 上一篇:??考勤猫? 下一篇:C# 操作Excel、PDF 文章评论 [ 聊聊技术 聊聊自己 ] 在巴甫洛夫条件反射 试验中:给定一条狗,每次摇铃后喂食,足够次数后,狗则听到铃声将会习惯性的分泌唾液,由此引发对铃声的依恋。延伸到实际,给定一个喜欢的妹子,每次见面赠与巴甫洛夫式 的礼品或者零食,由此引发妹子的依恋。引入薛定谔的猫 理论,在未表白前,妹子与自己一直处于一种“概率云”的状态,一旦表白则“概率云”将消失成为实际。在 巴甫洛夫式 后且未表白前,自己与妹子的关系为“既是恋人又不是恋人”的矛盾体。返回巴甫洛夫式 试验中,在妹纸形成足够的依恋过后,则可以打破薛定谔 “概率云”的状态。这个谜一样的自己,这一刻 薛定谔 附体,带着量子论般深沉的哀愁,让她从此不能自拔! 自此创作 巴甫洛夫薛定谔把妹法,深藏功与名。