美文网首页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