谷美 | 如何使用node爬取某平台音乐,并保存到本地


注意:本项目仅供个人研究学习使用,切勿商用!

项目截图

歌曲下载中
周杰伦专辑
叶惠美专辑音乐

项目部署环境与使用

  • nodejs(用来做文件流的操做)
  • axios(用来发送请求,获取音频的文件流)
    • 使用
  • 执行

项目思路

  1. 获取url地址
  2. 发送网络请求,使其以流的形式进行返回
  3. 使用nodejs的fs模块对返回的流文件进行操作

获取音乐url

目前网络上已经有很多的个人开放了各音乐平台的api接口,大家可以进行自行选择使用,也可以联系我获知比较优秀的几个api接口。

发送请求,并以流的形式进行返回

async function getMusicUrl(musicID, quality = "320") {
    let res,resdata;
    try{
        res = await axios(`${baseURL}/url?id=${musicID}&quality=${quality}`,{
            responseType: 'stream'
        });
        resdata = res.data;
    }catch(e){
        console.log(e)
    };
    return resdata;
}

按照 音乐人/专辑名/歌曲名的形式 创建文件夹

const getAlbumBySingerID = require("./api/1/getAlbumBySinger")
const getAlbumMusic = require("./api/1/getAlbumMusic")
const getMusicUrl = require("./api/1/getMusicURl")
const getSingerList = require("./api/1/getsingerlist")
const fs = require("fs");

// 下载音乐
async function downloadMusic(singerID){
    let albumArr = await getAlbumBySingerID(singerID);
    for(let i = 0;i < albumArr.length;i++){
        // 获取到专辑信息
        let ablumInfo = albumArr[i].musicData;
        // 专辑名称
        let albumName = ablumInfo.albumname;
        // 专辑ID
        let albumID = ablumInfo.albummid;
        // 获取歌手名称(要注意这个地方的歌手名字可能不止一个)
        let singerName = ablumInfo.singer[0].name;
        let albumMusicArrInfo = await getAlbumMusic(albumID);
        let albumMusicArr = albumMusicArrInfo.getSongInfo;
        for(let j = 0;j < albumMusicArr.length;j++){
            let musicInfo = albumMusicArr[j];
            let musicID = musicInfo.songmid;
            let musicName = musicInfo.songname;
            console.log(musicName)
            // 获取音乐  文件流数据
            let streamData = await getMusicUrl(musicID);
            // 如果音乐文件不存在,就跳过本次循环
            if(!streamData){
                break;
            }
            saveMusicToLocal("Music",singerName,albumName,musicName,streamData);
        }
    }
}

使用nodejs进行储存

// 储存音乐
async function saveMusicToLocal(basePath,singerName,albumName,musicName,data){
    let pathName = `${basePath}/${singerName}/${albumName}`
    try{
        let temp = await fs.mkdirSync(pathName, { recursive: true })
    }catch(e){
        console.log(e)
    }
    // 检查文件夹是否存在
    // 避免在创建流的时候出错
    fs.exists(pathName,(flag)=>{
        if(!flag){
            // 如果文件夹不存在就递归创建
            fs.mkdirSync(pathName,{ recursive: true})
        }
        // 当存在时执行以下操作
        // 创建可写流
        console.log(`${pathName}/${musicName}.mp3`)
        let writeStream = fs.createWriteStream(`${pathName}/${musicName}.mp3`,{ encoding: "binary" })
        data.pipe(writeStream);
        data.on("close", function () {
            writeStream.close()
        })
    })
}   

注意

  • 由于音乐平台的不同,某些歌曲可能在某个平台并不能够爬取到,所以在代码编写时一定要做好容错处理
  • 创建流的时候,编码类型一定要是二进制格式,如下:fs.createWriteStream(`${pathName}/${musicName}.mp3`,{ encoding: "binary" })
  • 若有问题,欢迎评论交流!
原创文章 2 获赞 3 访问量 130

猜你喜欢

转载自blog.csdn.net/qq_42581023/article/details/105293820