前面已经给大家介绍了在设计天气预报demo中如何设计界面和从网络天气API接口中获取天气数据,但是实际应用中我们可能只需要非常少的一部分天气数据,并且能够见这部分数据提取出来进行单独的显示或者应用,如在你的DIY中你可能只需要在界面中显示一些指数提示,或者只需要简单的天气状态等,这时候我们就需要对获取的数据进行解析了,今天这篇blog中将进一步教大家如何对获取到的XML格式的天气数据进行解析。
下图是天气XML数据格式,其实XML的语法非常简单,主要由标签和内容组成,标签是由起始标签和结尾标签组成,并且可以进行嵌套,这样在解析的过程中,我们通常可以通过判断是否是起始标签,然后读入数据即可,采用循环或者递归的方法都可以完成对xml的解析。
目前对于XML的解析,已经有很多组件接口可以直接调用,而不需要我们再去从最底层的字符匹配,标签匹配等去编程了,我们只需要掌握这些接口的调用即可,在pyqt中也提供了QtXml类来用于解析XML文件,这里提供了多种xml文件解析方法,我们将用其提供的QXmlStreamReader方法来实现对XML的处理,这是一种基于流的解析方法,通常比较适合不需要反复的读取数据的场合,在该方法中提供的API接口主要有以下几个常用的,当然还有许多其他的API接口,大家可以参考QT官方文档。
readNext():从xml输入流中读取下一个记号
name():记号的名称,即<名称></名称>
isStartElement():判断当前已读取的记号是否为开始元素,开始元素即<>
isEndElement():判断当前已读取的记号是否为结束元素,结束元素即</>
readElementText():读取当前记号对应的文本值,<>文本值</>
atEnd():判断是否为文件结尾
了解了这些我们就可以调用这些接口来获取标签名和判断是否是起始标签,并且可以放的读取标签文本信息。
上一篇blog中,我们用weatherInfo = bytes.decode(pbyte)语句获取了天气信息并进行了打印,这里其实我们weatherInfo实一个字符数组,我们可以直接调用weatherXml= QtCore.QXmlStreamReader(weatherInfo)函数就可以读入到XML流中,这样就可以通过weatherXML对象来实现对XML流的相关操作,这里我们写了一个解析从新浪获取的天气数据的python类来实现对天气数据的解析,其中代码如下:
from PyQt5 import QtWidgets, QtCore, QtXml, QtGui,QtNetwork
from mainwindow import Ui_MainWindow
#from QtGui import QPixmap
import res
import time
class getWeatherInfo(object):
def __init__(self,weatherXml):
self.weather_updateOK=0
self.weather_city=""
self.weather_wendu=""
self.weahter_updatetime=""
self.weather_suggest=""
self.weather_fengli=""
self.weather_fengxiang=""
self.weather_sunrise=""
self.weather_sunset=""
self.forecast_weather_info_date=[]
self.forecast_weather_info_high=[]
self.forecast_weather_info_low=[]
self.forecast_weather_info_dtype=[]
self.forecast_weather_info_dfengxiang=[]
self.forecast_weather_info_dfengli=[]
self.forecast_weather_info_ntype=[]
self.forecast_weather_info_nfengxiang=[]
self.forecast_weather_info_nfengli=[]
#指数
self.weather_zhishu_name=[]
self.weather_zhishu_vale=[]
self.weather_zhishu_data=[]
self.prassWeatherInfo(weatherXml)
def prassWeatherInfo(self,weatherXml):
print("start prassWeatherInfo")
while not weatherXml.atEnd():
if weatherXml.hasError():
print ("error: get weather data error")
return -1
elif weatherXml.isStartElement():
if weatherXml.name()=="city":
self.weather_city = weatherXml.readElementText()
#print(city)
weatherXml.readNext()
elif weatherXml.name()=="updatetime":
self.weahter_updatetime=weatherXml.readElementText()
weatherXml.readNext()
elif weatherXml.name()=="wendu":
self.weather_wendu=weatherXml.readElementText()
weatherXml.readNext()
elif weatherXml.name()=="fengli":
self.weather_fengli=weatherXml.readElementText()
weatherXml.readNext()
elif weatherXml.name()=="shidu":
self.weather_shidu=weatherXml.readElementText()
weatherXml.readNext()
elif weatherXml.name()=="fengxiang":
self.weather_fengxiang=weatherXml.readElementText()
weatherXml.readNext()
elif weatherXml.name()=="sunrise_1":
self.weather_sunrise=weatherXml.readElementText()
weatherXml.readNext()
elif weatherXml.name()=="sunset_1":
self.weather_sunset=weatherXml.readElementText()
weatherXml.readNext()
elif weatherXml.name()=="environment":
print("environment")
while not weatherXml.atEnd():
print("test")
if weatherXml.name()=="suggest":
self.weather_suggest=weatherXml.readElementText()
print("suggest")
break
else:
weatherXml.readNext()
elif weatherXml.name()=="forecast":
#print(weatherXml.readElementText())
print("forecast")
weatherXml.readNext()
while not weatherXml.atEnd():
if weatherXml.isStartElement():
if weatherXml.name()=="weather":
weatherXml.readNext()
while not weatherXml.atEnd():
if weatherXml.isStartElement():
if weatherXml.name()=="date":
#print("weather info")
date = weatherXml.readElementText()
self.forecast_weather_info_date.append(date)
weatherXml.readNext()
#print(date)
elif weatherXml.name()=="high":
high=weatherXml.readElementText()
self.forecast_weather_info_high.append(high)
weatherXml.readNext()
#print(high)
elif weatherXml.name()=="low":
low=weatherXml.readElementText()
self.forecast_weather_info_low.append(low)
weatherXml.readNext()
#print(low)
elif weatherXml.name()=="day":
#print("day info")
weatherXml.readNext()
while not weatherXml.atEnd():
if weatherXml.isStartElement():
if weatherXml.name()=="type":
type = weatherXml.readElementText()
self.forecast_weather_info_dtype.append(type)
weatherXml.readNext()
#print("type:")
#print(type)
elif weatherXml.name()=="fengxiang":
ffengxiang=weatherXml.readElementText()
self.forecast_weather_info_dfengxiang.append(ffengxiang)
weatherXml.readNext()
#print(ffengxiang)
elif weatherXml.name()=="fengli":
ffengli=weatherXml.readElementText()
print("fenli")
self.forecast_weather_info_dfengli.append(ffengli)
weatherXml.readNext()
#print(ffengli)
else:
weatherXml.readNext()
#break
else:
weatherXml.readNext()
break
elif weatherXml.name()=="night":
#print("night info:")
weatherXml.readNext()
while not weatherXml.atEnd():
if weatherXml.isStartElement():
if weatherXml.name()=="type":
ntype=weatherXml.readElementText()
self.forecast_weather_info_ntype.append(ntype)
weatherXml.readNext()
#print(ntype)
elif weatherXml.name()=="fengxiang":
nfengxiang=weatherXml.readElementText()
self.forecast_weather_info_nfengxiang.append(nfengxiang)
weatherXml.readNext()
#print(nfengxiang)
elif weatherXml.name()=="fengli":
nfengli=weatherXml.readElementText()
print("nfenli")
self.forecast_weather_info_nfengli.append(nfengli)
weatherXml.readNext()
#print(nfengli)
else:
weatherXml.readNext()
#break
else:
weatherXml.readNext()
break
else:
weatherXml.readNext()
else:
weatherXml.readNext()
break
else:
weatherXml.readNext()
else:
weatherXml.readNext()
break
elif weatherXml.name()=="zhishus":
#print("zhishus:")
weatherXml.readNext()
while not weatherXml.atEnd():
if weatherXml.isStartElement():
if weatherXml.name()=="zhishu":
print("zhishu2:")
weatherXml.readNext()
while not weatherXml.atEnd():
if weatherXml.isStartElement():
if weatherXml.name()=="name":
self.weather_zhishu_name.append(weatherXml.readElementText())
#print("name")
#print(self.weather_zhishu_name)
weatherXml.readNext()
elif weatherXml.name()=="value":
self.weather_zhishu_vale.append(weatherXml.readElementText())
#print("value")
weatherXml.readNext()
elif weatherXml.name()=="detail":
self.weather_zhishu_data.append(weatherXml.readElementText())
#print("detail")
#print(weatherXml.readElementText())
weatherXml.readNext()
else:
weatherXml.readNext()
else:
weatherXml.readNext()
break
else:
weatherXml.readNext()
else:
weatherXml.readNext()
break
else:
weatherXml.readNext()
else:
weatherXml.readNext()
weatherXml.clear()
self.updateOK=1
for i in range(0,5):
print(self.weather_zhishu_name[i])
print(self.weather_zhishu_vale[i])
print(self.weather_zhishu_data[i])
def updateOK(self):
return self.updateOK
通过调用该类就可以实现对xml文件中个的天气数据的解析,并且通过访问类成员就可以获取相应的天气信息。
如下图所示,是调用该类解析得到的天气指数数据:
以上就是整个天气xml数据解析的过程,后期blog中我将用该类来实现天气demo中的xml数据解析,并且在dragonboard 410c平台上完成整个天气demo的设计和实现。