前言:在学习慕课网课程制作企业级音乐app中,发现之前的qq音乐播放地址均不可用了。于是折腾了一下,重新抓包获取地址。
在之前的代码里,如下红色圆中的歌单-歌曲列表显示不出来,因为之前qq音乐改变了源地址,现在只能通过node来做接入层转发一下。
原来获取歌单列表的代码:
发现不能获取了,如果发现报错Uncaught ReferenceError: jp1 is not defined之类的东西,这是jsonp的问题,去config.js添加prefix:‘playlistinfoCallback’能解决,但是还是不能获得数据
去打开qq音乐pc版,找到https://c.y.qq.com/qzone/fcg-bin/fcg_ucc_getcdinfo_byids_cp.fcg?type=1&json=1&utf8=1&onlysong=0&disstid=6543771358&g_tk=5381&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq.json&needNewCode=0 的链接,如果没有多刷新几次
双击链接,返回msg invalid referer,这个链接不能直接获取了,需要node转发
所以现在结构明确了
新代码如下:
在dev-server.js中添加
可能会注意到 我这里多了一部分内容
const url = '' + prefixHost.prefixHost + '/api/getplaysongvkey'
这是我用来判断是否是dev环境启动,还是直接打开打包好的build/index.html,这样做我可以在连接局域网的情况下直接用手机访问这个页面,如果要用手机访问,记得开启一个新的node服务器,比如node prod.server.js用来做转发。然后手机输入电脑ip和node服务器开启的端口即可。
这部分代码在config中添加host.js,
module.exports = {
prefixHost: process.env.NODE_ENV === 'development' ? '' :'http://192.168.1.104:9000'
}
然后在recommend.js中引入的,来做判断的
var prefixHost = require('../../config/host')
经过这样就可以顺利获取榜单中的歌曲列表。
随便找到榜单列表的一首歌,比如《知否知否》,点击进入下面这个音乐播放页面(目前是这个页面才能抓到需要的包,不知以后是否会变)
先清空或刷新下,在点击播放,可以看到这个地址,双击能拿到真正的播放地址
拿到这个地址http://dl.stream.qqmusic.qq.com/C400002krvKI4Jgvq9.m4a?guid=7347620869&vkey=0FA4AD518A295E845C2E2F375494A197473C3B7266A7DBB5D81C9D70204380FD5044DD1CA8209DF0C49C0FC182647AD8AEF441D49396FA16&uin=0&fromtag=66
仔细分析一下,再去之前榜单列表中,抓到的包中展开看看点击的这首歌《知否知否》的情况,
不难发现真正的地址是由
http://dl.stream.qqmusic.qq.com/C400${songmid}.m4a?guid=7347620869&vkey=${vkey}&uin=0&fromtag=66
构成,多次抓取不同歌曲后发现只要能获取vkey就行,然后就可以拼接成播放源地址。
下面找看那个url里面返回了vkey,主要还是在当前播放页面瞎找或上一个页面找找,找不到刷新刷新看看
突然,找到了这个请求,这不就是需要的vkey吗,而且看到purl正是拼接后的请求链接
看看Headers,发现这是需要设置请求源地址的,那么就要node转发了
origin:https://y.qq.com
referer:https://y.qq.com/portal/player.html
在看看Query parmeters这些参数我们都可以伪造的,里面data需要一个songmid也是可以拿到的
所以现在思路清晰了
代码如下先获取vkey
export function getplaysongvkey(songmid) {
const url = '' + prefixHost.prefixHost + '/api/getplaysongvkey'
const data = Object.assign({}, commonParams, {
// -: 'getplaysongvkey7257571376863041',
g_tk: 5381,
loginUin: 0,
hostUin: 0,
format: 'json',
inCharset: 'utf8',
outCharset: 'utf-8',
notice: 0,
platform: 'yqq.json',
needNewCode: 0,
data: `{"req":{"module":"CDN.SrfCdnDispatchServer","method":"GetCdnDispatch","param":{"guid":"7347620869","calltype":0,"userip":""}},"req_0":{"module":"vkey.GetVkeyServer","method":"CgiGetVkey","param":{"guid":"7347620869","songmid":["${songmid}"],"songtype":[0],"uin":"0","loginflag":1,"platform":"20"}},"comm":{"uin":0,"format":"json","ct":24,"cv":0}}`
})
return axios.get(url, {
params: data
}).then((res) => {
return Promise.resolve(res.data.req_0.data.midurlinfo[0].purl)
})
}
apiRoutes.get('/getplaysongvkey', function (req, res) {
var url = 'https://u.y.qq.com/cgi-bin/musicu.fcg'
axios.get(url, {
headers: {
origin: 'https://y.qq.com',
referer: 'https://y.qq.com/portal/player.html'
},
params: req.query
}).then((response) => {
res.json(response.data)
}).catch((e)=>{
console.log(e)
})
})
由于在之前的代码recommend.vue点击一个热门榜单,就会进入disc.vue中传入榜单id,就会获得榜单歌曲列表,构建一个songs类,包含该榜单中的所有歌曲信息
正是因为之前songs类中的url拼接不对(被qq音乐屏蔽掉了),所以先去掉,变成没有url的songs集合,显示如下
考虑到歌曲的源地址需要一个个去请求才能拿到,所以为了优化性能,在点击播放一首歌时,才通过这首歌的songmid获取其vkey,再更改songs类中的url形成这首歌的播放源地址
比如我点击了《知否知否》这首歌,就会去做如下改变,只更改获取该歌曲的url播放源地址,其他歌曲的url还是为空
因为是在点击时才请求vkey,所以修改music-list.vue中点击部分代码,还有songs是保存在vuex中,this.setlectPlay({list:this.songs,index}),所以要修改songs中的url,必须通过mapMutations,
在musci-list.vue中更改如下:
selectItem(item, index) {
getplaysongvkey(item.mid).then((vkey) => {
let url = `http://dl.stream.qqmusic.qq.com/${vkey}`
this.setPlaylistUrl({
index,
url,
})
})
this.selectPlay({
list: this.songs,
index
})
},
...mapMutations({
setPlaylistUrl: 'SET_PLAYLIST_URL'
})
在mutations.js中添加
[types.SET_PLAYLIST_URL](state, keyUrl) {
let index = keyUrl.index
let url = keyUrl.url
state.playlist[index].url = url
}
全部完成,经测试迄今为止这是有效方式~~~