写在前面
最近一位很火的央视美女主持,没错,说的就是王冰冰,入驻B站啦,她在2020年的最后一天发布了一条vlog,疯狂涨粉200w,成功跻身2020百大up,那么B站的网友们在评论区说了什么呢?让我们一起来看看吧!
思路分析
B站评论接口如下:
https://api.bilibili.com/x/v2/reply
参数有:
#固定值,可省略
'jsonp':'jsonp'
#固定值,不可缺省
'type':'1'
#评论页数
"pn":1
#排序方式,2代表从旧到新,1代表从新到旧,默认为1
'sort':'2'
#视频的av号,可以通过开发者工具获取
'oid':"800760067"
#毫秒级时间戳,可省略
'_':"1609912833995"
代码部分
用到的包
#网页请求
import requests
#获取时间戳
import time
#连接到MongoDB
import pymongo
#操作excel
import openpyxl
#进度条
from tqdm import tqdm
#处理数据
import pandas as pd
#结巴分词
import jieba
#词云
from wordcloud import WordCloud
#统计词频
from tkinter import _flatten
#默认停用词
from wordcloud import STOPWORDS
#加载词云背景图
import matplotlib.pyplot as plt
Bilibili类
#修改oid可以抓取不同视频的评论
oid = '800760067'
class Bilibili(object):
#初始化,从外部获取oid和想要抓取的总页数(从第一页开始算起)
def __init__(self,oid,pn):
#评论接口
self.url = 'https://api.bilibili.com/x/v2/reply'
#参数,评论排序方式为从旧到新
self.params = {
'jsonp':'jsonp',
'type':'1',
'sort':'2',
'oid':oid,
'_':self.get_curl(),
}
#请求头
self.headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
}
#要抓取的总页数
self.pn = pn
#连接到MongoDB,改成自己的用户名和密码
self.client = pymongo.MongoClient("mongodb://username:pwd@localhost:27017")
#指定数据库,不存在则自动创建
self.db = self.client.bilibili
#指定表,不存在则自定创建
self.collection = self.db.comment
#初始化excel工作表
self.wb = openpyxl.Workbook()
#创建一个默认sheet
self.ws = self.wb.active
#创建一个文本文件
self.file = open('bilibili.txt','wt',encoding = 'utf-8')
#获取毫秒级时间戳
def get_curl(self):
return str(round(time.time() * 1000))
#python内置装饰器,将类中函数装饰为属性
@property
def get_comment(self):
#为excel表格添加索引
self.ws.append(['用户','性别','评论','等级','点赞'])
#循环抓取并启用进度条
for i in tqdm(range(1,self.pn + 1),desc = '正在下载...',ncols = 80):
#更新参数
self.params['pn'] = i
#有时候会出现某一页无响应,捕捉一下异常
try:
#发起get请求,将超时时间设置为5s,超时则会引发异常进入except
res = requests.get(url = self.url,headers = self.headers,params = self.params,timeout = 5)
#将response转换为json格式并获取当前页所有评论
self.comments = res.json()['data']['replies']
#逐条分析
for comment in self.comments:
#发表评论的用户名
username = comment['member']['uname']
#用户性别
sex = comment['member']['sex']
#评论内容
content = comment['content']['message']
#用户等级
level = comment['member']['level_info']['current_level']
#点赞数量
like = comment['like']
#封装为字典
reply = {"用户":username,"性别":sex,"评论":content,"等级":level,"点赞":like}
#向MongoDB中插入一条数据
self.collection.insert_one(reply)
#向excel表格中插入一条数据
self.ws.append([username,sex,content,level,like])
#将评论内容写入txt文件
self.file.write(content + '\n')
#暂停2s
time.sleep(2)
#遇到异常的话无视,继续下一页
except:
pass
#将类中函数装饰为属性
@property
def save(self):
#调用前述方法获取评论
self.get_comment
#保存excel表
self.wb.save('bilibili.xlsx')
#关闭文本文件
self.file.close()
#写一个内容类用于制作词云
class Word_Cloud(object):
def __init__(self):
#从excel中读取数据
self.data = pd.read_excel('bilibili.xlsx')
#自定义停用词
self.words = ['量', '…', '还', '🍑','\u3000',' ','🧊','▓','\xa0',"啊","这",'・',"就","在","站","你",'\n','_','的','[',']','?','!','那','都','是','吧','个','我','和','有','呢','号','\\','(',')','(',')','doge',';',';','。','@',',',':','!','https','/','“','”','了',]
#词云背景图
self.img="1.jpeg"
#将默认停用词与自定义停用词合并(python的列表居然可以直接加!)
self.stopWords = list(STOPWORDS) + self.words
#装饰为属性
@property
def word_cloud(self):
#自定义词库,这里是一个示例,不加的话会把“打call”拆开
jieba.load_userdict(['打call'])
#获取评论并调用jieba分词
dataCut = self.data['评论'].apply(jieba.lcut)
#去除停用词,并去除单字符词
dataAfter = dataCut.apply(lambda x: [i for i in x if i not in self.stopWords and len(i) > 1])
#统计词频
wordFre = pd.Series(_flatten(list(dataAfter))).value_counts()
#加载背景图
mask = plt.imread(self.img)
#创建wordcloud对象,参数分别为:放大比例(与原始画布)、字体、背景图、背景颜色
wc = WordCloud(scale=10,font_path='C:/Windows/Fonts/simsun.ttc',mask=mask,background_color="white",)
#将分好的词填充到词云
wc.fit_words(wordFre)
#保存词云图
wc.to_file('bilibili.png')
从txt文件生成词云:
from collections import Counter
class Word_Cloud(object):
def __init__(self):
self.cn_words = ['量', '…', '还', '🍑','\u3000',' ','🧊','▓','\xa0',"啊","这",'・',"就","在","站","你",'\n','_','的','[',']','?','!','那','都','是','吧','个','我','和','有','呢','号','\\','(',')','(',')','doge',';',';','。','@',',',':','!','https','/','“','”','了',]
self.img="1.jpeg"
self.stopWords = list(STOPWORDS) + self.cn_words
#读取文本文件
self.f = open('bingbing.txt','r',encoding = 'utf-8').read()
@property
def word_cloud(self):
#添加自定义词库
jieba.load_userdict(['打call'])
#分词
words_cut = jieba.lcut(self.f)
#去除停用词和单字符
words = [i for i in words_cut if i not in self.stopWords and len(i) > 1]
mask = plt.imread(self.img)
#统计词频并按从大到小排序,这里是根据元组的第二个属性,reverse为True则按倒序排序
count_list = sorted(Counter(words).items(), key = lambda x:x[1],reverse = True)
#输出高频词汇
print(count_list[0:20])
#生成词云
wc = WordCloud(scale=5,font_path='C:/Windows/Fonts/simsun.ttc',mask=mask,background_color="white",)
wc.fit_words(dict(count_list))
wc.to_file('bilibili.png')
调用方式
#修改pn为你要抓的总页数
bilibili = Bilibili(oid = oid,pn = 0)
bilibili.save
bilibili.Word_Cloud().word_cloud
词云背景图
美女主持王冰冰
写在后面
词云部分参考了CSDN的文章,另外,本文的爬虫部分更适合用scrapy来写,调度起来十分方便,有兴趣的读者可以研究一下。