Причина: Папа попросил меня скачать тысячи песен для него, чтобы он играл в машине.Я чувствую, что скачиваю вручную, даже если это занимает время для скачивания партиями, я просто пишу краулер, чтобы скачивать автоматически. .
Для этого небольшого проекта искателя выбран узел + koa2 для инициализации проекта.koa2 projectName
(сначала необходимо установить глобальноkoa-generator
), затем в файл проекта,npm install && npm start
, в котором используются зависимостиsuperagent, cheerio, async, fs, path
Откройте веб-версию NetEase Cloud, щелкните страницу списка воспроизведения, я выбрал категорию «Китайский язык», щелкните правой кнопкой мыши, чтобы просмотреть исходный код фреймворка, получить реальный URL-адрес и найти идентификатор какm-pl-container
html, это список плейлистов, которые нужно просканировать на этот раз, напрямую используйтеsuperagent
URL запроса, можно сканировать только данные первой страницы, нужноasync
ползать одновременно
static getPlayList(){
const pageUrlList = this.getPageUrl();
return new Promise((resolve, reject) => {
asy.mapLimit(pageUrlList, 1, (url, callback) => {
this.requestPlayList(url, callback);
}, (err, result) => {
if(err){
reject(err);
}
resolve(result);
})
})
}
вconst asy = require('async')
, потому что с помощьюasync/await
, так различайте,requestPlayList
это запрос, инициированный суперагентом
static requestPlayList(url, callback){
superagent.get(url).set({
'Connection': 'keep-alive'
}).end((err, res) => {
if(err){
console.info(err);
callback(null, null);
return;
}
const $ = cheerio.load(res.text);
let curList = this.getCurPalyList($);
callback(null, curList);
})
}
getCurPalyList
это получить информацию на странице, передать$
для манипуляций с домом
static getCurPalyList($){
let list = [];
$('#m-pl-container li').each(function(i, elem){
let _this = $(elem);
list.push({
name: _this.find('.dec a').text(),
href: _this.find('.dec a').attr('href'),
number: _this.find('.nb').text()
});
});
return list;
}
На этом сканирование списка плейлистов завершено, и следующим шагом будет сканирование списка песен.
static async getSongList(){
const urlCollection = await playList.getPlayList();
let urlList = [];
for(let item of urlCollection){
for(let subItem of item){
urlList.push(baseUrl + subItem.href);
}
}
return new Promise((resolve, reject) => {
asy.mapLimit(urlList, 1, (url, callback) => {
this.requestSongList(url, callback);
}, (err, result) => {
if(err){
reject(err);
}
resolve(result);
})
})
}
requestSongList
Использование аналогично плейлисту выше, поэтому повторяться не буду. После того, как приведенный выше код получит список песен, его необходимо загрузить локально.
static async downloadSongList(){
const songList = await this.getSongList();
let songUrlList = [];
for(let item of songList){
for(let subItem of item){
let id = subItem.url.split('=')[1];
songUrlList.push({
name: subItem.name,
downloadUrl: downloadUrl + '?id=' + id + '.mp3'
});
}
}
if(!fs.existsSync(dirname)){
fs.mkdirSync(dirname);
}
return new Promise((resolve, reject) => {
asy.mapSeries(songUrlList, (item, callback) => {
setTimeout(() => {
this.requestDownload(item, callback);
callback(null, item);
}, 5e3);
}, (err, result) => {
if(err){
reject(err);
}
resolve(result);
})
})
}
вrequestDownload
заключается в том, чтобы запросить URL-адрес загрузки, загрузить и сохранить его локально
static requestDownload(item, callback){
let stream = fs.createWriteStream(path.join(dirname, item.name + '.mp3'));
superagent.get(item.downloadUrl).set({
'Connection': 'keep-alive'
}).pipe(stream).on('error', (err) => {
console.info(err); // error处理,爬取错误时,打印错误并继续向下执行
})
}
На этом апплет искателя завершен. Проект просматривает список воспроизведения --> список песен --> загружает на локальный сайт, конечно, вы также можете напрямую найти домашнюю страницу певца, изменить URL-адрес, переданный в список песен, и напрямую загрузить популярные песни певца.