python爬取网易云音乐评论并制作词云_小太阳️的博客-程序员宝宝

技术标签: 爬虫  网易云音乐  评论  requests  json解析  Python  

 这几天一直在想我还没爬取过的网站,以及会遇到的难点。

每天使用网易云听歌,想着选首喜欢的歌去爬爬它的评论,我是用《小宇》这首歌做实例的。

爬虫写的多了,自然也知道在源码里面找不到的数据,基本上都是动态加载出来的,这个时候我一般会打开网页右击检查(我一般使用的都是Google浏览器),选中它的NetWork,上图(不知道为什么粘贴下来的图片这样别扭)。选中XHR(感觉一直用这个还不知道是啥意思,特意去百度了一波,详情链接:

http://www.w3school.com.cn/ajax/ajax_xmlhttprequest_create.asp),然后我是挨个去点击每个请求的,查看它的内容有哪些,评论内容在里面,就是找到这个接口了,这些都是很好找的。

 

找到接口后,第一反应是复制链接打开看一下(我的Google浏览器有一个查看json文件的扩展程序JSON-handle,复制链接能直接格式化json内容),却是啥都没有,看了一下请求方式,竟然是post请求,对于post请求的解决我还是不够熟练的。我知道会有个form表单需要提交去请求,具体的原理我还没有摸透,还需好好学习进步一波。

 往下翻你会看到一个Form Data,它就是我们要提交的表单,但是两个参数params和encSecKey的值会因为刷新页面而改变的,我查了很多大佬的博客,说是采用了 AES,rsa 加密算法,对数据进行了两次 AES 加密等等,所以需要解密,但是渣渣的我还是没能搞明白那个解密的方式,就根据大佬的提示啥的采用了另一种方式解决了评论的爬取。

代码我在下面粘上了,我都写了注释,其中获取精彩评论是使用我知道的最简单的表单提交的方法请求的,获取全部评论是根据链接http://music.163.com/api/v1/resource/comments/R_SO_4_410714325?limit=2920&offset=2939写的循环代入limit和offset两个参数,其实这个并没有完全实现自动化的原则。后面都是同样的方式将请求的json内容转成我们常用的字典形式获取相应的内容,我主要是抓取了用户头像、用户id、用户名、评论时间、获赞的数量、评论内容

后面将获取的评论文件制作词云的代码也在下面了,也是我这两天到处查资料琢磨的,它主要依靠wordcloud包来制作的,依靠matplotlib包来展示,PIL和numpy是为了设置背景图片而导入的:

pip install wordcloud

pip install matplotlib

pip install PIL

pip install numpy

最后附上我使用的背景图片

代码如下:

# -*- coding:utf-8 -*-
"""
# @PROJECT: Study
# @Author: admin
# @Date:   2018-09-04 17:02:43
# @Last Modified by:   admin
# @Last Modified time: 2018-09-04 17:02:43
"""
import requests
import json
import csv
import time

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.84 Safari/537.36",
}

# 获得接口,解析评论接口
def parse_comments_json(comments_list, path):

    for hotComments in comments_list:
        print("==============================================")
        user_icon = hotComments.get('user').get('avatarUrl')
        print("user_icon: ", user_icon)

        userId = hotComments.get('user').get('userId')
        print("userId: ", userId)

        user_nickname = hotComments.get('user').get('nickname')
        print("user_nickname: ", user_nickname)

        comment_time = hotComments.get('time')
        print("comment_time: ", comment_time)
        comment_time = time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime(float(comment_time)/1000))
        print(comment_time)

        zan_count = hotComments.get('likedCount')
        print("zan_count: ", zan_count)

        comment_content = hotComments.get('content')
        print("comment_content: ", comment_content)


        try:
            # 读写文件
            with open(path, 'a+', encoding='utf-8') as f:
                f.write(str(userId) + ";" + user_nickname + ";" + comment_content + ";" + str(
                    zan_count) + ";" + user_icon + "; " + comment_time + "\n")
                # f.write(comment_content + "\n")
            # # csv文件
            # with open('comment.csv', 'a+', encoding='gbk') as f:
            #     writer = csv.writer(f)
            #
            #     writer.writerow([userId, user_nickname, comment_content, zan_count, user_icon, comment_time])
        except Exception as e:
            pass
            # with open('load_error.txt', 'a+', encoding='utf-8') as f:
            #     f.write("==============="+str(e)+"\n")
            #     writer = csv.writer(f)
            #     writer.writerow([userId, user_nickname, comment_content, zan_count, user_icon, comment_time])

# 获取精彩评论
def get_wangyiyun_hotcomments(url, path):
    data = {
        "params": "fe0TVdyT+VuJ55uu+LgTsXlea7dROxXPYGv/FVSJMsm6Vh4nDodf59/qk0EnA/ZcFV7ZfzseLNQgnx7P/7Xnmg0mAO5kMVzNIoGwXr4ya8ZtkS0pU2b9/qwzszDgXp5LyJ8BxOJh6ZqcPFl8Vm7pF8ZpwiKlkPbRACtUnZmzdSEIK1vTXK2Lhlm4nDlw2K2tzNvYRiSesRApZZqBYJqBBvEMu4w/2dICbq8C10GkT1EZY4sX9irB/e7gOrzbYcAVm4pGDSuSWTdG+KoAg4+nCV0wAw2u4IBXw1J/c8tRXfsy0UhM/RrT/ABCHWrndb64mR/nsjResiTbTblHR9EwBh6knLSneQR/0PacjB7Zp6tLlbvhLCAENhTgMfmyRuu1qNb0unshrC/su5u48suwyRdwzCCZIQC/D1atjYpyUirEwBkyFqHN0OVeSsWZf5XjeXyIkJcXZUOu+/kGrYWrm6sLSqGqzJXgYeTYvoHaX0w=",
        "encSecKey": "13948d0b5288185467075eb5bbc36b66759c6cc8ee6cb4676016c47fb114d135fb4225c7072fab489e30ba63af1cc8f2852444d8989064958df436c498a18a7a3c43f290a053021ae0d8653b5f3f27dbb8b3a705ddaa7b9060124c86e065a493ceb4595fe5c6ea1e97ea301d4f6f774e5a5051747cda4d84af2180078fe8c8f5",
    }

    # postdata = requests
    resp = requests.post(url, data=data, headers=headers)
    # print(resp.text)
    comments_dict = json.loads(resp.text)
    hotComments_list = comments_dict.get('hotComments')
    print(hotComments_list)

    parse_comments_json(hotComments_list, path)

# 获取全部评论
def get_wangyiyu_comments(url, path):
    header = {
        'Accept': "*/*",
        'Accept-Language': "zh-CN,zh;q=0.9",
        'Connection': "keep-alive",
        'Host': "music.163.com",
        'User-Agent': "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.79 Safari/537.36"
    }

    # get_url = 'http://music.163.com/api/v1/resource/comments/R_SO_4_410714325'

    n = 1
    for i in range(0, 125290, 20):
        param = {
            'limit': str(i),
            'offset': str(n * 20 - 1)
        }
        n += 1
        response = requests.post(url, headers=header, params=param)
        # print(response.text)
        comments_dict = json.loads(response.text)
        comments_list = comments_dict.get('comments')
        print(comments_list)
        parse_comments_json(comments_list, path=path)

# 制作评论词云
def draw_wordcloud(path):
    from wordcloud import WordCloud, ImageColorGenerator
    from PIL import Image
    import matplotlib.pyplot as plt
    import numpy as np

    bg_mask = np.array(Image.open('bg1.jpg'))
    text = open(path, encoding='utf-8').read()
    my_wordcloud = WordCloud(background_color='white',  # 设置背景颜色
                             mask=bg_mask,     # 设置背景图片
                             max_words=2000,    # 设置最大显示的字数
                             font_path=r'C:\Windows\Fonts\STZHONGS.TTF',      # 设置中文字体,使的词云可以显示
                             max_font_size=250,  # 设置最大字体大小
                             random_state=30,   # 设置有多少种随机生成状态, 即有多少种配色方案
                            )
    myword = my_wordcloud.generate(text)

    plt.imshow(myword)
    plt.axis('off')
    plt.show()

if __name__ == '__main__':
    # url = "https://music.163.com/#/song?id=410714325"
    url = "https://music.163.com/weapi/v1/resource/comments/R_SO_4_410714325?csrf_token="
    # get_wangyiyun_hotcomments(url)

    path = 'xiaoyu.txt'

    start_time = time.time()
    comments_url = "http://music.163.com/api/v1/resource/comments/R_SO_4_410714325" # 小宇
   
    get_wangyiyu_comments(comments_url, path)
    end_time = time.time()
    print("程序耗时%f秒." % (end_time - start_time))

    draw_wordcloud(path)

 

【注意】 尽量使用代理ip,不然访问多了会封IP的

写到这里已经完成我想要的功能,并且获取想要的数据了,后续还想用这些数据进行分析,敬请期待!!!

 欢迎大家评论和关注

 

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_38105596/article/details/82454007

智能推荐

iOS_SDK_API_使用说明_"ios @\"api/sendcode\" 什么文件"_ios and Android的博客-程序员宝宝

iOS_SDK_API_使用说明1. SSO安全登录QQ帐号iOS SDK支持应用跳转到手机QQ进行登录,给用户提供更加安全、快捷的体验 。如果用户没有安装手机QQ,将打开登录页面。2. 分享到QQ和QQ空间2.1 分享到QQ好友分享到QQ好友支持发送:– 纯文本消息(QQApiTextObject)– 纯图片消息(QQApiImageObjec

Git:在一个仓库中存放多个IDEA项目_一个仓库放多个仓库代码_NiXGo的博客-程序员宝宝

目录引言解决方案实际操作引言最近由于课设的原因,在学习Java Web开发,因为要混Git的小绿点,我把之前学习Servlet的代码传到了Github上。像这样:这两周到了课设开发的时间,虽然组员们不用Git,但是本着开源(混绿点)精神,我还是想传到Git上,但是由于我不是一个职业的Java选手,我认为再为它开一个仓库不太美观。是的,我希望我的学习代码和课设代码共存一个仓库。很显然,我无法通过在同个仓库下创建lean_web和class_design文件夹去解决这个方案,因为它们在不同的IDEA

timeline的使用和参数说明_Green_1001的博客-程序员宝宝

关于swidget-timeline的使用和需要的文件在使用之前,你可以进入官方网站下载源码,或者直接使用附件中的源码,附件中的源码我将logo去掉了样式也做了修改,点击事件显示的时候要显示的时间我也给去掉了,主要是它的时间格式不是我们所需要的格式,改为我们需要的格式比较麻烦,接下来我根据我的使用介绍一下部分参数信息1.首先我们可以根据index.html或者jfk/jfk.htm...

飞凌嵌入式 RK3399核心板 iMX6ULL核心板 iMX6UL核心板 PX30,RK3368,RK3288,RK3399,i.mx6芯片参数对比分析_imx6ull和rk3399有啥区别_学无止境2022的博客-程序员宝宝

飞凌嵌入式 RK3399核心板 iMX6ULL核心板 iMX6UL核心板https://blog.csdn.net/qq_42792038/article/details/89382711?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164846454816782246423134%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&re

Oh, duty!_AngusSL的博客-程序员宝宝

1.市场调研计划  2.实施需求调研  3.《市场分析报告》或称之为《市场需求说明书》。  4.《立项建议书》  5.发起产品立项会  6.通过立项,进入产品建设期(角色项目经理)  7.细化产品需求,编写《产品需求说明书》,评审需求,定稿,打上基线。

强化学习之利用Q学习解决出租车问题_北木.的博客-程序员宝宝

''' 利用Q学习解决出租车问题 '''"""智能体必须在一个位置上接上乘客并在另一个位置放下乘客。成功放下乘客,那么智能体将会得到奖励+20分,且每经过一个时间步得到-1分。如果智能体错误搭载和放下,则会得到-10分。因此,智能体的目标就是学习在最短时间内在正确的位置搭载和放下乘客,且不会搭载非法乘客。 +---------+ |R:...

随便推点

作业案例-评委打分_渴望飞翔的鲸鱼的博客-程序员宝宝

//作业案例-评委打分 #include <iostream> #include <deque> #include <vector> #include <string.h> #include <stdlib.h> #in

什么是信息架构?_Tingzii的博客-程序员宝宝

<br />       信息架构,原文是information architecture,简称 IA。<br />       信息架构是在信息环境中,影响系统组织、导览、及分类标签的组合结构。这是将架构和设计学运用在数位环境中的一门学问。<br />       信息架构会影响信息的可用性(Usability)和可寻性(Findability),除此之外,仍有许多因素会影响,例如设计经验的累积、图形的设计、人机间的互动、知识内容的管理……等,这些都是与信息架构相关的领域。<br />       它是一

textarea文本保存到数据库,前端输出保存换行回车解决方案_textarea写入数据库时不能保存回车换行_岁末Zzz的博客-程序员宝宝

处理这种文本输出格式的,使用富文本编辑器是比较方便的,但我这里写的不是使用富文本编辑器的处理方法!那么,从数据库取出text文本到前端展示格式一致的解决方案主要有两种(仅Web端,其他平台没有调试):一:提交数据之前,将textarea的回车、空格先转换格式,再提交数据存入数据库,那样取出数据输出到web端也能保证格式一致//关键js代码var text = $("textarea").t...

C++求解二叉树的高度以及最大宽度_coolsunxu的博客-程序员宝宝

#include&amp;lt;iostream&amp;gt;#include&amp;lt;stdlib.h&amp;gt; #include&amp;lt;deque&amp;gt; //插入标准库中的头文件using namespace std;typedef struct treenode{ char data; treenode *right; treenode *left;}*Node;//创建二叉树v...

百度云 人脸检测_woshigemengxin的博客-程序员宝宝

首先 获取 accesstokenfunction request_post($url = '', $param = '') { if (empty($url) || empty($param)) { return false; } $postUrl = $url; $curlPost = $param; ...

推荐文章

热门文章

相关标签