爬虫很难吗?手把手酷我音乐解析

这篇具有很好参考价值的文章主要介绍了爬虫很难吗?手把手酷我音乐解析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。



1.排行榜列表

  1. 打开 kuwo.cn, 浏览器F12 监听网络请求,刷新一次页面
  2. 根据网页信息,定位接口地址。
  3. F12界面全局搜索(ctrl+shift+F)排行榜中的向云端 (你看到什么就搜什么 不固定)

酷我api,爬虫,爬虫,javascript,前端

  1. 点击搜索结果,跳转至关键词数据所在页面,在此页面搜索(ctrl+F)向云端,结论:数据来源于页面window._NUXT_.data.bang对象。如下图:
    酷我api,爬虫,爬虫,javascript,前端
    酷我api,爬虫,爬虫,javascript,前端
    页面用的是Nuxt服务器端渲染,看到a,b,c,d,e,f...了吧,这段js被混淆了

  2. 数据提取。可能首先想到的是用正则匹配,那有没有办法办法直接获取到 __NUXT__ 对象呢?既然是js,那就想办法运行这段js。

  3. 技术选型。那就用 nodejs 吧! nodejs 爬虫实战,看代码:

    let url = 'http://www.kuwo.cn/';
    //模拟访问首页
    let result = await get(url);//get方法为request封装
    //正则匹配那段js
    var mc = result.match(/<script>.*?<\/script>/gi);
    //console.log(mc);
    var __NUXT__;//定义接收变量
    let sc = mc[0] ?? '';
    //一系列的替换
    if (sc) {
        sc = sc.replace('<script>', '');
        sc = sc.replace('</script>', '');
        sc = sc.replace('window.', '');//由于不是浏览器没有window对象,就替换为空
        sc = sc.replace(/\r/gi, '');
        sc = sc.replace(/\n/gi, '');
        //console.log(sc);
    }
    let js = eval(sc);//用nodejs的方便之处,eval搞定,直接把结果赋值给__NUXT__
    //console.log(js);
    let bangs = __NUXT__.data[0].bang;

结果:

[
    {
        "leader":"酷我热歌榜",
        "num":"300",
        "name":"酷我热歌榜",
        "pic":"https://img4.kuwo.cn/star/albumcover/120/1/29/1934979845.jpg",
        "id":"16",
        "pub":"2023-07-14",
        "musicList":[
            {
                "musicrid":"MUSIC_279292599",
                "barrage":"0",
                "ad_type":"",
                "artist":"小霞&海洋Bo",
                "mvpayinfo":{
                    "play":0,
                    "vid":0,
                    "down":0
                },
                "pic":"https://img4.kuwo.cn/star/albumcover/500/1/29/1934979845.jpg",
                "isstar":0,
                "rid":279292599,
                "duration":251,
                "score100":"93",
                "ad_subtype":"0",
                "content_type":"0",
                "track":1,
                "hasmv":0,
                "releaseDate":"2023-06-29",
                "album":"向云端",
                "albumid":38777035,
                "pay":"16515324",
                "artistid":8854278,
                "albumpic":"https://img4.kuwo.cn/star/albumcover/500/1/29/1934979845.jpg",
                "originalsongtype":0,
                "isListenFee":false,
                "pic120":"https://img4.kuwo.cn/star/albumcover/120/1/29/1934979845.jpg",
                "name":"向云端",
                "online":1,

2.排行榜榜单详情

  1. 点击首页排行榜更多,监听网络请求
    酷我api,爬虫,爬虫,javascript,前端

详情地址为:
GET => https://www.kuwo.cn/api/www/bang/bang/musicList?bangId=93&pn=1&rn=20&httpsStatus=1&reqId=16fffd81-21fa-11ee-9cdf-25abfdc1606c&plat=web_www&from=

bangId=93//上个步骤中的id
pn=1//页码
rn=20//每页多少条
reqId=16fffd81-21fa-11ee-9cdf-25abfdc1606//可有可无

同样用 nodejs 模拟这个请求,结果:

{
    "success":false,
    "message":"CSRF token Invalid!",
    "now":"2023-07-14T05:49:44.720Z"
}
  1. 爬虫的关键部分来了,请求头模拟。简单来说,就是用程序把请求做的像浏览器发出的一样。通过分析请求头,以及反复测试,最终得出以下两个头信息为必备:(把以下所有头信息都模拟更好)
    酷我api,爬虫,爬虫,javascript,前端
  2. F12 界面全局搜Cross 定位出算法:
    酷我api,爬虫,爬虫,javascript,前端
    由上面代码可以看出来,Cross 是通过以 Hm_token 为参数,调用A()方法生成的。打断点调试A():
    酷我api,爬虫,爬虫,javascript,前端
  3. 梳理这两个参数的关系:

Cross 是由 Hm_token 加密处理得到。

由经验得知:Cross = md5(sha1(Hm_token))

常用的加密算法:md5 aes des sha 不知道数据用什么加密方式就全局搜,或者一个一个加密方法试。最后才选择单步调试~

  1. 加密算法有了,寻找 Hm_token :
    酷我api,爬虫,爬虫,javascript,前端
    每次请求,都会往cookie里面写入Hm_token ,用程序模拟并获取cookie:
async function hmToken() {
    let url = `https://www.kuwo.cn/`;
    let result = await superagent.get(url);
    let cookie = result.header['set-cookie'][0] ?? '';
    //console.log(cookie);
    let mc = cookie.match(/Hm_token=(.*?);/);
    let hm = mc[1] ?? '';
    return hm;
}
  1. 排行榜榜单详情最终代码:
async function getBangMusicList(id, pn, rn) {
    let hm = await hmToken();
    console.log(hm)
    
    var obj = crypto.createHash('sha1');
    obj.update(hm);
    let hmSha = obj.digest('hex');
    console.log(hmSha);

    obj = crypto.createHash('md5');
    obj.update(hmSha);
    var cross = obj.digest('hex');//hex是十六进制
    console.log(cross);

    let url = `http://www.kuwo.cn/api/www/bang/bang/musicList?bangId=${id}&pn=${pn}&rn=${rn}&httpsStatus=1&plat=web_www&reqId=`;
    var result = await get(url, {}, { Cross: cross, cookie: `Hm_token=${hm}` });

    var obj = JSON.parse(result);

    return obj;
}

3.根据rid获取歌曲mp3地址

  1. 点首歌,监听网络请求:
    酷我api,爬虫,爬虫,javascript,前端
  2. 程序模拟:
async function getAudio(id) {
    let url = 'https://www.kuwo.cn/api/v1/www/music/playUrl?mid=' + id + '&type=music&httpsStatus=1&reqId=&plat=web_www&from=';
    let result = await get(url);
    //console.log(result);
    return result;
}
======================================
getAudio(279292599) result 结果:
{
    "code":200,
    "msg":"success",
    "reqId":"b9ca2ee89fec9ad131105ce494d05a2b",
    "data":{
        "url":"https://other-web-nf01-sycdn.kuwo.cn/b09d144c5526bbb95e8d1166f1c8db8a/64b0fa4a/resource/n2/60/65/902137489.mp3?from$unkown&plat$web_www"
    },
    "profileId":"site",
    "curTime":1689320311016,
    "success":true
}

4.2023.07.17更新,请求头由“Cross”改为“Secret”

酷我api,爬虫,爬虫,javascript,前端
F12定位Secret:
酷我api,爬虫,爬虫,javascript,前端
单步调试这个h()方法:
酷我api,爬虫,爬虫,javascript,前端

分析完毕,看具体实现:

  1. 新增一个加密函数:(来源:某度)
function encrypt(str, pwd) {
    if (pwd == null || pwd.length <= 0) {
        alert("Please enter a password with which to encrypt the message.");
        return null;
    }
    var prand = "";
    for (var i = 0; i < pwd.length; i++) {
        prand += pwd.charCodeAt(i).toString();
    }
    var sPos = Math.floor(prand.length / 5);
    var mult = parseInt(prand.charAt(sPos) + prand.charAt(sPos * 2) + prand.charAt(sPos * 3) + prand.charAt(sPos * 4) + prand.charAt(sPos * 5));
    var incr = Math.ceil(pwd.length / 2);
    var modu = Math.pow(2, 31) - 1;
    if (mult < 2) {
        alert("Algorithm cannot find a suitable hash. Please choose a different password. \nPossible considerations are to choose a more complex or longer password.");
        return null;
    }
    var salt = Math.round(Math.random() * 1000000000) % 100000000;
    prand += salt;
    while (prand.length > 10) {
        prand = (parseInt(prand.substring(0, 10)) + parseInt(prand.substring(10, prand.length))).toString();
    }
    prand = (mult * prand + incr) % modu;
    var enc_chr = "";
    var enc_str = "";
    for (var i = 0; i < str.length; i++) {
        enc_chr = parseInt(str.charCodeAt(i) ^ Math.floor((prand / modu) * 255));
        if (enc_chr < 16) {
            enc_str += "0" + enc_chr.toString(16);
        } else enc_str += enc_chr.toString(16);
        prand = (mult * prand + incr) % modu;
    }
    salt = salt.toString(16);
    while (salt.length < 8) salt = "0" + salt;
    enc_str += salt;
    return enc_str;
}
  1. 新增获取请求头方法:
async function getHmIuvt() {
    let url = `https://www.kuwo.cn/`;
    var result = await superagent.get(url);
    let cookie = result.header['set-cookie'][0] ?? '';
    //console.log(cookie);
    if (cookie) {
        cookie = cookie.replace(/;.*/ig, '');
    }
    let sp = cookie.split('=');
    let data = {
        key: sp[0] ?? '',
        token: sp[1] ?? ''
    };
    return data;
}
  1. 完整代码示例(获取榜单列表):
async function getBangMusicList(id, pn, rn) {
    let iuvt = await getHmIuvt();
    let secret = encrypt(iuvt.token, iuvt.key);
    let url = `http://www.kuwo.cn/api/www/bang/bang/musicList?bangId=${id}&pn=${pn}&rn=${rn}&httpsStatus=1&plat=web_www&reqId=`;
    var result = await get(url, {}, { Secret: secret, cookie: `${iuvt.key}=${iuvt.token}` });
    var obj = JSON.parse(result);
    return obj;
}

5.根据rid获取VIP/高音质音乐链接

rid:281472652 音乐Url,请打开以下链接↓↓↓↓

https://nmobi.kuwo.cn/mobi.s?f=kuwo&q=NI8S5evAnmGldi4g47EsqtfDbGsJckckbTQQd2LAgmDPITUWSd51OkjHRFj6xHPEQxNN6u+tD3K2e3HYhbE4U0pUYwqjd2kt
结果是有过期时间的哦~每打开一次会获取最新

format=flac
bitrate=2000
url=http://ll.sycdn.kuwo.cn/0f304a22b30673380bb9646d6737302d/64b512bc/resource/s1/77/85/2165046264.flac?bitrate$2000&format$flac&type$convert_url2
sig=9298802900736320721
rid=281472652
type=0

rid:228908 音乐Url,请打开以下链接↓↓↓↓

http://nmobi.kuwo.cn/mobi.s?f=kuwo&q=NI8S5evAnmGldi4g47EsqtfDbGsJckckbTQQd2LAgmDPITUWSd51OkjHRFj6xHPEQxNN6u+tD3KtKpZdbgOTWA==
结果是有过期时间的哦~每打开一次会获取最新

format=flac
bitrate=2000
url=http://sy.sycdn.kuwo.cn/188862a666b9fff315836ac0dc168441/64b51570/resource/s1/96/9/3483822377.flac?bitrate$2000&format$flac&type$convert_url2
sig=14962903177885333588
rid=260839262
type=1

注意:电脑端访问:F12 将浏览器切换为手机模式才可访问!!!!!;或者发送到手机端直接访问即可!

6.根据rid获取歌词

async function musicLrc(rid) {
    let url = `https://m.kuwo.cn/newh5/singles/songinfoandlrc?musicId=${rid}`;
    let result = await superagent.get(url);
    if (result?.text) {
        let data = JSON.parse(result.text);
        return data.data.lrclist;
    }
    return null;
}

rid:228908 歌词 musicLrc(228908)

[{"lineLyric":"晴天-周杰伦","time":"0.0"},{"lineLyric":"词:周杰伦","time":"1.88"},{"lineLyric":"曲:周杰伦","time":"3.76"},{"lineLyric":"编曲:周杰伦","time":"5.65"},{"lineLyric":"制作人:周杰伦","time":"7.53"},{"lineLyric":"合声:周杰伦","time":"9.42"},{"lineLyric":"合声编写:周杰伦","time":"11.3"},{"lineLyric":"吉他:蔡科俊Again","time":"13.18"},{"lineLyric":"贝斯:陈任佑","time":"15.07"},{"lineLyric":"鼓:陈柏州","time":"16.95"},{"lineLyric":"录音助理:刘勇志","time":"18.84"},{"lineLyric":"录音工程:杨瑞代Alfa Studio","time":"20.73"},{"lineLyric":"混音工程:杨大纬杨大纬录音工作室","time":"27.72"},{"lineLyric":"故事的小黄花","time":"29.22"},{"lineLyric":"从出生那年就飘着","time":"32.67"},{"lineLyric":"童年的荡秋千","time":"36.15"},{"lineLyric":"随记忆一直晃到现在","time":"39.6"},{"lineLyric":"Re So So Si Do Si La","time":"44.55"},{"lineLyric":"So La Si Si Si Si La Si La So","time":"45.72"},{"lineLyric":"吹着前奏望着天空","time":"49.74"},{"lineLyric":"我想起花瓣试着掉落","time":"53.1"},{"lineLyric":"为你翘课的那一天","time":"56.58"},{"lineLyric":"花落的那一天","time":"58.8"},{"lineLyric":"教室的那一间","time":"60.51"},{"lineLyric":"我怎么看不见","time":"62.16"},{"lineLyric":"消失的下雨天","time":"64.01"},{"lineLyric":"我好想再淋一遍","time":"65.76"},{"lineLyric":"没想到失去的勇气我还留着","time":"69.75"},{"lineLyric":"好想再问一遍","time":"75.81"},{"lineLyric":"你会等待还是离开","time":"77.88"},{"lineLyric":"刮风这天我试过握着你手","time":"84.75"},{"lineLyric":"但偏偏雨渐渐大到我看你不见","time":"90.51"},{"lineLyric":"还要多久我才能在你身边","time":"98.7"},{"lineLyric":"等到放晴的那天也许我会比较好一点","time":"105.39"},{"lineLyric":"从前从前有个人爱你很久","time":"112.740005"},{"lineLyric":"但偏偏风渐渐把距离吹得好远","time":"118.53"},{"lineLyric":"好不容易又能再多爱一天","time":"126.72"},{"lineLyric":"但故事的最后你好像还是说了拜拜","time":"133.38"},{"lineLyric":"为你翘课的那一天","time":"154.59"},{"lineLyric":"花落的那一天","time":"156.81"},{"lineLyric":"教室的那一间","time":"158.52"},{"lineLyric":"我怎么看不见","time":"160.32"},{"lineLyric":"消失的下雨天","time":"162.03"},{"lineLyric":"我好想再淋一遍","time":"163.83"},{"lineLyric":"没想到失去的勇气我还留着","time":"167.97"},{"lineLyric":"好想再问一遍","time":"172.14"},{"lineLyric":"你会等待还是离开","time":"175.98"},{"lineLyric":"刮风这天我试过握着你手","time":"182.82"},{"lineLyric":"但偏偏雨渐渐大到我看你不见","time":"188.37"},{"lineLyric":"还要多久我才能在你身边","time":"196.8"},{"lineLyric":"等到放晴的那天也许我会比较好一点","time":"203.45999"},{"lineLyric":"从前从前有个人爱你很久","time":"210.87"},{"lineLyric":"偏偏风渐渐把距离吹得好远","time":"216.99"},{"lineLyric":"好不容易又能再多爱一天","time":"224.79001"},{"lineLyric":"但故事的最后你好像还是说了拜拜","time":"231.45"},{"lineLyric":"刮风这天我试过握着你手","time":"238.95"},{"lineLyric":"但偏偏雨渐渐大到我看你不见","time":"241.77"},{"lineLyric":"还要多久我才能够在你身边","time":"245.43"},{"lineLyric":"等到放晴那天也许我会比较好一点","time":"248.94"},{"lineLyric":"从前从前有个人爱你很久","time":"252.69"},{"lineLyric":"但偏偏雨渐渐把距离吹得好远","time":"255.78"},{"lineLyric":"好不容易又能再多爱一天","time":"259.26"},{"lineLyric":"但故事的最后你好像还是说了拜","time":"262.74"}]

声明:仅用于学习交流,切勿用于其他用途~文章来源地址https://www.toymoban.com/news/detail-630138.html

到了这里,关于爬虫很难吗?手把手酷我音乐解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 用Python手把手教你实现一个爬虫(含前端界面)

    前言 爬虫基本原理 使用Python的requests库发送HTTP请求 使用BeautifulSoup库解析HTML页面 使用PyQt5构建前端界面 实现一个完整的爬虫程序 结语 随着互联网的飞速发展,再加上科技圈的技术翻天覆地的革新,互联网上每天都会产生海量的数据,这些数据对于企业和个人都具有重要的

    2024年04月28日
    浏览(30)
  • 四步带你爬虫入门,手把手教学爬取电影数据

    本文内容是通过Pycharm来进行实操 创建项目的虚拟环境,目的是为了不让其他的环境资源干扰到当前的项目 本文将以豆瓣作为手把手学习参考,网址:https://movie.douban.com/top250, 1. 进入Terminal终端,安装我们需要的scrapy模块 pip install scrapy 2. 通过pycharm进入Terminal终端,输入我们

    2024年02月22日
    浏览(31)
  • 爬虫实战-手把手教你爬豆瓣电影 | 附详细源码和讲解

    写在前面的话 目前为止,你应该已经了解爬虫的三个基本小节: 来源:xiaqo.com   正文 明确需求 我们今天要爬的数据是 豆瓣电影Top250 ,是的,只有250条数据,你没猜错。 输入网址  https://movie.douban.com/top250  我们可以看到网页长这样:   ​ 编辑 ​ 编辑 `250条数据`清清楚楚

    2024年04月08日
    浏览(25)
  • Python爬虫入门教程!手把手教会你爬取网页数据

    其实在当今社会,网络上充斥着大量有用的数据,我们只需要耐心的观察,再加上一些技术手段,就可以获取到大量的有价值数据。这里的“技术手段”就是网络爬虫。今天就给大家分享一篇爬虫基础知识和入门教程: 爬虫就是自动获取网页内容的程序,例如搜索引擎,Go

    2023年04月26日
    浏览(54)
  • 『爬虫四步走』手把手教你使用Python抓取并存储网页数据!

    爬虫是Python的一个重要的应用,使用Python爬虫我们可以轻松的从互联网中抓取我们想要的数据,**本文将基于爬取B站视频热搜榜单数据并存储为例,详细介绍Python爬虫的基本流程。**如果你还在入门爬虫阶段或者不清楚爬虫的具体工作流程,那么应该仔细阅读本文! 第一步:

    2024年02月04日
    浏览(42)
  • 手把手教你FreeRTOS源码解析(一)——内存管理

    FreeRTOS中一共有5种内存分配的方法,分别在文件heap_1.c,heap_2.c, heap_3.c,heap_4.c,heap_5.c种。 虽然标准C库中的 malloc()和 free()也可以实现动态内存管理,但是它有以下缺陷: 1、在小型嵌入式系统种效率不高。 2、线程不安全。 3、具有不确定性,每次执行的时间不同。 4、会导致内

    2024年02月07日
    浏览(23)
  • OpenWrt路由器设置域名动态解析手把手教程

    因为一直用着内网穿透(zerotier或者是Cloudflare Access tunnel),访问我的内网设备也很是方便,所以就已经很久没有折腾域名的动态解析了。最近也想尝试重新开启动态解析模式,把主动权掌握在自己的手里,本以为利用OpenWrt来设置是很简单的事,结果在折腾的过程中还是遇到

    2024年02月21日
    浏览(65)
  • 手把手kubernetes本地化部署(含疑难杂症排查解析)

    公众号: MCNU云原生 ,文章首发地,欢迎微信搜索关注,更多干货,第一时间掌握! Kubernetes是一个容器编排系统,用于自动化应用程序部署、扩展和管理。本指南将介绍Kubernetes的基础知识,包括基本概念、安装部署和基础用法。 一、什么是Kubernetes? Kubernetes是Google开发的开

    2024年02月01日
    浏览(75)
  • 手把手教你写一个JSON在线解析的前端网站1

    作为一名Android开发,经常要跟后端同事联调接口,那么总避免不了要格式化接口返回值,将其转换为清晰直观高亮的UI样式以及折叠部分内容,方便我们查看定位关键的信息。 一直以来都是打开Google 搜索json格式化,然后选择Google推荐的前三名的网址,比如 bejson网站

    2024年02月08日
    浏览(30)
  • 【手把手】分布式定时任务调度解析之xxl-job

    在之前我写的讲解Quartz中有介绍过,Quartz有差不多二十年的历史,调度模型已经非常成熟了,而且很容易集成到Spring中去,用来执行业务任务是一个很好的选择。但是越早的设计存在的问题也越明显,比如: 1、调度逻辑(Scheduler)和任务类耦合在同一个项目中,随着调度任

    2024年01月19日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包