标签搜索

aplayer+meting 的妙用

sterling
2023-04-24 / 0 评论 / 1 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2023年12月10日,已超过495天没有更新,若内容或图片失效,请留言反馈。

Aplayer是一个功能强大的HTML5音乐播放器,兼容所有浏览器。

Meting.js 介绍

![Meting JS]

Meting.js 依赖 APlayer.js,扩展了 APlayer.js 的功能,能够使 APlayer.js 加载网易云音乐、QQ 音乐、虾米音乐中的歌单。

apayer+meting 简单调用

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>    
    <!-- require APlayer -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css">
    <script src="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script>
    <!-- require MetingJS -->
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/Meting.min.js"></script>
    </head>
    <body>

    <meting-js server="netease" type="playlist" id="60198"></meting-js>
        
    </body>
</html>

Metingjs 的简单说明

解析:server="netease" type="playlist" id="60198"

server指音乐平台,netease指网易云音乐, type类型,playlist列表,id指歌曲的i或者专辑或列表外链id
因此重点在于指定平台,指定外链id

Metingjs 的源码解析

class MetingJSElement extends HTMLElement {
  /**
   * 当自定义元素第一次被连接到文档 DOM 时被调用
   * connectedCallback
   * https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements#using_the_lifecycle_callbacks
   */
  connectedCallback() {
    if (window.APlayer && window.fetch) {
      this._init()
      this._parse()
    }
  }

  /**
   * 与 connectedCallback 反
   */
  disconnectedCallback() {
    if (!this.lock) {
      this.aplayer.destroy()
    }
  }

  /**
   * 驼峰化
   * @param { string } str
   * @returns { string } str
   */
  _camelize(str) {
    return str
      .replace(/^[_.\- ]+/, '')
      .toLowerCase()
      .replace(/[_.\- ]+(\w|$)/g, (m, p1) => p1.toUpperCase())
  }

  /**
   * 初始化
   */
  _init() {
    let config = {}

    // attributes -> NamedNodeMap
    // https://developer.mozilla.org/zh-CN/docs/Web/API/NamedNodeMap
    for (let i = 0; i < this.attributes.length; i += 1) {
      config[this._camelize(this.attributes[i].name)] = this.attributes[i].value
    }

    let keys = [
      'server',
      'type',
      'id',
      'api',
      'auth',
      'auto',
      'lock',
      'name',
      'title',
      'artist',
      'author',
      'url',
      'cover',
      'pic',
      'lyric',
      'lrc',
    ]

    this.meta = {}

    // 构建 meta
    // config 保留 keys 数组中没有的属性
    // keys 中有 config 中也有的属性给 meta 赋值,没有的先设为 undefined
    for (let key of keys) {
      this.meta[key] = config[key]
      delete config[key]
    }

    this.config = config
    this.api =
      this.meta.api ||
      window.meting_api ||
      'https://api.injahow.cn/meting/api?server=:server&type=:type&id=:id&r=:r'

    if (this.meta.auto) this._parse_link()
  }

  /**
   * 解析 auto 属性的值
   * 将解析后的结果赋值给 meta 对象的 server、type、id
   */
  _parse_link() {
    let rules = [
      ['music.163.com.*song.*id=(\\d+)', 'netease', 'song'],
      ['music.163.com.*album.*id=(\\d+)', 'netease', 'album'],
      ['music.163.com.*artist.*id=(\\d+)', 'netease', 'artist'],
      ['music.163.com.*playlist.*id=(\\d+)', 'netease', 'playlist'],
      ['music.163.com.*discover/toplist.*id=(\\d+)', 'netease', 'playlist'],
      ['y.qq.com.*song/(\\w+).html', 'tencent', 'song'],
      ['y.qq.com.*album/(\\w+).html', 'tencent', 'album'],
      ['y.qq.com.*singer/(\\w+).html', 'tencent', 'artist'],
      ['y.qq.com.*playsquare/(\\w+).html', 'tencent', 'playlist'],
      ['y.qq.com.*playlist/(\\w+).html', 'tencent', 'playlist'],
      ['xiami.com.*song/(\\w+)', 'xiami', 'song'],
      ['xiami.com.*album/(\\w+)', 'xiami', 'album'],
      ['xiami.com.*artist/(\\w+)', 'xiami', 'artist'],
      ['xiami.com.*collect/(\\w+)', 'xiami', 'playlist'],
    ]

    for (let rule of rules) {
      // 返回匹配
      // eg: "https://y.qq.com/n/yqq/song/001RGrEX3ija5X.html"
      // ["y.qq.com/n/yqq/song/001RGrEX3ija5X.html", "001RGrEX3ija5X"]
      let patt = new RegExp(rule[0])
      let res = patt.exec(this.meta.auto)

      if (res !== null) {
        this.meta.server = rule[1]
        this.meta.type = rule[2]
        this.meta.id = res[1]
        return
      }
    }
  }

  /**
   * 对不同 url 进行处理
   * 生成配置并加载 APlayer
   */
  _parse() {
    if (this.meta.url) {
      // 直接构建 APlayer 配置并加载 APlayer
      let result = {
        name: this.meta.name || this.meta.title || 'Audio name',
        artist: this.meta.artist || this.meta.author || 'Audio artist',
        url: this.meta.url,
        cover: this.meta.cover || this.meta.pic,
        lrc: this.meta.lrc || this.meta.lyric || '',
        type: this.meta.type || 'auto',
      }
      if (!result.lrc) {
        this.meta.lrcType = 0
      }
      if (this.innerText) {
        result.lrc = this.innerText
        this.meta.lrcType = 2
      }
      this._loadPlayer([result])
      return
    }

    // 1. 通过 meta 拼凑接口参数获得完整接口 (_init 中存放的默认 api)
    // 2. 请求接口,得到播放列表数据
    // 3. 加载 APlayer
    let url = this.api
      .replace(':server', this.meta.server)
      .replace(':type', this.meta.type)
      .replace(':id', this.meta.id)
      .replace(':auth', this.meta.auth)
      .replace(':r', Math.random())

    fetch(url)
      .then(res => res.json())
      .then(result => this._loadPlayer(result))
  }

  _loadPlayer(data) {
    let defaultOption = {
      audio: data,
      mutex: true,
      lrcType: this.meta.lrcType || 3,
      storageName: 'metingjs',
    }

    if (!data.length) return

    let options = {
      ...defaultOption,
      ...this.config,
    }

    for (let optkey in options) {
      if (options[optkey] === 'true' || options[optkey] === 'false') {
        options[optkey] = options[optkey] === 'true'
      }
    }

    let div = document.createElement('div')
    options.container = div

    this.appendChild(div)
    this.aplayer = new APlayer(options)
  }
}

// 创建标签
// customElements -> https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements
if (window.customElements && !window.customElements.get('meting-js')) {
  window.MetingJSElement = MetingJSElement
  window.customElements.define('meting-js', MetingJSElement)
}

Metingjs的高级调用方法

当我们需要听vip版权歌曲,需要调用私人api,所以不能再使用无登陆访客状态,需更改cookie值,下面看下代码解析。

 private function curlset()
    {
        switch ($this->server) {
            case 'netease':
            return array(
                'Referer'         => 'https://music.163.com/',
                'Cookie'          => 'appver=8.2.30; os=iPhone OS; osver=15.0; EVNSM=1.0.0; buildver=2206; channel=distribution; machineid=iPhone13.3',
                'User-Agent'      => 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 CloudMusic/0.1.1 NeteaseMusic/8.2.30',
                'X-Real-IP'       => long2ip(mt_rand(1884815360, 1884890111)),
                'Accept'          => '*/*',
                'Accept-Language' => 'zh-CN,zh;q=0.8,gl;q=0.6,zh-TW;q=0.4',
                'Connection'      => 'keep-alive',
                'Content-Type'    => 'application/x-www-form-urlencoded',
            );
            case 'tencent':
            return array(
                'Referer'         => 'http://y.qq.com',
                'Cookie'          => 'pgv_pvi=22038528; pgv_si=s3156287488; pgv_pvid=5535248600; yplayer_open=1; ts_last=y.qq.com/portal/player.html; ts_uid=4847550686; yq_index=0; qqmusic_fromtag=66; player_exist=1',
                'User-Agent'      => 'QQ%E9%9F%B3%E4%B9%90/54409 CFNetwork/901.1 Darwin/17.6.0 (x86_64)',
                'Accept'          => '*/*',
                'Accept-Language' => 'zh-CN,zh;q=0.8,gl;q=0.6,zh-TW;q=0.4',
                'Connection'      => 'keep-alive',
                'Content-Type'    => 'application/x-www-form-urlencoded',
            );
            case 'xiami':
            return array(
                'Cookie'          => '_m_h5_tk=15d3402511a022796d88b249f83fb968_1511163656929; _m_h5_tk_enc=b6b3e64d81dae577fc314b5c5692df3c',
                'User-Agent'      => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) XIAMI-MUSIC/3.1.1 Chrome/56.0.2924.87 Electron/1.6.11 Safari/537.36',
                'Accept'          => 'application/json',
                'Content-type'    => 'application/x-www-form-urlencoded',
                'Accept-Language' => 'zh-CN',
            );
            case 'kugou':
            return array(
                'User-Agent'      => 'IPhone-8990-searchSong',
                'UNI-UserAgent'   => 'iOS11.4-Phone8990-1009-0-WiFi',
            );
            case 'baidu':
            return array(
                'Cookie'          => 'BAIDUID='.$this->getRandomHex(32).':FG=1',
                'User-Agent'      => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) baidu-music/1.2.1 Chrome/66.0.3359.181 Electron/3.0.5 Safari/537.36',
                'Accept'          => '*/*',
                'Content-type'    => 'application/json;charset=UTF-8',
                'Accept-Language' => 'zh-CN',
            );
            case 'kuwo':
            return array(
                'Cookie'          => 'Hm_lvt_cdb524f42f0ce19b169a8071123a4797=1623339177,1623339183; _ga=GA1.2.1195980605.1579367081; Hm_lpvt_cdb524f42f0ce19b169a8071123a4797=1623339982; kw_token=3E7JFQ7MRPL; _gid=GA1.2.747985028.1623339179; _gat=1',
                'csrf'            => '3E7JFQ7MRPL',
                'Host'            => 'www.kuwo.cn',
                'Referer'         => 'http://www.kuwo.cn/',
                'User-Agent'      => 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36',
            );
        }
    }

我们需要自行更改对应平台的cookie值,然后调用私人api。

私人api好处:稳定不会挂,可以听版权音乐,即使是某抑变灰歌曲。

0

评论 (0)

取消