golang知识图谱NLP实战第四节——关系抽取完善逻辑

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hotqin888/article/details/81322890

 陈同学将hanlp做成了服务:https://gitee.com/Erichan/EngineerCMS-HanLPService

用golang应用提交文字给这个hanlp服务,返回json数据格式的依存句法分析结果。

//这个是专门解析json的
package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/url"

	"github.com/astaxie/beego/httplib"
)

type Dict struct {
	SBV []HanlpJson
	VOB []HanlpJson
	IOB []HanlpJson
	FOB []HanlpJson
	DBL []HanlpJson
	ATT []HanlpJson
	ADV []HanlpJson
	CMP []HanlpJson
	COO []HanlpJson
	POB []HanlpJson
	LAD []HanlpJson
	RAD []HanlpJson
	IS  []HanlpJson
	HED []HanlpJson
}

type HanlpResult struct {
	Result HanlpWord `json:"result"`
}

type HanlpWord struct {
	Word []HanlpJson `json:"word"`
}

//用于json数据解析
type HanlpJson struct {
	ID      int64
	LEMMA   string
	CPOSTAG string
	POSTAG  string
	HEAD    Json
	DEPREL  string
	NAME    string
}

type Json struct {
	ID      int64
	LEMMA   string
	CPOSTAG string
	POSTAG  string
	DEPREL  string
	NAME    string
}

type Ltp2 struct {
	Ltptwo []Ltp1
}

type Ltp1 struct { //这个办法不行,保留!
	Ltpone []Ltp
}

type Ltp struct {
	Id        int64  `json:"id"`
	Cont      string `json:"cont"`
	Pos       string `json:"pos"`
	Ne        string `json:"ne"`
	Parent    int64  `json:"parent"`
	Relate    string `json:"relate"`
	Semparent int64  `json:"semparent"`
	Semrelate string `json:"semrelate"`
	Arg       []Arg1 `json:"arg"`
	Sem       []Sem1 `json:"sem"`
}

type Sem1 struct {
	Id     int64  `json:"id"`
	Parent int64  `json:"parent"`
	Relate string `json:"relate"`
}

type Arg1 struct {
	Id   int64  `json:"id"`
	Type string `json:"type"`
	Beg  int64  `json:"beg"`
	End  int64  `json:"end"`
}

func main() {
	link := url.QueryEscape("输水干线从佛山市顺德区杏坛镇西江干流中央的鲤鱼洲岛端部取水")
	req := httplib.Post("http://localhost:8888/max?sentence=" + link)
	str, err := req.String()
	if err != nil {
		log.Fatal(err)
	}
	//	fmt.Println(str)
	//json字符串解析到结构体
	var hanlpresult HanlpResult
	err = json.Unmarshal([]byte(str), &hanlpresult)
	if err != nil {
		log.Fatal(err)
	}
	//	fmt.Println(hanlpresult.Result.Word)
	hanlp := hanlpresult.Result.Word
	dict := make([]Dict, 0)
	for _, w := range hanlp {
		dict1 := make([]Dict, 1)
		for _, x := range hanlp {
			if w.ID == x.HEAD.ID {
				list1 := make([]HanlpJson, 1)
				list1[0] = x
				switch x.DEPREL {
				case "主谓关系":
					dict1[0].SBV = list1
				case "动宾关系":
					dict1[0].VOB = list1
				case "间宾关系":
					dict1[0].IOB = list1
				case "前置宾语":
					dict1[0].FOB = list1
				case "兼语":
					dict1[0].DBL = list1
				case "定中关系":
					dict1[0].ATT = list1
				case "状中结构":
					dict1[0].ADV = list1
				case "动补结构":
					dict1[0].CMP = list1
				case "并列关系":
					dict1[0].COO = list1
				case "介宾关系":
					dict1[0].POB = list1
				case "左附加关系":
					dict1[0].LAD = list1
				case "右附加关系":
					dict1[0].RAD = list1
				case "独立结构":
					dict1[0].IS = list1
				case "核心关系":
					dict1[0].HED = list1
				}
				//				bb = make([]Hanlp, 0)
			}
		}
		dict = append(dict, dict1...)
	}
	//	fmt.Println(dict)
	for i := 0; i < len(dict); i++ {
		extract(hanlp, dict, i)
	}
}

func extract(hanlp []HanlpJson, dict []Dict, i int) {
	w := hanlp[i]
	ww := dict[i]
	//主谓宾关系:刘小绪生于四川
	if len(ww.SBV) > 0 && len(ww.VOB) > 0 {
		entity1 := ww.SBV[0].LEMMA
		// 排除:刘小绪和李华是朋友
		prep := ww.SBV[0]
		prepIndex := prep.ID - 1
		prepDict := dict[prepIndex] //这个写法注意,当做dict数组的索引和它ID是一致的
		if len(prepDict.COO) > 0 {
			relation := ww.VOB[0].LEMMA
			entity2 := prepDict.COO[0].LEMMA
			fmt.Println(entity1 + "," + relation + "," + entity2)
		} else {
			entity2 := ww.VOB[0].LEMMA
			relation := w.LEMMA
			fmt.Println(entity1 + "," + relation + "," + entity2)
		}
	}

	// 动补结构:刘小绪洗干净了衣服
	//"主谓关系"]
	//"动宾关系"]
	//"动补结构"]
	if len(ww.SBV) > 0 && len(ww.VOB) > 0 && len(ww.CMP) > 0 {
		entity1 := ww.SBV[0].LEMMA
		complement := ww.CMP[0].LEMMA
		entity2 := ww.VOB[0].LEMMA
		if len(ww.RAD) > 0 { //右附加关系
			subjoin := ww.RAD[0].LEMMA
			relation := w.LEMMA + complement + subjoin
			fmt.Println(entity1 + "," + relation + "," + entity2)
		} else {
			relation := w.LEMMA + complement
			fmt.Println(entity1 + "," + relation + "," + entity2)
		}
	}

	//定中关系
	if len(ww.ATT) > 0 {
		entity1 := ww.ATT[0].LEMMA
		relation := w.LEMMA
		for _, ii := range dict { //这里要用dict maps数组
			//"主谓关系"]
			//"动宾关系"]
			if len(ii.SBV) > 0 && len(ii.VOB) > 0 {
				if ii.SBV[0].LEMMA == relation {
					entity2 := ii.VOB[0].LEMMA
					fmt.Println(entity1 + "," + relation + "," + entity2)
				}
			}
		}
	}

	// 状动结构:父亲非常喜欢跑步
	// 非常 是 跑步的状语,关系应该为非常喜欢
	//"主谓关系"]
	//动宾关系"]
	//"状中结构"]
	if len(ww.SBV) > 0 && len(ww.VOB) > 0 && len(ww.ADV) > 0 {
		entity1 := ww.SBV[0].LEMMA
		adverbial := ww.ADV[0].LEMMA
		entity2 := ww.VOB[0].LEMMA
		relation := adverbial + w.LEMMA
		fmt.Println(entity1 + "," + relation + "," + entity2)
	}

	// 状动补结构
	//"主谓关系"]
	//"动宾关系"]
	//"状中结构"]
	//"动补结构"]
	if len(ww.SBV) > 0 && len(ww.VOB) > 0 && len(ww.ADV) > 0 && len(ww.CMP) > 0 {
		entity1 := ww.SBV[0].LEMMA
		adverbial := ww.ADV[0].LEMMA
		complement := ww.CMP[0].LEMMA
		entity2 := ww.VOB[0].LEMMA
		relation := adverbial + w.LEMMA + complement
		fmt.Println(entity1 + "," + relation + "," + entity2)
	}

	// 定语后置:父亲是来自肯尼亚的留学生
	if w.DEPREL == "定中关系" {
		if len(ww.VOB) > 0 {
			entity1 := hanlp[w.HEAD.ID-1].LEMMA
			relation := w.LEMMA
			entity2 := ww.VOB[0].LEMMA
			fmt.Println(entity1 + "," + relation + "," + entity2)
		}
	}

	// 介宾关系:刘小绪就职于学校
	// 于 和 学校 是介宾关系
	//"主谓关系"]
	//"动补结构"]
	if len(ww.SBV) > 0 && len(ww.CMP) > 0 {
		entity1 := ww.SBV[0].LEMMA
		prep := ww.CMP[0] //maps["动补结构"][0]
		prepIndex := prep.ID - 1
		prepDict := dict[prepIndex] //这个写法注意,当做dict数组的索引和它ID是一致的
		if len(prepDict.POB) > 0 {
			entity2 := prepDict.POB[0].LEMMA //"介宾关系"][0]
			relation := w.LEMMA + prep.LEMMA
			fmt.Println(entity1 + "," + relation + "," + entity2)
		}
	}

	// 宾语前置结构:海洋由水组成
	if len(ww.FOB) > 0 {
		entity2 := ww.FOB[0].LEMMA //maps["前置宾语"][0]
		if len(ww.ADV) > 0 {
			adverbial := ww.ADV[0] //maps["状中结构"][0]
			prepIndex := adverbial.ID - 1
			prepDict := dict[prepIndex]
			if len(prepDict.POB) > 0 {
				entity1 := prepDict.POB[0].LEMMA
				relation := w.LEMMA
				fmt.Println(entity1 + "," + relation + "," + entity2)
			}
		}
	}
}

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏前端小叙

vue select二级城市联动及第二级默认选中第一个option值

当二级联动比如选择国家的时候,希望选中一个国家的时候后面城市默认选中第一个城市,则给国家的select加一个@change事件就可以了 <div class=...

70050
来自专栏数据结构与算法

TopcoderSRM679 Div1 250 FiringEmployees(树形dp)

有一个 \(n\) 个点的树,每个点有点权(点权可能为负) ,求包含点\(1\)的最 大权连通子图(的权值和) 。 \(n \leqslant 2500\)

6830
来自专栏前端小叙

react文档demo实现输入展示搜索结果列表

当二级联动比如选择国家的时候,希望选中一个国家的时候后面城市默认选中第一个城市,则给国家的select加一个@change事件就可以了 <div class=...

403100
来自专栏布尔

基于Aspose.Pdf把pdf文件每一页转换为图片

如题,直接上代码片段             //1.选择pdf文件 var dialog = new OpenFileDialog();       ...

60290
来自专栏陈满iOS

iOS开发·runtime原理与实践: 关联对象篇(Associated Object)(应用场景:为分类添加“属性”,为UI控件关联事件Block体,为了不重复获得某种数据)

分类(category)与关联对象(Associated Object)作为objective-c的扩展机制的两个特性:分类,可以通过它来扩展方法;Associ...

51820
来自专栏跟着阿笨一起玩NET

ZPL打印中文信息

  相信各位在实际的项目中,需要开发打条码模块的也会有不少,很多同行肯定也一直觉得斑马打印机很不错,但是ZPL打印中文字符很麻烦。如果购买字体卡,或者通过COD...

48810
来自专栏数据结构与算法

洛谷P2286 [HNOI2004]宠物收养场

题目描述 凡凡开了一间宠物收养场。收养场提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物。 每个领养者都希望领养到自己满意的宠物,凡凡根据领养者的要求...

26850
来自专栏一个会写诗的程序员的博客

【Kotlin 反应式编程】第1讲 你好,Reactive Programming

【Kotlin 反应式编程】第1讲 你好,Reactive Programming

9620
来自专栏数据结构与算法

洛谷P2866 [USACO06NOV]糟糕的一天Bad Hair Day(单调栈)

15000
来自专栏非典型技术宅

iOS实践:一步步实现星级评分1. 创建星星2. 优化3. 灵异事件

19640

扫码关注云+社区

领取腾讯云代金券