出自廖雪峰python3教程课后练习题:
首先写一下两个让我掉坑里的知识点:
一、SAX解析XML
在Python中使用SAX解析XML非常简洁,SAX是流模式,边读边解析,占用内存小,解析快,缺点是我们需要自己处理事件。
常我们关心的事件是start_element
,end_element
和char_data
,准备好这3个函数,然后就可以解析xml了。
举个例子,当SAX解析器读到一个节点时:
<a href="/">python</a>
会产生3个事件:
-
start_element事件,在读取
<a href="/">
时; -
char_data事件,在读取
python
时; -
end_element事件,在读取
</a>
时。
再结合本练习题说明:
SAX解析器读到一个节点:
<yweather:condition code="32" date="Sat, 10 Mar 2018 08:00 AM CST" temp="37" text="Sunny"/>
因为没有单独的关闭标签,所以会产生2个事件:
1、start_element事件,name是yweather:condition,attrs是dict类型,值为{'code': '32', 'date': 'Sat, 10 Mar 2018 08:00 AM CST', 'temp': '37', 'text': 'Sunny'};
2、end_element事件,name是yweather:condition。
二、结果的存放
练习题的最后结果要是这种格式:
{ 'city': 'Beijing', 'forecast': [ { 'date': '2017-11-17', 'high': 43, 'low' : 26 }, { 'date': '2017-11-18', 'high': 41, 'low' : 20 }, { 'date': '2017-11-19', 'high': 43, 'low' : 19 } ] }
分析可得,结果是dict类型,key('city')对应的value是'Beijing',key('forecast)对应的value是一个list,并且list中存放的是一个个dict!!!
由于先前对dict和list认识不清,是这样错误的存放数据的:
Weather['city'] = attrs['city'] #读取城市,没问题,接下来读取每天天气情况就出错了 day = 0 #第一天的天气情况 Weather['forecast'][day]['date'] = attrs['date'] Weather['forecast'][day]['high'] = attrs['high'] Weather['forecast'][day]['low'] = attrs['low'] day = day + 1 #接下去一天
任何一门语言,入门容易,想熟练掌握,无他,只能唯手熟尔!
最后贴出自己写的练习题代码:
# -*- coding: utf-8 -*- from xml.parsers.expat import ParserCreate from urllib import request class DefaultSaxHandler(object): def __init__(self): self.data = {} #存放天气预报结果,是dict类型 def start_element(self, name, attrs): if name == 'yweather:location': #读取城市 self.data['city'] = attrs['city'] #键为‘city’, 值为city self.data['forecast'] = [] #键为‘forecast’,值为list类型,其中以dict类型存放每天的时间、最高温度、最低温度 if name == 'yweather:forecast': dateDict = {} #每天的天气情况 dateDict['date'] = attrs['date'] #日期 dateDict['high'] = attrs['high'] #最高温度 dateDict['low'] = attrs['low'] #最低温度 self.data['forecast'].append(dateDict) #将该日天气情况添加到list中 def parseXml(xml_str): print(xml_str) handler = DefaultSaxHandler() parser = ParserCreate() parser.StartElementHandler = handler.start_element parser.Parse(xml_str) #print(handler.data) #结果 return handler.data # 测试: URL = 'https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20%3D%202151330&format=xml' with request.urlopen(URL, timeout=4) as f: data = f.read() result = parseXml(data.decode('utf-8')) assert result['city'] == 'Beijing'