爬取网易云音乐

爬取网易云音乐

该爬虫使用PhantomJS,cheerio,bluebird以及Node.js内置模块来实现

首先,我们需要认识到利用普通爬取静态网页的方式是爬取不到源码的,你只会拿到源码的模板,数据根本没有被填充,所以我们需要使用PhantomJS这个工具。它的功能,就是提供一个浏览器环境的命令行接口,你可以把它看做一个虚拟的浏览器,除了不能浏览,其它与正常浏览器一样。它的内核是wenkit引擎,不提供图形界面,只能在命令行下使用。其次,我们使用cheerio模块,其提供了类似于jquery的方法来解析爬取到的HTML代码,另外,我们使用blueBird来异步爬取。(这些模块可以使用npm来下载安装)

  1. 官网下载到的phantomJS是一个可执行程序,下载完成后配置其环境变量。然后利用Node.js的child_process新起进程来调用此命令。具体代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//1.js文件
var page = require('webpage').create();
page.onConsoleMessage = function(msg) {
console.log('Page title is ' + msg);
};
page.settings.userAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36";
page.open('url', function(status) {//open方法的第一个参数是需要爬去的网址
if (status !== 'success') {
console.log('Unable to access network');
}else{
console.log('正在爬取请稍后');
setTimeout(function() {
var result = page.evaluate(function() {
return document.getElementById("g_iframe").contentDocument.documentElement.innerHTML;
});
console.log(result);
phantom.exit();
}, 7000); //需进行延迟等待,带页面渲染完毕再进行爬取
}
});
  1. 主程序代码如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    var cp = require('child_process');
    var http = require('http');
    var cheerio = require('cheerio');
    var Promise = require("bluebird");
    var fs = require('fs');
    var ids = []; //存取歌曲ID
    var list=[]; //存取所有promise对象
    var details = []; //存取歌曲信息
    var url = 'http://music.163.com/api/song/detail/?id=425137664&ids=[425137664]&csrf_token=';
    var urls = []; //存取歌曲json文件信息
    function getJson(u){
    return new Promise(function(resolve,reject){
    http.get(u, function(res) {
    var html = "";
    res.on("data", function(data) {
    html += data;
    });
    res.on("end", function() {
    resolve(html);
    });
    }).on("error", function(e){
    reject(e);
    console.log("获取信息出错!");
    });
    });
    }
    /**
    * 解析网页
    */
    function parseContent($){
    var tr = $('tbody').find('tr');
    tr.each(function(i,t){
    var td = $(t).find('td').eq(1);
    var id = $(td).find('a').attr('href').split('=')[1];
    ids.push(id); //获取到歌曲id
    });
    //拼接URL,获取到歌曲的json文件
    ids.forEach(function(num){
    var u = url.replace(/\d{4,}/g,num);
    urls.push(u);
    });
    urls.forEach(function(url){
    list.push(getJson(url));
    });
    Promise.all(list).then(function(jsons){//解析获取到的json文件
    jsons.forEach(function(json){
    var json = JSON.parse(json);
    //获取到歌曲的基本信息
    var name = json.songs[0].name;
    var singer = json.songs[0].artists[0].name;
    var picUrl = json.songs[0].album.picUrl;
    var src = json.songs[0].mp3Url;
    details.push({
    "name": name,
    "singer":singer,
    "picUrl":picUrl,
    "src" : src
    });
    });
    fs.writeFile('music.json',JSON.stringify(details)); //将获取到的数据以json格式写入到文件中
    });
    }
    //新建进程利用phantomJS来运行1.js文件
    cp.exec('phantomjs.exe 1.js',{
    timeout: 20000000, //超时时间
    },function(error,stdout,stderr){ //传给回调的 stdout 和 stderr 参数会包含子进程的 stdout 和 stderr 的输出
    if(error){
    console.error(`exec error ${error}`);
    return;
    }
    let $ = cheerio.load(stdout); //利用cheerio来解析爬取到的HTML
    parseContent($);
    });

然后,你就可以在music.json中看到自己需要爬去的歌曲信息了 。