在简单学习了 python 爬虫后, 又想继续折腾, 进而找到了这个网易云音乐, 因为本人平时就是用它听的歌, 也喜欢看歌里的评论, 所以就爬网易云音乐评论吧, 那么开始吧!
正式进入主题
首先还是去找目标网页并开始分析网页结构, 如下
上面的三个箭头都是所要找的数据, 分别是评论用户, 评论和点赞数, 都可以用正则表达式找出来, 接下来继续找怎样找到下一页的数据, 还是用开发者工具, 但是当点击下一页的时候, 网页的 url 没有变, 说明网页是动态加载, 所以就不能在当前网页找数据了, 应该在他的 xhr 文件里找, 所以点入 network 看看, 然后也点击下一页一看, 果然有想要的
看到这里, 就兴奋地去敲代码了
一点击运行, 结果什么东西都没有, 但是他的状态码是 200, 明显请求成功啊, 却没有东西返回, 再去 network 仔细看看这个网页, 看到他是个 post 请求, 也看到了需要 post 两个参数 params 和 ensSecKey
一看到这个, 密密麻麻的数字和字母, 就猜应该是被加密了, 不过可以复制下来看看有没有用接下来看下他的 Response, 咦, 这是个 json, 不是 html 结构的, 所以需要用到 Json 库来进行解析
现在开始敲代码吧, 先把上面的两个参数复制过来看看
现在把每条评论的评论用户和点赞数和评论获取出来
可以看到, 利用 json.loads() 方法把数据转成 python 格式里的字典后就可以把想要的数据取出来了, 但是, 下一页怎样取? 总不能每次都复制粘贴那两个参数吧? 那唯一的方法就是不爬了怎么可能? 我的继续, 那我就要进行破解这两个参数了, 那好继续看 network, 因为要加密, 肯定要用 js 进行加密的
看到刚才那个网站的发起者 core.js,, 然后把它文件下载下来慢慢研究
保存后在经过美化, 然后进行查找那个 encSecKey 参数 (ps:JSj'e'tong'yang'de 美化网址为 www.CSS88.com/tool/js_bea
看到 window.asrsea() 方法有四个参数, 先不去管这个函数, 先看看他的四个参数是什什, 这里没必要去研究那四个参数怎样来的, 只需要知道他是什么, 那么我们可以加点代码上去让他显示出来, 从而利用 fiddler 来进行调试
加入代码如下
可以分别获取上面的每一个参数, 也把那个 params 获取看看, 然后在 fiddler 上操作如下
完成上面的设置后刷新网页就可以在 console 上面找到参数信息, 如果没有的话这是因为你之前浏览该网页的时候它被缓存了下来, 所以要清除缓存文件 (在清除浏览器记录里面有)
那个 rid 有本歌曲的 id, 明显是与评论有关的, 我试着连翻几页后, 发现那个 offset 就是评论偏移数, offset 就是 (页数 - 1)*20,total 在第一页是 true, 在其他页是 false
同样的方法也得到第二个参数为: 010001
第三个参数为: 00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7
第四个参数为: 0CoJUm6Qyw8W8jud
接下来就要看 window.asrsea() 方法是什么操作的了, 还是通过查找 js 文件可以看到这个
通过研究 i 是随机获取十六个字符而 b 函数是 AES 加密, 其中偏移量为 0102030405060708, 模式为 CBC, 看回 d 函数, 其中 params 连续两次加密, 第一次加密时, 文本为第一个参数密钥为第四个参数, 第二次加密时文本为第一次加密的值, 密钥为随机数 a 而 encSeckey 是一个 RSA 加密, 他的公钥是第二个参数, 模式是第三个参数, 文本为那个随机字符串 a
终于分析完了, 接着开始敲代码
先来个获取第一页评论的代码
这是获取两个参数的类
这是解析网易云音乐和获取评论的类
然而一点击运行, 直接给我报了个错: TypeError: can't concat str to bytes
原来是因为在第二次加密的时候, 那个 params 是个 byte 类型, 所以把他转成字符串类型就可以了
再次点击运行, 结果还是报错了: json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
这个报错因为我的 json 解析错了, 回头调试一看, 网页返回的东西是空的, 但他的状态码是 200, 这是什么鬼? 接着我再试了把那两个参数的值直接复制和前面一样看看, 结果运行成功, 这就说明我的是加密过程错了, 然后我就回去看了几篇, 看不出什么错误, 上网百度找到了这个知乎文章 https://zhuanlan.zhihu.com/p/32069543, 我把她的代码复制过来运行下, 结果是可以的, 我就继续看看我和她的区别, 原来我在用那个 16 个随机字符的时候用错了, 我在两个参数给了两个不同的, 而是需要给共同一个的, 看到这里, 我就直接回去改了下, 果然运行成功, 代码我就不贴出来了, 效果如下
接着是获取每一页的评论, 而每一页与第一个参数的 offset 有关, 其中的公式为 offse=(页数 - 1)*20,total 在第一页是 true, 在其他页是 false
而写入数据库我用的是我这篇文章的操作
http://mp.weixin.qq.com/s/6sQ_ER39P2NtXaPOnGdQNA
, 由于篇幅过长, 就不贴出来了, 感兴趣的可以去看看
接下来点运行就可以了, 但是运行到第八页的时候出现了这个异常
- raise errorclass(errno, errval)
- pymysql.err.InternalError: (1366, "Incorrect string value:'\xF0\x9F\x92\x94'for column'content'at row 1")
原因是这条评论有个识别不了的表情, 之后百度参考这篇文章 blog.csdn.net/HHTNAN/arti
这是首页数据库效果
获取完成 (家驹的歌评论这么少吗? 不解)
来源: https://juejin.im/post/5aa20d03518825558358d047