用Python爬取柯南弹幕+Gephi梳理主线剧情

导语:9000后的童年里有什么?

红白机魂斗罗、魔兽世界、梦幻西游、穿越火线、英雄联盟、植物大战僵尸、超级玛丽、扫雷等各种游戏还是街头玩的玻璃弹珠、打画片、跳房子、或是一堆小伙伴守着电视看家有儿女武林外传还是暑期无限循环的还珠格格但我相信还有许多小可爱的童年里绝对离不开漫画!!小时候窝在书店看一整个下午的漫画简直不要太满足啦

柯南是小编最喜欢的漫画人物

柯南经典口头禅:

1.江户川柯南,是一个侦探

每次柯南揭穿了凶手的真面目或者帮助他人解决了时间之后,凶手或者其他人总是会问一句“你究竟是谁?”,这时候柯南就会摆出一个很酷的姿势,然后嘴角微微上扬,说出这句话“江户川柯南,是一个侦探”。很可惜我们的毛利小五郎在被扎了这么多次之后,也不会问一句“你究竟是谁?”

2.原来如此,是这么回事啊!

每次在遇到案件的时候,一般情况下柯南并不能轻松的就解决这个案件,他会遇到某个瓶颈。而在这个时候旁人一个不经意间的行为或者一句话就会让柯南灵光一闪,之后眼睛反光“原来如此,是这么回事啊!”。此时很多观众一定都还处于懵逼的状态,柯南怎么又明白了。

3.这么说犯人就只有……

大部分案件中,柯南虽然解开了犯罪的手法,但是却缺乏决定性的证据,也无法推理出真正的犯人。在经过他“仔细”的调查之后,他总会找到关键性的线索和证据,然后根据这个线索和证据推理出犯人真正的身份,这时候他就会来一句“这么说犯人就只有……”。

4.真相只有一个

这句“真相只有一个”可以说是《名侦探柯南》中最经典的一句话了,基本上每集动画片的片头都有这句话,而且每次柯南说这句话的时候都是正气凛然。现实中很多粉丝在日常生活中也会模仿柯南说这句话,“新机词挖一此莫禾多此!”。

5.啊嘞嘞

如果说到《名侦探柯南》中柯南令人印象最深刻的口头禅,除了上面的“真相只有一个”外就是这一句“啊嘞嘞”了。在剧情中,柯南在犯罪现场找到什么线索的时候,都会故意用小孩子的口气说出这句“啊嘞嘞”来提醒其他人。而在最近的红色修学篇中,柯南在恢复工藤新一的身份后,在破案的时候还不自觉的说出了这句“啊嘞嘞”,可见这个口头禅对他的影响有多深了。

好了~回忆到这下边干正事😎👌

一、爬取介绍

利用Chrome浏览器抓包可知,某站弹幕文件以XML文档式进行储存,如下所示(共三千条实时弹幕)

其URL为:comment.bilibili.com/183362119.x…

数字183362119则代表该视频专属ID,通过改变数字即可得到相应的弹幕文件。打开第1集的视频,查看源码,如下图所示。

不难看出,CID则是对应着各个视频的ID,接下来用正则提取即可。

完整爬取代码如下

import requests
import re
from bs4 import BeautifulSoup as BS
import os
path='C:/Users/dell/Desktop/柯南'
if os.path.exists(path)==False:
    os.makedirs(path)
os.chdir(path)
 
def gethtml(url,header):
    r=requests.get(url,headers=header)
    r.encoding='utf-8'
    return r.text
 
def crawl_comments(r_text):
    txt1=gethtml(url,header)
    pat='"cid":(\d+)'
    chapter_total=re.findall(pat,txt1)[1:-2]
    count=1
    for chapter in chapter_total:
        url_base='http://comment.bilibili.com/{}.xml'.format(chapter)
        txt2=gethtml(url_base,header)
        soup=BS(txt2,'lxml')
        all_d=soup.find_all('d')
        with open('{}.txt'.format(count),'w',encoding='utf-8') as f:
            for d in all_d:
                f.write(d.get_text()+'\n')
        print('第{}话弹幕写入完毕'.format(count))
        count+=1
 
if __name__=='__main__':
    url='https://www.bilibili.com/bangumi/play/ep321808'
    header={'user-agent':'Opera/12.80 (Windows NT 5.1; U; en) Presto/2.10.289 Version/12.02'}
    r_text=gethtml(url,header)
    crawl_comments(r_text)
复制代码

最终的全部弹幕文件都在桌面的"柯南"文件下

注:这里共爬取到980个弹幕文件。【自941集后就跳到994集(大会员才能观看的)。虽然目前更新到1032话,但并没有1032集内容,如下图所示】

二、弹幕可视化

I.主要人物讨论总次数分析

(1)统计人数总次数注:role.txt是主要人物名文件(需考虑到弹幕一般不会对人物的全名进行称呼,多数使用的是昵称,否则可能与实际情况相差较大。)

import jieba
import os
import pandas as pd
os.chdir('C:/Users/dell/Desktop')
jieba.load_userdict('role.txt')
role=[ i.replace('\n','') for i in open('role.txt','r',encoding='utf-8').readlines()]
txt_all=os.listdir('./柯南/')
txt_all.sort(key=lambda x:int(x.split('.')[0]))  #按集数排序
count=1
def role_count():
df = pd.DataFrame()
 for chapter in txt_all:
     names={}
     data=[]
     with open('./柯南/{}'.format(chapter),'r',encoding='utf-8') as f:
         for line in f.readlines():
             poss=jieba.cut(line)
             for word in poss:
                 if word in role:
                     if names.get(word) is None:
                         names[word]=0
                     names[word]+=1
         df_new = pd.DataFrame.from_dict(names,orient='index',columns=['{}'.format(count)])   
         df = pd.concat([df,df_new],axis=1)
     print('第{}集人物统计完毕'.format(count))
     count+=1
df.T.to_csv('role_count.csv',encoding='gb18030')
复制代码

(2)可视化

import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['kaiti']
plt.style.use('ggplot')
df=pd.read_csv('role_count.csv',encoding='gbk')
df=df.fillna(0).set_index('episode')
plt.figure(figsize=(10,5))
role_sum=df.sum().to_frame().sort_values(by=0,ascending=False)
g=sns.barplot(role_sum.index,role_sum[0],palette='Set3',alpha=0.8)
index=np.arange(len(role_sum))
for name,count in zip(index,role_sum[0]):
    g.text(name,count+50,int(count),ha='center',va='bottom',)
plt.title('B站名侦探柯南弹幕——主要人物讨论总次数分布')
plt.ylabel('讨论次数')
plt.show()
复制代码

虽说是万年小学生,柯南还是有变回新一的时候,且剧情也并不只是"找犯人—抓犯人"。接下来从数据的角度来,扒扒一些精彩剧情集数。

II.柯南变回新一集数统计

考虑到部分集数中新一是在回忆中出现的,为减少偏差,将讨论的阈值设为250次,绘制如下分布图

其讨论次数结果及剧集名如下表所示

有兴趣的小可爱们可以码一下,除235集外,均是柯南变回新一的集数。

相关代码如下:

df=pd.read_csv('role_count.csv',encoding='gbk')
df=df.fillna(0).set_index('episode')
xinyi=df[df['新一']>=250]['新一'].to_frame()
print(xinyi) #新一登场集数
plt.figure(figsize=(10,5))
plt.plot(df.index,df['新一'],label='新一',color='blue',alpha=0.6)
plt.annotate('集数:50,讨论次数:309', 
             xy=(50,309),
             xytext=(40,330),
             arrowprops=dict(color='red',headwidth=8,headlength=8)
            )
plt.annotate('集数:206,讨论次数:263', 
             xy=(206,263),
             xytext=(195,280),
             arrowprops=dict(color='red',headwidth=8,headlength=8)
            )
plt.annotate('集数:571,讨论次数:290', 
             xy=(571,290),
             xytext=(585,310),
             arrowprops=dict(color='red',headwidth=8,headlength=8)
            )
plt.hlines(xmin=df.index.min(),xmax=df.index.max(),y=250,linestyles='--',colors='red')
plt.legend(loc='best',frameon=False)
plt.xlabel('集数')
plt.ylabel('讨论次数')
plt.title('工藤新一讨论次数分布图')
plt.show()
复制代码

以讨论次数最多的572集,绘制词云图(剔除了高频词"新一",防止遗漏其他信息)如下所示:

从图中可看出,出现频率较高地词有整容、服部、声音、爱情等。(看来凶手是整成了新一的模样进行犯罪的,还有新兰的感情戏在里面,值得一看)

III.主线集数内容分析

主线剧情主要是围绕着组织成员(琴酒、伏特加、贝尔摩德)展开,绘制分布图如下:

plt.figure(figsize=(10,5))
names=['琴酒','伏特加','贝姐']
colors=['#090707','#004e66','#EC7357']
alphas=[0.8,0.7,0.6]
for name,color,alpha in zip(names,colors,alphas):
    plt.plot(df.index,df[name],label=name,color=color,alpha=alpha)
plt.legend(loc='best',frameon=False)
plt.annotate('集数:{},讨论次数:{}'.
             format(df['贝姐'].idxmax(),int(df['贝姐'].max())), 
             xy=(df['贝姐'].idxmax(),df['贝姐'].max()),
             xytext=(df['贝姐'].idxmax()+30,df['贝姐'].max()),
             arrowprops=dict(color='red',headwidth=8,headlength=8)
            )
plt.xlabel('集数')
plt.ylabel('讨论次数')
plt.title('酒厂成员讨论次数分布图')
plt.hlines(xmin=df.index.min(),xmax=df.index.max(),y=200,linestyles='--',colors='red')
plt.ylim(0,400)
 
#输出主线剧集
mainline=set(list(df[df['贝姐']>=200].index)+list(df[df['琴酒']>=200].index))  #伏特加可忽略不计
print(mainline) 
复制代码

从上图分析可知,组织成员的行动基本一致,其中贝姐(贝尔摩德)的人气在三人中是较高的,特别是在375集(与黑暗组织直面对决系列),讨论次数高达379。此外,统计其讨论次数大于200次的集数,结果如下:

以讨论次数最高的375集为内容,绘制词云图(剔除了高频词"贝姐",防止遗漏其他信息)如下

从图中可知,天使、琴酒、干妈、心疼、狙击手等词汇出现频率较高。从词频较低的败北主线中可以看出,这次酒厂行动应该是失败告终。

三、人物形象网络分析

I.合并txt文件

为尽可能反映出弹幕观众对人物形象的描述,考虑到一集弹幕共3000条,为减少运行成本,这里仅选取特定人物讨论次数最多的20集合并后再进行分析。

import os
import pandas as pd
df=pd.read_csv('role_count.csv',encoding='gbk')
df=df.fillna(0).set_index('episode')
huiyuan_ep=list(df.sort_values(by='灰原哀',ascending=False).index[:20])
mergefiledir = 'C:/Users/dell/Desktop/柯南'
file=open('txt_all.txt','w',encoding='UTF-8')   
count=0
for filename in huiyuan_ep:
    filepath=mergefiledir+'/'+str(filename)+'.txt'
    for line in open(filepath,encoding='UTF-8'):
        file.writelines(line)
    file.write('\n')
    count+=1
    print('第{}集写入完毕'.format(count))
file.close()
复制代码

II.人物形象可视化

借助共现矩阵的思想,即同一句话中出现两个指定的词则计数1。指定起始点Source为灰原哀,代码如下所示:(注:其中,stopwods.txt为停止词文件,role.txt为人物昵称文件)

import codecs
import csv
import jieba
linesName=[]
names={}
relationship={}
jieba.load_userdict('role.txt')
txt=[ line.strip() for line in open('stopwords.txt','r',encoding='utf-8')]
name_list=[ i.replace('\n','') for i in open('role.txt','r',encoding='utf-8').readlines()]
 
def base(path):
    with codecs.open(path,'r','UTF-8') as f:
        for line in f.readlines():
            line=line.replace('\r\n','')
            poss = jieba.cut(line)
            linesName.append([])
            for word in poss:  
                if word in txt:
                    continue
                linesName[-1].append(word)
                if names.get(word) is None:
                    names[word]=0
                    relationship[word]={}
                names[word]+=1
    return linesName,relationship
 
def relationships(linesName,relationship,name_list):          
    for line in linesName:
        for name1 in line:
            if name1 in name_list:
                for name2 in line:
                    if name1==name2:
                        continue
                    if relationship[name1].get(name2) is None:
                        relationship[name1][name2]=1
                    else:
                        relationship[name1][name2]+=1
    return relationship
 
def write_csv(relationship):
    csv_writer2=open('edges.csv','w',encoding='gb18030')
    writer=csv.writer(csv_writer2,delimiter=',',lineterminator='\n')
    writer.writerow(['Source','Target','Weight'])
    for name,edges in relationship.items():
        for k,v in edges.items():
            if v>10:
                writer.writerow([name,k,v])
    csv_writer2.close()    
 
if __name__=='__main__':
    linesName,relationship=base('txt_all.txt')
    data=relationships(linesName,relationship,name_list)
    write_csv(data) 
复制代码

将生成的文件导入Gephi,得到如下人物形象图

线条越粗的线,代表该人物特征越明显。不难看出,大家对于哀酱的评价主要是美腻、可爱、心疼。

END:

好了此上就是PYTHON实战的全部内容啦喜欢的小可爱们记得给小编三连呦🤞😘

以后会每日上线更新的家人们的支持是本🍒最大的动力!!

还有有关PYTHON的源码分享可私信wo~~

分类:
代码人生
标签: