去年做的大作業,實現用tkinter庫制作簡單的GUI界面并且顯示爬取成功的彈幕,并且制作詞云、分析出現次數最多的十條彈幕,彈幕類型,彈幕顏色,提取封面圖片等。
@[toc]
完整代碼
#大作業 b站彈幕分析系統
from imageio import imread #加載圖片
import requests #發出請求
import csv #文件格式
import re #正則表達式篩選
import jieba #中文分詞
import json
import urllib3
from urllib import request
from PIL import Image,ImageTk #呈現png,jpg圖片
import wordcloud #繪制詞云
import tkinter as tk
from tkinter import Button
from tkinter import messagebox
import matplotlib.pyplot as plt #繪圖
import matplotlib as mpl
from bs4 import BeautifulSoup as BS #解析
mpl.rcParams['font.sans-serif'] = ['STKaiti'] #正常顯示中文
main=tk.Tk() #建立主窗體
main.title('B站彈幕爬取界面')
main.geometry('1000x600')
label=tk.Label(main,text='請輸入bv號')
label.grid(row=0,column=0)
entry=tk.Entry(main)
entry.grid(row=0,column=1)
Button(main,text='分析',command=lambda:menu0()).grid(row=0,column=2)
def menu0():
bv=entry.get() #獲得輸入內容
try:
if bv!='': #利用bv號獲得cid,順便獲取duration和pic
url='http://api.bilibili.com/x/web-interface/view?bvid='+bv
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36"
}
urllib3.disable_warnings() #從urllib3中消除警告
response = requests.get(url,headers=headers)
content = json.loads(response.text)
# 獲取到的是str字符串 需要解析成json數據
# print(response.content.decode('utf-8'))
statue_code = content.get('code')
#print(statue_code)
if statue_code == 0:
data=content['data']['pic']
name='fengmian.jpg'
request.urlretrieve(data,filename=name)
cid=content['data']['cid']
duration=content['data']['duration']
else:
print('該bv號不存在')
#利用cid獲取并分析彈幕文件
url1='http://api.bilibili.com/x/v1/dm/list.so?oid='+str(cid)
response1 = requests.get(url1,headers=headers)
danmu_html = response1.content.decode('utf-8')
soup = BS(danmu_html, 'lxml') #解析
all_d = soup.select('d')
time,leixing,color=[],[],[]
for d in all_d:
biao=d['p'].split(',')
#把d標簽中P的各個屬性分離開
yanse=hex(int(biao[3]))[2:]
while len(yanse)<6: #處理顏色
yanse='0'+yanse
yanse1='#'+yanse
#print(yanse1)
color.append(yanse1)
time.append(int(eval(biao[0]))) #處理時間
leixing.append(int(biao[1])) #處理類型
res = re.compile('<d.*?>(.*?)</d>') #處理彈幕文件
danmu = re.findall(res,danmu_html)
for i in danmu: #將彈幕按行寫入csv文件
with open('b站彈幕.csv','a',newline='',encoding='utf-8-sig') as file:
writer = csv.writer(file)
danmu = []
danmu.append(i)
writer.writerow(danmu)
f = open('b站彈幕.csv',encoding='utf-8')
txt = f.read()
f.close() #打開文件,在文本框插入所有彈幕
text=tk.Text(main,height=30)
text.grid(row=1,column=1)
text.insert('insert',txt)
scrollbar = tk.Scrollbar() #關聯文本框和滾動條
scrollbar.grid(row=1, column=1, sticky=tk.N+tk.S)
text['yscrollcommand'] = scrollbar.set
scrollbar['command'] = text.yview
def menu1():
count=[]
for i in range(duration):
count.append(time.count(i)) #統計每秒彈幕條數
plt.plot(range(duration),count,'b-',linewidth=2.5,label='彈幕密度')
plt.xlabel('時間')
plt.ylabel('彈幕條數')
plt.legend()
plt.title('高能進度條') #繪制折線圖
plt.savefig('gaoneng.png',dpi=100)
#填充
plt.fill_between(x=range(duration),y1=0,y2=count,facecolor='blue', alpha=0.5)
plt.show()
top0=tk.Toplevel()
top0.title('高能進度條')
top0.geometry('600x400')
global img_png1 #顯示圖片
img = Image.open('gaoneng.png')
img_png1 = ImageTk.PhotoImage(img)
label =tk.Label(top0, image = img_png1)
label.pack()
def menu2():
txt_list = jieba.lcut(txt) #精確分詞
string = ' '.join((txt_list)) #連接成字符串
#這里需要一張本地圖片,設置成mask參數
mk = imread('C:/Users/lenovo/Pictures/google.png')
#這里需要一份停用詞表
f1=open('F:/stopwords.txt',encoding='utf-8')
txtt=f1.read()
f1.close()
w = wordcloud.WordCloud(max_font_size=10,
background_color='white',
font_path='C:/Windows/SIMLI.TTF',
mask=mk,
scale=2,
stopwords={txtt},
collocations=False,
contour_width=5)
#contour_color='red'
w.generate(string) #生成詞云
w.to_file('axwordcloud.png')
global img_png2
top=tk.Toplevel()
top.title('詞云圖')
top.geometry('800x600')
img = Image.open('axwordcloud.png')
img_png2 = ImageTk.PhotoImage(img)
label =tk.Label(top, image = img_png2)
label.pack()
def menu3():
global img_png3
dic,txt1={},[]
f = open('b站彈幕.csv',encoding='utf-8')
txt= f.readlines() #這個方法是形成一個長列表
f.close()
for line in txt:
danm='' #刪除一些無關信息
stop=',./,。?、‘“;;!! ·~`^&*()@#$%[]{}'
line=line[:-1] #去掉換行符\n
for item in line:
if item not in stop:
danm+=item
txt1.append(danm)
for i in range(len(txt1)):
num=0
for j in txt1:
if j==txt1[i]:
num+=1
dic[txt1[i]]=num #統計彈幕出現次數
#字典排序
dic1=sorted(dic.items(),key=lambda x:x[1],reverse=True)
x,y=[],[]
for i in range(10):
x.append(dic1[i][0])
y.append(dic1[i][1])
#繪制水平柱狀圖
bar=plt.barh(range(10),y,height=0.5,color='rgb')
for rect in bar: #顯示數字
w = rect.get_width()
plt.text(w, rect.get_y()+rect.get_height()/2, '%d' %
int(w), ha='left', va='center')
plt.yticks(range(10),labels=x) #導入標簽
plt.xlabel('彈幕數量')
plt.ylabel('彈幕排名')
plt.savefig('danmutop10.png',dpi=100)
plt.show()
top1=tk.Toplevel()
top1.title('彈幕數量top10柱狀圖')
top1.geometry('700x500')
img = Image.open('danmutop10.png')
img_png3 = ImageTk.PhotoImage(img)
label =tk.Label(top1, image = img_png3)
label.pack()
def menu4():
global img_png4
x=['滾動彈幕','滾動彈幕','滾動彈幕','底端彈幕','頂端彈幕','逆向彈幕','精準定位','高級彈幕']
y=[0 for i in range(8)]
for i in leixing:
y[i-1]+=1 #彈幕類型
plt.bar(range(1,9),y,color='rgb',tick_label=x)
for i in range(1,9):
plt.text(i,y[i-1],'%d'%y[i-1],ha='center',va='bottom')
plt.savefig('leixing.png',dpi=100)
plt.show()
top3=tk.Toplevel()
top3.title('彈幕類型')
top3.geometry('700x500')
img = Image.open('leixing.png')
img_png4 = ImageTk.PhotoImage(img)
label =tk.Label(top3, image = img_png4)
label.pack()
def menu5():
dic={}
global img_png5
for i in color:
if i not in dic.keys():
dic[i]=1 #字典的鍵代表彈幕顏色,值代表出現次數
dic[i]+=1
dic1 = dict(sorted(dic.items(), key=lambda x: x[1],reverse=True))
size=dic1.values()
color1=dic1.keys()
plt.style.use('Solarize_Light2') #設置背景顏色
plt.pie(size,colors=color1, #autopct='%1.1f%%',
startangle=90,counterclock=False)
plt.savefig('color.png')
plt.show()
top4=tk.Toplevel()
top4.title('彈幕顏色')
top4.geometry('600x400')
img = Image.open('color.png')
img_png5 = ImageTk.PhotoImage(img)
label =tk.Label(top4, image = img_png5)
label.pack()
def menu6():
global img_png6
top2=tk.Toplevel()
top2.title('封面圖片') #封面圖片
top2.geometry('1000x800')
img = Image.open('fengmian.jpg')
img_png6 = ImageTk.PhotoImage(img)
label =tk.Label(top2, image = img_png6)
label.pack()
Button(main,text='高能進度條',command=menu1).grid(row=1,column=2)
Button(main,text='生成詞云圖',command=menu2).grid(row=2,column=0)
Button(main,text='彈幕數量top10柱狀圖',command=menu3).grid(row=2,column=2)
Button(main,text='彈幕類型統計圖',command=menu4).grid(row=2,column=3)
Button(main,text='彈幕顏色統計圖',command=menu5).grid(row=3,column=2)
Button(main,text='彈幕封面圖片',command=menu6).grid(row=3,column=3)
else:
messagebox.showinfo(message='請輸入bv號')
except:
messagebox.showerror(title='爬取失敗',message='bv號錯誤或網絡異常')
main.mainloop()
具體實現
1.尋找視頻的bv號:BV15K411u7t1
2.運行程序,開始分析
3.點擊各個按鈕,就可以實現各種功能
詞云圖:
封面圖片:
仿B站高能進度條
前十彈幕
彈幕類型
彈幕顏色比例
完整工程地址:https://download.csdn.net/download/weixin_46530492/12789116