知识图谱系统研发

2019-10-21 09:15袁若瀛
现代信息科技 2019年5期
关键词:网络爬虫知识图谱

摘  要:本工程要实现一个关于“动物”的知识图谱系统,用来描述“动物”的各种实体和概念,以及它们之间的强关系,我们用SPO三元组(Subject-Predicate-Object)去描述两个实体间的关联,简单理解就是“实体-实体关系-实体”,例如,猫和猫科动物之间的关系是科,用“猫-科-猫科”来表示,把实体看作结点,实体关系看作一条边,那么就可以构建一个庞大的关于“动物”的知识图。构建“动物”知识图谱需要动物的实体和实体间关系,这些数据需要通过网络爬虫技术从网上获取,但网上获取的数据是文本形式,不能直接使用,所以需要用到知识抽取技术,本文使用基于句法依存关系的方法,实现了提取文本中的实体及实体间关系,然后以三元组的形式将这种关系表现出来,最后将生成的SPO三元组存入Neo4j图数据库,形成一个“动物”知识图谱。

关键词:知识图谱;网络爬虫;知识抽取;SPO三元组;NEO4J图数据库

中图分类号:TP391.1      文献标识码:A 文章编号:2096-4706(2019)05-0013-05

Abstract:This project is to implement a knowledge atlas system about “animals” to describe the various entities and concepts of “animals” and the strong relationship between them. We use SPO triple (Subject-Predicate-Object) to describe the relationship between two entities. The simple understanding is that the relationship between (entity-entity relationship-entity) such as cats and catamount is science. We use “cat-family-cat family” to express it. We regard entities as nodes and entity relations as one side. Then we can construct a huge knowledge map about animals. Constructing the knowledge map of “animal” requires the relationship between animal entities and entities,and these data need to be obtained from the internet through web crawler technology,but the data obtained on the internet is in the form of text. It can't be used directly,so we need to use knowledge extraction technology. This paper uses the method based on the syntactic dependency relation to extract the relationship between entities in the text,and then express the relationship in the form of triples. Finally,the generated SPO triples need to be stored in Neo4j graph database to form an “animal” knowledge map.

Keywords:knowledge map;web crawler;knowledge extraction;SPO triple;NEO4J graph database

1  針对复杂工程问题的方案设计与实现

1.1  “动物”知识图谱的方案设计

问题分析:关于“动物”的知识图谱系统,知识图谱的主要作用是描述“动物”的各种实体和概念及实体间关系,我们必须使用一种数据结构来描述这种联系,于是我们采用SPO三元组(Subject-Predicate-Object)去描述两个实体间的关联,简单理解就是“实体-实体关系-实体”,例如,猫和猫科动物之间的关系是科,我们就用“猫-科-猫科”来表示,把实体看作结点,实体关系看作一条边,那么就可以构建一个庞大的关于“动物”的知识图谱。

设计思路:构建“动物”知识图谱需要动物的实体和实体间关系,而这些数据需要通过网络爬虫技术从网上获取,但网上获取的数据是非结构化数据的形式(如文本),不能直接使用,所以需要用到知识抽取技术。本文使用基于句法依存关系的方法实现了提取文本中的实体及实体间关系,然后以三元组的形式将这种关系表现出来,最后将生成的SPO三元组存入图数据库,形成一个“动物”知识图谱。

在系统总体设计中,将本工程划分为四个基本模块,以实现知识图谱系统。

首先在第一个模块中,需要完成网络爬虫进行数据获取工作,设计一个多源数据获取系统。该模块被分为两个子模块,分别从百度百科和互动百科中获取动物分类中的词条信息,对该词条信息进行基本的文本处理,然后存入txt文件中。其中,词条信息包含半结构化的基本信息和非结构化的简介信息。

第二个模块是基于句法依存关系的关系抽取模块,主要功能是对多源数据获取模块输出的文本通过关系抽取,提取词语和依存关系等显性特征,然后根据这些显性特征,通过知识推理,得到隐性特征。由于此模块功能复杂且内聚性低,所以应分为显性特征提取模块和隐形特征提取模块,显性特征提取模块的输出作为隐形特征提取模块的输入。这个过程用到了pyltp库基于依存句法的关系三元组抽取。

第三个模块是生成三元组模块,这一阶段的任务是将特征提取模块得到的实体属性和实体间的关系形成SPO三元组。

最后的模块是存入数据库模块,即将生成的三元组存入Neo4j图形数据库。选择Neo4j图形数据库是因为需要一个图形数据库。

1.2  针对“动物”知识图谱问题的推理分析

知识抽取(实体关系抽取)是知识图谱构建的核心环节,实体关系抽取作为一项基本技术,在自然语言处理应用中发挥着重要作用,也是本项目的关键步骤之一。关系抽取的方法非常多,有基于规则的方法和基于学习的方法等,由于基于学习的方法涉及到深度学习模型等非常复杂的算法,所以我们选择了基于规则的方法。基于规则的方法中有诸如基于触发词的特征,但由于这种方法是基于模板的关系抽取方法,因此只适合小规模应用,而且模板的构建需要专业知识,并花费大量的时间,考虑到本工程要做整个“动物”的知识图谱,数据量非常大,所以不适合本工程。综合本工程的实际需求和实际情况,我们的初步设想是使用基于句法解析的关系抽取方法,虽然也是基于模板,但是因为本工程的文本信息全部出自百科动物类的基本词条,所以模板的构建是切合实际的。

1.3  针对“动物”知识图谱问题的方案实现

开发环境为Win10(x64)操作系统下python3.6.4,用到的工具库有Beautiful Soup4(一个HTML/XML的解析器)、pyltp(中文自然语言处理)和Neo4j(图数据库)。

1.3.1  网络爬虫

网络爬虫实现了从互动百科、百度百科上爬取与“动物”相关的词条信息,而爬虫问题的关键在于如何只爬取与“动物”相关的网页,我们采用的思路是先爬取“动物”分类下的一部分动物名字、类名、界名等词语,作为爬虫初始的url的关键字,然后在这些页面中找出该页面中所有的百科url。

links = soup.find_all('a', href=re.compile(r"/  item/"))#搜索所有满足条件的url

这里需要用到Beautiful Soup4工具对网页进行解析,具体过程是先通过调用Beautiful Soup4的库函数Beautiful Soup将用utf-8编码的网页进行解析,处理成格式化后的字符串,然后调用find和find_all找到我们需要的标签,可是词条是带有注释的,而我们不需要注释,所以要用正则表达式删除注释。

re_comment = re.compile('\[[0-9]+\]')#去掉的形式为中括号里面带数字的结构

attributes_value = re_comment.sub('', attributes_value)

提取出来的信息包括基本词条信息和简介信息,基本词条信息已经是结构化数据,即是现成的SPO三元组,如“猫{'科:'猫科}”,而简介信息还是文本的形式,需要在接下来用关系抽取,从文本中抽取关系三元组。

1.3.2  关系抽取

关系抽取采用依存句法分析,其基本原理为:

(1)一个句子中,必须只有一个独立成分,且该成分不依存于其他成分;

(2)在一个句子中,其他成分必须依存与某一成分;

(3)在一个句子中,无论对于任何成分而言,其依存的成分最高数量为1,不能超过这一数量,简单地说,句子中的任意成分,其所依存的成分量不能大于等于2;

(4)假设句子中存在三个成分,分别为1、2和3,在三个成分当中,如果1直接依赖于2,而3在1与2中间,那么3既可以依存于1,又可以依存于2,但需要认識到的是,一定要坚持第三点公理,3必须单独依赖于1或2。除此之外,成分3也可以既不依赖于1,也不依赖于2,而是依赖于两者之间的某一成分N。

简单来讲,就是通过分析语言单位内成分之间的依存关系揭示其句法结构。依存句法分析识别句子中的“主谓宾”、“定状补”这些语法成分,并分析各成分之间的关系。依存句法分析本质上可以转换为分类问题,所以将依存句法作为序列标注任务进行解决也是可行的。

具体算法实现如下:

首先,我们导入了第三方分词库pyltp用于中文分词处理和词性(名词、动词等等)的分析,首先调用pyltp的库函数进行句子的成分分析,得到句子的分词结果,每个词的词性和每两个词之间的关系,例如,输入的数据是“猫,属于猫科动物,分家猫、野猫,是全世界家庭中较为广泛的宠物。家猫的祖先据推测是起源于古埃及的沙漠猫,波斯的波斯猫,已经被人类驯化了3500年(但未像狗一样完全地被驯化)。”这是百度百科猫的简介,也是需要进行关系抽取的对象之一。

tags = soup.find('dd', {'id': 'open-tag-item'})

#调用pyltp库得到分词结果

words = list(self.segmentor.segment(sentence))

#得到每个词的词性

postags = list(self.postagger.postag(words))

#得到词语之间的依存关系

arcs = self.parser.parse(words, postags)

#对arcs进行规范化,将其容易读一点,并存入字典,方便使用

child_dict_list, format_parse_list = self.build_parse_child_dict(words, postags, arcs)

得到的标注关系很长,在此不一一罗列,这是其中的两个例子:

['SBV', '猫', 0, 'n', '属于', 2, 'v']

['ATT', '猫科', 3, 'n', '动物', 4, 'n']

第一个,SBV是指主谓关系,“猫”是主语,0是“猫”的索引值,因为“猫”是句子的第一个词,n是“猫”的词性,为名词。因为“猫”和“属于”间有个逗号,所以“属于”的索引值为2,然后“属于”是动词。

第二个同理,ATT是指定中关系。

标注的关系有很多种,以下是12种依存句法分析标注关系,如表1所示。

由于关系抽取想要获得的关系是用于进行知识图谱的构建,SPO三元组中比较好处理的一种类型就是主谓宾的形式,所以利用语义关系标注,获取所有的主谓宾三元组。

if 'SBV' in child_dict and 'VOB' in child_dict:

r = words[index]

e1 = self.complete_e(words, postags, child_dict_list, child_dict['SBV'][0])

e2 = self.complete_e(words, postags, child_dict_list, child_dict['VOB'][0])

svos.append([e1, r, e2])

提取得到三元组后,这个三元组的主语和宾语其实是不完整的,缺少对主语和宾语的修饰语,所以还需要对三元组中的主语和宾语进行扩展。我们用主语和宾语相关的定中关系,即加上名词的修饰语。

if 'ATT' in child_dict:

for i in range(len(child_dict['ATT'])):

prefix += self.complete_e(words, postags, child_dict_list, child_dict['ATT'][i])

postfix = ''

if postags[word_index] == 'v':

if 'VOB' in child_dict:

postfix += self.complete_e(words, postags, child_dict_list, child_dict['VOB'][0])

if 'SBV' in child_dict:

prefix = self.complete_e(words, postags, child_dict_list, child_dict['SBV'][0]) + prefix

现在可以抽取得到刚才那段话中的三元组了:

['猫', '属于', '猫科动物'], ['猫', '是', '全世界家庭中较为广泛宠物'], ['家猫祖先', '是', '起源']

可以看到,前两个三元组非常合理,证明句法依存确实能提取出有价值的三元组,但是,同时也出现了一些问题,第三个三元组缺少了“起源”修饰语。这也是本系统需要改进的地方。

1.3.4  生成知识图谱

这一模块的功能是将所有的三元组导入Neo4j图形数据库,利用图形数据库生成知识图谱。这个过程包含知识库的融合,需要将来自于不同数据源(百度百科、互动百科)、以不同方法(从半结构化数据中直接提取、基于句法依存关系的知识抽取)提取的三元组存储到同一个数据库中。在知识融合的过程中,需要去除冲突项、冗余项。

(1)Neo4j數据库简介。Neo4j数据库是一种NOSQL图形数据库,与传统关系数据库相比,它将结构化数据存储在网络(图)中,而不是表中。网络或者图是一种灵活的数据结构,它具有有灵活、敏捷的特点。

网络由节点、边、属性构成。每一个节点代表一个实体;实体之间通过边进行连接,边代表实体之间的关系;无论是顶点或者边都可以有任意多的属性,以key:balue的形式进行存储。

(2)py2ne模块。py2ne模块是一个面向Neo4j数据库管理的python库。py2ne封装了大量的Neo4j的数据库操作,包括连接Neo4j数据库、创建节点、创建关系、通过节点/关系进行查询等。

(3)导入三元组。这一步骤分两步进行,首先将从半结构化的数据中提取的三元组导入数据库,然后在此基础上导入从文本中经过知识抽取得到的三元组,这个过程包括去除冗余项和冲突项。

导入三元组具体的操作步骤如下所示:

1)首先调用py2neo的Graph()方法,通过参数输入账号、密码,连接数据库;

2)调用Node()方法创建节点,创建节点时根据实体进行查询,若图中已经有该实体对应的节点,不再创建节点,反之,则创建节点,调用create()方法将节点存入数据库;

3)调用Relationship()方法创建关系,调用create()方法将关系存入数据库。

(4)Neo4j的Web控制台。打开Neo4j数据库的Web控制台,在这里可以对数据库进行增删查改等基本操作,而这些操作通过Neo4j自带的Cypher语言实现。

当三元组完全且正确地导入数据库后,我们的知识图谱基本上已经构建完成,但是需要以Graph的形式显示出来。在Web控制台页面的左侧,我们可以点击Entity,进而查看一部分知识图谱,点击其中任一个节点,选择展开Expand child relationships就可以得到更多的节点和关系,这样一步步展开,可以显示完整的知识图谱,但这种方式无疑是很笨拙。如果要查看完整的知识图谱,只需要修改查询语句,设置Limit节点数足够大,就可以显示出完整的知识图谱。需要注意的是,数据库将最多显示节点数初始值设置为300个,我们在使用时要将其值修改为一个足够大的数,不然无论怎么修改查询语句,也最多只能显示300个节点。

为了更好地查看完整的知识图谱,可以将其保存为svg图片格式,再通过svg图片查看器(例如Inkscape)进行查看。

2  系统测试

测试环境为Win10(x64)操作系统下python3.6.4,用到的工具库有Beautiful Soup4(一个HTML/XML的解析器)、pyltp(中文自然语言处理)和Neo4j(图数据库)。

2.1  关系抽取测试

将百度百科简介信息进行依句法依存关系完成关系抽取的结果。

处理前:

金眼鲷目(Beryciformes)是硬骨鱼纲辐鳍鱼亚纲的1目。化石始于白垩纪。现有3亚目14科约38属164种。

角鲨目(Squaliformes),软骨鱼纲板鳃亚纲的一目。有3科21属87种。背鳍2个,硬棘有或无;臀鳍消失。鳃孔5个,椎体环型或多环型。吻软骨1个。主要分布于世界各温水、冷水海区或深海。

鸟臀目(拉丁目名Ornithischia或Predentata)也称为鸟盘目。是一类有喙(外观类似鸟喙)的草食性恐龙。意思是“如鸟类般的臀部”。之所以有这种名字,是因为它们拥有与鸟类相似的骨盆结构。

海鲂目(Zeiformes)是硬骨鱼纲的1目。约有6科21属36种,均为海产。体侧极扁且高;上颌显著突出,无辅上颌骨;鳞细小或仅有痕迹;背、臀鳍基部及胸腹部有棘状骨板;后颞骨不分叉,与头盖骨连接;第一脊椎骨与头盖骨密切连接;背鳍鳍棘部发达,与鳍条部区分显明;背鳍有5~10鳍条,棘间膜延长呈丝状;臀鳍有1~4鳍棘;背、臀鳍及胸鳍条均不分枝;腹鳍胸位,通常有1鳍棘5~9鳍条;无目匡蝶骨;鳔无管,有或无牙。

燕鸟目是今鸟亚纲的一目,仅有1科1属,即燕鸟科燕鸟。

处理后:

[['金眼鲷目', '是', '硬骨鱼纲辐鳍鱼亚纲1目'], ['化石', '始', '白垩纪'], ['现有', '属', '164种']]

[['3科', '属', '87']]

[['鸟臀目', '称为', '鸟盘目'], ['意思', '是', '鸟类臀部'], ['它们', '拥有', '与鸟类相似骨盆结构']]

[['海鲂目', '是', '硬骨鱼纲1目'], ['6科', '属', '36'], ['鳞', '有', '痕迹'], ['背臀鳍基部及胸腹部', '有', '棘状骨板'], ['与鳍条部', '区分', '鳍棘部'], ['背鳍', '有', '510鳍条'], ['棘间膜', '延长', '呈丝状'], ['臀鳍', '有', '14鳍棘'], ['背', '分', '枝'], ['腹鳍胸位', '有', '1鳍棘5条'], ['鳔', '无', '管'], ['鳔', '有', '牙'], ['鳔', '无', '牙']]

[['燕鸟目', '是', '今鸟亚纲一目'], ['燕鸟目', '有', '1科1属']]

可以看出,“燕鸟目是今鸟亚纲一目”被分为了[['燕鸟目', '是', '今鸟亚纲一目']],成功提取了实体间关系并生成三元组,但是由于是通过句法依存分析得到的,所以会有很多不合理的三元组。

2.2  Neo4j圖数据库测试

总体效果:共生成接近6000个结点,10000多个联系。

“动物”知识图谱总体效果如图1所示,结点之间的联系非常多,且大部分结点都有相互关联的结点,证明知识图谱构建比较成功,但由于整体效果无法判断知识图谱是否准确,所以选择了一小部分结点,测试效果如图2所示。

可以看到,SPO三元组以图的形式呈现出来(因为只取了一小部分结点和联系,所以图上很多结点没有相互关联,其实很多是有关联的)。可以清楚地找到一个动物和与之相关的实体和实体间联系。

参考文献:

[1] 王延领.python 3.x 爬虫基础——Requersts,Beautiful-Soup4(bs4) [EB/OL].http://www.cnblogs.com/kmonkeywyl/ p/8482962.html,2018-04-03.

[2] Pelhans.知识图谱入门(三)知识抽取 [EB/OL].https: //blog.csdn.net/pelhans/article/details/80020309,2018-04-20.

[3] MihaiWang.Python操作Neo4j的基本操作 [EB/OL].https://blog.csdn.net/wmh13262227870/article/details/77842 513,2017-09-04.

作者简介:袁若瀛(1998.06-),男,汉族,山东菏泽人人,本科,主要研究方向:大数据、机器学习。

猜你喜欢
网络爬虫知识图谱
炼铁厂铁量网页数据获取系统的设计与实现
国内图书馆嵌入式服务研究主题分析
国内外政府信息公开研究的脉络、流派与趋势
基于知识图谱的产业集群创新绩效可视化分析
基于知识图谱的产业集群创新绩效可视化分析
基于知识图谱的智慧教育研究热点与趋势分析
从《ET&S》与《电化教育研究》对比分析中管窥教育技术发展
基于社会网络分析的权威网页挖掘研究
主题搜索引擎中网络爬虫的实现研究
浅析如何应对网络爬虫流量