大师兄的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'}]}
参考资料
- https://blog.csdn.net/u010138758/article/details/80152151 J-Ombudsman
- https://www.cnblogs.com/zhuluqing/p/8832205.html moisiet
- https://www.runoob.com 菜鸟教程
- http://www.tulingxueyuan.com/ 北京图灵学院
- http://www.imooc.com/article/19184?block_id=tuijian_wz#child_5_1 两点水
- https://blog.csdn.net/weixin_44213550/article/details/91346411 python老菜鸟
- https://realpython.com/python-string-formatting/ Dan Bader
- https://www.liaoxuefeng.com/ 廖雪峰
- https://blog.csdn.net/Gnewocean/article/details/85319590 新海说
- https://www.cnblogs.com/Nicholas0707/p/9021672.html Nicholas
- https://www.cnblogs.com/dalaoban/p/9331113.html 超天大圣
- https://blog.csdn.net/zhubao124/article/details/81662775 zhubao124
- https://blog.csdn.net/z59d8m6e40/article/details/72871485 z59d8m6e40
- 《Python学习手册》Mark Lutz
- 《Python编程 从入门到实践》Eric Matthes
本文作者:大师兄(superkmi)
网友评论