python处理xml大文件[xml.sax]

来源:互联网 发布:js防水 施工 编辑:程序博客网 时间:2024/05/01 23:28

博客已迁移, 新地址

=====================

之前使用过python使用dom读取简单配置xml文件的http://blog.csdn.net/wklken/article/details/7270117

今天遇到大文件处理,使用dom占用资源太多,改用sax处理

dom和sax区别可以自己google下


需求:读取xml数据文件,文件较大,需要实时处理插入到数据库

使用到的包:xml.sax


xml文件格式:

<PERSONS> <person>     <id>100000</id>     <sex>男</sex>     <address>北京,海淀区</address>     <fansNum>437</fansNum>     <summary>1989</summary>     <wbNum>333</wbNum>     <gzNum>242</gzNum>     <blog>null</blog>     <edu>大学</edu>     <work></work>     <renZh>1</renZh>     <brithday>2月14日</brithday> </person></PERSONS>

xml.sax

处理时并不会像dom一样可以以类似节点的维度进行读取

它只有 开始标签  内容  结束标签 之分

处理思想是:通过一个handler,对开始标签,内容,结束标签各有一个处理函数

直接上代码+注解

#person 处理类from xml.sax import handler,parseStringclass PersonHandler(handler.ContentHandler):  def __init__(self, db_ops):    #db op obj    self.db_ops = db_ops    #存储一个person的map    self.person = {}    #当前的tag    self.current_tag = ""    #是否是tag之间的内容 ,目的拿到tag间内容,不受空白的干扰    self.in_quote = 0  #开始,清空map  def startElement(self, name, attr):    #以person,清空map    if name == "person":      self.person = {}    #记录 状态    self.current_tag = name    self.in_quote = 1  #结束,插入数据库  def endElement(self, name):    #以person结尾  代表读取一个person的信息结束    if name == "person":      #do something      in_fields = tuple([ ('"' + self.person.get(i,"") + '"')  for i in fields ])      print in_sql % in_fields      db_ops.insert( in_sql%(in_fields))    #处理    self.in_quote = 0  def characters(self, content):    #若是在tag之间的内容,更新到map中    if self.in_quote:      self.person.update({self.current_tag: content})



最后加上插入数据库的部分

#!/usr/bin/python# -*- coding:utf-8 -*-#parse_person.py#version : 0.1#author : wukunliang@163.com#desc : parse person.xml and out sqlimport sys,osimport MySQLdbreload(sys)sys.setdefaultencoding('utf-8')in_sql = "insert into person(id,sex,address,fansNum,summary,wbNum,gzNum,blog,edu,work,renZh,brithday) values(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"fields = ("id","sex","address","fansNum","summary","wbNum","gzNum","blog","edu","work","renZh","brithday")#数据库方法class Db_Connect:  def __init__(self, db_host, user, pwd, db_name, charset="utf8",  use_unicode = True):    print "init begin"    print db_host, user, pwd, db_name, charset , use_unicode    self.conn = MySQLdb.Connection(db_host, user, pwd, db_name, charset=charset , use_unicode=use_unicode)    print "init end"  def insert(self, sql):     try:      n = self.conn.cursor().execute(sql)      return n     except MySQLdb.Warning, e:      print "Error: execute sql '",sql,"' failed"  def close(self):    self.conn.close()#person 处理类from xml.sax import handler,parseStringclass PersonHandler(handler.ContentHandler):  def __init__(self, db_ops):    #db op obj    self.db_ops = db_ops    #存储一个person的map    self.person = {}    #当前的tag    self.current_tag = ""    #是否是tag之间的内容    self.in_quote = 0  #开始,清空map  def startElement(self, name, attr):    #以person,清空map    if name == "person":      self.person = {}    #记录 状态    self.current_tag = name    self.in_quote = 1  #结束,插入数据库  def endElement(self, name):    #以person结尾  代表读取一个person的信息结束    if name == "person":      #do something      in_fields = tuple([ ('"' + self.person.get(i,"") + '"')  for i in fields ])      print in_sql % in_fields      db_ops.insert( in_sql%(in_fields))    #处理    self.in_quote = 0  def characters(self, content):    #若是在tag之间的内容,更新到map中    if self.in_quote:      self.person.update({self.current_tag: content})if __name__ == "__main__":  f = open("./person.xml")  #如果源文件gbk  转码      若是utf-8,去掉decode.encode  db_ops = Db_Connect("127.0.0.1", "root", "root", "test")  parseString(f.read().decode("gbk").encode("utf-8"), PersonHandler(db_ops))  f.close()  db_ops.close()


平时拿python来分析数据,工具脚本还有hadoop streamming,但是用的面和深度实在欠缺

只能说道行还浅,需要多多实践


The end!

原创粉丝点击