调用网易云音乐api,爬取网易云音乐歌单

Scroll Down

来源:NanCheung`s Blog
链接:https://blog.nancheung.com /archives/8354688
商业转载请联系作者获得授权,非商业转载请注明出处。



偶尔在微博上看到,要是歌单里谁的歌超过30首,那肯定是真爱吧。
我看了连忙打开网易云音乐我的歌单,结果1000多首歌。。。这让我自己数得数到猴年马月呀.

于是萌生出了写一段小爬虫来统计的想法。

刚开始想直接解析网页元素,后发现很麻烦,很多信息不能一次抓取到,于是找到网页请求的接口,结果接口有加密参数,看了一下js加密参数的方法,头都晕了。没法子,我在网上查资料,终于找到一个api(原文:http://moonlib.com/606.html ):
http://music.163.com/api/playlist/detail?id=歌单ID

比如我喜欢的歌单:https://music.163.com/#/playlist?id=40882617那么歌单id就是 40882617 。
组合一下就知道了我们需要请求的接口地址:http://music.163.com/api/playlist/detail?id=40882617

我们可以先用浏览器或者postman等工具得到接口返回的json,利用Gson等工具生成对应的Bean。

我生成一个PlayListVo 来接收歌单详情信息,此处不详述。

等生成Bean之后,现在我们就需要写一段代码,来请求这个接口了。

由于这个接口有请求头的验证,我们需要添加一些信息
以下代码抛砖引玉:

@Test
public void test1() {
    //定义请求头
    HttpHeaders headers = new HttpHeaders();
    headers.set("Accept", "*/*");
    headers.set("Accept-Language", "zh-CN,zh;q=0.8");
    headers.set("Host", "music.163.com");
    headers.set("Referer", "http://music.163.com/");
    headers.set("cookies", "appver=2.0.2");
    headers.setConnection("keep-alive");
    headers.set("User-Agent",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36");
    //  执行HTTP请求
    String post = new RestTemplate().exchange("http://music.163.com/api/playlist/detail?id=40882617",
            HttpMethod.POST, new HttpEntity<>(headers, headers), String.class).getBody();
    System.out.println(post + "\n\n\n\n\n\n\n\n\n");
    PlayListVo playListVo = JSON.parseObject(post, PlayListVo.class);
    //统计每位歌手的歌曲数量
    Map<String, Integer> map = new TreeMap<>();
    Objects.requireNonNull(playListVo).getResult().getTracks()
            .forEach(tracksBean -> tracksBean.getAlbum().getArtists().forEach(artistsBean -> {
                String name = artistsBean.getName();
                map.put(name, map.get(name) == null ? 1 : map.get(name) + 1);
            }));
    List<Map.Entry<String, Integer>> list = new ArrayList<>(map.entrySet());
    list.stream().sorted(Comparator.comparing(Map.Entry::getValue)).forEach(System.out::print);
}

代码只提供思路吧,如需详细源码,请戳:https://github.com/nancheung97/music163reptile