前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >golang知识图谱NLP实战第四节——关系抽取完善逻辑

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

作者头像
hotqin888
发布2018-09-11 15:33:01
9770
发布2018-09-11 15:33:01
举报
文章被收录于专栏:hotqin888的专栏hotqin888的专栏

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://cloud.tencent.com/developer/article/1334589

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

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

代码语言:javascript
复制
//这个是专门解析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)
			}
		}
	}
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年07月31日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档