Python3实战之爬虫抓取网易云音乐的热门评论


Posted in Python onOctober 09, 2017

前言

之前刚刚入门python爬虫,有大概半个月时间没有写python了,都快遗忘了。于是准备写个简单的爬虫练练手,我觉得网易云音乐最优特色的就是其精准的歌曲推荐和独具特色的用户评论,于是写了这个抓取网易云音乐热歌榜里的热评的爬虫。我也是刚刚入门爬虫,有什么意见和问题欢迎提出,大家一起共同进步。

废话就不多说了~下面来一起看看详细的介绍吧。

我们的目标是爬取网易云中的热歌排行榜中所有歌曲的热门评论。

这样既可以减少我们需要爬取的工作量,又可以保存到高质量的评论。

实现分析

首先,我们打开网易云网页版,如图:

Python3实战之爬虫抓取网易云音乐的热门评论

点击排行榜,然后点击左侧云音乐热歌榜,如图:

Python3实战之爬虫抓取网易云音乐的热门评论

我们先随便打开一个歌曲,找到如何抓取指定的歌曲的热门歌评的方法,如图,我选了一个最近我比较喜欢的歌曲为例:

Python3实战之爬虫抓取网易云音乐的热门评论

进去后我们会看到歌评就在这个页面的下面,接下来我们就要想办法获取这些评论。

接下来打开web控制台(chrom的话打开开发者工具,如果是其他浏览器应该也是类似),chrom下按F12,如图:

Python3实战之爬虫抓取网易云音乐的热门评论

选则Network,然后我们按F5刷新一下,刷新之后得到的数据如下图所示:

Python3实战之爬虫抓取网易云音乐的热门评论

可以看到浏览器发送了非常多的信息,那么哪一个才是我们想要的呢?这里我们可以通过状态码做一个初步的判断,status code(状态码)标志了服务器请求的状态,这里状态码为200即表示请求正常,而304则表示不正常(状态码种类非常多,如果要想详细了解可以自行搜索,这里不说304具体的含义了)。所以我们一般只用看状态码为200的请求就可以了,还有就是,我们可以通过右边栏的预览来粗略观察服务器返回了什么信息(或者查看响应)。通过这两种方法结合一般我们就可以快速找到我们想要分析的请求。通过反复的查找,终于找到了含有歌评的请求,如图:

Python3实战之爬虫抓取网易云音乐的热门评论

可能截图在CSDN上不是很清楚,我们在一个Name为R_SO_4_489998494?csrf_token=的POST请求中找到了包含这首歌的歌评。我们把这个分块截图发出来,这样可以看的清楚一些:

请求基本信息:

Python3实战之爬虫抓取网易云音乐的热门评论

请求头部:

Python3实战之爬虫抓取网易云音乐的热门评论 

请求中的表单数据:

Python3实战之爬虫抓取网易云音乐的热门评论

我们可以看到,包含这首歌歌评的请求url为http://music.163.com/weapi/v1/resource/comments/R_SO_4_489998494?csrf_token= ,我们换了几首歌后发现,这个请求的前部分都是一样的,只是R_SO_4_后面紧跟的一串数字不一样。我们可以推测出,每一首歌都有一个指定的id,R_SO_4_后面紧跟的就是这首歌的id。

我们再看一下提交的表单数据,我们会发现表单中需要填两个数据,名称为params和encSecKey。后面紧跟的是一大串字符,换几首歌会发现,每首歌的params和encSecKey都是不一样的,因此,这两个数据可能经过一个特定的算法进行加密过的。

服务器返回的和评论相关的数据为json格式的,里面含有非常丰富的信息(比如有关评论者的信息,评论日期,点赞数,评论内容等等),其中hotComments就是我们要找的热门评论,总共15条,如图所示:

Python3实战之爬虫抓取网易云音乐的热门评论

至此,我们已经确定了方向了,即只需要确定params和encSecKey这两个参数值即可。但是这两个参数是经过特定的算法进行加密的,怎么办呢?我发现了一个规律,http://music.163.com/weapi/v1/resource/comments/R_SO_4_489998494?csrf_token= 中 R_SO_4_后面的数字就是这首歌的id值,而对于不同的歌曲的param和encSecKey值,如果把一首歌比如A的这两个参数值传给B这首歌,那么对于相同的页数,这种参数是通用的,即A的第一页的两个参数值传给其他任何一首歌的两个参数,都可以获得相应歌曲的第一页的评论,对于第二页,第三页等也是类似。

而我们其实只需要获取第一页的15条热门评论,所以我们只需要随便找一首歌,将这首歌第一页中的该请求中的params和encSecKey这两个参数值复制下来,就可以使用了。

关于这两个参数如何解密,强大的知乎上其实已经有答案的了,感兴趣的朋友可以进去看一下(https://www.zhihu.com/question/36081767),我们在这里就只需要用我们这种偷懒的办法就可以完成需求了,xixi。

到此为止,我们如何抓取网易云音乐的热门评论已经分析完了,我们再分析一下如何获取云音乐热歌榜中所有歌曲的信息。

我们需要获取云音乐热歌榜中的所有歌曲的歌曲名和对应的id值。

跟上面的分析步骤类似,我们先进入热歌榜的网址,如图:

Python3实战之爬虫抓取网易云音乐的热门评论

按F12,进入WEB工作台,如图:

Python3实战之爬虫抓取网易云音乐的热门评论

我们在一个名为toplist?id=3778678的GET请求中,找到了该榜单的所有歌曲信息。

请求对应的信息如图:

Python3实战之爬虫抓取网易云音乐的热门评论

我们预览一下该请求返回的结果,如图:

Python3实战之爬虫抓取网易云音乐的热门评论

我们在代码的第524行我们找到了包含歌曲信息的代码,如图:

Python3实战之爬虫抓取网易云音乐的热门评论

因此,我们只需要将该请求的代码中,将包含信息的代码筛选出来。

我们在这里使用正则表达式进行数据筛选。

通过观察特点,我们可以通过两次正则表达式的筛选,将我们需要的歌曲信息提取出来。

第一次正则表达式我们将该请求返回的所有代码中,提取出第525行代码。

第一次正则表达式如下:<ul class="f-hide"><li><a href="/song\?id=\d*?" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >.*</a></li></ul>

第二次正则表达式我们将该第524行中我们需要的歌曲信息提取出来,我们需要歌曲的歌名和id,对应的正则表达式如下:

获取歌名:<li><a href="/song\?id=\d*?" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >(.*?)</a></li>

获取歌曲的id:<li><a href="/song\?id=(\d*?)" rel="external nofollow" rel="external nofollow" >.*?</a></li>

到此,我们整个过程已经分析完了,上代码看具体细节~~

代码如下:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import re
import urllib.request
import urllib.error
import urllib.parse
import json



def get_all_hotSong():  #获取热歌榜所有歌曲名称和id
 url='http://music.163.com/discover/toplist?id=3778678' #网易云云音乐热歌榜url
 html=urllib.request.urlopen(url).read().decode('utf8') #打开url
 html=str(html)  #转换成str
 pat1=r'<ul class="f-hide"><li><a href="/song\?id=\d*?">.*</a></li></ul>' #进行第一次筛选的正则表达式
 result=re.compile(pat1).findall(html)  #用正则表达式进行筛选
 result=result[0]  #获取tuple的第一个元素

 pat2=r'<li><a href="/song\?id=\d*?">(.*?)</a></li>' #进行歌名筛选的正则表达式
 pat3=r'<li><a href="/song\?id=(\d*?)">.*?</a></li>' #进行歌ID筛选的正则表达式
 hot_song_name=re.compile(pat2).findall(result) #获取所有热门歌曲名称
 hot_song_id=re.compile(pat3).findall(result) #获取所有热门歌曲对应的Id

 return hot_song_name,hot_song_id

def get_hotComments(hot_song_name,hot_song_id):
 url='http://music.163.com/weapi/v1/resource/comments/R_SO_4_' + hot_song_id + '?csrf_token=' #歌评url
 header={ #请求头部
 'User-Agent':'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
}
 #post请求表单数据
 data={'params':'zC7fzWBKxxsm6TZ3PiRjd056g9iGHtbtc8vjTpBXshKIboaPnUyAXKze+KNi9QiEz/IieyRnZfNztp7yvTFyBXOlVQP/JdYNZw2+GRQDg7grOR2ZjroqoOU2z0TNhy+qDHKSV8ZXOnxUF93w3DA51ADDQHB0IngL+v6N8KthdVZeZBe0d3EsUFS8ZJltNRUJ','encSecKey':'4801507e42c326dfc6b50539395a4fe417594f7cf122cf3d061d1447372ba3aa804541a8ae3b3811c081eb0f2b71827850af59af411a10a1795f7a16a5189d163bc9f67b3d1907f5e6fac652f7ef66e5a1f12d6949be851fcf4f39a0c2379580a040dc53b306d5c807bf313cc0e8f39bf7d35de691c497cda1d436b808549acc'}
 postdata=urllib.parse.urlencode(data).encode('utf8') #进行编码
 request=urllib.request.Request(url,headers=header,data=postdata)
 reponse=urllib.request.urlopen(request).read().decode('utf8')
 json_dict=json.loads(reponse) #获取json
 hot_commit=json_dict['hotComments'] #获取json中的热门评论


 num=0
 fhandle=open('./song_comments','a') #写入文件
 fhandle.write(hot_song_name+':'+'\n')

 for item in hot_commit:
  num+=1
  fhandle.write(str(num)+'.'+item['content']+'\n')
 fhandle.write('\n==============================================\n\n')
 fhandle.close()




hot_song_name,hot_song_id=get_all_hotSong() #获取热歌榜所有歌曲名称和id

num=0
while num < len(hot_song_name): #保存所有热歌榜中的热评
 print('正在抓取第%d首歌曲热评...'%(num+1))
 get_hotComments(hot_song_name[num],hot_song_id[num])
 print('第%d首歌曲热评抓取成功'%(num+1))
 num+=1

码运行结果如下:

Python3实战之爬虫抓取网易云音乐的热门评论

对比一下网页上《如果我爱你》这首歌的歌评和我们保存下的歌评:

Python3实战之爬虫抓取网易云音乐的热门评论

Python3实战之爬虫抓取网易云音乐的热门评论

信息无误~

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
Python和GO语言实现的消息摘要算法示例
Mar 10 Python
Python使用metaclass实现Singleton模式的方法
May 05 Python
mysql 之通过配置文件链接数据库
Aug 12 Python
python 常用的基础函数
Jul 10 Python
python实现彩票系统
Jun 28 Python
Python中一个for循环循环多个变量的示例
Jul 16 Python
Python简易计算器制作方法代码详解
Oct 31 Python
Python for循环及基础用法详解
Nov 08 Python
tensorflow实现二维平面模拟三维数据教程
Feb 11 Python
python字符串,元组,列表,字典互转代码实例详解
Feb 14 Python
python zip,lambda,map函数代码实例
Apr 04 Python
Python使用Selenium实现淘宝抢单的流程分析
Jun 23 Python
Python读取文件内容的三种常用方式及效率比较
Oct 07 #Python
Python引用传值概念与用法实例小结
Oct 07 #Python
Python中执行存储过程及获取存储过程返回值的方法
Oct 07 #Python
Python使用cx_Oracle调用Oracle存储过程的方法示例
Oct 07 #Python
深入理解Django中内置的用户认证
Oct 06 #Python
Python3学习笔记之列表方法示例详解
Oct 06 #Python
python获取外网IP并发邮件的实现方法
Oct 01 #Python
You might like
PHP UTF8中文字符截断函数代码
2012/09/11 PHP
解密ThinkPHP3.1.2版本之独立分组功能应用
2014/06/19 PHP
使用PHP反射机制来构造&quot;CREATE TABLE&quot;的sql语句
2019/03/21 PHP
关于删除时的提示处理(确定删除吗)
2013/11/03 Javascript
js加载之使用DOM方法动态加载Javascript文件
2013/11/08 Javascript
JS如何判断移动端访问设备并解析对应CSS
2013/11/27 Javascript
Javascript中常见的校验如域名、手机、邮箱等等
2014/01/02 Javascript
浅谈JavaScript正则表达式分组匹配
2015/04/10 Javascript
wangEditor编辑器失去焦点后仍然可以在原位置插入图片分析
2015/05/06 Javascript
js实现黑色简易的滑动门网页tab选项卡效果
2015/08/31 Javascript
分享使用AngularJS创建应用的5个框架
2015/12/05 Javascript
详解Javascript ES6中的箭头函数(Arrow Functions)
2016/08/24 Javascript
Vue数据驱动模拟实现2
2017/01/11 Javascript
jQuery extend()详解及简单实例
2017/05/06 jQuery
详解如何实现一个简单的Node.js脚手架
2017/12/04 Javascript
Vue中使用vue-i18插件实现多语言切换功能
2018/04/25 Javascript
对mac下nodejs 更新到最新版本的最新方法(推荐)
2018/05/17 NodeJs
使用vue完成微信公众号网页小记(推荐)
2019/04/28 Javascript
详解小程序毫秒级倒计时(适用于拼团秒杀功能)
2019/05/05 Javascript
JavaScript 异步时序问题
2020/11/20 Javascript
[46:23]完美世界DOTA2联赛PWL S2 FTD vs Magma 第一场 11.20
2020/11/23 DOTA
《与孩子一起学编程》python自测题
2018/05/27 Python
Python使用Pandas库常见操作详解
2020/01/16 Python
Keras设定GPU使用内存大小方式(Tensorflow backend)
2020/05/22 Python
css3实例教程 一款纯css3实现的发光屏幕旋转特效
2014/12/07 HTML / CSS
日常奢侈品,轻松购物:Verishop
2019/08/20 全球购物
90后毕业生的求职信范文
2013/09/21 职场文书
大学生毕业求职的自我评价
2013/09/29 职场文书
2014年五四青年节活动策划书
2014/04/22 职场文书
财务总监岗位职责
2015/02/03 职场文书
初中教师个人工作总结
2015/02/10 职场文书
2015年感恩父亲节活动策划方案
2015/05/05 职场文书
2015年惩防体系建设工作总结
2015/05/22 职场文书
JS不要再到处使用绝对等于运算符了
2021/04/30 Javascript
为什么代码规范要求SQL语句不要过多的join
2021/06/23 MySQL
Node与Python 双向通信的实现代码
2021/07/16 Javascript