Python 爬虫学习(一)
之前突然想到去爬取网易云音乐的歌词查了很多资料也有很多详细的解释,但还是走了不少弯路,其中有些是因为时间过去太久和python的版本不同造成的关系,还有一些粗心造成的。总之过程会都详细的写在下面
既然要爬取网易云音乐,最重要的还是要去抓包。然后分析。
在这里 我是用的工具时 chrome,和Fiddler
随便打开一首歌曲 ,f12 打开调试工具 f5刷新页面
首先要知道歌词是js生成的不是可以直接通过网页访问歌曲页面直接抓取的
所以我们选择 xhr 然后就可以一条一条去筛选
通过简单的查看就能发现这两条中的某一条有我们想要的信息(歌词)
可以看到其中第一条 时歌曲评论消息(其实整个看完之后 评论和歌词的抓取只有一步的差别就是关于window.asrsea这个函数第一个参数的区别)
然后我们看下一条
这就是我们需要的歌词消息
请求信息
其中就有params,和encseckey两个参数需要我们关注
具体怎么去找
可以看
https://www.zhihu.com/question/36081767
我这里就说一下我遇到的坑
调试的时候一定要调试的是lyric这条 在他之前还有很多条用到这个代码所以要注意区别
关于python下的 AES 加密用的是pyCrypto (这个最新只支持到python3.3 我之前用的python3.6 折腾了很久…3.6下好像有一个叫 crypto 可以安装,还没研究。。。另外windows下安装python模块真的时很烦的一件事,总会有莫名其妙的错误。其他平台还没有试过,也不好评论)
之后查看readme 发现crypto好像是 linux 和mac 下 加密文件的
下面贴出代码 跟知乎里面略有不同稍加修改,我是可以在python3.3下直接跑通的
from Crypto.Cipher import AES
import requests
import base64
import json
import re
class Get_lyric(object):
def __init__(self,songid):
self.songid=songid
self.first_param = "{\"id\":\"" + songid + "\",\"lv\":-1,\"tv\":-1,\"csrf_token\":\"\"}"
self.second_param = "010001"
self.forth_param = "0CoJUm6Qyw8W8jud"
self.__encSecKey = "257348aecb5e556c066de214e531faadd1c55d814f9be95fd06d6bff9f4c7a41f831f6394d5" \
"a3fd2e3881736d94a02ca919d952872e7d0a50ebfa1769a7a62d512f5f1ca21aec60bc3819a9" \
"c3ffca5eca9a0dba6d6f7249b06f5965ecfff3695b54e1c28f3f624750ed39e7de08fc849324" \
"2e26dbc4484a01c76f739e135637c"
self.headers = {
'Host': 'music.163.com',
'Origin': 'http://music.163.com',
'Accept': '*/*',
'Accept-Language': 'zh-CN,zh;q=0.8',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/5'
'7.0.2987.98 Safari/537.36',
'Connection: ': 'keep-alive',
'Content-Type': 'application/x-www-form-urlencoded'
}
def AES_encrypt(self,text, key, iv):
pad = 16 - len(text) % 16
text = text + pad * chr(pad)
encryptor = AES.new(key, AES.MODE_CBC, iv)
encrypt_text = encryptor.encrypt(text)
encrypt_text = base64.b64encode(encrypt_text)
return encrypt_text
def get_params(self):
iv = "0102030405060708"
second_key = 16 * 'F'
h_encText = self.AES_encrypt(self.first_param, self.forth_param, iv)
h_encTexts = bytes.decode(h_encText)
h_encTexts = self.AES_encrypt(h_encTexts, second_key, iv)
self.h_encTexts=h_encTexts
def lyric(self):
self.get_params()
data = {
"params": self.h_encTexts,
"encSecKey": self.__encSecKey
}
url = "http://music.163.com/weapi/song/lyric?csrf_token="
response = requests.post(url, headers=self.headers, data=data)
json_text = response.text
j = json.loads(json_text)
lrc = j['lrc']['lyric']
pat = re.compile(r'\[.*\]')
lrc = re.sub(pat, "", lrc)
lrc = lrc.strip()
return lrc
if __name__ == "__main__":
get=Get_lyric("479219330")
print(get.lyric())
最后再说一下 fiddler 真的是一个很好用的软件。在自己调试js的时候一定要善用fiddler的composer功能可以节约很多时间