使用Python自动生成事件分析图谱
内容编辑:想读博的针针 中山大学图书情报学硕士,python爱好者
如何将输入的文档转变为只含有关键信息的图谱?
本文来自https://github.com/liuhuanyong/TextGrapher
在运行程序前,请确保已安装pyltp,详细的pyltp安装教材请参考:https://github.com/HIT-SCIR/pyltp
项目介绍
如何用图谱和结构化的方式,即以简洁的方式对输入的文本内容进行最佳的语义表示是个难题。Text Grapher对这一问题进行了尝试,采用的方法为:输入一篇文档,将文档进行关键信息提取,并进行结构化,并最终组织成图谱组织形式,形成对文章语义信息的图谱化展示。
使用方法
在项目文件下下新建一个python文件,输入以下代码:
from text_grapher import *
content = '你要分析的文本'
handler = CrimeMining()
handler.main(content)
运行该文件,生成的图谱内容保存在项目文件夹graph.html的文件中。
以中科院研究所遇害案为例:
新建text.py文件,输入以下代码:
# -*- coding: utf-8 -*-
from text_grapher import *
content = '''
(原标题:中科院研究生遇害案:凶手系同乡学霸,老师同学已为死者发起捐款)
6月14日下午6点多,中科院信息工程研究所硕士研究生谢雕在饭馆招待自重庆远道而来的高中同学周凯旋时,被周凯旋用匕首杀害。随后,周凯旋被北京警方抓获。
周凯旋被抓后,他的家人向被警方递交了精神鉴定材料,称周凯旋患有精神性疾病。
谢雕的家人罗发明告诉南都记者,谢雕被害后,他的研究生老师和同学发起了捐款。并说,谢雕的遗体已经进行尸检,等尸检结果出来后,家人将会把火化后的骨灰带回老家安葬,之后,他们将等待北京检察机关的公诉。
高中同学千里赴京去杀人
今年25岁的谢雕生长于重庆垫江县的一个小山村,谢雕和周凯旋同在垫江中学读高中,两人学习成绩名列前茅,周凯旋经常考年级第一,两人都是垫江中学的优秀毕业生,谢雕考上了西安电子科技大学,周凯旋考取了四川大学。
微信图片_20180627174901_副本.jpg案发现场的行凶者周凯旋(受访者提供)。
学习优秀的周凯旋认为自己应该能考上北大清华等名校,于是在入读四川大学两三个月后,选择了退学复读。经过半年多的苦读,周凯旋以优异成绩考取了西安交通大学,来到了谢雕所在的城市,且是硕博连读。
但周凯旋因大学本科期间因沉迷游戏,考试不及格,最终失掉了硕博连读的机会,本科毕业后就回到重庆寻找就业机会。谢雕自西安电子科技大学毕业后,在2016年考取了中国科学院大学的硕士研究生,所读专业隶属于中科院信息工程研究所。
谢雕的家人告诉南都记者,6月14日下午6点,谢雕在西五环外的中科院信息工程研究所门口见到了久未见面的高中同学周凯旋。把他带到旁边的饭馆吃饭,两人还合影发到了高中同学微信群。这时,谢雕还没意识到周凯旋即将对他带来致命伤害。
南都记者在谢雕遇害现场视频中看到,在谢雕点菜时,周凯旋用匕首刺向他胸部,谢雕中刀站起后退时,周凯旋用匕首又刺向他颈部,谢雕倒地后,周凯旋又从背部向他连刺几刀。之后,又持刀割断了谢雕的颈部动脉。这时,有食客拿起椅子砸向正在行凶的周凯旋。刺死谢雕后,周凯旋举起双手挥舞,随后扬长而去。后来,周凯旋被北京警方抓获。
同学聚会时自己觉得受伤害起杀心
罗发明告诉南都记者,作为被害人家属,他们向北京警方了解到,凶案原因来自两年前的一场同学聚会,谢雕的一些话对周凯旋带来很大心理压力,让他不能释怀。
两年前的一次高中同学聚会中,大家聊的话题很多,也聊到了周凯旋喜欢打游戏的事情,谢雕说了一些激励周凯旋的话,让他不要再打游戏,要振作起来。在参与聚会的同学们看来,这些话是常理之中的,但在周凯旋看来,对他带来很大伤害,两年来给他带来很大心理压力。
参与那次聚会的同学后来回忆,在一起玩“狼人杀”游戏时,谢雕、周凯旋发生了争执,但不愉快的瞬间很快就过去了,大家也都没当回事。
那次聚会之后的春节,不少同学发现被周凯旋拉黑,中断了联系。直至一年之后,周凯旋才加入了高中同学微信群。
谢雕的家人说,周凯旋在网上购买了杀人凶器匕首,收货地址填写了北京,他在北京拿到网购的匕首后,才暗藏在身前来面见谢雕。
师生捐款助他家人渡难关
周凯旋被北京警方抓获后,他的家人向警方称周凯旋患有精神病,并提供了一些证明材料,希望得到从轻处置。
谢雕遇害后,他的学校为失去这么优秀的学生感到惋惜。谢雕的老师说,“谢雕家境并不富裕,本科尚有2.5万助学贷款未偿还,前不久还向同学借款1万,父亲也患有鼻咽癌。”
谢雕的老师和同学发起了捐款,希望能帮助谢雕的家人暂时渡过难关。
谢雕的家人告诉南都记者,他们向谢雕的学校提出要求,希望案件能尽快解决。
罗发明对南都记者说,谢雕的遗体已经进行尸检,尸检后十天至十五天出来结果,等拿到尸检报告后,他们会尽快火化谢雕的遗体,把他的骨灰带回重庆老家安葬。
对于这一案件,谢雕的家人告诉南都记者,他们将等待北京的检察机关提起公诉。
'''
handler = CrimeMining()
handler.main(content)
运行text.py,得到自动生成的graph.html文件。
分析
本项目采用了高频词,关键词,命名实体识别,主谓宾短语识别等抽取方式,并尝试将三类信息进行图谱组织表示,这种表示方式是一种尝试。
主要的信息处理分为以下几个步骤:
1)对文章进行处理,处理内容包括去噪、长句切分、短句切分
'''移除括号内的信息,去除噪声'''
def remove_noisy(self, content):
p1 = re.compile(r'([^)]*)')
p2 = re.compile(r'\([^\)]*\)')
return p2.sub('', p1.sub('', content))
'''对文章进行分句处理'''
def seg_content(self, content):
return [sentence for sentence in re.split(r'[??!!。;;::\n\r]', content) if sentence]
'''利用标点符号,将文章进行短句切分处理'''
def seg_short_content(self, content):
return [sentence for sentence in re.split(r'[,,??!!。;;::\n\r\t ]', content) if sentence]
2)对句子进行分词,词性标注处理,并收集其中的命名实体;
'''对句子进行分词,词性标注处理'''
def process_sent(self, sent):
words, postags = self.parser.basic_process(sent)
return words, postags
'''收集命名实体'''
def collect_ners(self, words, postags):
ners = []
for index, pos in enumerate(postags):
if pos in self.ners:
ners.append(words[index] + '/' + pos)
return ners
3)获取文章关键词;
'''对文章进行关键词挖掘'''
def extract_keywords(self, words_list):
return self.textranker.extract_keywords(words_list, 10)
4)构建事件三元组;
'''抽取出事件三元组'''
def extract_triples(self, words, postags):
svo = []
tuples, child_dict_list = self.parser.parser_main(words, postags)
for tuple in tuples:
rel = tuple[-1]
if rel in ['SBV']:
sub_wd = tuple[1]
verb_wd = tuple[3]
obj = self.complete_VOB(verb_wd, child_dict_list)
subj = sub_wd
verb = verb_wd
if not obj:
svo.append([subj, verb])
else:
svo.append([subj, verb+obj])
return svo
5)过滤出与命名实体相关的事件三元组;
def filter_triples(self, triples, ners):
ner_triples = []
for ner in ners:
for triple in triples:
if ner in triple:
ner_triples.append(triple)
return ner_triples
6)基于文章关键词,建立起实体与关键词之间的关系;
'''基于文章关键词,建立起实体与关键词之间的关系'''
def rel_entity_keyword(self, ners, keyword, subsent):
events = []
rels = []
sents = []
ners = [i.split('/')[0] for i in set(ners)]
keyword = [i[0] for i in keyword]
for sent in subsent:
tmp = []
for wd in sent:
if wd in ners + keyword:
tmp.append(wd)
if len(tmp) > 1:
sents.append(tmp)
for ner in ners:
for sent in sents:
if ner in sent:
tmp = ['->'.join([ner, wd]) for wd in sent if wd in keyword and wd != ner and len(wd) > 1]
if tmp:
rels += tmp
for e in set(rels):
events.append([e.split('->')[0], e.split('->')[1]])
return events
7)对事件网络进行图谱化展示;
总结
1、该项目可以帮助快速理清事情的脉络,了解人物之间的各种关系;
2、可以应用在其他领域进行文本的语义信息图谱化展示。