爬取网易云音乐
该爬虫使用PhantomJS,cheerio,bluebird以及Node.js内置模块来实现
首先,我们需要认识到利用普通爬取静态网页的方式是爬取不到源码的,你只会拿到源码的模板,数据根本没有被填充,所以我们需要使用PhantomJS这个工具。它的功能,就是提供一个浏览器环境的命令行接口,你可以把它看做一个虚拟的浏览器,除了不能浏览,其它与正常浏览器一样。它的内核是wenkit引擎,不提供图形界面,只能在命令行下使用。其次,我们使用cheerio模块,其提供了类似于jquery的方法来解析爬取到的HTML代码,另外,我们使用blueBird来异步爬取。(这些模块可以使用npm来下载安装)
- 官网下载到的phantomJS是一个可执行程序,下载完成后配置其环境变量。然后利用Node.js的child_process新起进程来调用此命令。具体代码如下:
|
|
- 主程序代码如下:1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677var cp = require('child_process');var http = require('http');var cheerio = require('cheerio');var Promise = require("bluebird");var fs = require('fs');var ids = []; //存取歌曲IDvar 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来解析爬取到的HTMLparseContent($);});
然后,你就可以在music.json中看到自己需要爬去的歌曲信息了 。