双城之战更新啦!!!!!《孤勇者》也在b站上线了!!!!
《孤勇者》 是真的好听!!!!没听的快给我去听;《双城之战》也是真的好看,没看到快给我去看!!!!
今天我们主要是要对《孤勇者》的评论进行爬取,以及简单数据分析和可视化
首先开始爬虫传统艺能,找url鼠标右键点检查,然后点击网络
然后往下翻到评论区,右边搜索reply
点开文件,找到url
可以知道url="https://api.bilibili.com/x/v2/reply/main?callback=jQuery172007128930691894197_1636903294408&jsonp=jsonp&next=0&type=1&oid=764108122&mode=3&plat=1&_=1636903368457"
但是经验告诉我们要删掉callback=jQuery172007128930691894197_1636903294408&
所以正确的url为 "https://api.bilibili.com/x/v2/reply/main?jsonp=jsonp&next=0&type=1&oid=764108122&mode=3&plat=1&_=16"
实践得知 其中next={}是页数
可以判断这是json格式的文件
复制放进在线json解析格式化进行解析
然后我们就可以根据我们想要的东西开始爬虫并保存了from os import system
import urllib.request as request
import time
from urllib.error import*
import re
from urllib.parse import urljoin
import pprint
import time
import sys
import requests
def download(url:str,page:int,user_agent='wswp',num_retries=2,proxies=None):
##print('Downloading',url)
print('正在爬取第{}页数据'.format(page))
headers={'User-agent':user_agent}
try:
r=requests.get(url=url,headers=headers,proxies=proxies)
r.encoding="utf-8"
html=r.json()
if r.status_code>=400:
print('Error code',r.status_code)
html=None
if num_retries>0 and(500<=r.status_code<600):
delay=10
##print('Pause for {delay} seconds.')
time.sleep(delay)
##print('Retry to dowmload.')
return download(url,num_retries=num_retries-1,proxies=proxise)
##else:
##print('encoding=',r.encoding)
except requests.exceptions.RequestException as e:
print('Download error',e.reason)
return html
reply_data_lst=[]
for i in range(20):
page=i+1
url='https://api.bilibili.com/x/v2/reply/main?next={}&type=1&oid=764108122&mode=3&plat=1&_=1636892525330'.format(page)
message=download(url,page)
alldata=message['data']['replies']
for data in alldata:
dic_reply={}
dic_reply["评论"]=data["content"]["message"]
dic_reply["用户名"]=data["member"]["uname"]
dic_reply["性别"]=data["member"]["sex"]
dic_reply["点赞数"]=data["like"]
reply_data_lst.append(dic_reply)
print("爬取完毕!!!!")
看看reply_data_list里存了什么
然后转为dataframe
import pandas as pd df = pd.Dataframe(reply_data_lst)接下来让我们看看点赞数最多的20条数据吧
df=df.sort_values(by = '点赞数',ascending = False)
“
| 八号生日六号夺冠,七号老婆告诉我怀孕了,八号Eason发了新歌,这一定是我最喜欢的生日礼物了... |
” 真是暖心呀
然后稍稍可视化一下(因为评论的字数过多,所以采用pyecharts库可视化应该会好点)
from pyecharts.charts import Bar
bar = Bar()
bar.add_xaxis(list(df_top20['评论']))
bar.add_yaxis("点赞数", list(df_top20['点赞数']))
# render 会生成本地 HTML 文件,默认会在当前目录生成 render.html 文件
# 也可以传入路径参数,如 bar.render("mycharts.html")
bar.render_notebook()
别看横坐标只有一条评论,鼠标放到柱状图上是可以交互显示的(原谅我不会截取动态图。。。)
对用户名也按照点赞数进行可视化
from pyecharts.charts import Bar
bar = Bar()
bar.add_xaxis(list(df_top20['用户名']))
bar.add_yaxis("点赞数", list(df_top20['点赞数']))
# render 会生成本地 HTML 文件,默认会在当前目录生成 render.html 文件
# 也可以传入路径参数,如 bar.render("mycharts.html")
bar.render_notebook()
我们接下来看看有没有水军呢?
看看每个用户的评论数,并且可视化一下
df_shuijun = df[['用户名','评论']].groupby(by = '用户名').count().sort_values(by = '评论',ascending = False)
#进行分组计数,然后按照从大到小的顺序进行排列
#df[df['member'].str.contains('华洛丽桑卓')]
#这个是用来查找包含某个内容的原始数据
##用一下排前十的数据进行可视化
x = df_shuijun[:10].index.tolist()
y = df_shuijun[:10]['评论'].tolist()
#设置x,y数据
bar = Bar()
bar.add_xaxis(x)
bar.add_yaxis("评论数", y)
bar.render_notebook()
可以看出,每个用户最多才评论三条,所以这是没有水军的,人家是靠实力火的!!!!
我们来看看男女比例这里有点赶时间没来得及细想了,就用了比较原始的方法
dic_sex={}
dic_sex["男"]=0
dic_sex["女"]=0
dic_sex["保密"]=0
nan=0
nv=0
baomi=0
for i in range(400):
if (df.loc[i]["性别"]=="男"):
dic_sex["男"]+=1
if(df.loc[i]["性别"]=="女"):
dic_sex["女"]+=1
if(df.loc[i]["性别"]=="保密"):
dic_sex["保密"]+=1
import matplotlib.pyplot as plt labels ='男','女','保密' fraces = [174,22,204] explode = [0,0.1,0] plt.axes(aspect=1) plt.pie(x=fraces,labels= labels,autopct='%0f%%',explode= explode,shadow=True) plt.show()
男:女接近于8:1可以看出男生才是主力军呀
最后我们来搞个词云图!import jieba
from wordcloud import WordCloud
import matplotlib.pyplot as plt
from imageio import imread
import warnings
warnings.filterwarnings("ignore")
# 注意:动态添加词语集
for i in ["杰斯","金克斯","lol","好听","陈奕迅"]:
jieba.add_word(i)
data_cut = [jieba.lcut(x) for x in df["评论"]]
# 3 读取停用词
with open("stoplist.txt",encoding="utf-8") as f:
stop = f.read()
stop = stop.split()
stop = [" "] + stop
# 4 去掉停用词之后的最终词
s_data_cut = pd.Series(data_cut)
all_words_after = s_data_cut.apply(lambda x:[i for i in x if i not in stop])
# 5 词频统计
all_words = []
for i in all_words_after:
all_words.extend(i)
word_count = pd.Series(all_words).value_counts()
# 6 词云图的绘制
# 1)读取背景图片
back_picture = imread("R-C.jpg")
# 2)设置词云参数
wc = WordCloud(font_path="simhei.ttf",
background_color="white",
max_words=1000,
mask=back_picture,
max_font_size=200,
random_state=42
)
wc2 = wc.fit_words(word_count)
# 3)绘制词云图
plt.figure(figsize=(16,8))
plt.imshow(wc2)
plt.axis("off")
plt.show()
wc.to_file("词云.png")



