在网易云音乐网页版上加下载按键进行下载歌曲 |
您所在的位置:网站首页 › track单曲 › 在网易云音乐网页版上加下载按键进行下载歌曲 |
源由原理代码解决
思路Ajax 请求函数获取 id 和歌名点击下载利用 a 标签利用 audio 标签更改歌曲名
a 标签的 download 属性利用 Ajax 请求歌曲内容利用后台设置下载前询问 利用剪贴板 代码逻辑操作流程总结
源由
每一次放假回家的时候,都会帮家里面的人下载歌曲,当然差不多用的都是网易云音乐网页版,但是只有客户端才提供下载按键,所以每次都是从 Chrome 的开发者工具的 Network 中找链接,进行下载。所以我就想着能不能用 JS 代码来实现一个按键,一键就可以下载音乐。其实我可以直接用客户端来进行下载的,但随便为了学习一下,用 JS 来实现。 原理其实原理很简单,先打开 Chrome 的开发者工具的 Network 中,数据类型选为 Media,再打开网易云音乐的界面,点击一首歌,即可看到数据的 URL 地址,下载即可。 大概看云音乐界面情况,可知播放控制栏为固定的,则可以肯定,数据是通过 Ajax 发送,获取歌曲的 URL 地址,再进行加载播放。 在开发者的 Network 中记录了所有的请求数据,请求的数据是按照时间来排序的,我们按照刚才的原理可以获取到歌曲的 URL 地址,所以在该歌曲的请求数据上面,肯定会有一个发送 Ajax 的请求,来请求歌曲的 URL 地址信息。 所以我的思路是这样的,找到该 Ajax 请求函数,模拟发送歌曲信息请求,获取歌曲的 URL 地址,然后进行下载。 我们把 Network 中的数据类型选中为 All,即可看到发送的 Ajax 歌曲信息请求。 将该条目的具体信息关掉,也就是点击 Headers 左边的小叉叉,即可看到: 将 core.js 文件下载下来,再格式化代码,为什么我会把该代码下载下来呢,我是这么想的他发送 Ajax 请求,可能会是先填入发送的相关 URL 地址,然后需要的时候再加上参数调用发送,所以我们还需要知道发送该 Ajax 的具体 URL 地址是什么,在 Network 中点击发送获取歌曲信息的条目,可看到为: Request URL: http://music.163.com/weapi/song/enhance/player/url?csrf_token=将该 URL 在格式化后的 core.js 代码中进行查找。我们首先查找 weapi/song/enhance/player/url 无果,再次去除一些,再查找 song/enhance/player/url 我们再一次的全局搜索 v5A.bl5q 的定义代码,发送有一处代码为: 我们很肯定这个就是云音乐发送 Ajax 的代码,只不过被混淆了,不过我们可以进行黑箱操作,我们把该代码块提取出来,也就是 (function() { … })(); 中的代码,我们把提取出来的代码,复制在游览器云音乐页面的开发者工具 Console 中,但报错了: 可以在 Console 中输入这个,即可获得歌曲的 URL 地址,但这里要发送有两个参数,一个是 ids、br。ids 应该是歌曲的 id 进行加密,所以this.cP6J.id 为歌曲的 id。全局找到 DEFAULT_BR,可知道这个是一个变量,我猜测这里应该是音质的选择: var DEFAULT_BR = 128e3;
onload 请求成功时调用,onerror 请求失败是调用,我们可以用下面这个函数来打印响应的数据。 var a = function() {console.log(arguments)}ids: JSON.stringify([id]),id 为歌曲的 id,点击一首歌的主页可看见 URL 为 http://music.163.com/#/song?id=418602116, 即 id 为418602116,br 为320e3,将该请求代码复制到 Console 中,可将 onerror 函数去掉。 此时我们已经知道获取歌曲 URL 地址的 Ajax 函数。 若参数还无法确定时,可采用在线调试云音乐的 core.js 代码,利用我之前写的在线调试 JS 的方法(点击即可访问),获取 Ajax 发送的请求数据,即可以在代码中输出对应的参数信息,即可观察到。 b4f.bFx0x = function() { this.zJ3x(); console.log("************debug***********请求数据") console.log(this.cP6J.id) console.log(DEFAULT_BR) console.log("************debug***********请求数据") v5A.bl5q("/api/song/enhance/player/url", { type: "json", query: { ids: JSON.stringify([this.cP6J.id]), br: DEFAULT_BR }, onload: this.bGl1x.f5k(this), onerror: this.bGl1x.f5k(this) }) }; 获取 id 和歌名在偶然间我发现,云音乐有一个 window.player 对象: 我们通过上面,已经得到发送 Ajax 的函数和需要的参数,所以我们可以在页面中插入一个固定位置的超链接,点击即可下载。 // 添加 css var css = ` .ztz-easyd {position:relative; top:70%; font-size:15px; left:40px; color:black;} ` var html = `下载` document.head.insertAdjacentHTML('beforeEnd', css) document.body.insertAdjacentHTML('beforeEnd', html);然后再 downloadCurrent() 加入下载的逻辑,先获取到歌曲 id,再发送 Ajax 请求歌曲信息,然后得到的歌曲 URL 地址,再用 window.open(mp3Url) 打开。 经过尝试后,发现一个问题,Chrome 游览器会拦截这个弹窗,这样不太友好。 利用 a 标签将 window.open(mp3Url) 替换为设置该下载也就是 a 标签的 href 属性值的后,可弹出。 有个问题,点击第一次时,并没有弹出,因为点击时,href 属性没有值,href 的值是点击函数中赋值的,点击第二次时,可访问但是访问的是前一次的歌曲 URL,这次的歌曲 URL 还未赋值给 href。这是一个问题,但我们也可以解决的。 当点开 a 标签时,新的页面是一个 audio 标签播放界面。所以我就想,直接在云音乐页面中插入 audio 标签,并且是可视的,这样一点击就可以下载了,就可以避免上面的 href 赋值问题了。 利用 audio 标签所以该下载的 a 标签,改名为加载,意思就是加载 audio 标签。 云音乐的播放过程是这样的,请求下来的歌曲 URL,放入 audio 标签中,即可播放,而在 Chrome 游览器中,默认的 audio 的控制栏中有下载按键。 // css 属性 var css = ` .ztz-down {position:relative; top:75%; width:200px; left:-30px;} ` document.head.insertAdjacentHTML('beforeEnd', css) // 停止页面的播放 window.player.pause(); var audio = new Audio(); audio.src = mp3Url; audio.controls = true; audio.setAttribute('class', 'ztz-down'); audio.removeAttribute('preload'); document.body.appendChild(audio); 更改歌曲名 a 标签的 download 属性a 标签中有一个 download 属性,可以支持设置下载名,但仅限于同源的,而他这个歌曲 URL 是不同源的。 利用 Ajax 请求歌曲内容我又想着,再通过 Ajax 请求歌曲 URL,这样就能把返回的歌曲内容转化为 base64,再加到 a 标签的 src 中,这样就不受同源策略影响了,download 属性就可以用了。 但尝试了无解,Ajax 禁止非同源加载数据,而且请求歌曲 URL,不能使用 CORS(跨域资源共享 )。 这里也发现了一个问题,数据时请求下来的,受游览器的同源安全策略,数据只是没有在游览器中显示。 利用后台其实这里用后台来解决的话,很方便,弄一个支持 CORS 的后台,请求的时候把歌曲的 URL 地址和歌曲的名字(FILENAME)发过去,然后返回数据,在响应头中设置 MIME,这样下载的时候,就会自带名字。 Content-Disposition: attachment; filename=FILENAME 设置下载前询问我们也可以在下载的时候,更改名字,Chrome 默认的是,一点击就下载,这里我们就无法进行更改名字了,所以应该把 Chrome 下载前询问打开,方便我们进行修改名字。 打开 Chrome 设置 -> 高级 -> 下载内容 -> 打开下载前询问每个文件的保存位置具体操作。 利用剪贴板我们更改文件名是采用设置下载前询问, 到目前为止我们已经解决了点击下载,就剩下 自动复制歌曲名了。 每次上 github 下载项目时,都会有一个点击即可复制下载链接,我通过搜索大概知道了原理,利用的是剪贴板实现的功能,用户点击时,自动把内容复制。 我们采用clipboard 这个库,具体使用方法点击,大概如下: 1. 引用该 JS 文件。 2. 设置可自动复制的 class,运行 new ClipboardJS('.btn'); btn 为class。 3. 设置需要点击复制的超链接或者按键的 class、data-clipboard-text 属性,前者就是第二步设置的可自动复制的 class,后者就是复制的内容。 代码逻辑 1. 云音乐页面中插入 a 标签,并有点击事件。 2. 点击后,暂停播放,生成 audio 标签,并复制了歌名。具体代码点击代码。 操作流程 点击 复制里面的全部 JS 代码。复制到游览器云音乐界面的开发者工具的 Console 中,回车运行。关闭开发者工具。打开 Chrome 下载文件前询问,设置下载前询问。播放需要下载的歌,然后点击加载,再点击 audio 的下载图标,粘贴(Ctrl+C)更改名字后下载即可。多尝试,多观察,就能知道哪些能做,哪些不能做。 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |