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

"(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结构,方便继续分析。

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

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

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

附上代码:

# -*- coding:utf-8 -*-
import re from pprint import pprint
from pandas import DataFrame
class Transtrees:
"""
将字符串按“)”数目分层和计算父节点ID
1、层数的计算公式为ID-")"数目
2、父节点计算方式为:
∆")"数目 =0:父ID 为自身ID-1
∆")"数目 >0 :父ID 为搜索自身之前所有的ID,取最后层数相同的节点的父ID为自身父ID
例如:
u'(ROOT(IP(LCP(IP(NP(NN)) VP(VV)))))'
ROOT IP LCP IP NP NN VP VV
id 1 2 3 4 5 6 7 8
")" 0 0 0 0 0 0 2 2
floor 1 2 3 4 5 6 5 6
fid 0 1 2 3 4 5 4 7
""" def __init__(self,strtree):
"""
初始化的同时,加载数据结果
_nlist 为一个装有[id,文本,右括号数目,层数]的列表
_fid_dict 是一个格式如{id:父ID}的字典
_tree_data 是一个装有[id,文本,层数,父ID]的列表
"""
self._strtree = strtree
self._nlist = []
self._nlist = self.get_ID_COUNT()
self._fid_dict ={}
self._fid_dict = self.get_fid()
self._tree_data =[]
self._tree_data = self.get_tree_data() def get_ID_COUNT(self): flag=1
namelist = re.findall("[^()]+",self._strtree)
while flag:
try:
namelist.remove(' ')
except:
flag=0 for i in range(len(namelist)):
name_index = len(self._strtree)-len(self._strtree.split('(',i+1)[-1])-1
bk_count = self._strtree[:name_index].count(')')
self._nlist.append([i,namelist[i],bk_count,i-bk_count]) return self._nlist def get_fid(self): treedata = DataFrame(self._nlist, columns=["ID", "TEXT", "BK_COUNT", "FLOOR"])
tag=0
for i in range(1,len(treedata)):
if treedata["BK_COUNT"][i] == treedata["BK_COUNT"][i-1]:
self._fid_dict[i] = treedata['ID'][i-1]
else:
for j in range(1,i):
if treedata['FLOOR'][j] == treedata['FLOOR'][i]:
self._fid_dict[i] = self._fid_dict[j]
self._fid_dict[0] =-1
return self._fid_dict def get_tree_data(self):
for i in range(len(self._nlist)):
self._tree_data.append([str(i+1),self._nlist[i][1]+' '+str(i+1),str(self._fid_dict[i]+1)])
return self._tree_data class bandModel:
"""
绑定父子关系辅助类
"""
def __init__(self, ID, TEXT, FID): self._ID = ID
self._TEXT = TEXT
self._FID = FID
self._children = [] def addChild(self, *child): self._children += child def printTree(self,blist):
"""
blist 返回的结果为:(以u'(ROOT(IP(LCP(IP(NP(NN)) VP(VV)))))'为例子)
[{VP:VV},{NP:NN},{IP:NP},{LCP:IP},{IP:LCP},{ROOT:IP}]
即由深到浅,每层的父子关系的列表。
"""
map(lambda child:child.printTree(blist), self._children)
for i in self._children:
blist.append({self._TEXT:i._TEXT}) def get_tree(a,b):
"""
根据bandModel生成的blist重构树状结构
"""
if b.values()[0] in a.keys():
if (b.keys()[0] in a.keys()) & (b.values()[0] in a.keys()):
if isinstance(a[b.keys()[0]], list):
a[b.keys()[0]].append({b.values()[0]:a.pop(b.values()[0])})
return a
a[b.keys()[0]] =[a[b.keys()[0]],{b.values()[0]:a.pop(b.values()[0])}]
return a
if b.keys()[0] in a.keys():
a[b.keys()[0]].append({b.values()[0]:a.pop(b.values()[0])})
a[b.keys()[0]] = {b.values()[0]:a.pop(b.values()[0])}
return a
for k in range(len(a.keys())):
if a.keys()[k] == b.keys()[0]:
if isinstance(a[b.keys()[0]], list):
a[b.keys()[0]].append(b.values()[0])
return a
a[b.keys()[0]] =[a[b.keys()[0]], b.values()[0]]
return a return dict(a,**b) def get_id(tree,strs=None): """
查找时的辅助函数,获取输入字符串的id列表
"""
id_list = []
data = DataFrame(tree._nlist,columns=['id', 'text', 'bk_count', 'floor'])
for i in range(len(tree._nlist)):
if len(re.findall("^"+strs,data['text'][i])) == 1 :
id_list.append(i+1)
return id_list def get_result(tree,strs):
"""
结果返回
id_list 查找的字符串的id的列表
tree_list 每个ID节点的具体结构组成的列表
"""
alist=[]
blist=[]
tree_list=[]
for i in tree._tree_data:
alist.append(bandModel(i[0],i[1],i[2])) for i in range(0, len(alist)):
for j in range(0, len(alist)):
if alist[j]._FID == alist[i]._ID:
alist[i].addChild(alist[j]) id_list = get_id(tree, strs)
if len(id_list) == 0:
return "'%s' is not the nodes of the tree!" % strs,id_list
else:
z=0
for i in id_list:
if len(alist[i-1]._children) == 0:
tree_list.append("%s is the deepest nodes of the tree!" % tree._nlist[i-1][1])
else:
alist[i-1].printTree(blist)
z=reduce(get_tree,blist)
if z :
tree_list.append(z)
return tree_list,id_list
if __name__ == '__main__': 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)))") tree_list,id_list=get_result(tree,'IP') 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. c#或获取系统的特殊路径,如我的文档等

    Console.WriteLine(System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)); System.E ...

  2. ArtTemplate 使用笔记

    新一代 javascript 模板引擎:artTemplate-3.0 下载地址:https://github.com/aui/artTemplate 快速上手请参考:https://github.c ...

  3. python之5关于_name_和_main_的具体含义

    关于_name_和_main_的具体含义如下: _name_:在模块中就是模块名,在类中就是类名 _main_:模块自身 "The namespace for a module is aut ...

  4. App开发革命进阶路

    APP开发的成败,或许不是程序编辑的多么完美,界面设计的多么精致,其实这就是一场用户体验的革命. APP的使用场景是移动设备,人机交互以单指手“触点”为主,大段文字输入是交互的禁区.因此,APP带来了 ...

  5. 那些年的那些事CISC和RISC发展中的纠缠

    本文来自http://www.cnbeta.com/articles/224544.htm ARM.ARM.ARM,没错ARM仿佛一夜之间就火了,平板.手机等领域随处可见它的影子,甚至已经有人预言未来 ...

  6. Java中的native方法

    博客引用地址:Java中的native方法 今天花了两个小时把一份关于什么是Native Method的英文文章好好了读了一遍,以下是我依据原文的理解. 一. 什么是Native Method 简单地 ...

  7. Bridging signals(二分 二分+stl dp)

    欢迎参加——每周六晚的BestCoder(有米!) Bridging signals Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 6 ...

  8. apache 开启压缩功能

    apache如何开启压缩功能. 1,首先先确认是安装deflatte模块.如果未安装,可以重新编译apache添加参数--enable-deflate=shared ,或者扩展安装deflate模块, ...

  9. javascript 控制input

    1.只允许输入数字     <input name="username" type="text" onkeyup="value=this.val ...

  10. UILabel + 导入字体

    UILabel * label = [[UILabel alloc]initWithFrame:CGRectMake(10, 100, 300, 100)]; 1.设置文字颜色 label.textC ...