爬取网易云某歌曲所有评论,并输出词云图
声明:本文只作学习研究,禁止用于非法用途,否则后果自负,如有侵权,请告知删除,谢谢!
项目场景:
我上一篇文章写了网易云参数的解密,这次我们来爬取画画的baby的全部评论。
解决方案:
1.先来看看评论的接口,可以看出是https://music.163.com/weapi/comment/resource/comments/get?csrf_token=ff57cff46ebe79b9a51dd10f8c9181bb
这个接口,并且还携带了两个加密参数params和encSecKey,上一篇讲到的是获取歌曲接口的这两参数的解密,其实评论的这两个参数解密方法是一样的,就不细说了。
2.这里直接贴出评论接口的加密参数params和encSecKey生成方式,这里有这几个参数需要注意,一个是cursor,一个是pageSize,经过我的多次测试发现,每一页的评论都是基于该业最后的一条评论时间生成的cursor,然后每一页pagesize是20
{"rid":"R_SO_4_1474342935","threadId":"R_SO_4_1474342935","pageNo":"3","pageSize":"20","cursor":"1600190813154","offset":"0","orderType":"1","csrf_token":"ff57cff46ebe79b9a51dd10f8c9181bb"} 复制代码
3.那么问题就来了,我不知道每一页最后一条的评论时间是多少,无法生成相应的cursor怎么办,我的解决办法是:从发的第一条评论的当天日期(比如是2020-08-27),那么我就将cursor定义成最后一天时间的最后一秒,即‘2020-08-27 23:59:59‘的时间戳1598543999000(13位补3个0),一直到当天(比如是2020-09-16)最后一秒的时间戳即‘1600271999000’,然后设置pagesize=1000(1000条是最大值,orderType=1(按时间排序)),并且用相应的方法来避免每日会获取重复的评论,其实这样获取的评论数是不完整的,可以根据page和offset来细分当天的评论来获取完整评论信息(这里楼主懒,就没用这方法),如果大家有其他好的想法可以评论下哦!
param = {"rid": "R_SO_4_" + song_id, "threadId": "R_SO_4_" + song_id, "pageNo": "1", "pageSize": "1000", "cursor": cursor, "offset": "0", "orderType": "1", "csrf_token": "ff57cff46ebe79b9a51dd10f8c9181bb"} 复制代码
4.经过分析后,我们可以获取到该歌曲大部分的评论,代码如下:
now_day = datetime.date.today() #当天日期 flag_info = None #重复评论标志 num = 0 for i in range(20, -1, -1): # 获取 2020-08-27---2020-09-16 的日期 pre_day = str(now_day - datetime.timedelta(days=i)) + ' 23:59:59' # 获取T+1日期 # 先转换为时间数组 timeArray = time.strptime(pre_day, "%Y-%m-%d %H:%M:%S") # 转换为时间戳 cursor = str(int(time.mktime(timeArray))) + '000' # 拼接成13位时间戳 print(pre_day, cursor) # 评论接口参数 param = {"rid": "R_SO_4_" + song_id, "threadId": "R_SO_4_" + song_id, "pageNo": "1", "pageSize": "1000", "cursor": cursor, "offset": "0", "orderType": "1", "csrf_token": "ff57cff46ebe79b9a51dd10f8c9181bb"} pdata = js_tool.call('d', str(param)) response = requests.post('https://music.163.com/weapi/comment/resource/comments/get', headers=headers,data=pdata) # 获取评论信息 data = json.loads(response.text)['data'] comments = data.get('comments') # 存储评论信息 with open('comments.txt', 'a', encoding='utf8') as f: for comment in comments: info = comment.get('content') if flag_info == info: # 取到重复的评论则跳出循环,防止重复获取 break print(info) f.write(info + '\n') # folow_comments = comment.get('beReplied') # 附加的评论,暂不获取 # if folow_comments: # for folow_comment in folow_comments: # print(folow_comment.get('content')) num += 1 # 获取评论数+1 flag_info = comments[0]['content'] # 取每次请求的第一条 print('每次请求的第一条', flag_info, '\n') print('获取评论数:', num) 复制代码
5.然后我们就拿到了评论的数据,在用jieba对数据进行分词统计,输出词云图:
# 分词 def fc_CN(text): # 接收分词的字符串 word_list = jieba.cut(text) # 分词后在单独个体之间加上空格 result = " ".join(word_list) return result # 输出云词 def word_cloud(): with open("./comments.txt", encoding='utf8') as fp: text = fp.read() # 将读取的中文文档进行分词 text = fc_CN(text).replace('\n', '').split(' ') # 过滤部分分词 filter_str = ['的', ',', '了', '我', '[', '你', '是', '就', ']', '!', '。', '?', '这', '不', '也', '都', '吧', '啊', '在', '吗', '和', '吗', '听', '有', '说', '去', '好', '人', '给', '他', '…', '小', '来', '还', '没', '一', ''] new_text = [] for data in text: if data not in filter_str: new_text.append(data) print(new_text) # 词频统计 word_counts = collections.Counter(new_text) # 对分词做词频统计 word_counts_top10 = word_counts.most_common(10) # 获取前10最高频的词 print(word_counts_top10) # 输出检查 # 词频展示 mask = np.array(image.open('./love.jpg')) # 定义词频背景--需要自行导入 wc = wordcloud.WordCloud( # background_color='white', # 设置背景颜色 font_path='C:\Windows\Fonts\simhei.TTF', # 设置字体格式 mask=mask, # 设置背景图 max_words=200, # 最多显示词数 max_font_size=300, # 字体最大值 # scale=32 # 调整图片清晰度,值越大越清楚 ) wc.generate_from_frequencies(word_counts) # 从字典生成词云 image_colors = wordcloud.ImageColorGenerator(mask) # 从背景图建立颜色方案 wc.recolor(color_func=image_colors) # 将词云颜色设置为背景图方案 wc.to_file("./tmp.jpg") # 将图片输出为文件 plt.imshow(wc) # 显示词云 plt.axis('off') # 关闭坐标轴 plt.show() # 显示图像 复制代码
6.最后,Run!,总共评论数是8544条,爬到了8230条,还是有几百条没爬到的。
7.然后看看我们输出的词云图,哈哈哈,大写的giao字映入眼帘,不愧是我giao哥!,完整代码可访问我的git来获取:github.com/934050259/w…
作者:逆向阿J
链接:https://juejin.cn/post/7023552504038162462