资讯专栏INFORMATION COLUMN

nodejs爬虫爬取 喜马拉雅FM 指定主播歌单并下载

andycall / 2655人阅读

摘要:如图点击音频发出请求,请求返回数据里面包含真实音频链接,如图写爬虫需求分析完了,那现在当然是写爬虫了,首先爬取主播页,拿到,然后根据发送请求拿到真实音频地址。

最近一直在学英语,因此写了个爬虫爬取歌单并下载,然后随时都可以听。
GitHub地址:https://github.com/leeseean/nodejs-crawler。
页面分析
要用爬虫下载音频,那自然是要找到音频链接了。而网站的音频链接没有直接暴露出来,因此需要分析找出获取音频链接的办法。
进入喜马拉雅官网主页,随便找一个主播的页面进入,我这里找的是[英语主播Emily](http://www.ximalaya.com/29101549/album/2801092)的主页,然后里面有她的播单,F12打开一看这些歌单都没有直接写音频链接。但是还是有一些规律的,每个音频都有一个ID,后面点击这个音频的时候,会有一个AJAX请求,请求的链接就包含这个ID,这个请求会返回音频的真实链接,这样就拿到了音频链接。如图

点击音频发出AJAX请求,请求返回数据里面包含真实音频链接,如图

写爬虫
需求分析完了,那现在当然是写爬虫了,首先爬取主播页,拿到ID,然后根据ID发送AJAX请求拿到真实音频地址。
用的模块有cheerio和request。
   const request = require("request");

   const fs = require("fs");
   const cheerio = require("cheerio");
   //这个时间后面设置cookie需要用到
   const formatTime = (new Date()).toLocaleString().replace(///g, "-").replace(/[u4E00-u9FA5]/g, "");

直接用request(url,callcack)发现返回一个301重定向的页面,因此要设置uset-agent和cookie才能正确访问到页面。如图,

相应设置代码如下:

function setOptions({
    url,
    cookies,
    contentType
}) {
    const jar = request.jar();
    jar.setCookie(request.cookie(cookies), url);
    return {
        url: url,
        jar: jar,
        method: "GET",
        headers: {
            "Connection": "keep-alive",
            "Content-Type": contentType,
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36"
        }
    };
}
请求到页面到拿到所有音频的ID,并根据音频ID发送AJAX请求,代码如下:
function getListIdsCallback(error, response, body) {
    if (!error && response.statusCode === 200) {
        const listIds = [];//存放所有音频ID的数组
        const $ = cheerio.load(body);
        $("div.album_soundlist > ul > li > div > a.title").each((index, item) => {
            listIds.push($(item).attr("href").split("/")[3]);
        });   
        getAudioJson(listIds);//获取音频真实链接并下载音频
    }
}
获取音频真实链接并下载音频
代码如下:
function getAudioJson(listIds) {
    if (listIds.length === 0) {
        return;
    }
    const id = listIds.shift();
    request(setOptions({
        url: `http://www.ximalaya.com/tracks/${id}.json`,
        cookies: `_xmLog=xm_1510364052559_j9unrdjjmwt7gx; login_from=qq; nickname=All2005; login_type=QQ; 1&remember_me=y; 1&_token=96575028&ecb632710362104767080ce01362b33cc881; trackType=web; x_xmly_traffic=utm_source%3A%26utm_medium%3A%26utm_campaign%3A%26utm_content%3A%26utm_term%3A%26utm_from%3A; Hm_lvt_4a7d8ec50cfd6af753c4f8aee3425070=1510364053; Hm_lpvt_4a7d8ec50cfd6af753c4f8aee3425070=1510376453; _ga=GA1.2.1519968795.1510364053; _gat=1; 1_l_flag=96575028&ecb632710362104767080ce01362b33cc881_${formatTime}; msgwarn=%7B%22category%22%3A%22%22%2C%22newMessage%22%3A0%2C%22newNotice%22%3A0%2C%22newComment%22%3A0%2C%22newQuan%22%3A0%2C%22newFollower%22%3A0%2C%22newLikes%22%3A0%7D`,
        contentType: "text/html;charset=utf-8",
    }), (error, response, body) => {
        return getAudioJsonCallback(error, response, body, listIds);
    });
}

function getAudioJsonCallback(error, response, body, listIds) {
    if (!error && response.statusCode === 200) {
        const JsonData = JSON.parse(body);
        downloadFile(JsonData["play_path"], `${JsonData["id"]}.m4a`, (e) => {
            console.log(`下载完毕${JsonData["id"]}`);
            getAudioJson(listIds);
        });
    }
}


function downloadFile(url, filename, callback) {
    const stream = fs.createWriteStream(filename);
    request(url).pipe(stream).on("close", callback);
}
代码技巧
这里获取到listIds一开始是使用一个循环去下载,后面发现一下子同时开启几十个下载node根本吃不消,下下来的音频不完整,后面采用一个一个下载的办法,就完全解决的这个问题。相关代码如下:
const id = listIds.shift();//每次取出一个id去请求
downloadFile(JsonData["play_path"], `${JsonData["id"]}.m4a`, (e) => {
    console.log(`下载完毕${JsonData["id"]}`);
    getAudioJson(listIds);//下载完后再次启动请求
});
总结
先写到这了。爬虫的关键就是找出真实地址,然后抓页面的时候如果抓不到记得补充cookie,设置user-agent等一类参数。


文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/89717.html

相关文章

  • 爬虫nodejs爬斗鱼直播间数据实战

    摘要:前提本项目地址如果需要,可以到本地打开可直接查看爬虫数据目标爬取斗鱼正在直播的主播数据房间号,在线人数,房间标题,主播名称,直播分类等等依赖构建安装包的应用程序框架小型渐进式客户端请求库,和模块具有相同的,具有许多高级客户端功能可以 前提 本项目github地址:https://github.com/janyin/dou...如果需要,可以clone到本地 $ npm install ...

    KunMinX 评论0 收藏0
  • 15行Python代码搞定网易云热门歌单

    摘要:引言马上情人节就要来了,是否需要一首歌来抚慰你,受伤或躁动的心灵。来吧,今天教你用行代码搞定热门歌单。爬取的效果如下总结本文旨在安抚你因情人节受伤的小心灵,同时带你入个爬虫的门,感受下的强大。 0. 引言 马上314情人节就要来了,是否需要一首歌来抚慰你,受伤或躁动的心灵。来吧,今天教你用15行代码搞定热门歌单。学起来并听起来吧。 本文使用的是Selenium模块,它是一个自动化测试工...

    StonePanda 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<