首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Python 自然语言处理,文本挖掘红楼梦中人物关系图

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()

最后得到以下人物关系图:

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180101G07GAB00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券