pyqt 把控制台信息显示到_实战PyQt5: 131-使用HTTP请求获得城市天气信息

eb4c9c1ceb06d0300e49e5c764ef0fff.png

在网络时代,我们随时可能要关注的信息之一就是天气,在本文中我们使用HTTP请求来从网站上抓取天气信息的JSON数据,并使用Qt中有关JSON数据处理类来完成对这些数据的解析,并提取天气状态(阴,晴,雨等),最低最高温,风力,感冒指数等信息并显示出来。

PyQt中对JSON的支持

JSON是一种编码来自Javascript的对象数据的格式,现已广泛用作Internet上的数据交换格式。PyQt提供了处理JSON数据的支持。

PyQt中的JSON支持包括以下类:

  • QJsonDocument:读写JSON文档的方式
  • QJsonParseError:用于在JSON解析期间报告错误
  • QJsonValue:将值封装在JSON中

QJsonDocument

QJsonDocument类提供了一种读取和写入JSON文档的方法。QJsonDocument是包装完整的JSON文档的类,可以从基于UTF-8编码的文本表示形式以及Qt自己的二进制格式读取和写入此文档。使用QJsonDocument. fromJson()将JSON文档从其基于文本的表示形式转换为QJsonDocument. 使用toJson()将其转换回文本。

常用函数:

  • fromJson(json, error): 静态方法, 将json解析为UTF-8编码的JSON文档,并从中创建QJsonDocument。如果解析成功,则返回有效的QJsonDocument。如果失败,则返回的文档将为null,并且可选的error变量将包含有关该错误的更多详细信息。
  • toJson(self): 将QJsonDocument转换为缩进的UTF-8编码的JSON文档。

QJsonParseError

QJsonParseError类用于在JSON解析期间报告错误。错误类型由枚举量QJsonParseError.ParseError表示:

  • QJsonParseError.NoError (0): 没有发生错误
  • QJsonParseError.UnterminatedObject (1): 对象未正确用大括号括起来
  • QJsonParseError.MissingNameSeparator (2): 缺少分隔不同项目的逗号
  • QJsonParseError.UnterminatedArray (3): 数组未正确用方括号括起来
  • QJsonParseError.MissingValueSeparator (4): 缺少将键与对象内的值分隔开的冒号
  • QJsonParseError.IllegalValue (5): 该值是非法的
  • QJsonParseError.TerminationByNumber (6): 输入流在解析数字时结束
  • QJsonParseError.IllegalNumber (7): 数字格式不正确
  • QJsonParseError.IllegalEscapeSequence (8): 输入中发生非法的转义序列
  • QJsonParseError.IllegalUTF8String (9): 输入中出现非法的UTF8序列
  • QJsonParseError.UnterminatedString (10): 字符串未以引号终止
  • QJsonParseError.MissingObject (11): 预期有一个对象,但找不到
  • QJsonParseError.DeepNesting (12): JSON文档的嵌套太深,解析器无法对其进行解析
  • QJsonParseError.DocumentTooLarge (13): JSON文档太大,解析器无法解析它
  • QJsonParseError.GarbageAtEnd (14): 解析的文档末尾包含其他垃圾字符

QJsonParseError常用函数:

  • errorString(self):返回适合于所报告的JSON解析错误的人类可读信息。

QJsonValue

JSON是一种存储结构化数据的格式。它具有6种基本数据类型:

  • QJsonValue.Null: 空类型
  • QJsonValue.Bool:布尔型
  • QJsonValue.Double:双精度浮点数
  • QJsonValue.String:字符串
  • QJsonValue.Array:数组
  • QJsonValue.Object:对象类型

城市天气信息演示

代码演示了使用Http请求从网站中下载天气信息,并使用Qt提供的JSON支持,将数据解析提出出来,显示在界面上,在程序中, 省会级一些知名城市可以直接选择,然后获得天气信息,也可以手动输入城市名来查询天气信息。完整代码如下:

import sysfrom PyQt5 import QtCore, QtGui, QtWidgetsfrom PyQt5.QtCore import Qt, QJsonDocument, QJsonParseError, QUrl, pyqtSignalfrom PyQt5.QtWidgets import (QApplication, QWidget, QLabel, QPushButton, QLineEdit,                             QGroupBox,QComboBox, QVBoxLayout, QHBoxLayout, QFormLayout,                             QFrame, QPlainTextEdit)from PyQt5.QtNetwork import QNetworkRequest, QNetworkAccessManager, QNetworkReply class DemoWeather(QWidget):    getWeather = pyqtSignal(bool)        def __init__(self, parent=None):        super(DemoWeather, self).__init__(parent)                    # 设置窗口标题        self.setWindowTitle('实战 Qt for Python: 天气信息查询')              # 设置窗口大小        self.resize(420, 200)              self.initUi()                #保存数据        self.comfortLevel = ''  #舒适度(感冒指数)        self.cityName=''        #城市名称        self.weather=''         #天气类型        self.temperature=''     #温度范围        self.wind=''            #风                self.nam = QNetworkAccessManager(self)        self.nam.finished.connect(self.replyFinished)                self.getWeather.connect(self.slotGetWeather)                #初始情况,加入北京的天气        self.getWeatherData('北京')           #设置外观界面     def initUi(self):                #采用选择方式查询        cities = ['北京', '天津', '上海', '重庆', '哈尔滨', '长春', '沈阳', '石家庄', '济南', '郑州',                  '太原', '西安','呼和浩特', '银川', '兰州', '西宁','乌鲁木齐', '拉萨', '昆明', '成都',                   '贵阳','南宁', '广州', '海口', '福州', '南昌', '长沙', '武汉', '合肥', '南京', '杭州',                   '台北', '香港', '澳门', '深圳', '厦门', '青岛', '大连']        self.comboBoxCity = QComboBox()        self.comboBoxCity.addItems(cities)        self.comboBoxCity.activated.connect(self.selectCityChanged)                labelCity = QLabel('城市(&C)')        labelCity.setBuddy(self.comboBoxCity)                cityLayout = QFormLayout()        cityLayout.setSpacing(16)        cityLayout.addRow(labelCity, self.comboBoxCity)                #手动输入城市的方式查询        grpBox = QGroupBox('手动查询(&M)')        grpBox.setMaximumWidth(120)        self.editCity = QLineEdit()        #输入完成敲回车键查询        self.editCity.returnPressed.connect(self.slotQueryWeather)        btnQuery = QPushButton('查询')        btnQuery.clicked.connect(self.slotQueryWeather)                manualLayout = QFormLayout()        manualLayout.addRow('请输入城市名称:', self.editCity)        manualLayout.addRow('', btnQuery)        grpBox.setLayout(manualLayout)                #左边的布局        leftLayout = QVBoxLayout()        leftLayout.setSpacing(20)        leftLayout.addLayout(cityLayout)        leftLayout.addWidget(grpBox)        leftLayout.addStretch(1)                #右边信息显示        self.showCity = QLineEdit()        self.showCity.setReadOnly(True)        self.showWeather = QLineEdit()        self.showWeather.setReadOnly(True)        self.showTemperature = QLineEdit()        self.showTemperature.setReadOnly(True)        self.showWind = QLineEdit()        self.showWind.setReadOnly(True)        self.showComfortLevel = QPlainTextEdit()        self.showComfortLevel.setReadOnly(True)                #右边的布局        rightLayout = QFormLayout()        rightLayout.addRow('城市:', self.showCity)        rightLayout.addRow('天气:', self.showWeather)        rightLayout.addRow('温度:', self.showTemperature)        rightLayout.addRow('风力', self.showWind)        rightLayout.addRow('感冒指数:', self.showComfortLevel)                #分隔线        spacerLine = QFrame()        spacerLine.setFrameShape(QFrame.VLine)                mainLayout = QHBoxLayout()        mainLayout.setSpacing(16)        mainLayout.addLayout(leftLayout)        mainLayout.addWidget(spacerLine)        mainLayout.addLayout(rightLayout)        self.setLayout(mainLayout)              def selectCityChanged(self):        cityName = self.comboBoxCity.currentText()        self.getWeatherData(cityName)            def slotQueryWeather(self):        cityName = self.editCity.text()        self.getWeatherData(cityName)        #从网络上获得指定城市的天气数据信息    def getWeatherData(self, cityName):        url = 'http://wthrcdn.etouch.cn/weather_mini?city=%s' % cityName        print(url)        self.nam.get(QNetworkRequest(QUrl(url)))            #接收网络的回复数据    def replyFinished(self, reply):        data = reply.readAll()        #编码转换        #text = bytes.decode(data.data(), encoding='utf8')        #print(text)        self.processReplyData(data)        reply.deleteLater()        #解析接收到的数据    def processReplyData(self, data):        desc = ''        jsonErr = QJsonParseError()        jsonDoc = QJsonDocument.fromJson(data, jsonErr)        if jsonDoc.isNull():            #空对象,返回            return        rootObj = jsonDoc.object()        if 'data' in rootObj:            dataObj = rootObj['data'].toObject()            if 'forecast' in dataObj:                forecastObj = dataObj['forecast']                if forecastObj.isArray():                    valArray = forecastObj.toArray()                    #只取当天的数据                    val = valArray[0].toObject()                    self.weather=val['type'].toString() #天气类型                    lowTemp=val['low'].toString() #最低温度                    highTemp=val['high'].toString() #最高温度                    self.temperature=lowTemp[2:] + ' -' + highTemp[2:]                    fengxiang = val['fengxiang'].toString()                    fengli = val['fengli'].toString()                    self.wind = fengxiang + fengli[9:-3]                              if 'city' in dataObj:                cityObj = dataObj['city']                if cityObj.isString():                    self.cityName = cityObj.toString()                if 'ganmao': #舒适度指数                ganmaoObj = dataObj['ganmao']                if ganmaoObj.isString():                    self.comfortLevel = ganmaoObj.toString()        if 'desc' in rootObj: #描述信息            descObj = rootObj['desc']            if descObj.isString():                desc = descObj.toString()                        if desc == 'OK':            self.getWeather.emit(True)        else:            self.getWeather.emit(False)         def slotGetWeather(self, isGet):        if isGet:            self.showCity.setText(self.cityName)             self.showWeather.setText(self.weather)            self.showTemperature.setText(self.temperature)            self.showWind.setText(self.wind)            self.showComfortLevel.setPlainText(self.comfortLevel)        else:            self.showCity.setText('没有该城市天气信息')             self.showWeather.setText('')            self.showTemperature.setText('')            self.showWind.setText('')            self.showComfortLevel.setPlainText('')     if __name__ == '__main__':    app = QApplication(sys.argv)    window = DemoWeather()    window.show()    sys.exit(app.exec())   

运行结果如下图:

268e3fd66687e27efed76d068f0163db.gif

解析JSON数据

本文知识点

  • QT对JSON数据的支持;
  • 使用HTTP请求下载城市天气信息;
  • JSON数据解析方法。

前一篇:实战PyQt5: 130-使用HTTP请求下载文件

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
中怎么实现? 很简单,可以使用QPlainTextEdit控件来实现。首先在UI设计中添加一个QPlainTextEdit控件,并设置好其属性,然后在代码中将控制台的输出重定向到QPlainTextEdit控件中即可。 具体代码如下: ```python import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QPlainTextEdit class MainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.initUI() def initUI(self): self.resize(400, 300) # 添加QPlainTextEdit控件 self.text_edit = QPlainTextEdit(self) self.setCentralWidget(self.text_edit) # 重定向控制台输出到QPlainTextEdit控件中 sys.stdout = EmittingStream(textWritten=self.outputWritten) sys.stderr = EmittingStream(textWritten=self.outputWritten) def outputWritten(self, text): cursor = self.text_edit.textCursor() cursor.movePosition(cursor.End) cursor.insertText(text) self.text_edit.setTextCursor(cursor) self.text_edit.ensureCursorVisible() class EmittingStream(object): def __init__(self, textWritten=None): self.textWritten = textWritten def write(self, text): if self.textWritten: self.textWritten.emit(str(text)) if __name__ == '__main__': app = QApplication(sys.argv) window = MainWindow() window.show() # 启动应用程序的主循环,进入事件循环,等待事件的发生 sys.exit(app.exec_()) ``` 通过将sys.stdout和sys.stderr重定向到EmittingStream中,将控制台输出重定向到自定义的textWritten方法中,然后将输出添加到QPlainTextEdit控件中即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值