【Python3爬虫】网易云音乐爬虫
此次的目标是爬取网易云音乐上指定歌曲所有评论并生成词云
具体步骤:
一:实现JS加密
找到这个ajax接口没什么难度,问题在于传递的数据,是通过js加密得到的,因此需要查看js代码。
通过断掉调试可以找到数据是由core_8556f33641851a422ec534e33e6fa5a4.js?8556f33641851a422ec534e33e6fa5a4.js里的window.asrsea函数加密的。
通过进一步的查找,可以找到下面这个函数:
function() {
// 生成长度为16的随机字符串
function a(a) {
var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";
for (d = 0; a > d; d += 1)
e = Math.random() * b.length,
e = Math.floor(e),
c += b.charAt(e);
return c
}
// 实现AES加密
function b(a, b) {
var c = CryptoJS.enc.Utf8.parse(b)
, d = CryptoJS.enc.Utf8.parse("0102030405060708")
, e = CryptoJS.enc.Utf8.parse(a)
, f = CryptoJS.AES.encrypt(e, c, {
iv: d,
mode: CryptoJS.mode.CBC
});
return f.toString()
}
// 实现RSA加密
function c(a, b, c) {
var d, e;
return setMaxDigits(131),
d = new RSAKeyPair(b,"",c),
e = encryptedString(d, a)
}
// 得到加密后的结果
function d(d, e, f, g) {
var h = {}
, i = a(16);
return h.encText = b(d, g),
h.encText = b(h.encText, i),
h.encSecKey = c(i, e, f),
h
}
function e(a, b, d, e) {
var f = {};
return f.encText = c(a + e, b, d),
f
}
}()
因此我们需要用Python实现上面四个函数。第一个生成随机字符串的函数没难度,实现的代码如下:
# 生成随机字符串
def generate_random_string(length):
string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
# 初始化随机字符串
random_string = ""
# 生成一个长度为length的随机字符串
for i in range(length):
random_string += string[int(floor(random() * len(string)))]
return random_string
第二个是实现AES加密的函数,而用AES加密需要使用Crypto这个库。如果没有安装这个库的话,需要先安装pycrypto库,然后再安装Crypto库。在成功安装之后,如果import的时候没有Crypto而只有crypto,先打开Python安装目录下的Lib\site-packages\crypto文件夹,如果里面有Cipher文件夹,就返回到Lib\site-packages目录下把crypto重命名为Crypto,然后应该就可以成功导入了。
由于AES加密的明文长度必须是16的倍数,因此我们需要对明文进行必要的填充,以满足它的长度是16的倍数,AES加密的模式是AES.MODE_CBC,初始化向量iv='0102030405060708′。
实现AES加密的代码如下:
# AES加密
def aes_encrypt(msg, key):
# 如果不是16的倍数则进行填充
padding = 16 - len(msg) % 16
# 这里使用padding对应的单字符进行填充
msg += padding * chr(padding)
# 用来加密或者解密的初始向量(必须是16位)
iv = ''
# AES加密
cipher = AES.new(key, AES.MODE_CBC, iv)
# 加密后得到的是bytes类型的数据
encrypt_bytes = cipher.encrypt(msg)
# 使用Base64进行编码,返回byte字符串
encode_string = base64.b64encode(encrypt_bytes)
# 对byte字符串按utf-8进行解码
encrypt_text = encode_string.decode('utf-8')
# 返回结果
return encrypt_text
第三个是实现RSA加密的函数,在RSA加密中,明文和密文都是数字,RSA的密文是对代表明文的数字的E次方求mod N 的结果,RSA加密后得到的字符串长为256,这里不够长我们用x字符填充。
实现RSA加密的代码如下:
# RSA加密
def rsa_encrypt(random_string, key, f):
# 随机字符串逆序排列
string = random_string[::-1]
# 将随机字符串转换成byte类型数据
text = bytes(string, 'utf-8')
# RSA加密
sec_key = int(codecs.encode(text, encoding='hex'), 16) ** int(key, 16) % int(f, 16)
# 返回结果
return format(sec_key, 'x').zfill(256)
第四个函数是得到两个加密参数的函数,传入的四个参数,第一个参数JSON.stringify(i3x)是以下内容,其中offset和limit参数是必须要有的,offset的值是(页数-1)*20,limit的值是20
'{"offset":'+str(offset)+',"total":"True","limit":"20","csrf_token":""}'
第二个参数,第三个参数和第四个参数的值都是根据Zj4n.emj得到的:
encText的值是通过两次AES加密得到的,encSecKey是通过RSA加密得到的,实现的具体代码如下:
# 获取参数
def get_params(page):
# 偏移量
offset = (page - 1) * 20
# offset和limit是必选参数,其他参数是可选的
msg = '{"offset":' + str(offset) + ',"total":"True","limit":"20","csrf_token":""}'
key = '0CoJUm6Qyw8W8jud'
f = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a87' \
'6aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9' \
'd05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b' \
'8e289dc6935b3ece0462db0a22b8e7'
e = ''
# 生成长度为16的随机字符串
i = generate_random_string(16)
# 第一次AES加密
enc_text = aes_encrypt(msg, key)
# 第二次AES加密之后得到params的值
encText = aes_encrypt(enc_text, i)
# RSA加密之后得到encSecKey的值
encSecKey = rsa_encrypt(i, e, f)
return encText, encSecKey
二、解析并保存评论
通过查看preview的信息可以发现用户名和评论内容都是保存在json格式的数据里的
因此解析起来会很容易,直接提取nickname和content就好了。对于得到的数据,都保存在以歌名为文件名的txt文件中。实现的代码如下:
# 爬取评论内容
def get_comments(data):
# data=[song_id,song_name,page_num]
url = 'https://music.163.com/weapi/v1/resource/comments/R_SO_4_' + str(data[0]) + '?csrf_token='
# 得到两个加密参数
text, key = get_params(data[2])
# 发送post请求
res = requests.post(url, headers=headers, data={"params": text, "encSecKey": key})
if res.status_code == 200:
print("正在爬取第{}页的评论".format(data[2]))
# 解析
comments = res.json()['comments']
# 存储
with open(data[1] + '.txt', 'a', encoding="utf-8") as f:
for i in comments:
f.write(i['content'] + "\n")
else:
print("爬取失败!")
三、生成词云
在进行这一步之前,需要先安装好jieba和wordcloud两个模块,jieba模块是一个用于中文分词的模块,wordcloud模块是一个用于生成词云的模块,可以自行了解学习。
这部分就不赘述了,具体代码如下:
# 生成词云
def make_cloud(txt_name):
with open(txt_name + ".txt", 'r', encoding="utf-8") as f:
txt = f.read()
# 结巴分词
text = ''.join(jieba.cut(txt))
# 定义一个词云
wc = WordCloud(
font_path="font.ttf",
width=1200,
height=800,
max_words=100,
max_font_size=200,
min_font_size=10
)
# 生成词云
wc.generate(text)
# 保存为图片
wc.to_file(txt_name + ".png")
最后生成的词云如下:
完整代码已经上传到GitHub!
【Python3爬虫】网易云音乐爬虫的更多相关文章
- 关于网易云音乐爬虫的api接口?
抓包能力有限,分析了一下网易云音乐的一些api接口,但是关于它很多post请求都是加了密,没有弄太明白.之前在知乎看到过一个豆瓣工程师写的教程,但是被投诉删掉了,请问有网友fork了的吗?因为我觉得他 ...
- 爬虫综合大作业——网易云音乐爬虫 & 数据可视化分析
作业要求来自于https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/3075 爬虫综合大作业 选择一个热点或者你感兴趣的主题. 选择爬取的对象 ...
- NetCloud——一个网易云音乐评论抓取和分析的Python库
在17的四月份,我曾经写了一篇关于网易云音乐爬虫的文章,还写了一篇关于评论数据可视化的文章.在这大半年的时间里,有时会有一些朋友给我发私信询问一些关于代码方面的问题.所以我最近抽空干脆将原来的代码整理 ...
- python3爬虫应用--爬取网易云音乐(两种办法)
一.需求 好久没有碰爬虫了,竟不知道从何入手.偶然看到一篇知乎的评论(https://www.zhihu.com/question/20799742/answer/99491808),一时兴起就也照葫 ...
- 【Python3爬虫】网易云音乐歌单下载
一.目标: 下载网易云音乐热门歌单 二.用到的模块: requests,multiprocessing,re. 三.步骤: (1)页面分析:首先打开网易云音乐,选择热门歌单,可以看到以下歌单列表,然后 ...
- Python爬虫小白入门(六)爬取披头士乐队历年专辑封面-网易云音乐
一.前言 前文说过我的设计师小伙伴的设计需求,他想做一个披头士乐队历年专辑的瀑布图. 通过搜索,发现网易云音乐上有比较全的历年专辑信息加配图,图片质量还可以,虽然有大有小. 我的例子怎么都是爬取图片? ...
- 网易云音乐综合爬虫python库NetCloud v1版本发布
以前写的太烂了,这次基本把之前的代码全部重构了一遍.github地址是:NetCloud.下面是简单的介绍以及quick start. NetCloud--一个完善的网易云音乐综合爬虫Python库 ...
- 爬取网易云音乐评论!python 爬虫入门实战(六)selenium 入门!
说到爬虫,第一时间可能就会想到网易云音乐的评论.网易云音乐评论里藏了许多宝藏,那么让我们一起学习如何用 python 挖宝藏吧! 既然是宝藏,肯定是用要用钥匙加密的.打开 Chrome 分析 Head ...
- 使用webcollector爬虫技术获取网易云音乐全部歌曲
最近在知乎上看到一个话题,说使用爬虫技术获取网易云音乐上的歌曲,甚至还包括付费的歌曲,哥瞬间心动了,这年头,好听的流行音乐或者经典老歌都开始收费了,只能听不能下载,着实很郁闷,现在机会来了,于是开始研 ...
随机推荐
- scrapy递归解析和post请求
递归解析 递归爬取解析多页页面数据 每一个页面对应一个url,则scrapy工程需要对每一个页码对应的url依次发起请求,然后通过对应的解析方法进行作者和段子内容的解析. 实现方案: 1.将每一个页码 ...
- opencv imwrite保存图片花屏的问题
问题:在项目中用opencv的imwrite保存图片出现花屏的问题,如下图: 思路:1. 因为项目中的图像数据(float类型,0-255)是在GPU中,保存的话:可以用CPU保存图片,也可以用GP ...
- 【安全性测试】drozer中关于AttackSurface的一些理解
在推荐扫描Android APP的工具中,扫描组件可以推荐drozer.使用过drozer的使用者知道,如何查找各个组件上的攻击层面 run app.package.AttackSurface . 它 ...
- date函数的属性
date () a: "am"或是"pm" A: "AM"或是"PM" d: 几日,两位数字,若不足则补零:从" ...
- Kubernetes中的RBAC
Kubernetes中,授权有ABAC(基于属性的访问控制).RBAC(基于角色的访问控制).Webhook.Node.AlwaysDeny(一直拒绝)和AlwaysAllow(一直允许)这6种模式. ...
- React的类型检测PropTypes
React.propTypes:React.PropTypes 提供很多验证器来验证传入数据的有效性,当向props传入无效数据时,JavaScript 控制台会抛出警告. ; class MyTit ...
- 动态规划-LIS
https://vjudge.net/contest/297216?tdsourcetag=s_pctim_aiomsg#problem/E #include<bits/stdc++.h> ...
- K8s 入门
中文文档:https://www.kubernetes.org.cn/kubernetes%E8%AE%BE%E8%AE%A1%E6%9E%B6%E6%9E%84 小结大白话 Portainer 挺好 ...
- unittest测试套件
测试套件就是测试集,测试集是测试用例的集合. a.按用例顺序执行(addtest) 当addtest与unittest的测试规则冲突时,仍然按照ASCII码的顺序执行. import unittest ...
- ThinkPHP5 打开多语言支持
1.在thinkphp\start.php 页面中添加多语言的切换函数的参数格式,本贴目前只支持两种语言,并注意必须全部小写!全部小写!!全部小写!!!,注意这一步很关键 Lang::setAllow ...