python文本分析与处理

所需积分/C币:45 2018-01-25 13:10:12 787KB PDF
收藏 收藏 1
举报

python文本分析与处理,比较轻量级的资源文件。 python文本分析与处理,比较轻量级的资源文件。
else #少于4个单词的行排在后面 lines[n]=([\377'l, lines[nD) lines. sorto #排序 for n in range(len (lines) #转换回原先内容 lines[n]= lines[n][1] end= time. timeo wrerr("Schwartzian transform sort in %3 2f secs\n"%(end-start)) open('tmp. schwartzian, w).Writelines(lines 这只有一个特别的例子,但读者应该能够用任何形式来使用这种技术,特别是对于大文 件。 主题-排版 虽然使用ASCI文本作为通讯格式并不好-通常不会很复杂文件不会很大-但其生命力 还是很强的。 README文件, HOWTO文件,电子邮件,新闻组,包括本书都仍然是 使用ASCI码文本(至少原文加工技术通常是很有价值的)。此外,许多像HTML和 Latex的格式往往也需要手动修改,清晰的排版是非常重要的。 段落排版对于文本文件来说是极为常见的工作。 Python2.3增加了[ textwrap模块做一 些有限的排版工作。在大多数情况下,这项工作可以使用文本编辑器来完成。不过,有 时候自动化排版会更方便。这项工作很简单,比较奇怪的是, Python没有相应的标准 模块功能实现这一点。有一个 formatter. Dumb Writer类和 formatter. AbstractWriter抽象类可以用于此项工作。相关讨论在第5章,坦率地说, 使用这些类需要大量的定制工作而且很复杂,往往不适合用于解决手头的任务。 下面是一种简单的解决办法,可以当作命令行工具(从标准输入读取和输出到标准输 出),或用于较大的应用程序 reformat_para. py #简单排版。主要用于左右对齐。 LEFT RIGHT CENTER= LEFT RIGHT CENTER def mat_para(para=eft=O, right=/2 /ust=LEFT words para split lines =D d=0 end words= o While not end word flen( words[word])> right-left:#过长的单词 line words[word] ord +=1 if word >=len(words) end words else #收集一行可以容纳的单词 hile len (line)len( words[word])<= right-left line + words[word]+ word +=1 if word >=len(words) end words break lines. append(line) e Just==CENTER r, I= right, left return '\n, join([*left+In center(r-I)for Inin lines]) lif just==RIght return'n' join ([line. rjust(right) for line in lines]) else: left justify return'\n' join([ *left +line for line in lines]) name三三man Import sys if len(sys. argv)<>4 print "Please specify left_margin, right_marg, justification else ft it(sys. argv[ID) right int(sys. argv[2]) ys. argvB] upper #排版每一段 for p in sys. stdin. readosplit('\n\n) print reformat_para(p, left, right, just),'"n 留给读者一些改进任努。例如您可能需要首行缩进。或者有些段落需要的格式不适合用 此排版(例如题头等等)。具体的应用程序还可能需要确定如何分段等等。 主题--处理字段 数据表,DBMS,日志文件以及平面数据库往往在每行放置同样的纪录,每条记录有相 同的字段。通常这些字段要么是用分割符间隔要么是用固定位置来存放 分析这些记录的结构很容易,进行表格计算上也同样很简单。对于各种文本结构数据 可以使用几乎相同的代码来做处理。 下面的例子中提供了一种通用的框架来处理结构化文本。 fields_stats. py ----------#t #处理文本数据库里的多个字段 import from types import from xreadlines import xreadlines#需要 Python2.1,提高效率 #21以下使用 readline0 #-格式常量 DELIMITED =1 FLATFILE 2 #--—些简单的处理过程(使用函数式风格) illFunc lambda lst: none toFloat = lambda Ist: map(float, Ist) avg_Ist= lambda Ist: reduce(operator. add, to Float(lst)/len(Ist) sum_Ist= lambda Ist: reduce(operator. add to Float(lst)) max_lst= lambda Ist: reduce(max, to Float(lst)) class field stats "“统计资料 text db可以是字符串(包括 Unicode字符串)或文件类对象 stye有2种格式 DELIMITED, FLATFILE)分隔符或位置 默认使用分隔符格式 column_ positions位置列表,第一列的位置为1。 例如:(1,7,40)表示3个字段,起始位置分别为1,7,40 field_ funcs是字典,储存需要处理的字段和对应处理过程。 例如:{L: avg_Ist,4: sum st,5 max st} 表示对第一个字段做求平均值处理 对第四个字段做合计处理,对第5个字段求最大值 其他字段不做处理。 def init ( self text db style=DELIMITED, delimiter column_positions=(1), field_funcs=0) selftext db= text db self style style selfdelimiter delimiter self column_positions =column_positions self field funds field funcs def calc(self) "计算" #-第一步先建立列表的列表来存放数据。 used_cols= self field_funcs keys used cols. sorto #:不使用 column[o columns =D for n in range(l+used_cols[-1l #提示:这里可以使用]num来代替 columns. append([) #-第二步生成需要计算的列表数据 # text db是字符串对象 if type(self. text_db) in(String Type, UnicodeType for line in self. text_db. split('\n) fields self splitter(line) for d field= fields[col-1]#注意这里是由0开始的索引 columns[col]. append(field) else:# text db是文件对象 for line in xreadlines(self. text db) fields selfsplitter(line) for col in used cols field= fields[col-1]#注意这里是由0开始的索引 columns[col]. append(field) #-第三步作处理计算 results [None*(1 +used cols[-1) for col in used cols. results[col]=\ apply(self field_funcs[col]. (columns[coll,) #--Finally, return the result list return results def splitter(self, line ""分解一行为字段表" if self style = DELIMITED: return line split(self delimiter) elif self style = FLATFILE Fields #注意这里是以0开始的索引 #最后加上结束位置 num_positions= len(self column_positions) offsets =[(pos-1)for pos in self column_positions offsets append(len(line)) for pos in range(num_positions start= offsets [pos end offsets[pos+1] fields. append(line[start: end]) return fields else raise value error, Text database must be delimited or flatfile #-测试数据 First Name, Last Name, Salary, Years Seniority, Department delim= Kevin. Smith, 50000,5. Media Relations Tom, Woo, 30000,7, Accounting Sally, Jones, 62000, 10, Management . strip no leading/trailing newlines Comment First Last Salary Years Dept flat tech note Kevin Smith 50000 Media relations nore filler Tom Woo 30000 yet more. Sally Jones 62000 10 Accounting Management strip no leading/trailing newlines #- Run self-test code name main getdelim FieldStats(delim, field_funcs=3: avg_Ist, 4 max_Ist)) print'Delimited Calculations results getdelim calcO print Average salary -,results[3] print Max years worked- results 4 getflat FieldStats(flat, field_funcs= 3: avg_Ist, 4: max_Ist). style= FLATFILE column_positions =(15, 25, 35, 45, 52) print 'Flat Calculations results =getflat calcO print Average salary -, results[B] print Max years worked- results[4] 上面的例子中包括了一些效率上的考虑,可以用于大型数据集。首先, Fieldstats类是 动态处理文本,而没有保存整个数据。 headlines. xreadlineso是一个极其快速和有效 的行阅读器,但它需要 Python21+,其他版本可以使用 FILE. readline(0或 FILE, readlines0。此外,只关心实际上需要用到的数据,以便节省内存。这里没有考 虑同时使用多个相关字段做处理的应用,不过可以提取出数据作再次运算 还有就是没有考虑在同一个字段上作多种处理,这个留给读者作思考 主题--字词数统计 Unⅸx系统下有个工具wc可以做这个任务。这是个基本工具不能统计段落。wc只能统 计字符,单词和行。有几个命令选项可以控制显示的结果,不过我很少用到它们。 在写这一段的时候,我发现自己的系统里没有装wc。下面的例子实际上是一个增强版 wc',不过缺少了很多命令行选项。在 Python里可以非常简单的实现wc的功能。其 主要使用的技术是jin0和".spit0。 # wC.py # #统计字符数,单词数,行数和段落数 #可以STDN输入或使用文件通配符 port sys, gl if len (sys. argv) C,w,L,p=0.0,0,0 for pat in sys. argv[1:] for file in globglob(pat) pen (file. reado wC=len(s), len(s split), len(ssplit(\n )), len(ssplit(\n\n,)) print It' join(map(str, wc), \It'+file W,I,p C[0],W+WC[1]J|+wc[2]p+Wc[3] WC=(c,W,L, p) print t join(map(str, wc)),tTOTAL else sys. stdin. reado WC=len(s), len(s split), len(s split(\nD),\ len(ssplit('\n\n)) print tjoin(map(str, wc)),tSTDIN 这个小功能可以在一个函数里实现,不过它太过于紧凑。不过在使用解释器的环境下者 只需要两行。 上面的解决方法符合 Python的准则,用一种显而易见的方式来完成任务。还有个方法 也可以完成同样的任务,读者可以思考一下(这只是好玩): >>>WC=map(len, [s]+map(s split, (None, n'n\n)) 如果再加上 print语句,就可以用一行来解决问题了。 主题-以二进制数据传送ASCI码信息 许多文本信息都是采用7位ASCⅡ编码。特别是用在互联网传送的时候非ASC码的信 息需要先编成7位AS码才能正常传送,否则会因为最高位被分解导致出现乱码。像 简单邮件传输协议(SMTP),网络新闻传输协议(NNTP)或HTTP的内容编码等等都会需 要用到编解码。编码8位二进制数据成ASCⅡ码有一些通用的技术。 编码技术大都是将二进制数据转换成十六进制数据。UU编码是—种很早的编码标准 主要用于新闻组和BBS传输二进制文件。 Binhex编码主要用于Mac的系统。base64 是MIME的一种编码方式。这些编码技术基本上是在四个字节的ASCI码和三个字节的 二进制数据之间转换,开始标记和结束标记等略有不同。QP编码也是一种MIME编码, 不过它的编码长度是可变的,主要用于非ASCⅡ码信息,对7位ASC文本无需再次编 码,仅将8位数据转换为7位。 β thorη提供了上述几种编码的相关模块。包裝好的模块[uu,[ binheⅪ]base64]和 quop操作起来和文件对象差不多。当然之间也略有不同。例如[ binhex是在编码以 后才关闭输出文件,这使得它无法用于像 StringS之类的文件对象。所有的这些编码 工具都要使用到底层的C模块[ binasco。实际上真正执行转换的是[ binasco模块,不 过它不会区分正确的编码块大小 标准库并没有提供通用的编解码功能,不过很容易就可以实现一个通用的编解码程序 #----------encode_binary. py ---------# Provide encoders for arbitrary binary data in Python strings handles block size issues transparently, and returns a string #f Precompression of the input string can reduce or eliminate any size penalty for encoding mport sys import zlib import binascii UU=45 BASE64=57 BINHEX= sys. maxint def asCilencode(s=, type=BASE64, compress=I) ASCⅡ文本转换为二进制数据 #先选择编码方式 if type == BASE64: encode= binascii b2a base 64 elif type ==UU: encode= binascii b2a_ut elif type = BINHEX: encode binascii b2a_hq else: raise Value Error, "Encoding must be in UU, BASE64, BINHEX #再判断是否进行压缩 if compress: s= Zlib compress(s) #一块一块开始编码 offset blocks while 1. blocks. append(encode(s[offset: offset+typel) offset + type if offset>len(s): break #返回编码后的数据 return oin(blocks) def ascIldecode(s, type=BA SE64, compress=1) "由二进制数据解码至ASCⅡ文本" #解码 if type = BASE64: S= binascii a2b_base 64(s) elif type = BINHEX: S= binascii a2b_hqx(s) elif type ==UU s=oin(binascia2b_uu(line)for line in s. split(In 27 #判断是否进行解压缩 if compress: S= Zlib decompress(s) #返回结果 return s Encode/decode stdin for self-test if name main decode type=0. bASE64 for arg in sys. argy if arg. lower(=='d: decode=1 elif arg.upper(==UU: TYPE=UU elif arg. upper(==BINHEX: TYPE=BINHEX elif arg.upper(==BASE64: TYPE=BASE64 if decode print ASClldecode(sys. stdin. reado, type=TYPE) else print ASCllencode(sys. stdin. reado, type=TYPE) 上面的例子并没有包含任何头数据或需要的分界数据,这些可以通过使用[ uu]minify 或 [MimeWriter来解决。或者你也可以编写自己需要的 encode binary,py 主题-词频统计 分析文本里单词的出现频率是很有用的。在文字处理里,几乎要么是处理字节要么是处 理单词。创建词频统计很简单,只需要使用 Python字典就可以了,不过不是每个人都 能立即找到最明显的解决方案。下面的这个例子有很好的通用性,提供了多种实用功能, 并且还可用于命令行操作模式 #--------- histogram py ----------# #统计词频 #有几个工具函数可以提取需要的结果 from string import split, maketrans translate, punctuation, digits port sys from types import import types def word_histogram(source) "对词作统计(不包括标点和数字)"" hist =t trans= maketrans( if type( source)in( String type, Unicode Type):#字符串 for word in split(source) word translate( word, trans, punctuation+digits) if len(word)>0 hist[word]= hist. get(word, 0)+1 elif hasattr(source, 'read") #文件 from xreadlines import xreadlines#测试是否可用 for line in xreadlines(source) for word in split(line word= translate(word, trans, punctuation +digits) if len (word)>0 hist[word]= hist. get(word, 0)+1 except ImportError #使用日版本 line source. readlineo #速度慢,但内存占用少 while line for word in split(line) word translate(word, trans, punctuation +digits) if len (word)>0 hist[word] =hist. get(word, 0)+1 line source. readlineo else raise TypeError, source must be a string-like or file-like object return hist def char_histogram(source, sizehint =1024*1024) hist= f if type( source)in( String Type, Unicode Type):#字符串 for char in sot hist[char]= hist. get(char, 0 elif hasattr(source, read) #文件 chunk= source. read (sizehint) while chunk. for char in chunk hist[char]= hist. get(char, 0)+1 chunk source read(sizehint Ise raise TypeError,

...展开详情
试读 34P python文本分析与处理
立即下载 低至0.43元/次 身份认证VIP会员低至7折
抢沙发
一个资源只可评论一次,评论内容不能少于5个字
关注 私信 TA的资源
上传资源赚积分,得勋章
最新推荐
python文本分析与处理 45积分/C币 立即下载
1/34
python文本分析与处理第1页
python文本分析与处理第2页
python文本分析与处理第3页
python文本分析与处理第4页
python文本分析与处理第5页
python文本分析与处理第6页
python文本分析与处理第7页

试读结束, 可继续读4页

45积分/C币 立即下载 >