Python爬取网易云音乐评论(附加密算法)

丶灬走出姿态 提交于 2019-11-29 00:50:19

网易云音乐,里面汇聚了哲学家,小说家,story-teller,皮皮虾等各种人才,某些评论非常值得收藏(甚至开了一个歌单专门收藏它们)。竟然这么好玩,何不尝试把他们爬取下来呢?
在这里插入图片描述

前置需求

可选:fiddler 捉包工具 (官网下载)
可选:了解一点AES,RSA加密
任一浏览器
pycryptodome模块 (直接pip安装)
base64及binascii模块 (直接导入)
可选是指:如果你要深入了解如何找到加密方法,就选

结构分析

我们要爬的是歌曲的评论,而歌曲的来源有多种,有的来源于专辑,有的来源于歌单,有的来源于歌手页;而歌单和专辑的来源又有多种。所以爬取多个歌曲的评论之前,我们要分析一下信息的结构,最好写下来,这样头脑会更清晰减少代码修改量。这里放出一张我自己整理的结构,并选择一条线路来实现(发现音乐→→歌单→→歌曲→→评论)
在这里插入图片描述
至于上图所列的其他信息,读者可以过完这个实战后自己动手实现,但是要注意的是:某些信息是无法直接通过网页源码提取出来的,需要通过加密的动态包(其实是API)获得,如果有需要的话我可能会出一篇文章总结网易云音乐的API

收集歌单id

每个歌单都有唯一的id,通过http://music.163.com/playlist… 这个链接就可以找到歌单,所以第一步我们要收集发现音乐下的多个歌单id
在这里插入图片描述

'''
遇到不懂的问题?Python学习交流群:821460695满足你的需求,资料都已经上传群文件,可以自行下载!
'''
def get_playlists(pages,order,cat):#页数(一页获取35个歌单id),排序,分类
    playlist_ids = []
    for page in range(pages):
        url = 'http://music.163.com/discover/playlist/?order={}&cat={}&limit=35&offset={}'.format(order,cat,str(page*35))
        print(url)
        r = requests.get(url,headers=headers)
        playlist_ids.extend(re.findall(r'playlist\?id=(\d+?)" class="msk"',r.text))
    return playlist_ids

参数处理细节处理请看代码

import json
from Crypto.Cipher import AES  #新的加密模块只接受bytes数据,否者报错,密匙明文什么的要先转码
import base64
import binascii
import random
'''
遇到不懂的问题?Python学习交流群:821460695满足你的需求,资料都已经上传群文件,可以自行下载!
'''
secret_key = b'0CoJUm6Qyw8W8jud'#第四参数,aes密匙
pub_key ="010001"#第二参数,rsa公匙组成
modulus = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7"
#第三参数,rsa公匙组成


#生成随机长度为16的字符串的二进制编码
def random_16():
    return bytes(''.join(random.sample('1234567890DeepDarkFantasy',16)),'utf-8')


#aes加密
def aes_encrypt(text,key):
    pad = 16 - len(text)%16 #对长度不是16倍数的字符串进行补全,然后在转为bytes数据
    try:                    #如果接到bytes数据(如第一次aes加密得到的密文)要解码再进行补全
        text = text.decode()
    except:
        pass
    text = text + pad * chr(pad)
    try:
        text = text.encode()
    except:
        pass
    encryptor = AES.new(key,AES.MODE_CBC,b'0102030405060708')
    ciphertext = encryptor.encrypt(text)
    ciphertext = base64.b64encode(ciphertext)#得到的密文还要进行base64编码
    return ciphertext

#rsa加密
def rsa_encrypt(ran_16,pub_key,modulus):
    text = ran_16[::-1]#明文处理,反序并hex编码
    rsa = int(binascii.hexlify(text), 16) ** int(pub_key, 16) % int(modulus, 16)
    return format(rsa, 'x').zfill(256)

#返回加密后内容
def encrypt_data(data):#接收第一参数,传个字典进去
    ran_16 = random_16()
    text = json.dumps(data)
    params = aes_encrypt(text,secret_key)#两次aes加密
    params = aes_encrypt(params,ran_16)
    encSecKey = rsa_encrypt(ran_16,pub_key,modulus)
    return  {'params':params.decode(),
             'encSecKey':encSecKey  }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!