播放器歌詞數據須要從qq官網上抓取,打開qq音樂任意一首歌曲的播放頁面,在chrome的Network中搜索lyric,即獲取歌詞的接口
vue
qq對接口進行了安全控制,在devserver中模擬請求頭等從而避開
在config文件夾中index.js文件中,配置proxyTableios
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': '' } } }
在api文件夾下建立song.jschrome
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) } } }) }
爲何寫在class Song{}中:由於這樣能夠它的實例直接調用本身的歌詞json
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')) } }) }) } }
在player.vue中methods,調取方法axios
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 }) },