当我用Stanford CoreNLPA Python wrapper for the Java Stanford Core NLP tools(NLP的python调用工具)进行句法分析时,遇到一个很讨人厌的事情。

  1. "(ROOT (IP (ADVP (AD \u4f46)) (NP (NN \u52a0\u5de5\u5382)) (VP (ADVP (AD \u8fd8\u662f)) (VP (VV \u7ee7\u7eed) (VP (VP (VV \u71c3\u70e7) (NP (NN \u80f6) (NN \u5236\u54c1))) (VP (VV \u6392\u653e) (NP (NN \u5e9f\u6c14)))))) (PU \u3002)))"

  句法分析结果如上述所示,但是并没有相关的python包能提供像这样的把一个字符串里面包括层次结果的数据结构化。(好吧,是我了解不深,如果您有的话,请一定要告诉我)我所说的结构化的意思是把上述字符串转换成json结构,方便继续分析。

  1. [{u'IP 2': [{u'ADVP 3': u'AD \u4f46 4'},
  2. {u'NP 5': u'NN \u52a0\u5de5\u5382 6'},
  3. {u'VP 7': [{u'ADVP 8': u'AD \u8fd8\u662f 9'},
  4. {u'VP 10': [u'VV \u7ee7\u7eed 11',
  5. {u'VP 12': [{u'VP 13': [u'VV \u71c3\u70e7 14',
  6. {u'NP 15': [u'NN \u80f6 16',
  7. u'NN \u5236\u54c1 17']}]},
  8. {u'VP 18': [u'VV \u6392\u653e 19',
  9. {u'NP 20': u'NN \u5e9f\u6c14 21'}]}]}]}]},
  10. u'PU \u3002 22']}]
    #ROOT为最外层ID=1,其他按字符的出现次序递增
    #字符后面加个ID 是当字符相同时用ID 区别他们

  故,自己写了一个算法,先把算法逻辑po上。

  1. #1.分层及父级计算算法
  2. #1.1分层:
  3. #条目所在层数=条目ID值-条目前”)”数目
  4. #1.2条目的父级条目计算公式:
  5. #if ∆”)”==0:父ID=self.ID-1
  6. #if ∆”)”>0:父ID=查找self.ID之前的数据,选取最后层数=当前条目层数的父ID为自身的父ID(其中∆”)”为相邻的两个条目的右括号数目之差,如NN的父ID为8、VP的父ID为7)

附上代码:

  1. # -*- coding:utf-8 -*-
  2. import re
  3.  
  4. from pprint import pprint
  5. from pandas import DataFrame
  6. class Transtrees:
  7. """
  8. 将字符串按“)”数目分层和计算父节点ID
  9. 1、层数的计算公式为ID-")"数目
  10. 2、父节点计算方式为:
  11. ∆")"数目 =0:父ID 为自身ID-1
  12. ∆")"数目 >0 :父ID 为搜索自身之前所有的ID,取最后层数相同的节点的父ID为自身父ID
  13. 例如:
  14. u'(ROOT(IP(LCP(IP(NP(NN)) VP(VV)))))'
  15. ROOT IP LCP IP NP NN VP VV
  16. id 1 2 3 4 5 6 7 8
  17. ")" 0 0 0 0 0 0 2 2
  18. floor 1 2 3 4 5 6 5 6
  19. fid 0 1 2 3 4 5 4 7
  20. """
  21.  
  22. def __init__(self,strtree):
  23. """
  24. 初始化的同时,加载数据结果
  25. _nlist 为一个装有[id,文本,右括号数目,层数]的列表
  26. _fid_dict 是一个格式如{id:父ID}的字典
  27. _tree_data 是一个装有[id,文本,层数,父ID]的列表
  28. """
  29. self._strtree = strtree
  30. self._nlist = []
  31. self._nlist = self.get_ID_COUNT()
  32. self._fid_dict ={}
  33. self._fid_dict = self.get_fid()
  34. self._tree_data =[]
  35. self._tree_data = self.get_tree_data()
  36.  
  37. def get_ID_COUNT(self):
  38.  
  39. flag=1
  40. namelist = re.findall("[^()]+",self._strtree)
  41. while flag:
  42. try:
  43. namelist.remove(' ')
  44. except:
  45. flag=0
  46.  
  47. for i in range(len(namelist)):
  48. name_index = len(self._strtree)-len(self._strtree.split('(',i+1)[-1])-1
  49. bk_count = self._strtree[:name_index].count(')')
  50. self._nlist.append([i,namelist[i],bk_count,i-bk_count])
  51.  
  52. return self._nlist
  53.  
  54. def get_fid(self):
  55.  
  56. treedata = DataFrame(self._nlist, columns=["ID", "TEXT", "BK_COUNT", "FLOOR"])
  57. tag=0
  58. for i in range(1,len(treedata)):
  59. if treedata["BK_COUNT"][i] == treedata["BK_COUNT"][i-1]:
  60. self._fid_dict[i] = treedata['ID'][i-1]
  61. else:
  62. for j in range(1,i):
  63. if treedata['FLOOR'][j] == treedata['FLOOR'][i]:
  64. self._fid_dict[i] = self._fid_dict[j]
  65. self._fid_dict[0] =-1
  66. return self._fid_dict
  67.  
  68. def get_tree_data(self):
  69. for i in range(len(self._nlist)):
  70. self._tree_data.append([str(i+1),self._nlist[i][1]+' '+str(i+1),str(self._fid_dict[i]+1)])
  71. return self._tree_data
  72.  
  73. class bandModel:
  74. """
  75. 绑定父子关系辅助类
  76. """
  77. def __init__(self, ID, TEXT, FID):
  78.  
  79. self._ID = ID
  80. self._TEXT = TEXT
  81. self._FID = FID
  82. self._children = []
  83.  
  84. def addChild(self, *child):
  85.  
  86. self._children += child
  87.  
  88. def printTree(self,blist):
  89. """
  90. blist 返回的结果为:(以u'(ROOT(IP(LCP(IP(NP(NN)) VP(VV)))))'为例子)
  91. [{VP:VV},{NP:NN},{IP:NP},{LCP:IP},{IP:LCP},{ROOT:IP}]
  92. 即由深到浅,每层的父子关系的列表。
  93. """
  94. map(lambda child:child.printTree(blist), self._children)
  95. for i in self._children:
  96. blist.append({self._TEXT:i._TEXT})
  97.  
  98. def get_tree(a,b):
  99. """
  100. 根据bandModel生成的blist重构树状结构
  101. """
  102. if b.values()[0] in a.keys():
  103. if (b.keys()[0] in a.keys()) & (b.values()[0] in a.keys()):
  104. if isinstance(a[b.keys()[0]], list):
  105. a[b.keys()[0]].append({b.values()[0]:a.pop(b.values()[0])})
  106. return a
  107. a[b.keys()[0]] =[a[b.keys()[0]],{b.values()[0]:a.pop(b.values()[0])}]
  108. return a
  109. if b.keys()[0] in a.keys():
  110. a[b.keys()[0]].append({b.values()[0]:a.pop(b.values()[0])})
  111. a[b.keys()[0]] = {b.values()[0]:a.pop(b.values()[0])}
  112. return a
  113. for k in range(len(a.keys())):
  114. if a.keys()[k] == b.keys()[0]:
  115. if isinstance(a[b.keys()[0]], list):
  116. a[b.keys()[0]].append(b.values()[0])
  117. return a
  118. a[b.keys()[0]] =[a[b.keys()[0]], b.values()[0]]
  119. return a
  120.  
  121. return dict(a,**b)
  122.  
  123. def get_id(tree,strs=None):
  124.  
  125. """
  126. 查找时的辅助函数,获取输入字符串的id列表
  127. """
  128. id_list = []
  129. data = DataFrame(tree._nlist,columns=['id', 'text', 'bk_count', 'floor'])
  130. for i in range(len(tree._nlist)):
  131. if len(re.findall("^"+strs,data['text'][i])) == 1 :
  132. id_list.append(i+1)
  133. return id_list
  134.  
  135. def get_result(tree,strs):
  136. """
  137. 结果返回
  138. id_list 查找的字符串的id的列表
  139. tree_list 每个ID节点的具体结构组成的列表
  140. """
  141. alist=[]
  142. blist=[]
  143. tree_list=[]
  144. for i in tree._tree_data:
  145. alist.append(bandModel(i[0],i[1],i[2]))
  146.  
  147. for i in range(0, len(alist)):
  148. for j in range(0, len(alist)):
  149. if alist[j]._FID == alist[i]._ID:
  150. alist[i].addChild(alist[j])
  151.  
  152. id_list = get_id(tree, strs)
  153. if len(id_list) == 0:
  154. return "'%s' is not the nodes of the tree!" % strs,id_list
  155. else:
  156. z=0
  157. for i in id_list:
  158. if len(alist[i-1]._children) == 0:
  159. tree_list.append("%s is the deepest nodes of the tree!" % tree._nlist[i-1][1])
  160. else:
  161. alist[i-1].printTree(blist)
  162. z=reduce(get_tree,blist)
  163. if z :
  164. tree_list.append(z)
  165. return tree_list,id_list
  166. if __name__ == '__main__':
  167.  
  168. tree=Transtrees(u"(ROOT (IP (ADVP (AD \u4f46)) (NP (NN \u52a0\u5de5\u5382)) (VP (ADVP (AD \u8fd8\u662f)) (VP (VV \u7ee7\u7eed) (VP (VP (VV \u71c3\u70e7) (NP (NN \u80f6) (NN \u5236\u54c1))) (VP (VV \u6392\u653e) (NP (NN \u5e9f\u6c14)))))) (PU \u3002)))")
  169.  
  170. tree_list,id_list=get_result(tree,'IP')
  171.  
  172. pprint(tree_list)

  完全手工,因为只是一个抽取工具,所以没有做相应的优化。

  个人劳动成果,转载请注明。

python提取隐含结构的字符串的更多相关文章

  1. Python内置数据结构之字符串str

    1. 数据结构回顾 所有标准序列操作(索引.切片.乘法.成员资格检查.长度.最小值和最大值)都适用于字符串,但是字符串是不可变序列,因此所有的元素赋值和切片赋值都是非法的. >>> ...

  2. python学习之路06——字符串

    字符串 1.概念 字符串就是由若干个字符组成的有限序列 字符:字母,数字,特殊符号,中文 表示形式:采用的单引号或者双引号 注意:字符串属于不可变实体 2.创建字符串 str1 = "hel ...

  3. python操作txt文件中数据教程[2]-python提取txt文件

    python操作txt文件中数据教程[2]-python提取txt文件中的行列元素 觉得有用的话,欢迎一起讨论相互学习~Follow Me 原始txt文件 程序实现后结果-将txt中元素提取并保存在c ...

  4. 转:python提取浏览器Cookie

    在用浏览器进行网页访问时,会向网页所在的服务器发送http协议的GET或者POST等请求,在请求中除了指定所请求的方法以及URI之外,后面还跟随着一段Request Header.Request He ...

  5. python与C结构体之间二进制数据转换

    python与C结构体之间数据转换 前言 在实际应用中,可能会遇到直接和C进行二进制字节流协议通信,这时要把数据解包成python数据,如果可能,最好与C定义的结构体完全对应上. python中有2种 ...

  6. 【Python基础学习四】字符串(string)

    Python 字符串 字符串是 Python 中最常用的数据类型.可以使用引号('或")来创建字符串. 创建字符串很简单,只要为变量分配一个值即可.例如: var1 = 'hello' va ...

  7. Python中用format函数格式化字符串的用法

    这篇文章主要介绍了Python中用format函数格式化字符串的用法,格式化字符串是Python学习当中的基础知识,本文主要针对Python2.7.x版本,需要的朋友可以参考下   自python2. ...

  8. Python基础:序列(字符串)

    一.概述 字符串 类似于C中的字符数组(功能上更像C++中的string),它是由一个个 字符 组成的序列.与C/C++不同的是,Python中没有 字符 这个类型,而是用 长度为1的字符串 来表示字 ...

  9. Python学习总结6:字符串格式化操作及方法总结

    1. 格式化操作(%) Python中内置有对字符串进行格式化的操作. 模板 格式化字符串时,Python使用一个字符串作为模板.模板中有格式符,这些格式符为真实值预留位置,并说明真实数值应该呈现的格 ...

随机推荐

  1. thinkphp使用模块/控制器/操作访问时出现No input file specified.解决方式

    thinkphp使用 http://serverName/index.php/模块/控制器/操作 访问时,出现了 No input file specified. 的错误 解决办法: 一: 开启cgi ...

  2. innobackupex 使用说明

    1.创建备份相关用户 '; grant reload,lock tables,replication client,process,super on *.* to 'backuper'@'127.0. ...

  3. Android IntentService 与Alarm开启任务关闭任务

    1:MyService public class MyService extends IntentService{ AlarmManager alarmManager = null; PendingI ...

  4. PL/SQL --> 动态SQL调用包中函数或过程

    动态SQL主要是用于针对不同的条件或查询任务来生成不同的SQL语句.最常用的方法是直接使用EXECUTE IMMEDIATE来执行动态SQL语句字符串或字符串变量.但是对于系统自定义的包或用户自定的包 ...

  5. Linux下程序崩溃,ulimit,coredump,gdbserver

    操作系统:Ubuntu10.04 前言:    在程序崩溃后,如何快速定位问题.    以下方法适用于开发调试阶段,不太适用成品.    本文着眼于嵌入式,PC方面更简单.    核心:gdbserv ...

  6. 理解*ptr++

    这是C语言中指针的基本用法之一,我们先来看一个小例子.下面是代码: int main(void) { char *p = "Hello"; while(*p++) printf(& ...

  7. XMPP通讯开发-1

    有关XMPP的相关知识这里就不讲解了,网上有很多,这里我使用的NetBeans+Openire+smack搭建一个以XMPP协议的通讯工具,对于这部分知识我也不是很了解,也是初识吧,可能有些概念会混淆 ...

  8. 找不到eth0,但能找到eth1的问题解决办法

    故障现象:Linux的网卡由eth0变成了eth1,如何修复?解决方案:在linux中,udev记录网络规则的脚本为:/etc/udev/rules.d/70-persistent-net.rules ...

  9. struct2-json

    一.JSON是什么? :JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.易于人阅读和编写,同时也易于机器解 析和生成.它基于JavaScript(Stan ...

  10. 编解码学习笔记(十):Ogg系列

    Ogg是一个自由且开放标准的容器格式,由Xiph.Org 基金会所维护.Ogg格式并不受到软件专利的限制,并设计用于有效率地串流媒体和处理高质量的数字多媒体. Ogg意指一种文件格式,能够纳入各式各样 ...