当我用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. php中12个魔术方法

    本文列举了php面向对象当中12个魔术方法,并对此进行一一详细介绍,希望对新手有所帮助. 1.构造方法: __construct() 参数:自定义 触发时机:new的一瞬间自动调用 作用:初始化成员属 ...

  2. [TYVJ] P1049 最长不下降子序列

    最长不下降子序列 描述 Description 求最长不下降子序列的长度   输入格式 InputFormat 第一行为n,表示n个数第二行n个数   输出格式 OutputFormat 最长不下降子 ...

  3. Qt制作Aero特效窗口

    转载请注明链接与作者huihui1988 初学QT,边看书边自己做点小东西.最近突然心血来潮,想自己做个小巧点的,界面美观一点的备忘当桌面上.想了半天,发现VISTA/WIN7的Aero效果就不错,况 ...

  4. jQuery插件之artDialog

    artDialog是一个非常强大的弹出框插件.默认有两个版本,一个是jQuery版,一个是javascript版.功能非常多,而且使用非常简单.不写了,直接贴上官网的预览运行地址,以后用得着的时候去那 ...

  5. javascript之Boolean

    一.new Boolean(value); //构造函数 Boolean(value); //转换函数 0,NaN,null,"",undefined都会转成false,其他都会返 ...

  6. HTTP -> Asp.net (第一篇)

    当用户在浏览器输入一个URL地址后,浏览器会发送一个请求到服务器.这时候在服务器上第一个负责处理请求的是IIS.然后IIS再根据请求的URL扩展名将请求分发给不同的ISAPI处理. 流程如下: 1.I ...

  7. GridFS

    GridFS是一个建立在MongoDB文档基础之上的轻量级的文件存储规范. GridFS的一个基本思想就是可以将一个大文件分成很多块.每块作为一个单独的文档存储. GridFS支持在文档中存储二进制数 ...

  8. linux下vi命令大全(转载)

    进入vi的命令 vi filename :打开或新建文件,并将光标置于第一行首 vi +n filename :打开文件,并将光标置于第n行首 vi + filename :打开文件,并将光标置于最后 ...

  9. 模块工具类--utils

    File: js\utils.js/** * 模块工具类,用来初始化各模块视图.自定绑定事件以及其他辅助功能等 * @class Utils */Utils = (function() { var i ...

  10. CentOS6.5下使用NetHogs监控进程网络使用情况

    Nethogs 是一个终端下的网络流量监控工具,它的特别之处在于能够显示每一个进程的带宽占用情况,这样能够更直观获取网络使用情况.它支持 IPv4 和 IPv6 协议.支持本地网卡及 PPP 链接. ...