专栏首页润风拂过存甘霖基于知识图谱的文本自动注释(python+html)

基于知识图谱的文本自动注释(python+html)

在探索知识图谱的过程中,发现它可以做一个有趣的应用——文本自动注释。在此整理并分享给大家。为了具体说明它的效果,让我们先来看一个例子:

世界杯期间,伪球迷小B为了融入大家的话题讨论,上网看了不少足球新闻。然而,眼前一堆陌生的人名和术语看的他眼花缭乱……

央视网消息:北京时间6月30日晚22点,2018年俄罗斯世界杯1/8决赛迎来一场强强对话,欧洲豪门法国队迎战南美劲旅阿根廷。上半场比赛姆巴佩制造点球,格列兹曼主罚命中,而且任意球还击中横梁,迪马利亚世界波扳平比分,半场战罢,法国暂时1-1平阿根廷。下半场梅尔卡多打进1球,帕瓦尔破门,姆巴佩梅开二度,阿圭罗补时破门,法国队最终4-3击败阿根廷,成为第一支打进8强的球队,未来将对阵乌拉圭和葡萄牙的胜者。

“世界波是什么?迪马利亚又是谁?要是有办法一边看新闻,一边也能够看到关于这些名词的解释就好了。”小B心想。

这个时候,就该让文本自动注释发挥作用了,下面是注释后的文本(鼠标放在超链接上可以看到简介,点击则会跳转到相应的百度百科页面):

央视网消息:北京时间6月30日晚22点,2018年俄罗斯世界杯1/8决赛迎来一场强强对话,欧洲豪门法国队迎战南美劲旅阿根廷。上半场比赛姆巴佩制造点球格列兹曼主罚命中,而且任意球还击中横梁,迪马利亚世界波扳平比分,半场战罢,法国暂时1-1平阿根廷。下半场梅尔卡多打进1球,帕瓦尔破门,姆巴佩梅开二度,阿圭罗补时破门,法国队最终4-3击败阿根廷,成为第一支打进8强的球队,未来将对阵乌拉圭葡萄牙的胜者。

下面就来讲讲其实现的基本原理,这里使用的是python3.6,与python2的区别在于这里使用urllib.request而不是urllib2。

# coding=utf-8
import urllib.request
import codecs
from time import sleep
import json
import os

我们需要使用CN-DBpedia的API,这是一个大型开放的中文知识图谱,具体见:

Bo Xu, Yong Xu, Jiaqing Liang, Chenhao Xie, Bin Liang, Wanyun Cui, and Yanghua Xiao. CN-DBpedia: A Never-Ending Chinese Knowledge Extraction System. In International Conference on Industrial, Engineering and Other Applications of Applied Intelligent Systems, pp. 428-438. Springer, Cham, 2017.

简介:http://kw.fudan.edu.cn/cndbpedia/intro/

API:http://kw.fudan.edu.cn/apis/intro/

entitylinking_api = u"http://shuyantech.com/api/entitylinking/cutsegment?q="
avpair_api = "http://shuyantech.com/api/cndbpedia/avpair?q="

为了能够在程序中正确调用API,我们还需要把python中的中文表示方法转换为域名中可以正确识别的字符,下面是个简单的处理函数。实际使用中可能还有更复杂的情形,可根据URL编码再改写。

zh2url = lambda x: str(x.encode("utf-8"))[2:-1].replace(u"\\x",u"%").replace(" ", "%20")
text0 = "世界杯"
print(text0.encode("utf-8"),zh2url(text0))
b'\xe4\xb8\x96\xe7\x95\x8c\xe6\x9d\xaf' %e4%b8%96%e7%95%8c%e6%9d%af

读取网页内容所需函数

def getPage(url):
    try:
        page = urllib.request.urlopen(url)
        html0 = page.read()
        sleep(2)
        return html0
    except:
        print("error at %s" % url)
        return ""

准备工作已经大功告成,现在来看看这些API的作用吧。

1.三元组API

三元组(或者说属性-值对,attribute value pair,avpair)的API帮助我们获得关于一个词条(实体)的各项属性及信息。

url0 = avpair_api+zh2url("任意球")
html0 = getPage(url0)
print(url0)
http://shuyantech.com/api/cndbpedia/avpair?q=%e4%bb%bb%e6%84%8f%e7%90%83
data = json.loads(html0)
print("status:{}".format(data["status"]))
for (attribute, value) in data["ret"]:
    print("{}:{}".format(attribute, value))
status:ok
用途:犯规后重新开始比赛
分类:直接任意球
分类:间接任意球
任意球大师:C罗
任意球大师:贝克汉姆
任意球大师:卡洛斯
任意球大师:梅西
CATEGORY_ZH:足球
CATEGORY_ZH:体育
DESC:任意球是一种在足球(或手球)比赛中发生犯规后重新开始比赛的方法。任意球分两种:直接任意球(踢球队员可将球直接射入犯规队球门得分)及间接任意球(踢球队员不得直接射门得分,球在进入球门前必须被其他队员踢或触及)。国际足联最新规则为,判罚任意球后会使用一种泡沫喷剂划定球的摆放位置,以及人墙的站位,发任意球时需要用手触球,然后再裁判哨响后踢球。
CATEGORY_ZH:体育项目
中文名:任意球
外文名:free kick
运动:足球
运动:手球
规定:在罚球区内

返回的数据是json格式,其中有两个基本的属性。

  • status:本次API访问状态,如果成功返回“ok”,如果失败返回“fail”【不过即使是ok,也可能因为找不到该实体而不返回任何其他属性】
  • ret: 返回attribute-value pair list, 每个pair也是一个list ([attribute, value])

ret下有一些基本所有实体都具有的属性,因为结构化而有着比较高的价值。

  • DESC:该词条的简介
  • CATEGORY_ZH:所属类别
  • 中文名、外文名:在实体链接(后面提到)中有时可用作别名

对于CN-DBpedia中没有收录的词语,ret对应的是一个空列表,比如细心的读者在一开始的例子中也许注意到了这次世界杯上闪耀的新星姆巴佩并没有被加上注释,这可能是因为截至本文写作时,CN-DBpedia还没有来得及包括这个年轻小将的资料。 参见:http://shuyantech.com/api/cndbpedia/avpair?q=姆巴佩

2.实体链接API

输入中文文本,输出分词后的文本,以及识别的实体,json格式。

返回字段

  • cuts: 文本分词的结果,格式为字符串的列表
  • entities:从文本中识别的实体,格式为一个列表,列表的每个元素是一个链接的实体,表示为一个长度为2的列表,列表第一个元素是实体在输入文本中出现的位置,第二个元素为实体在CN-DBpedia中的名字。>值为一个列表,列表的每个元素表示一个链接的实体,表示为一个长度为2的列表,列表第一个元素是实体在输入文本中出现的位置,第二个元素为实体在CN-DBpedia中的名字。
url0 = entitylinking_api+zh2url("北京时间6月30日晚22点,2018年俄罗斯世界杯1/8决赛迎来一场强强对话,欧洲豪门法国队迎战南美劲旅阿根廷。")
html0 = getPage(url0)
print(url0)
http://shuyantech.com/api/entitylinking/cutsegment?q=%e5%8c%97%e4%ba%ac%e6%97%b6%e9%97%b46%e6%9c%8830%e6%97%a5%e6%99%9a22%e7%82%b9%ef%bc%8c2018%e5%b9%b4%e4%bf%84%e7%bd%97%e6%96%af%e4%b8%96%e7%95%8c%e6%9d%af1/8%e5%86%b3%e8%b5%9b%e8%bf%8e%e6%9d%a5%e4%b8%80%e5%9c%ba%e5%bc%ba%e5%bc%ba%e5%af%b9%e8%af%9d%ef%bc%8c%e6%ac%a7%e6%b4%b2%e8%b1%aa%e9%97%a8%e6%b3%95%e5%9b%bd%e9%98%9f%e8%bf%8e%e6%88%98%e5%8d%97%e7%be%8e%e5%8a%b2%e6%97%85%e9%98%bf%e6%a0%b9%e5%bb%b7%e3%80%82
data = json.loads(html0)

print("分词结果:" + " ".join(data["cuts"]))
print("识别实体:")
for pos, entity in data["entities"]:
    print(pos,entity)
分词结果:北京时间 6月30日 晚 22点 , 2018年俄罗斯世界杯 1 / 8 决赛 迎来 一场 强强 对话 , 欧洲 豪门 法国队 迎战 南美 劲旅 阿根廷 。
识别实体:
[0, 4] 北京时间(中国国家标准时间)
[14, 25] 2018年俄罗斯世界杯
[39, 41] 欧洲(地球七大洲之一)
[43, 46] 法国国家男子足球队
[52, 55] 阿根廷(阿根廷共和国)

可以直接用识别到的实体名(注意,与原文内容不一定相同)代入三元组API中以获得其详细信息,比如可以参见:http://shuyantech.com/api/cndbpedia/avpair?q=法国国家男子足球队

百度百科词条的对应位置也可以用类似格式得到,比如:https://baike.baidu.com/item/法国国家男子足球队

完成注释

现在,我们既有了实体在句中的位置,又可以得到其具体信息和百科链接。接下来,文本注释要做的,就是把相应的信息和链接放到对应的文本位置上。这里我们就要使用HTML的特性:在href属性上放上超链接,在title属性上则可以放上鼠标悬停时会看到的注释。

为清晰起见,这里仅提供一个简单示例:

origin_text = "而且任意球还击中横梁"
l,r,origin_entity0 = 2,5,"任意球"                                                       # 来自实体链接
href0 = "https://baike.baidu.com/item/" + zh2url(origin_entity0)
annotation = "任意球是一种在足球(或手球)比赛中发生犯规后重新开始比赛的方法。"           # 一般使用实体的"DESC"属性
annotated = r'<a href="%s" title="%s">%s</a>' % (href0,annotation,origin_entity0)
annotated_text = origin_text[:l] + annotated + origin_text[r:]                            # 插入原文链接
print(annotated_text)
而且<a href="https://baike.baidu.com/item/%e4%bb%bb%e6%84%8f%e7%90%83" title="任意球是一种在足球(或手球)比赛中发生犯规后重新开始比赛的方法。">任意球</a>还击中横梁

网页中的实际效果:

而且任意球还击中横梁

本文涉及到的完整代码可以在我的Github上找到:https://github.com/blmoistawinde/auto_annotation 也可以在binder上在线体验。

上面实现了一个完整的从txt文件到注释好的html的流程,也处理了实际应用中可能会出现的一些小问题。

事实上这个工程还有很多改进的空间,比如实体链接不准确、遗漏等问题,如果使用更加专业的领域知识图谱说不定就可以获得更好的准确率。

总之,有什么问题和建议都欢迎与我交流。

当然,要是觉得这个项目还不错的话,也希望大家star一下我的项目啦。

补注: API的免费试用次数有限,比如我自己有段时间用的太多就被禁了233,所以大家要注意哈。 另外,对于英语等其他外语的实体链接,可以使用DBpedia的API: https://www.dbpedia-spotlight.org/

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 从根本解决python3 open的UnicodeDecodeError: 'gbk' codec问题

    在Windows下经常用python open函数的人相信都遇到过UnicodeDecodeError: ‘gbk’ codec…这种编码问题。而且很多有经验的...

    blmoistawinde
  • 实体知识+字典树辅助jieba的分词(并对三国演义进行简单分析)

    在做中文NLP的时候,分词可谓是基础中的基础。然而这个基础部分的内容直到今天还是让人不省心,在实际应用中【尤其是在人名等实体的识别上】总是显得漏洞百...

    blmoistawinde
  • NeuralCoref: 用指代消解来做一个“能多轮对话的问答对话机器人”

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    blmoistawinde
  • 「创意」这种技能太高冷,elfin带你体验无线充电的乐趣

    镁客网
  • 溯源智能:从触觉大脑到人工智能危机 —《机器崛起前传—自我意识与人类智慧的开端》新书推介

    新智元推荐 人工智能所能企及的高度即使存在争论,这个时代所面临的危机也不可避免。作为一本科学与人文、学术与科普之功兼具的人工智能著作,该书并未拘泥于每一秒...

    新智元
  • 用Kubernetes部署超级账本Fabric的区块链即服务(1)

    【注:下载本文PDF版本以及本文源代码,可关注本公众号:亨利笔记,后台发送消息“区块链即服务” 或 “baas”即可。】

    用户5128711
  • 使用AOP打印日志Controller和DubboService的请求参数和相应参数和响应时间

    前言:项目为了方便排查问题都会在请求的接口或者暴露的服务前后都会打上日志。这样就搬出了Spring核心功能AOP,前两天我问一年工作经验的javaer,AOP...

    王念博客
  • 马斯克的挖隧道公司再下一城,未来或将首次实现短途通勤

    日前,马斯克的挖隧道公司Boring发布了一份长达50页的大型报告,内容包括通过高速系统连接华盛顿特区和巴尔的摩的建议。可以说这是Boring公司实现东海岸Lo...

    镁客网
  • 美团要完成的无人配送事业:机器和人类的配送成本差不多了

    【新智元导读】7月25日,美团正式向外界发布无人配送开放平台,这意味着美团将迎来从软件、网络到硬件、整车以及实业等不同类型的合作伙伴。发布会上,美团还发布了L4...

    新智元
  • 【MIT】机器直觉:无需人类也能大数据分析

    摘要:据外媒报道,伴随着互联网的不断普及以及移动设备的不断流行,现在,数据及其设备中心要比过去任何一个时代都显得重要。这种被叫做大数据分析的处理过程大部分情况下...

    新智元

扫码关注云+社区

领取腾讯云代金券