NiceLeeのBlog 用爱发电 bilibili~

QQ音乐 个人收藏列表获取

2019-05-24
nIceLee

阅读:


        之前尝试过搜索关键词来获取QQ音乐信息 + 音乐直链。自己试过自建喜欢的音乐列表,并为此花费了较多功夫,也解决了几个小问题。(只是技术交流学习,以后就撤掉了😳
        例如,由于播放链接有时效性,故而保存的时候仅保留id,播放的时候根据id来自动获取直链。
        又比如,由于是静态网页,直接写死了HTML,新增更改十分费力。现在把歌曲内容信息和展示分开来,直接修改保存json即可。
        但还是有些麻烦,每新增N首曲目需要 搜索歌名 -> 打印信息 -> 修改json文件 xN,不太方便。于是,我就想能不能直接更进一步,再爬一下个人的收藏夹

目标

获取QQ音乐指定列表的音乐曲目(分页),并打印输出,格式如下:

{
    "title": "A cut in Love (被爱情切割)",
    "author": "줄라이 (July)",
    "pic": "https://y.gtimg.cn/music/photo_new/T002R300x300M000001mrdzu00xMPx.jpg",
    "mid": "004DCwDo41i7ja",
    "tag": ["haoting"],
    "brief": "Happiness (幸福)-"
},
{
    "title": "隐",
    "author": "New One Studio",
    "pic": "https://y.gtimg.cn/music/photo_new/T002R300x300M0000027mnht4733M5.jpg",
    "mid": "001ms6bA1qcrae",
    "tag": ["haoting"],
    "brief": "隐形守护者OST-《隐形守护者》BGM"
},
{
    "title": "aloha heja he-指弹前奏",
    "author": "雨人",
    "pic": "https://y.gtimg.cn/music/photo_new/T002R300x300M0000034pJDt1PDfyo.jpg",
    "mid": "003Gzohl2hl4Or",
    "tag": ["haoting"],
    "brief": "这段旋律很有感觉"
},
...

解析

在PC Web端登录QQ音乐,发现目标URL如下:(这种工作熟练度上来之后没啥难度…

https://c.y.qq.com/qzone/fcg-bin/fcg_ucc_getcdinfo_byids_cp.fcg?
type=1
&json=1
&utf8=1
&onlysong=1
&nosign=1
&new_format=1
&song_begin=0
&song_num=10
&ctx=1
&disstid=689219101
&_=1558690697209
&g_tk=7654321
&loginUin=1234567
&hostUin=0
&format=json
&inCharset=utf8
&outCharset=utf-8
&notice=0
&platform=yqq.json
&needNewCode=0

此时,请求头为:

accept-encoding:gzip, deflate, sdch, br
accept-language:zh-CN,zh;q=0.8
cookie:略
origin:https://y.qq.com
// referer:https://y.qq.com/n/yqq/playlist/{listId}.html 
// 上边referer是进入到具体列表,下面那个是登录后的“我喜欢”
referer:https://y.qq.com/portal/profile.html
user-agent:略
  • 参数释疑
    • URL中disstid即列表的id,很重要,因为量较少,所以就自己人工获取吧~
    • URL中song_beginsong_num,分页我就不说了
    • URL中g_tkloginUin,应该跟登录有关。loginUin为QQ号,g_tk未知。
      不登录,g_tk=5381&loginUin=0可以满足需求。
    • URL中_即时间
    • HEADER中cookie经测试没有影响

实现

以前的HtmlUnit等太重了,这里用的是自己封装的URLConnection,意思到了你懂的( ╯□╰ ))

public void printDesignedJson(int begin, int size, String albumId) {
    long time = System.currentTimeMillis();
    String g_tk = "5381"; //与user相对应?
    String user = "0"; // 未登录,登录后是qq号
    String url = "https://c.y.qq.com/qzone/fcg-bin/fcg_ucc_getcdinfo_byids_cp.fcg?type=1&json=1&utf8=1&onlysong=1&nosign=1&new_format=1&ctx=1&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0";
    url += String.format("&song_begin=%d&song_num=%d&_=%d&disstid=%s&g_tk=%s&loginUin=%s", begin, size, time, albumId, g_tk, user);
    
    
    HttpRequestUtil util = new HttpRequestUtil();
    HashMap<String, String> header = new HashMap<>();
    header.put("accept", "application/json, text/javascript, */*; q=0.01");
    header.put("accept-language", "zh-CN,zh;q=0.8");
    header.put("origin", "https://y.qq.com");
    header.put("referer", String.format("https://y.qq.com/n/yqq/playlist/%s.html", albumId));
    header.put("user-agent", "太长,略");
    String result = util.getContent(url, header);
    System.out.println(result);
    JSONArray musicList = new JSONObject(result).getJSONArray("songlist");
    
    StringBuilder sb = new StringBuilder();
    for(int i = 0; i < musicList.length(); i++) {
        JSONObject json = musicList.getJSONObject(i);
        JSONObject album = json.getJSONObject("album");
        String albumPic = String.format("https://y.gtimg.cn/music/photo_new/T002R300x300M000%s.jpg", album.getString("mid"));
        
        sb.append("{\r\n");
        formatJson(sb, "title", json.getString("title"), false);
        formatJson(sb, "author", json.getJSONArray("singer").getJSONObject(0).getString("title"), false);
        formatJson(sb, "pic", albumPic, false);
        formatJson(sb, "mid", json.getString("mid"), false);
        sb.append("    \"tag\": [\"haoting\"],\r\n");
        formatJson(sb, "brief", album.getString("title") + "-" + album.getString("subtitle"), true);
        sb.append("},\r\n");
    }
    System.out.println(sb.toString());
}

private void formatJson(StringBuilder sb, String key, String value, boolean isLast) {
    sb.append("    \"")
    .append(key)
    .append("\": \"")
    .append(value);
    if(isLast) {
        sb.append("\"\r\n");
    }else {
        sb.append("\",\r\n");
    }
}

内容
隐藏