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


    博客已迁移, 新地址

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

    之前使用过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,parseString
    class 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 sql
    
    import sys,os
    import MySQLdb
    
    reload(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,parseString
    class 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!

    Meet so Meet. C plusplus I-PLUS....
  • 相关阅读:
    PL/SQL Developer 远程连接oracle数据库
    Python 类与对象 __init__()参数
    微信公众号--发送模板消息
    微信公众号--进入菜单之前获取用户信息
    微信公众号-自定义菜单
    Java--时间转换
    微信公众号--被动回复用户消息
    {"errcode":40017,"errmsg":"invalid button type hint: [I8nq_a0783sha1]"}
    在使用XStream时没有processAnnotations方法
    在idea的控制台中中文显示为乱码
  • 原文地址:https://www.cnblogs.com/iplus/p/4464653.html
Copyright © 2020-2023  润新知