https://zhuanlan.zhihu.com/p/24767513//参考链接
这篇文章主要是参考知乎上的 基于人物关系的Python实现,它主要用到是Gephi 去对提取的文本进行实现。其实Python本身自带networks包
最基础的就是获得完整全面的情感词,但是不同领域的情感词是不同的,需要针对特定的领域进行针对性的建立词典。而这就需要用到共现理论,但之前苦于不懂如何实现。但是看到了这个知乎上的文本词提取,试着follow了一下,发现真的很好用。
这个小实验主要分成俩个部分,
第一部分:对红楼梦的文本进行提取人名,然后按照出现的人物次数来分析人物关系的远近,和红楼梦中主要出场的人物有哪些。
第二部分:对提取后的文本进行networks网络图建立:
主要的Python代码如下(至于红楼梦文本大家可以在网上随意下到):
importjieba
importcodecs
importjieba.possegaspseg
names = {}# 姓名字典
relationships = {}# 关系字典
lineNames = []# 每段内人物关系
# count names
jieba.load_userdict("C:\\Users\\look_smile\\Desktop\\复杂网络\\红楼梦\\dict.txt")# 加载字典
withcodecs.open("C:\\Users\\look_smile\\Desktop\\复杂网络\\红楼梦\\hlm1.txt","r","utf-8")asf:
forlineinf.readlines():
poss = pseg.cut(line)# 分词并返回该词词性
lineNames.append([])# 为新读入的一段添加人物名称列表
forwinposs:
ifw.flag !="nr"orlen(w.word)
continue# 当分词长度小于2或该词词性不为nr时认为该词不为人名
lineNames[-1].append(w.word)# 为当前段的环境增加一个人物
ifnames.get(w.word)is None:
names[w.word] =
relationships[w.word] = {}
names[w.word] +=1# 该人物出现次数加 1
# explore relationships
forlineinlineNames:# 对于每一段
forname1inline:
ifname1 =="明白"orname1 =="薛家"orname1 =="言语"orname1 =="从小儿"orname1 =="那玉":
continue
ifname1 =="冷笑"orname1 =="和尚":
continue
ifname1 =="向黛玉"orname1 =="林妹妹"orname1 =="林姑娘"orname1 =="那黛玉":
name1 ="黛玉"
ifname1 =="凤姐姐"orname1 =="凤丫头"orname1 =="凤姐儿":
name1 ="凤姐"
ifname1 =="贾母笑"orname1 =="贾母王"orname1 =="老太太"orname1 =="贾母问"orname1 =="贾母房"orname1 =="老祖宗"orname1 =="贾母忙":
name1 ="贾母"
ifname1 =="宝丫头"orname1 =="小丫头"orname1 =="宝钗笑":
name1 ="宝钗"
ifname1 =="宝兄弟"orname1 =="宝二爷":
name1 ="宝玉"
ifname1 =="周瑞家":
name1 ="周瑞"
ifname1 =="贾政道"orname1 =="贾政听"orname1 =="贾政道"orname1 =="贾政叹":
name1 ="贾政"
ifname1 =="大老爷":
name1 ="贾赦"
forname2inline:# 每段中的任意两个人
ifname2 =="明白"orname2 =="薛家"orname2 =="言语"orname2 =="从小儿"orname2 =="那玉"orname2 =="那婆子":
continue
ifname2 =="冷笑"orname2 =="和尚":
continue
ifname2 =="向黛玉"orname2 =="林妹妹"orname2 =="林姑娘"orname2 =="那黛玉":
name2 ="黛玉"
ifname2 =="凤姐姐"orname2 =="凤丫头"orname2 =="凤姐儿":
name2 ="凤姐"
ifname2 =="贾母笑"orname2 =="贾母王"orname2 =="老太太"orname2 =="贾母问"orname2 =="贾母房"orname2 =="老祖宗"orname2 =="贾母忙":
name2 ="贾母"
ifname2 =="宝丫头"orname2 =="小丫头"orname2 =="宝钗笑"orname2 =="宝钗忙":
name2 ="宝钗"
ifname2 =="宝兄弟"orname2 =="宝二爷"orname2 =="向宝玉"orname2 =="问宝玉":
name2 ="宝玉"
ifname2 =="周瑞家":
name2 ="周瑞"
ifname2 =="贾政道"orname2 =="贾政听"orname2 =="贾政道"orname2 =="贾政叹":
name2 ="贾政"
ifname2 =="大老爷":
name2 ="贾赦"
ifname1 == name2:
continue
ifrelationships[name1].get(name2)is None:# 若两人尚未同时出现则新建项
relationships[name1][name2]=1
else:
relationships[name1][name2] = relationships[name1][name2]+1# 两人共同出现次数加 1
# output
withcodecs.open("C:\\Users\\look_smile\\Desktop\\复杂网络\\红楼梦\\hlm_edge.txt","a+","utf-8")asf:
f.write("Source Target Weight\r\n")
forname,edgesinrelationships.items():
forv,winedges.items():
ifw >100:
f.write(name +" "+ v +" "+str(w) +"\r\n")
由于我找到的红楼梦是一个文言文版本,所以对一些词的识别还不够先进,比如“贾政叹”和“贾政”和“贾政笑”没有办法识别为同一个人,这里需要人为的进行重新设定。
最后得到的人物关系节点如下:
2.得到关系节点图之后我们用networks实现:
importnetworkxasnx
importmatplotlib.pyplotasplt
frompylabimport*
mpl.rcParams['font.sans-serif'] = ['SimHei']
a = []
f =open('C:\\Users\\look_smile\\Desktop\\复杂网络\\红楼梦\\hlm_edge.txt','r',encoding='utf-8')
defmkx(content):
content_new = content.split()
b =float(content_new[-1])
x = content_new[:-1]
x.append(b)
returnx
lines = f.readlines()
i =
j =
content = []
forlineinlines:
ifi
i = i +1
continue
try:
content.append(mkx(line))
j = j +1
exceptValueErrorasv:
print(v)
print(j)
j = j +1
f.close()
G = nx.Graph()
G.add_weighted_edges_from(content)
nx.draw(G,with_labels=True,font_size=8,node_size=500,node_color='r')
plt.show()
最后得到以下人物关系图:
领取专属 10元无门槛券
私享最新 技术干货