python提取隐含结构的字符串
当我用Stanford CoreNLP和A 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提取隐含结构的字符串的更多相关文章
- Python内置数据结构之字符串str
1. 数据结构回顾 所有标准序列操作(索引.切片.乘法.成员资格检查.长度.最小值和最大值)都适用于字符串,但是字符串是不可变序列,因此所有的元素赋值和切片赋值都是非法的. >>> ...
- python学习之路06——字符串
字符串 1.概念 字符串就是由若干个字符组成的有限序列 字符:字母,数字,特殊符号,中文 表示形式:采用的单引号或者双引号 注意:字符串属于不可变实体 2.创建字符串 str1 = "hel ...
- python操作txt文件中数据教程[2]-python提取txt文件
python操作txt文件中数据教程[2]-python提取txt文件中的行列元素 觉得有用的话,欢迎一起讨论相互学习~Follow Me 原始txt文件 程序实现后结果-将txt中元素提取并保存在c ...
- 转:python提取浏览器Cookie
在用浏览器进行网页访问时,会向网页所在的服务器发送http协议的GET或者POST等请求,在请求中除了指定所请求的方法以及URI之外,后面还跟随着一段Request Header.Request He ...
- python与C结构体之间二进制数据转换
python与C结构体之间数据转换 前言 在实际应用中,可能会遇到直接和C进行二进制字节流协议通信,这时要把数据解包成python数据,如果可能,最好与C定义的结构体完全对应上. python中有2种 ...
- 【Python基础学习四】字符串(string)
Python 字符串 字符串是 Python 中最常用的数据类型.可以使用引号('或")来创建字符串. 创建字符串很简单,只要为变量分配一个值即可.例如: var1 = 'hello' va ...
- Python中用format函数格式化字符串的用法
这篇文章主要介绍了Python中用format函数格式化字符串的用法,格式化字符串是Python学习当中的基础知识,本文主要针对Python2.7.x版本,需要的朋友可以参考下 自python2. ...
- Python基础:序列(字符串)
一.概述 字符串 类似于C中的字符数组(功能上更像C++中的string),它是由一个个 字符 组成的序列.与C/C++不同的是,Python中没有 字符 这个类型,而是用 长度为1的字符串 来表示字 ...
- Python学习总结6:字符串格式化操作及方法总结
1. 格式化操作(%) Python中内置有对字符串进行格式化的操作. 模板 格式化字符串时,Python使用一个字符串作为模板.模板中有格式符,这些格式符为真实值预留位置,并说明真实数值应该呈现的格 ...
随机推荐
- 让操作javascript对象数组像.net lamda表达式一样
让操作javascript对象数组像.net lamda表达式一样 随着web应用程序的富客户端化.ajax的广泛使用及复杂的前端业务逻辑.对js对象数组.json数组的各种操作越来越多.越来越复杂. ...
- js倒计时 重发 效果
<script type="text/javascript"> window.onload = function() { var wait = 60; function ...
- Android动态加载代码技术
Android动态加载代码技术 在开发Android App的过程当中,可能希望实现插件式软件架构,将一部分代码以另外一个APK的形式单独发布,而在主程序中加载并执行这个APK中的代码. 实现这个任务 ...
- css让图片居中显示在手机屏幕上
直接上代码了 <div class="showpic"> <span></span> <img src="" alt= ...
- Eloquent ORM 学习笔记
最近在学习Laravel,觉得ORM功能很强大,我这里只是简单探索了一点,如果有更好的笔记,还请分享. 因为重点在于Eloquent ORM,所以路由设置,控制器就不详细描述了,这里直接进入Model ...
- Cleaning Shifts(POJ 2376 贪心)
Cleaning Shifts Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 15143 Accepted: 3875 ...
- Android jar包混淆
具体可参考http://proguard.sourceforge.net/manual/examples.html#library 1.找到android的adt目录下的 D:\soft\adt-bu ...
- ViewBag、ViewData和TempData使用方法、区别与联系
一.区别与联系 ViewData 和 TempData 都可以传递弱类型数据,区别如下:TempData 只在当前 Action 中有效,生命周期和 View 相同:保存在Session中,Contr ...
- 认识元数据和IL(中)<第四篇>
书接上回[第二十四回:认识元数据和IL(上)],我们对PE文件.程序集.托管模块,这些概念与元数据.IL的关系进行了必要的铺垫,同时顺便熟悉了以ILDASM工具进行反编译的基本方法认知,下面是时候来了 ...
- css案例学习之ul li dl dt dd实现二级菜单
效果 代码实现 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www ...