
python爬取好友的全民K歌
三月初来的上海,遇到了疫封城。大家都待在家里,在家待着可以远程办公的还可以,没有远程办公权限的,比如我除了打游戏外也没有其他的事情可以做了。无意中打开了全民k歌发现好友都挺喜欢唱歌的,就没事的点开了几个好友的,朋友们唱的都挺好的,越听越想听。但是每次都得点开别人的主页听歌,难免有些尴尬。“要是可以将这些拉到本地多好啊…………”有了这样的一个念头,说干就干………………
1.分析网页
都知道哈,要想爬取某一个网站的数据,第一步并不是写代码。而是需要通过浏览器、抓包工具啥的对目标网页进行分析,全民k歌也是一样
1.1登陆全民k歌
是有效的链接,在浏览器中输入该链接,可以看到正是我们之前看的那首歌的主页

#### 1.2分析具体歌曲网页
找到了该主页,我们要如何才能获取到歌曲的源文件呢?
同样的办法,看一下网页的源代码,看能不能在其中找到有用的信息

看了一圈,发现并没有我们所需要的源文件的链接,都是一些页面展示图片的数据,毫无价值。
此时我陷入了沉思,想了一会我发现自己仿佛忽略了一个点,就是这些数据并不是写死的,而是在我们访问的时候,动态加载进来的。于是,我按下了F12检查了一下

由于这些链接大多是都是在src的标签下的,所以我试着CTRL+f搜索了一下src,发现有十几个数据,然而第二个src对应的数据比较的像,而且后缀为.m4a,大概率就是这个了

将这个链接复制一下,在浏览器中打开,发现果然这个就是源文件

其实到这里,已经完成了一大半了,但是到这里我们还没有来分析url呢
## 2.url的分析
#### 2.1主页的url分析
可以看到第一个好友的主页链接为:
```html/xml
https://kg.qq.com/node/personal?uid=639f9b862028378b37&shareUid=63999f252d378e&chain_share_id=ijR0cnc15gh978s4qtI3CKWAWReQ45hThqMHTI2Db0s&pageId=homepage_guest
第二个好友的主页信息为:```html/xmlhttps://kg.qq.com/node/personal?uid=609c9c862228378937&shareUid=63999f802d378e&chain_share_id=UCvDIkYj1zIWyNZCq9KMG4HPVp6p1IoFyhjNVtdC9Yw&pageId=homepage_guest
我们可以看到,实际上这两个链接的差别就再uid和shareid上,所以我们可以大胆的试,将第二个好友的主页链接的uid换成第一个好友的uid看一下,发现是可以访问到第一个好友的主页的

所以这里就可以断定访问哪一个主页是通过uid来控制的。
#### 2.2歌曲信息的url
在上面的查看网页源代码的过程中,我们可以发现,具体到哪一首歌的链接是嵌入在网页的源代码中的,但是在主页上所展示的信息并不是完整的,仅仅是展示了一小部分而已。
这里怎么办呢,怎样才能够让主页的信息展示的更加的全面呢?
这里的话,我在手机上输入对应得链接就是可以看到完整得歌曲数据得,对于电脑的浏览器要怎样才可以像手机一样的,这里我采用的是将浏览器源代码的检查界面的格式设置为手机的样式

这样的话往下滑就可以看到又数据加载进来了
这里我们应该就可以意识到了,其实这里的页面的音乐数据是通过动态加载的方式进行的。所以,这里我们需要将浏览器切换到network上面,可以看到这里有很多信息,我们打开一个看一下

打开一看,就是我们需要找的那些歌曲名字以及链接

所以说这个链接我们是需要拿下来的,
```html/xml
https://node.kg.qq.com/fcgi-bin/kg_ugc_get_homepage?outCharset=utf-8&from=1&nocache=1652856459444&format=json&type=get_uinfo&start=2&num=10&share_uid=639f9b862028378b37&g_tk=5381&g_tk_openkey=5381
2.3具体歌曲网页分析
可以看到一首歌的url为:```html/xmlhttps://kg.qq.com/node/NtmjrPr3oI/play_v2/?s=ybtyUVyXDQHCtyb8&g_f=personal&appsource=&pageId=personalH5
s后面刚好是每一首歌的shareid,到这里思路就很清晰了,
## 3.整理思路,编写代码
#### 3.1思路整理
第一步我们需要通过,主页信息获取到好友的uid,再通过uid拼接到下图的shareid下面,就可以获取到好友的歌曲数据信息了

我们可以通过request请求网页

可以看到,歌曲的信息都再网页中,所以我们需要写正则进行匹配,匹配到歌曲的shareid和title即可。
歌曲的shareid是用来进行拼接具体每一首的访问网页,
拿到没一首的访问数据之后,我们还需要拼接出获取源文件的链接,这里也需要使用正则匹配出src对应的链接
```python
obj = re.compile(r'.*?)">', re.S)
之后便可以进行下载了
4.源代码
源代码如下:
import requests
import re
import os
import time
from selenium.webdriver import Chrome
from selenium.webdriver.chrome.options import Options
url="https://node.kg.qq.com/fcgi-bin/kg_ugc_get_homepage?"
param={
"outCharset": "utf-8",
"from": "1",
"nocache": "1652758394305",
"format": "json",
"type": "get_uinfo",
"start": "1", # 起始的页数
"num": "15", # 每一次访问多少的数据
"share_uid": "639e9f8d2629378e3d", # 更换为需要爬取好友的uid就可以了
"g_tk": "5381",
"g_tk_openkey": "5381"
}
# share_uid放的是uid才可以
head={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
" AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/100.0.4896.127 Safari/537.36"}
username="" # 拿到用户的名字
total=0 # 拿到total用于计算后面需要循环多少次进行拿到歌单
# get请求的数据是params
resp=requests.get(url,params=param,headers=head)
print(resp.text) # 拿到第start页的数据
obj1=re.compile(r'.*?"nickname": (?P.*?),'
r'.*?"ugc_total_count": (?P.*?),',re.S)
res1=obj1.finditer(resp.text)
for it in res1:
username=it.group("nickname")
print(username)
total=int(it.group("total"))
print(total)
print("用户名为:",username)
print("用户作品:",total)
# print(type(total))
# print(type(username))
obj2=re.compile(r'.*?"shareid": "(?P.*?)".*?"title": "(?P.*?)",',re.S)
res2=obj2.findall(resp.text)
print(res2)
print(res2[0])
# print(len(res2))
# print(res2[0][0]) # 取到shareid
# print(res2[0][1]) # 取到title歌曲的名字
resp.close()
for i in range(len(res2)):
#
base_url="https://node.kg.qq.com/play?s="
# print(res2[i][0],res2[i][1])
# 拿到每一首歌的播放界面
url_first=base_url+str(res2[i][0])
# print(url_first)
# 创建以下载用户名音乐作品的文件夹
# os.mkdir('SKY')
opt = Options()
opt.add_argument("--headless")
opt.add_argument("--disable-gpu")
web = Chrome(options=opt)
web.get(url_first) # 拼接好每一首歌的url
time.sleep(1)
s = web.page_source
obj = re.compile(r'<audio.*?src="(?P<link>.*?)">', re.S)
result = obj.finditer(s)
for it in result:
# 打印下载链接
print("第"+str(i+1)+"首歌曲下载链接:"+it.group("link"))
download_url = it.group("link")
resp = requests.get(download_url)
# ('./name/嘉宾.m4a'
with open("./test/"+res2[i][1]+".m4a", 'wb') as f:
f.write(resp.content)
resp.close()
# resp.close()</p><p>5.运行</p><a href='https://www.eolink.com?utm=jiasou' target='_blank'><img style='width:100%;height:100%' src='https://www.eolink.com/news/zb_users/upload/2022/08/20220805174511165969271139602.jpg'></a><br>
<p>
<strong>版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。</strong>
</p></div>
<div class="article_footer clear">
<div class="fr tag">标签:<a href="https://www.eolink.com/news/tags-985.html">文件</a>
</div>
<div class="bdsharebuttonbox fl share">
<div class="share-widget fl">
<div class="social-share" data-sites="wechat,weibo, qq, qzone"></div>
</div>
</div>
</div>
<!-- 广告位ad4 -->
<div class="post-navigation clear">
<div class="post-previous fl">
<span>上一篇:</span><a href="https://www.eolink.com/news/post/18599.html">jdk8使用stream实现两个list集合合并成一个(对象属性的合并)</a>
</div>
<div class="post-next fr">
<span>下一篇:</span><a href="https://www.eolink.com/news/post/18601.html">记一次windows 2003下用pyinstaller打包失败的解决办法(记一次旅行)</a>
</div>
</div>
</div>
<div class="related_article">
<div class="box_title clear">
<span><i class="icon fa fa-paper-plane"></i>相关文章</span>
</div>
<div class="related_list clear">
<article class="fl">
<div class="related_img"><a href="https://www.eolink.com/news/post/89100.html"><img src="https://www.eolink.com/news/zb_users/theme/zblog5_news/image/random_img/1.jpg"></a></div>
<div class="related_detail">
<h3><a href="https://www.eolink.com/news/post/89100.html" title="java中的接口是类吗">java中的接口是类吗</a></h3>
<div class="meta">
<span><i class="fa fa-eye"></i>256</span>
<span><i class="fa fa-clock-o"></i>2022-09-03</span>
</div>
</div>
</article>
<article class="fl">
<div class="related_img"><a href="https://www.eolink.com/news/post/89090.html"><img src="https://www.eolink.com/news/zb_users/theme/zblog5_news/image/random_img/2.jpg"></a></div>
<div class="related_detail">
<h3><a href="https://www.eolink.com/news/post/89090.html" title="Spring中的aware接口详情">Spring中的aware接口详情</a></h3>
<div class="meta">
<span><i class="fa fa-eye"></i>256</span>
<span><i class="fa fa-clock-o"></i>2022-09-03</span>
</div>
</div>
</article>
<article class="fl">
<div class="related_img"><a href="https://www.eolink.com/news/post/89057.html"><img src="https://www.eolink.com/news/zb_users/theme/zblog5_news/image/random_img/7.jpg"></a></div>
<div class="related_detail">
<h3><a href="https://www.eolink.com/news/post/89057.html" title="Python接口自动化之文件上传/下载接口怎么实现">Python接口自动化之文件上传/下载接口怎么实现</a></h3>
<div class="meta">
<span><i class="fa fa-eye"></i>256</span>
<span><i class="fa fa-clock-o"></i>2022-09-03</span>
</div>
</div>
</article>
</div>
</div>
<div id="comment" class="post-comment clearfix sb br mt">
<p id="comments-title" class="c-title mb bn"><span><i class="fa fa-pencil"></i> 发表评论</span></p>
<div class="compost">
<form id="frmSumbit" target="_self" method="post" action="https://www.eolink.com/news/zb_system/cmd.php?act=cmt&postid=18600&key=42156654f48bd195b3625cf4cfa38740">
<input type="hidden" name="inpId" id="inpId" value="18600"/>
<input type="hidden" name="inpRevID" id="inpRevID" value="0"/>
<div class="com-name">
<a rel="nofollow" id="cancel-reply" href="#comments" style="display:none;">取消回复</a>
</div>
<div class="com-info">
<ul>
<li>
<span class="hide" for="author"></span>
<input class="ipt" type="text" name="inpName" id="inpName" value="" tabindex="2" placeholder="昵称(必填)">
</li>
<li>
<span class="hide" for="author"></span>
<input class="ipt" type="text" name="inpEmail" id="inpEmail" value="" tabindex="3" placeholder="邮箱">
</li>
<li>
<span class="hide" for="author"></span>
<input class="ipt" type="text" name="inpHomePage" id="inpHomePage" value="" tabindex="4" placeholder="网址">
</li>
</ul>
</div>
<div class="com-box">
<textarea placeholder="来都来了,说点什么吧..." class="textarea" name="txaArticle" id="txaArticle" cols="5" rows="5" tabindex="1"></textarea>
</div>
<div class="com-info"><button class="com-submit br brightness" name="sumbit" type="submit" tabindex="5" onclick="return zbp.comment.post()">发布评论</button></div>
</form>
</div> <div class="comment-list mt">
<p class="no-comment"><i class="iconfont icon-sofa"></i> 暂时没有评论,来抢沙发吧~</p> <span id="AjaxCommentBegin"></span>
<div class="pagination pagination-multi">
<ul>
</ul>
</div>
<span id="AjaxCommentEnd"></span>
</div>
</div>
</div>
</div>
<div class="sidebar">
<div id="newmodule" class="part clear 推荐文章">
<div class="top">
<h3 class="title">推荐文章</h3>
</div>
<div class="side newmodule"><ul><ul class="hot_posts"> <li><h4><a href="https://www.eolink.com/news/post/16753.html" title="接口调用是什么意思?几种常用接口调用方式">接口调用是什么意思?几种常用接口调用方式</a></h4></li><li><h4><a href="https://www.eolink.com/news/post/64809.html" title="接口设计(接口设计原则)">接口设计原则</a></h4></li><li><h4><a href="https://www.eolink.com/news/post/9069.html" title="API接口管理,8 款在线 API 接口文档管理工具;好用!">8款在线 API 接口文档管理工具</a></h4></li><li><h4><a href="https://www.eolink.com/news/post/64179.html" title="api管理系统">api管理系统是什么?</a></h4></li><li><h4><a href="https://www.eolink.com/news/post/17828.html" title="什么是接口调试?接口调试的步骤有哪些?">什么是接口调试?接口调试的步骤有哪些?</a></h4></li><li><h4><a href="https://www.eolink.com/news/post/63728.html" title="api 接口管理系统(接口统一管理平台)">api 接口管理系统有哪些?</a></h4></li><li><h4><a href="https://www.eolink.com/news/post/77372.html" title="接口测试常用测试方法,多线程免费手机短信压力测试,支持云端获取接口">接口测试有几种测试方法</a></h4></li><li><h4><a href="https://www.eolink.com/news/post/43657.html" title="api文档生成(api接口文档系统)">API文档生成工具有哪些?</a></h4></li><li><h4><a href="https://www.eolink.com/news/post/66400.html" title="微服务和api网关区别(微服务网关技术选型)">微服务和api网关区别</a></h4></li><li><h4><a href="https://www.eolink.com/news/post/64163.html" title="交换机配置步骤">交换机配置步骤</a></h4></li></ul></ul></div>
</div>
<div id="divPrevious" class="part clear previous">
<div class="top">
<h3 class="title">最近发表</h3>
</div>
<div class="side divPrevious"><ul><li><a title="多平台统一管理软件接口,如何实现多平台统一管理软件接口" href="https://www.eolink.com/news/post/89103.html">多平台统一管理软件接口,如何实现多平台统一管理软件接口</a></li>
<li><a title="Flask接口签名sign原理与实例代码浅析" href="https://www.eolink.com/news/post/89102.html">Flask接口签名sign原理与实例代码浅析</a></li>
<li><a title="java中的接口是类吗" href="https://www.eolink.com/news/post/89100.html">java中的接口是类吗</a></li>
<li><a title="vue项目接口域名动态的获取方法" href="https://www.eolink.com/news/post/89099.html">vue项目接口域名动态的获取方法</a></li>
<li><a title="zookeeper python接口实例详解" href="https://www.eolink.com/news/post/89097.html">zookeeper python接口实例详解</a></li>
<li><a title="Iterator与LIstIterator接口在java中的区别有哪些" href="https://www.eolink.com/news/post/89096.html">Iterator与LIstIterator接口在java中的区别有哪些</a></li>
<li><a title="c#自定义Attribute获取接口实现示例代码" href="https://www.eolink.com/news/post/89095.html">c#自定义Attribute获取接口实现示例代码</a></li>
<li><a title="hdml指的是什么接口" href="https://www.eolink.com/news/post/89093.html">hdml指的是什么接口</a></li>
<li><a title="分析EBS常用接口表" href="https://www.eolink.com/news/post/89092.html">分析EBS常用接口表</a></li>
<li><a title="java 单机接口限流处理方案" href="https://www.eolink.com/news/post/89091.html">java 单机接口限流处理方案</a></li>
</ul></div>
</div>
<div id="hot_posts" class="part clear hot_posts">
<div class="top">
<h3 class="title">热评文章</h3>
</div>
<ul class="hot_posts"><li><h4><a href="https://www.eolink.com/news/post/15822.html" title="在线接口文档管理工具推荐,支持在线测试,HTTP接口文档">在线接口文档管理工具推荐,支持在线测试,HTTP接口</a></h4></li><li><h4><a href="https://www.eolink.com/news/post/15841.html" title="开源的在线接口文档wiki工具Mindoc的介绍与使用,五款WEB前端工程师高效的在线接口文档管理工具">开源的在线接口文档wiki工具Mindoc的介绍与使</a></h4></li><li><h4><a href="https://www.eolink.com/news/post/17591.html" title="如何优雅的进行接口设计?接口设计的六大原则是什么?">如何优雅的进行接口设计?接口设计的六大原则是什么?</a></h4></li><li><h4><a href="https://www.eolink.com/news/post/16804.html" title="什么是API测试,api检测公司">什么是API测试,api检测公司</a></h4></li><li><h4><a href="https://www.eolink.com/news/post/29017.html" title="遇到百度网址安全中心提醒您该页面可能存在钓鱼欺诈信息的处理解决办法">遇到百度网址安全中心提醒您该页面可能存在钓鱼欺诈信息</a></h4></li><li><h4><a href="https://www.eolink.com/news/post/25723.html" title="软件接口设计怎么做?前后端分离软件接口设计思路">软件接口设计怎么做?前后端分离软件接口设计思路</a></h4></li></ul> </div> </div>
</div>
</section>
</div>
<footer class="p-footer">
<div class="contant_box">
<div class="discover_tmt">
<h5 class="" style="font-size: 1px; color: white;">Eolink</h5>
<div class="text_box">
<a href="https://www.jiasou.cn/article/" title="toB数字化营销SEO" style="font-size: 1px; color: white;">加搜toBSEO</a>
<a href="https://www.finclip.com/news/category-1.html" title="小程序工具" style="font-size: 1px; color: white;">前端框架</a>
<a href="https://www.jia-ai.com/info/" title="小红书营销攻略" style="font-size: 1px; color: white;">小红书营销攻略</a>
<a href="https://www.yanyin.tech/cms/" title="生物研究资讯" style="font-size: 1px; color: white;">生物研究资讯</a>
<a href="https://www.finclip.com/news/" title="FinClip 技术文档" style="font-size: 1px; color: white;">小程序容器帮助中心</a>
<a href="https://www.finclip.com/news/article/" title="小程序开发行业洞察" style="font-size: 1px; color: white;">小程序开发行业洞察</a>
<a href="https://www.foneplatform.com/jscms/" title="全面预算管理资讯" style="font-size: 1px; color: white;">全面预算管理资讯</a>
<a href="https://www.weiling.cn/article/" title="企微SCRM客户管理干货" style="font-size: 1px; color: white;">企微SCRM客户管理干货</a>
<a href="https://www.vbasm.com/zh/" title="数据筛选平台" style="font-size: 1px; color: white;">数据筛选平台"</a>
</div> </div>
<div class="collaboration_box">
</div>
<div class="we_img_box clear">
<div class="img_box">
<img src="https://www.eolink.com/news/zb_users/theme/zblog5_news/image/ewm.png" alt="" class="hover_tmt">
</div>
</div>
</div>
<p class="info">© 2023 XWNews <a href="#" target="_blank" rel="nofollow">京ICP备1111040123号-1</a>
<span>
<a href="https://www.zblogcn.com/">版权归zblog所有</a></span>
</p>
</footer>
<div id="backtop" class="backtop">
<div class="bt-box top">
<i class="fa fa-angle-up fa-2x"></i>
</div>
</div>
<script type='text/javascript' src="https://www.eolink.com/news/zb_users/theme/zblog5_news/script/custom.js"></script>
<script type='text/javascript' src="https://www.eolink.com/news/zb_users/theme/zblog5_news/script/nav.js"></script>
<link rel="stylesheet" href="https://www.eolink.com/news/zb_users/theme/zblog5_news/share/css/share.min.css">
<script src="https://www.eolink.com/news/zb_users/theme/zblog5_news/share/js/jquery.share.min.js"></script>
<!-- Initialize Swiper -->
<script>
var swiper = new Swiper('.swiper-container', {
pagination: '.swiper-pagination',
paginationClickable: true,
loop: true,
autoplay:2000,
nextButton: '.swiper-button-next',
prevButton: '.swiper-button-prev',
spaceBetween: 30,
effect: 'fade',
});
</script>
<script>
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?556b23f3809179e610086ba68e9a0c89";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
<script>
(()=>{const e="https://analyze.jiasou.cc/api/v1/page_view/report/",n="9e1fab3b60d44b87a9a33c16962df4b1";let t=null;const o=new Proxy({},{get:(e,n)=>localStorage.getItem(window.btoa(n)),set:(e,n,t)=>!!t&&(localStorage.setItem(window.btoa(n),t),!0)});new Promise((t=>{if(o.fingerprint)t();else{const a=function(){var e={};if(e.userAgent=navigator.userAgent||"",e.plugins=[],navigator.plugins&&navigator.plugins.length>0)for(var n=0;n<navigator.plugins.length;n++){var t={name:navigator.plugins[n].name||"",filename:navigator.plugins[n].filename||"",description:navigator.plugins[n].description||""};e.plugins.push(t)}e.languages=navigator.languages||[navigator.language||""],e.timezone=(new Date).getTimezoneOffset(),e.screenResolution={width:window.screen.width||0,height:window.screen.height||0,pixelDepth:window.screen.pixelDepth||0,colorDepth:window.screen.colorDepth||0};var o=document.createElement("canvas").getContext("2d"),a=[],i=["monospace","sans-serif","serif"];for(n=0;n<i.length;n++){var r=i[n];o.font="12px "+r,o.measureText("abcdefghijklmnopqrstuvwxyz0123456789").width>0&&a.push(r)}return e.fonts=a,e.cookieEnabled=navigator.cookieEnabled||!1,e.localStorage=void 0!==window.localStorage,e.sessionStorage=void 0!==window.sessionStorage,e.doNotTrack="1"===navigator.doNotTrack||"1"===window.doNotTrack||"1"===navigator.msDoNotTrack||"yes"===navigator.doNotTrack,e}();fetch(`${e}u/`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:n,f:window.btoa(JSON.stringify(a))})}).then((e=>{console.debug("browser fingerprint sent"),200===e.status&&e.json().then((e=>{console.debug("browser fingerprint received",e),o.fingerprint=e.fp,t()}))}))}})).then((()=>{e&&o.fingerprint&&fetch(e+`?${new URLSearchParams({token:n}).toString()}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({c:window.btoa(JSON.stringify({u:o.fingerprint,l:window.location.href,r:document.referrer}))})}).then((e=>{200==e.status&&e.json().then((e=>{e.track_id&&(t=e.track_id)}))}))})),window.addEventListener("beforeunload",(async n=>{t&&fetch(e+`?${new URLSearchParams({track_id:t}).toString()}`,{method:"GET",headers:{"Content-Type":"text/plain"},keepalive:!0}),n.returnValue=""}))})();
</script><script language="javascript" src="https://www.eolink.com/news/zb_users/plugin/ZF_ad/js/index.js?id=429"></script>
<script language="javascript" src="https://www.eolink.com/news/zb_users/plugin/ZF_ad/js/ZF_ad__cookie.js"></script>
</body>
</html><!--92.62 ms , 18 queries , 1772kb memory , 0 error-->