美文网首页Python
大师兄的Python学习笔记(十九): Python与(XML和

大师兄的Python学习笔记(十九): Python与(XML和

作者: superkmi | 来源:发表于2020-06-16 16:14 被阅读0次

    大师兄的Python学习笔记(十八): Python与HTTP
    大师兄的Python学习笔记(二十): 爬虫(一)

    一、XML和JSON简介

    1. 关于XML
    • XML(Extensible Markup Language, 扩展标记语言) ,是用于标记电子文件使其具有结构性的标记语言。
    • 可以标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。
    • 通常被用来传输和结构化存储数据。
    <?xml version="1.0" encoding="utf-8" ?>
    <Animal>
      <type>狗</type>
      <Dog category="dog1">
        <name>PP</name>
        <age>10</age>
        <sex>M</sex>
        <colour>lightgray</colour>   
      </Dog>
      <Dog category="dog2">
        <name>QQ</name>
        <age>1.5</age>
        <sex>M</sex>
        <colour>darkgray</colour>   
      </Dog>
      <Dog category="dog3">
        <name>doudou</name>
        <age>0</age>
        <sex>F</sex>
        <colour>gray</colour>   
      </Dog>
    </Animal>
    
    2. 关于JSON
    • JSON(JavaScript Object Notation)一种轻量级的数据交换格式。
    • 具有良好的可读和便于快速编写的特性。
    • 采用兼容性很高的、完全独立于语言文本格式,同时也具备类似于C语言的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)体系的行为。
    • 通常被用来存储数据或在不同平台之间进行数据交换。
    {
        "type":"狗",
        "Dog":[
            {
                "name":"PP",
                "age":10,
                "sex":"M",
                "colour":"lightgray"
            },
            {
                "name":"QQ",
                "age":1.5,
                "sex":"M",
                "colour":"darkgray"
            },
            {
                "name":"doudou",
                "age":0,
                "sex":"F",
                "colour":"gray"
            }
        ]
    }
    
    3. XML和JSON的比较
    3.1 XML的优缺点

    1) XML的优点

    • 与HTML格式相似,有利于页面展示。
    • 容易与其他系统进行远程交互,数据共享比较方便。

    2) XML的缺点

    • 文件庞大,文件格式复杂,传输占带宽。
    • 服务器端和客户端都需要花费大量代码来解析XML,导致服务器端和客户端代码变得异常复杂且不易维护。
    • 客户端不同浏览器之间解析XML的方式不一致,需要重复编写很多代码;
    • 数据类型只支持字符串。
    3.2 JSON的优缺点

    1) JSON的优点

    • 数据格式比较简单,易于读写,格式都是压缩的,占用带宽小;
    • 易于解析,客户端JavaScript可以简单的通过eval()进行JSON数据的读取;
    • 支持多种语言: ActionScript, C, C#, ColdFusion, Java, JavaScript, Perl, PHP, Python, Ruby等。
    • 支持多种数据类型:字符串,数字,数组,布尔值。

    2) JSON的缺点

    • 对人来说可读性比XML弱。

    二、Python与XML

    • XML包是Python处理XML语言的核心工具。
    • XML包包含四个子模块:
    模块 简介
    dom - 实现W3C制定的DOM API。
    - DOM解析器在任何处理开始之前,必须把基于XML文件生成的树状数据放在内存,所以DOM解析器的内存使用量完全根据输入资料的大小。
    sax - 实现SAX API。
    - sax牺牲了便捷性来换取速度和内存占用,它是事件驱动的,并不需要一次性读入整个文档,而文档的读入过程也就是SAX的解析过程。
    etree - 一个轻量级、Pythonic的API。
    - 与DOM相比,他的速度更快,API使用更直接、方便。
    - 与SAX相比,ET.iterparse函数同样提供了按需解析的功能,不会一次性在内存中读入整个文档。
    - ET的性能与SAX模块大致相仿,但是它的API更加高层次,用户使用起来更加便捷。
    parser 封装了XML解析器接口,目前只支持C语言编写的expat解析器。
    1. 生成XML
    • 使用xml.dom.minidom模块生成XML代码。
    import xml.dom.minidom
    
    # 创建XML内容
    >>>def create_Xml():
    >>>    # 创建dom文档
    >>>    doc = xml.dom.minidom.Document()
    
    >>>    # 创建根节点
    >>>    orderlist = doc.createElement('orderlist')
    
    >>>    # 插入dom树
    >>>    doc.appendChild(orderlist)
    
    >>>    node_type = doc.createElement('type')
    >>>    orderlist.appendChild(node_type)
    >>>    # 插入文字节点
    >>>    node_type_text = doc.createTextNode("dogs")
    >>>    node_type.appendChild(node_type_text)
    
    >>>    # 创建子节点
    >>>    node_dog_1 = doc.createElement('dog')
    >>>    node_dog_name = doc.createElement('name')
    >>>    node_dog_age = doc.createElement('age')
    >>>    node_dog_colour = doc.createElement('colour')
    >>>    orderlist.appendChild(node_dog_1)
    >>>    node_dog_1.appendChild(node_dog_name)
    >>>    node_dog_1.appendChild(node_dog_age)
    >>>    node_dog_1.appendChild(node_dog_colour)
    >>>    # 增加属性
    >>>    node_dog_1.setAttribute("category", "dog1")
    
    >>>    # 插入文字节点
    >>>    node_dog_1_name = doc.createTextNode("pp")
    >>>    node_dog_name.appendChild(node_dog_1_name)
    >>>    node_dog_1_age = doc.createTextNode("10")
    >>>    node_dog_age.appendChild(node_dog_1_age)
    >>>    node_dog_1_colour = doc.createTextNode("darkgray")
    >>>    node_dog_colour.appendChild(node_dog_1_colour)
    >>>    return doc.toprettyxml(indent='\t')
    
    >>>if __name__ == '__main__':
    >>>    print(create_Xml())
    
    <?xml version="1.0" ?>
    <orderlist>
        <type>dogs</type>
        <dog category="dog1">
            <name>pp</name>
            <age>10</age>
            <colour>darkgray</colour>
        </dog>
    </orderlist>
    
    2. 解析XML
    2.1 使用DOM解析XML
    >>>import xml.dom.minidom,os
    >>>from xml.dom.minidom import parse
    
    >>># 读取XML文档
    >>>path = os.path.join('D:\\','sample.xml')
    >>>DOMTree = parse(path)
    >>>animal = DOMTree.documentElement
    
    >>># 获取子节点
    >>>dogs = animal.getElementsByTagName("Dog")
    >>>for dog in dogs:
    >>>    # 获得属性
    >>>    if dog.hasAttribute("category"):
    >>>        print(f'category:{dog.getAttribute("category")}')
    >>>    # 获得子节点
    >>>    name = dog.getElementsByTagName("name")[0]
    >>>    print(f'name:{name.childNodes[0].data}')
    
    >>>    age = dog.getElementsByTagName("age")[0]
    >>>    print(f'age:{age.childNodes[0].data}')
    
    >>>    sex = dog.getElementsByTagName("sex")[0]
    >>>    print(f'sex:{sex.childNodes[0].data}')
    
    >>>    colour = dog.getElementsByTagName("colour")[0]
    >>>    print(f'colour:{colour.childNodes[0].data}')
    
    >>>    print(f"{'*'*20}")
    category:dog1
    name:PP
    age:10
    sex:M
    colour:lightgray
    ********************
    category:dog2
    name:QQ
    age:1.5
    sex:M
    colour:darkgray
    ********************
    category:dog3
    name:doudou
    age:0
    sex:F
    colour:gray
    ********************
    
    2.2 使用SAX解析XML
    • SAX基于事件驱动,解析XML文档涉及两个部分,解析器和事件处理器:

    1) 解析器 xml.sax.parse()

    • 负责读取XML文档,并向事件处理器发送事件,如元素开始跟元素结束事件。
    • xml.sax.make_parser(parser_list): 创建并返回一个解析器对象。
    • xml.sax.parse( xmlfile, contenthandler, errorhandler):创建一个 SAX 解析器并解析xml文档。
    • xml.sax.parseString(xmlstring, contenthandler, errorhandler):创建一个XML解析器并解析xml字符串。

    2) 事件处理器 xml.sax.handler.ContentHandler()

    • 负责对事件作出响应,对传递的XML数据进行处理。
    • characters(content): 遇到标签间内容时调用。
    • startDocument(): 文档启动的时候调用。
    • endDocument(): 解析器到达文档结尾时调用。
    • startElement(name, attrs) : 遇到XML开始标签时调用,name为标签名,attrs为标签属性值。
    • endElement(name): 遇到XML结束标签时调用。
    >>>import xml.sax,os
    >>>from xml.sax import make_parser
    
    >>>class AnimalHandler(xml.sax.ContentHandler):
    >>>    def __init__(self):
    >>>        self.CurrentData = ""
    >>>        self.type = ""
    >>>        self.name = ""
    >>>        self.age =""
    >>>        self.sex = ""
    >>>        self.colour = ""
    
    >>>    # 处理开始元素事件
    >>>    def startElement(self,tag,attributes):
    >>>        self.CurrentData = tag
    >>>        if tag == "Dog":
    >>>            print(f"{'*'*20}")
    >>>            print(f'category:{attributes["category"]}')
    
    >>>    # 处理结束元素事件
    >>>    def endElement(self,tag):
    >>>        if self.CurrentData == "type":
    >>>            print(f"type:{self.type}")
    >>>        elif self.CurrentData == "name":
    >>>            print(f"name:{self.name}")
    >>>        elif self.CurrentData == "age":
    >>>            print(f"age:{self.age}")
    >>>        elif self.CurrentData == "sex":
    >>>            print(f"sex:{self.sex}")
    >>>        elif self.CurrentData == "colour":
    >>>            print(f"colour:{self.colour}")
    >>>        self.CurrentData = ""
    
    >>>    # 文档结束时
    >>>    def endDocument(self):
    >>>        print(f"{'*'*20}")
    
    >>>    # 内容事件处理
    >>>    def characters(self,content):
    >>>        if self.CurrentData == "type":
    >>>            self.type = content
    >>>        elif self.CurrentData == "name":
    >>>            self.name = content
    >>>        elif self.CurrentData == "age":
    >>>            self.age = content
    >>>        elif self.CurrentData == "sex":
    >>>            self.sex = content
    >>>        elif self.CurrentData == "colour":
    >>>            self.colour = content
    
    >>>if __name__ == '__main__':
    >>>    path = os.path.join('D:\\', 'sample.xml')
    >>>    parser = make_parser() # 创建reader
    >>>    parser.setFeature(xml.sax.handler.feature_namespaces,0) # 去掉空格
    >>>    handler = AnimalHandler()
    >>>    parser.setContentHandler(handler)
    >>>    parser.parse(path)
    type:狗
    ********************
    category:dog1
    name:PP
    age:10
    sex:M
    colour:lightgray
    ********************
    category:dog2
    name:QQ
    age:1.5
    sex:M
    colour:darkgray
    ********************
    category:dog3
    name:doudou
    age:0
    sex:F
    colour:gray
    ********************
    
    2.3 使用ETREE解析XML
    >>>import xml.etree.ElementTree as et
    >>>import os
    
    >>>path = os.path.join('D:\\', 'sample.xml')
    
    >>>tree = et.parse(path) # 获得etree对象
    >>>root = tree.getroot() # 获取根节点
    
    >>># 遍历XML文件
    >>>for child in root:
    >>>    print(f"{'*'*20}\n{child.tag}:{child.attrib if child.attrib else child.text}")
    >>>    for sub in child:
    >>>        print(f'{sub.tag}:{sub.text}')
    ********************
    type:狗
    ********************
    Dog:{'category': 'dog1'}
    name:PP
    age:10
    sex:M
    colour:lightgray
    ********************
    Dog:{'category': 'dog2'}
    name:QQ
    age:1.5
    sex:M
    colour:darkgray
    ********************
    Dog:{'category': 'dog3'}
    name:doudou
    age:0
    sex:F
    colour:gray
    
    3. 查找XML节点
    • 使用etree查找节点。
    >>>import xml.etree.ElementTree as et
    >>>import os
    
    >>>path = os.path.join('D:\\', 'sample.xml')
    
    >>>tree = et.parse(path) # 获得etree对象
    >>>root = tree.getroot() # 获取根节点
    
    >>>aim_node = root.find('Dog') # 查找第一个Dog节点
    >>>print(aim_node.tag,aim_node.attrib)
    Dog {'category': 'dog1'}
    
    >>>aim_nodes = root.findall('Dog') # 查找所有Dog节点
    >>>print(aim_nodes[1].tag,aim_nodes[1].attrib)
    Dog {'category': 'dog2'}
    
    4. 删除XML节点
    • 使用etree删除节点。
    >>>import xml.etree.ElementTree as et
    >>>import os
    
    >>>path = os.path.join('D:\\', 'sample.xml')
    
    >>>tree = et.parse(path) # 获得etree对象
    >>>root = tree.getroot() # 获取根节点
    
    >>>aim_node = root.find('Dog') # 查找第一个Dog节点
    >>>root.remove(aim_node) # 删除节点
    >>>tree.write('temp.xml')
    
    <Animal>
    <type>狗</type>
    <Dog category="dog2">
    <name>QQ</name>
    <age>1.5</age>
    <sex>M</sex>
    <colour>darkgray</colour>
      
    </Dog>
    <Dog category="dog3">
    <name>doudou</name>
    <age>0</age>
    <sex>F</sex>
    <colour>gray</colour>
      
    </Dog>
    </Animal>
    

    三、Python与JSON

    • json包是Python的基础包,用于处理JSON格式文档或对象。
    • json包中常用以下四个方法:
    方法 简介
    dump 将Python对象序列化,转为符合JSON格式的String,并写入文件。
    dumps 将Python对象序列化,转为符合JSON格式的String。
    load 读取JSON文件,并创建dict。
    loads 将符合JSON格式的String转为dict。
    1. json.dump(obj,fp)
    • 将Python对象序列化,转为符合JSON格式的String,并写入文件。
    >>>import json,os
    
    >>>data = {
    >>>    "type":"狗",
    >>>    "Dog":[
    >>>        {
    >>>            "name":"PP",
    >>>            "age":10,
    >>>            "sex":"M",
    >>>            "colour":"lightgray"
    >>>        },
    >>>        {
    >>>            "name":"QQ",
    >>>            "age":1.5,
    >>>            "sex":"M",
    >>>            "colour":"darkgray"
    >>>        },
    >>>        {
    >>>            "name":"doudou",
    >>>            "age":0,
    >>>            "sex":"F",
    >>>            "colour":"gray"
    >>>        }
    >>>    ]
    >>>}
    >>>with open("sample1.json","w") as f:
    >>>    json.dump(data,f) # 将数据储存到json文件中
    >>>os.system("type sample1.json") # 控制台打印文件内容
    {"type": "\u72d7", "Dog": [{"name": "PP", "age": 10, "sex": "M", "colour": "lightgray"}, {"name": "QQ", "age": 1.5, "sex": "M", "colour": "darkgray"}, {"name": "doudou", "age": 0, "sex": "F", "colour": "gray"}]}
    
    2. json.dumps(obj)
    • 将Python对象序列化,转为符合JSON格式的String。
    >>>import json
    
    >>>data = {
    >>>    "type":"狗",
    >>>    "Dog":[
    >>>        {
    >>>            "name":"PP",
    >>>            "age":10,
    >>>            "sex":"M",
    >>>            "colour":"lightgray"
    >>>        },
    >>>        {
    >>>            "name":"QQ",
    >>>            "age":1.5,
    >>>            "sex":"M",
    >>>            "colour":"darkgray"
    >>>        },
    >>>        {
    >>>            "name":"doudou",
    >>>            "age":0,
    >>>            "sex":"F",
    >>>            "colour":"gray"
    >>>        }
    >>>    ]
    >>>}
    >>>data_json = json.dumps(data)
    >>>print(f"type:{type(data_json)}")
    >>>print(data_json)
    type:<class 'str'>
    {"type": "\u72d7", "Dog": [{"name": "PP", "age": 10, "sex": "M", "colour": "lightgray"}, {"name": "QQ", "age": 1.5, "sex": "M", "colour": "darkgray"}, {"name": "doudou", "age": 0, "sex": "F", "colour": "gray"}]}
    
    3. json.load(fp)
    • 读取JSON文件,并创建dict。
    >>>import json,os
    
    >>>path = os.path.join("sample1.json")
    >>>with open(path,'r') as f: # 读取文件并获得文件对象
    >>>    data = json.load(f) # 读取json文件并创建dict
    >>>print(f"type:{type(data)}")
    >>>print(data)
    type:<class 'dict'>
    {'type': '狗', 'Dog': [{'name': 'PP', 'age': 10, 'sex': 'M', 'colour': 'lightgray'}, {'name': 'QQ', 'age': 1.5, 'sex': 'M', 'colour': 'darkgray'}, {'name': 'doudou', 'age': 0, 'sex': 'F', 'colour': 'gray'}]}
    
    4. json.loads(s)
    • 将符合JSON格式的String转为dict。
    >>>import json
    
    >>>s = '{"type": "\u72d7", "Dog": [{"name": "PP", "age": 10, "sex": "M", "colour": "lightgray"}, {"name": "QQ", "age": 1.5, "sex": "M", "colour": "darkgray"}, {"name": "doudou", "age": 0, "sex": "F", "colour": "gray"}]}'
    >>>data = json.loads(s)
    >>>print(f"type:{type(data)}")
    >>>print(data)
    type:<class 'dict'>
    {'type': '狗', 'Dog': [{'name': 'PP', 'age': 10, 'sex': 'M', 'colour': 'lightgray'}, {'name': 'QQ', 'age': 1.5, 'sex': 'M', 'colour': 'darkgray'}, {'name': 'doudou', 'age': 0, 'sex': 'F', 'colour': 'gray'}]}
    

    参考资料



    本文作者:大师兄(superkmi)

    相关文章

      网友评论

        本文标题:大师兄的Python学习笔记(十九): Python与(XML和

        本文链接:https://www.haomeiwen.com/subject/bynstktx.html