我用python分析王冰冰B站视频,和冰冰一起逛北京!!

去年做的大作业,实现用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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,783评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,360评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,942评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,507评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,324评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,299评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,685评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,358评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,652评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,704评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,465评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,318评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,711评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,991评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,265评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,661评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,864评论 2 335

推荐阅读更多精彩内容

  • 学了一学期 大学计算机基础 的小白要开始做大作业了,从5个看起来都不太正经的题目里面选了个看起来顺眼的——简易B站...
    Cache_wood阅读 1,027评论 2 2
  • 夜莺2517阅读 127,696评论 1 9
  • 版本:ios 1.2.1 亮点: 1.app角标可以实时更新天气温度或选择空气质量,建议处女座就不要选了,不然老想...
    我就是沉沉阅读 6,865评论 1 6
  • 我是一名过去式的高三狗,很可悲,在这三年里我没有恋爱,看着同龄的小伙伴们一对儿一对儿的,我的心不好受。怎么说呢,高...
    小娘纸阅读 3,369评论 4 7
  • 那一年,我选择了独立远行,火车带着我在前进的轨道上爬行了超过23个小时; 那一年,我走过泥泞的柏油路,在那个远离故...
    木芽阅读 1,625评论 4 5