5.23 QQ音乐数据源(新)抓取完整步骤

抓获数据源思路:
1、任意打开一首歌,进入QQ音乐网页播放界面。先不播放歌曲,查看network发现,服务端传来music.fcg?-=getplaysongvkey,这是当前歌曲的vkey。
5.23 QQ音乐数据源(新)抓取完整步骤_第1张图片
2、分析该XHR应答。在req_0->data->midurlinfo[0]->purl。就是正确参数的后半截。
5.23 QQ音乐数据源(新)抓取完整步骤_第2张图片
3、继续分析XHR,在 req_0->data->sip中,发现可能是正确参数的前半截。
5.23 QQ音乐数据源(新)抓取完整步骤_第3张图片
4、尝试将参数拼接访问
5.23 QQ音乐数据源(新)抓取完整步骤_第4张图片

5、正确解析,那就是,只要获取歌曲的getplaysongkey,就能拼接出正确的Url。

注:其实这是不断尝试的过程,因为QQ音乐返回的数据源的域名并不是dl.stream.qqmusic而是变化的ip。但是sip映射的接口,也可以正确解析数据源。

可能你还没看懂,反正是一个接口抓获,以及分析的过程。接下来就是具体实现代码。

和ustbhuangyi导师一样,直接jsonp访问即可。在api/singer中
5.23 QQ音乐数据源(新)抓取完整步骤_第5张图片

// 文件写在singer.js中
// 传入歌曲的mid即可,获得正确的songkey

export function getPlaySongKey(mid) {
  const url = 'https://u.y.qq.com/cgi-bin/musicu.fcg'
  const data = Object.assign({}, commonParams, {
    loginUin: 0,
    hostUin: 0,
    platform: 'yqq.json',
    needNewCode: 0,
    data: `{"req_0":{"module":"vkey.GetVkeyServer","method":"CgiGetVkey","param":{"guid":"1933776370","songmid":["${mid}"],"songtype":[0],"uin":"0","loginflag":1,"platform":"20"}},"comm":{"uin":0,"format":"json","ct":24,"cv":0}}`
  })
  return jsonp(url, data, '')
}
// 这一段代码为的是拼接出正确参数,promise方法。你也可以不用这段代码。看你个人水平了。这是promise应答
如果不用这段代码,你直接使用getPlaySongKey,然后通过then(res => {这里是拼接参数的方法})也可以。

export function getSongUrl(mid) {
  return getPlaySongKey(mid).then(res => {
    if (res.code === 0) {
      const purl = res.req_0.data.midurlinfo[0].purl
      const host = res.req_0.data.sip[0]
      return Promise.resolve({code: 0, url: host + purl})
    }
  })
}

我这里还是用getSongUrl来讲咯。
成功获取到歌曲的url,那么接下来就是将url保存到song对象中。我的做法呢。就是遍历song数组,给每一首song增加对应的url

比如在singer-detail.vue组件中的_normalizeSongs方法中调用getSongUrl接口,在标准化数据的同时将url获取,并放入该对象中。

  methods: {
    _getDetail () {
      if (!this.singer.id) {
        this.$router.push('/singer')
        return
      }
      getSingerDetail(this.singer.id).then(res => {
        if (res.code === ERR_OK) {
          this.songs = this._normalizeSongs(res.singer.data.songlist)
          // console.log(this.songs)
        }
      })
    },
    _normalizeSongs(list) {
      let ret = []
      list.forEach((item, index) => {
        let musicData = item
        ret.push(createSong(musicData))
        if (musicData.id && musicData.album.id) {
          // 解析正确Vkey拼装url
          this._getSongUrl(musicData.mid).then(url => {
            // 指向正确的url
            ret[index].url = url
          })
        }
      })
      return ret
    },
    _getSongUrl (mid) {
      return getSongUrl(mid).then(res => {
        return Promise.resolve(res.url)
      })
    }
  }

简言之,你只需要获得播放源url就可以了,至于后续的数据渲染问题,方法可以有很多,不一定要标准化数据时扔url进去,如果歌曲长度50,则会发送50个XHR请求,很耗资源。好的做法就是侦听currentSong的变化,根据变化重新发送getSongUrl并将url丢给currentSong即可。

你可能感兴趣的:(5.23 QQ音乐数据源(新)抓取完整步骤)