播放器歌词数据需要从qq官网上抓取,打开qq音乐任意一首歌曲的播放页面,在chrome的Network中搜索lyric,即获取歌词的接口
1. 配置接口
qq对接口进行了安全控制,在devserver中模拟请求头等从而避开
在config文件夹中index.js文件中,配置proxyTable
proxyTable: {
//target:真实请求的值
//bypass:对应的函数是请求之前可以进行的操作
//req这个参数是请求的信息,可以在这里设置请求头信息
'/api/lyric':{
target: 'https://szc.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg',
bypass: function (req, res, proxyOptions) {
req.headers.referer = 'https://c.y.qq.com';
req.headers.host = 'c.y.qq.com';
},
pathRewrite: {
'^/api/lyric': ''
}
}
}
2. 调取接口的API
在api文件夹下创建song.js
export function getLyric(mid) {
const url = '/api/lyric'
const data = Object.assign({}, commonParams, {
songmid: mid,
platform: 'yqq',
hostUin: 0,
needNewCode: 0,
pcachetime: +new Date(),
format: 'json',
g_tk: 67232076
})
return axios.get(url, {
params: data
}).then((res) => {
if (typeof res.data === 'string') {
//返回的jsonp格式,利用正则,提取我们需要的json字段
const reg = /^\w+\(({[^()]+})\)$/
var matches = res.data.match(reg)
if (matches) {
let val = JSON.parse(matches[1])
//为什么用Promise:为了后边的方法调用的时候,进一步then,操作数据
return Promise.resolve(val)
}
}
})
}
3.在Song类中调用
为什么写在class Song{}中:因为这样可以它的实例直接调用自己的歌词
export default class Song {
....
//当初没有搞懂为什么lyric不再constructor中定义:下面的if判断,防止重复请求歌词
getLyric() {
if (this.lyric) {
return Promise.resolve(this.lyric)
}
//这里用Promsie返回,同样的道理:后面调用这个方法,方便进一步操作数据,同2中的promsie
return new Promise((resolve, reject) => {
getLyric(this.mid).then((res) => {
if (res.code === ERR_OK) {
//返回数据的是 base64 的字符串,需要解码,这里用到了第三方库: js-base64
this.lyric = Base64.decode(res.lyric)
resolve(this.lyric)
} else {
reject(new Error('no lyric'))
}
})
})
}
}
3.真正调取方法
在player.vue中methods,调取方法
getLyric() {
//在2中,方法定义在class Song{}类中,这个时候this.currentSong是类的实例,可以直接调用定义的实例方法
this.currentSong.getLyric().then((lyric) => {
//利用第三方库: js-lyric ,解析我们的歌词,生成方便操作的对象
//new Lyric生成的实例,还有一些api方便使用play、stop等等
//this.handleLyric回调函数handleLyric(lineNum,txt):(当前播放的行数,当前播放的文字)
this.currentLyric = new Lyric(lyric, this.handleLyric)
if (this.playing) {
this.currentLyric.play()
}
}).catch(() => {
//如果歌词有问题,初始化
this.currentLyric = null
this.playingLyric = ''
this.currentLineNum = 0
})
},
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。