利用JAVA发掘(爬取)酷狗流行音乐(或评论)

版权声明:本文为博主原创文章,未经博主允许不得转载,博客地址:https://blog.csdn.net/Asnet_ 原文地址: https://blog.csdn.net/Asnet_/article/details/80954826



前些天偶然听到了某首歌, 发现挺好听的,然后打开歌曲评论,发现评论数竟然高达80多万,紧接着我又看了下歌曲的发行日期,17年的,看到这就不能忍了,像我这种音乐达人(自恋一会大笑)怎麽能不知道这种好歌呢!!!


然后刚好最近考完试,于是决定写个类似的爬虫程序来爬取高评论数歌曲,好了,废话不多说,下面开始介绍下程序吧。


针对的是手机酷狗app(为啥不是别的我就懒得说了,没有啥原因),然后是Fiddler对手机抓包,抓包过程我就省略了。


抓包研究一会后,发现每首歌曲关键的地方是它对应的Hash值,通过这个Hash可以获取到诸多信息,比如评论,关联歌单信息等等。

然后主要就是模拟发包了,特别要注意包内的参数,具体参见代码注释吧!


import org.json.JSONArray;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 
 * @author As_
 * @since 2018/07/07
 * @email [email protected]
 * @github https://github.com/apknet
 *
 */

public class Main {
//    public static int n = 0;
    public static Map mapKey = new HashMap();
    public static void main(String[] args) {
     //以抓包获取到的某首歌曲Hash值为着手点
     //c3e7e3306a10374b801cc39e0de6bdca
        try {
//外面for遍历入口歌曲关联的歌单,里面for遍历每个歌单内的歌曲列表。如果想更大范围内爬取,可以多加几次循环!
            for(String colId : musToCol("c3e7e3306a10374b801cc39e0de6bdca")){
                for(Map.Entry<String, String> map : colToHash(colId).entrySet()){
                    hashToComment(map);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //由歌曲Hash提取推荐歌单
    static List<String> musToCol(String hash) {
        //仅更改歌曲Hash即可得到关联歌单信息
        //网址参数能减少的我都尽量减了,剩下差不多都是些必要参数
        String str = String.format("http://servicegz.mobile.kugou.com/v1/yueku/special_album_recommend?api_ver=1&album_audio_id=29010106&num=30&hash=%s", hash);
//        String str = "http://servicegz.mobile.kugou.com/v1/yueku/special_album_recommend?api_ver=1&album_audio_id=29010106&num=10&hash=791A040895D0D7998F63E0D9DACBE5B6";
        List<String> list = new ArrayList<>();
        try {
            URL url = new URL(str);
            InputStream in = url.openStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            StringBuilder stringBuilder = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                stringBuilder.append(line);
            }
            reader.close();
            in.close();
            String strJson = stringBuilder.toString();
//            System.out.println(strJson);
//下面操作是解析json获得歌单的识别码specialid

            JSONObject jsonObject = new JSONObject(strJson).getJSONObject("data").getJSONObject("info");

//            System.out.println(jsonObject);
            JSONArray jsonArray = jsonObject.getJSONArray("special");
            for (int i = 0; i < jsonArray.length(); i++) {
                jsonObject = (JSONObject) jsonArray.get(i);
                //   System.out.println(jsonObject.getString("specialid") + '\n');
                list.add(jsonObject.getString("specialid"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    //提取歌单中歌曲对应歌曲Hash值
    static Map<String, String> colToHash(String colId) {
        String str = String.format("http://mobilecdngz.kugou.com/api/v3/special/song?version=8983&plat=0&pagesize=-1&area_code=1&page=1&specialid=%s&with_res_tag=1", colId);
        //        List<String> list = new ArrayList<>();
        Map<String, String> map = new HashMap<>();
        try {
            URL url = new URL(str);
            InputStream in = url.openStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            StringBuilder stringBuilder = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                stringBuilder.append(line);
            }
            reader.close();
            in.close();            //去除头尾多余的信息,以免影响json的格式
            String strJson = stringBuilder.toString().replace("<!--KG_TAG_RES_START-->", "").replace("<!--KG_TAG_RES_END-->", "");
            //            System.out.println(strJson);
            JSONObject jsonObject = new JSONObject(strJson).getJSONObject("data");//            System.out.println(jsonObject);
            JSONArray jsonArray = jsonObject.getJSONArray("info");
            for (int i = 0; i < jsonArray.length(); i++) {
                jsonObject = (JSONObject) jsonArray.get(i);
                map.put(jsonObject.getString("hash"), jsonObject.getString("remark"));
                //                System.out.println(jsonObject.getString("hash") + '\n');
                //                list.add(jsonObject.getString("hash"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    // 由Hash值得到评论
    static void hashToComment(Map.Entry<String, String> map) {
//参数列表中的code好像是个定值, 每首歌曲都是对应的这个值。后面的extdata也就是歌曲hash值了
        String str = String.format("http://m.comment.service.kugou.com/index.php?r=commentsv2/getCommentWithLike&code=fc4be23b4e972707f36b8a828a93ba8a&clientver=8983&extdata=%s&p=1&pagesize=20", map.getKey());
        try {
            URL url = new URL(str);
            InputStream in = url.openStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            StringBuilder stringBuilder = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                stringBuilder.append(line);
            }
            reader.close();
            in.close();
            //            System.out.println(stringBuilder.toString());
            JSONObject jsonObject = new JSONObject(stringBuilder.toString());
            // 获取歌曲中的评论
                    /*  System.out.println(jsonObject.get("list"));
                                JSONArray jsonArray = jsonObject.getJSONArray("list");
                                for(int i = 0; i < jsonArray.length(); i++){
                                    jsonObject = (JSONObject) jsonArray.get(i);
                                    System.out.println(n + ". " + jsonObject.getString("content") + '\n');
                                    n++;
                     }*/
            //获得歌曲评论数
            int comCount = jsonObject.getInt("combine_count");
            //          System.out.println(comCount);
            //评论数15万以上的就打印出来
            if (comCount > 150000) {
                System.out.println(comCount + ": " + map.getValue());
                mapKey.put(map.getKey(), map.getValue());
            }
        } catch (Exception e) {
            System.out.println("- - - - - -> 抱歉,该歌曲未提供评论功能!");
            e.printStackTrace();
        }
    }



}
         

最后就是实验截图了


猜你喜欢

转载自blog.csdn.net/Asnet_/article/details/80954826