PyQt5应用实例]获取城市天气预报

hegangben
2025-05-20 / 0 评论 / 1 阅读 / 正在检测是否收录...

目录
一、获取天气数据
二、获取不同城市的天气预报API
三、界面实现
四、将界面文件转换为.py文件
五、调用主窗口类
六、使用PyInstaller打包项目生成EXE文件
一、获取天气数据
使用Python获取天气数据有两种方法:1、通过爬虫的方式,获取天气预报网站的HTML页面,然后使用XPath或BeautifulSoup解析HTML页面的内容;2、通过天气预报网站提供的API,直接获取结构化数据,省去了解析HTML页面这一步。
本例使用中国天气网站提供的API,中国天气官网地址:http://www.weather.com.cn。获取天气数据使用的是Requests库,它是使用Python语言基于urllib编写的HTTP库,需要使用pip命令进行安装。

pip install requests

Requests库包含一个名为json的方法,当请求的地址返回的是JSON格式的数据时,直接使用该方法访问即可,而不需要再使用Python标准库中的json库。

二、获取不同城市的天气预报API
请求地址是:http://www.weather.com.cn/data/sk/城市代码.html,部分城市代码:北京 101010100,上海 101020100,完整的城市代码可在网上搜索到(全国各个城市代码)。
返回参数如下表所示。

名称 描述
weatherinfo weatherInfo消息根节点
city 城市中文名
cityid 城市ID
temp 温度
WD 风向
WS 风力
SD 湿度
WSE 风力
time 发布时间
rain 是否下雨,1:有雨,0:无雨
isRadar 是否有雷达图,1:有雷达图,0:没有雷达图
Radar 雷达图编号,雷达图地址:http://www.weather.com.cn/html/radar/雷达图编号.shtml
测试代码:

import requests


if __name__ == "__main__":
    rep = requests.get("http://www.weather.com.cn/data/sk/101020100.html")
    rep.encoding = "utf-8"

    print("Result: %s" % rep.json())
    print("City: %s" % rep.json()["weatherinfo"]["city"])
    print("Wind Direction: %s" % rep.json()["weatherinfo"]["WD"])
    print("Temperature: %s" % rep.json()["weatherinfo"]["temp"] + " °C")
    print("Wind Strength: %s" % rep.json()["weatherinfo"]["WS"])
    print("Humidity: %s" % rep.json()["weatherinfo"]["SD"])

输出结果:

Result: {'weatherinfo': {'city': '上海', 'cityid': '101020100', 'temp': '23.5', 'WD': '东北风', 'WS': '小于3级', 'SD': '80%', 'AP': '1006.4hPa', 'njd': '2903', 'WSE': '<3', 'time': '17:00', 'sm': '1.1', 'isRadar': '1', 'Radar': 'JC_RADAR_AZ9210_JB'}}
City: 上海
Wind Direction: 东北风
Temperature: 23.5 °C
Wind Strength: 小于3级
Humidity: 80%

查询天气的业务逻辑代码调试成功。

三、界面实现
使用Qt Designer来设计天气预报窗口,如下图所示:

WeatherWin.ui代码:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>450</width>
    <height>347</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <widget class="QGroupBox" name="groupBox">
   <property name="geometry">
    <rect>
     <x>10</x>
     <y>10</y>
     <width>431</width>
     <height>251</height>
    </rect>
   </property>
   <property name="title">
    <string>查询城市天气</string>
   </property>
   <widget class="QComboBox" name="weatherComboBox">
    <property name="geometry">
     <rect>
      <x>80</x>
      <y>30</y>
      <width>221</width>
      <height>21</height>
     </rect>
    </property>
    <item>
     <property name="text">
      <string>北京</string>
     </property>
    </item>
    <item>
     <property name="text">
      <string>天津</string>
     </property>
    </item>
    <item>
     <property name="text">
      <string>上海</string>
     </property>
    </item>
   </widget>
   <widget class="QTextEdit" name="resultText">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>60</y>
      <width>411</width>
      <height>181</height>
     </rect>
    </property>
   </widget>
   <widget class="QLabel" name="label">
    <property name="geometry">
     <rect>
      <x>20</x>
      <y>30</y>
      <width>72</width>
      <height>21</height>
     </rect>
    </property>
    <property name="text">
     <string>城市</string>
    </property>
   </widget>
  </widget>
  <widget class="QPushButton" name="queryBtn">
   <property name="geometry">
    <rect>
     <x>90</x>
     <y>300</y>
     <width>93</width>
     <height>28</height>
    </rect>
   </property>
   <property name="text">
    <string>查询</string>
   </property>
  </widget>
  <widget class="QPushButton" name="clearBtn">
   <property name="geometry">
    <rect>
     <x>230</x>
     <y>300</y>
     <width>93</width>
     <height>28</height>
    </rect>
   </property>
   <property name="text">
    <string>清空</string>
   </property>
  </widget>
 </widget>
 <resources/>
 <connections>
  <connection>
   <sender>clearBtn</sender>
   <signal>clicked()</signal>
   <receiver>Form</receiver>
   <slot>clearResult()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>270</x>
     <y>314</y>
    </hint>
    <hint type="destinationlabel">
     <x>363</x>
     <y>288</y>
    </hint>
   </hints>
  </connection>
  <connection>
   <sender>queryBtn</sender>
   <signal>clicked()</signal>
   <receiver>Form</receiver>
   <slot>queryWeather()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>161</x>
     <y>313</y>
    </hint>
    <hint type="destinationlabel">
     <x>64</x>
     <y>286</y>
    </hint>
   </hints>
  </connection>
 </connections>
 <slots>
  <slot>clearResult()</slot>
  <slot>queryWeather()</slot>
 </slots>
</ui>

控件说明如下表所示:

四、将界面文件转换为.py文件
使用pyuic5命令将界面文件转换成.py文件,转换后的Python文件名是WeatherWin.py。

pyuic5 -o WeatherWin.py WeatherWin.ui

转换后的WeatherWin.py完整代码如下:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'weather.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(450, 347)
        self.groupBox = QtWidgets.QGroupBox(Form)
        self.groupBox.setGeometry(QtCore.QRect(10, 10, 431, 251))
        self.groupBox.setObjectName("groupBox")
        self.weatherComboBox = QtWidgets.QComboBox(self.groupBox)
        self.weatherComboBox.setGeometry(QtCore.QRect(80, 30, 221, 21))
        self.weatherComboBox.setObjectName("weatherComboBox")
        self.weatherComboBox.addItem("")
        self.weatherComboBox.addItem("")
        self.weatherComboBox.addItem("")
        self.resultText = QtWidgets.QTextEdit(self.groupBox)
        self.resultText.setGeometry(QtCore.QRect(10, 60, 411, 181))
        self.resultText.setObjectName("resultText")
        self.label = QtWidgets.QLabel(self.groupBox)
        self.label.setGeometry(QtCore.QRect(20, 30, 72, 21))
        self.label.setObjectName("label")
        self.queryBtn = QtWidgets.QPushButton(Form)
        self.queryBtn.setGeometry(QtCore.QRect(90, 300, 93, 28))
        self.queryBtn.setObjectName("queryBtn")
        self.clearBtn = QtWidgets.QPushButton(Form)
        self.clearBtn.setGeometry(QtCore.QRect(230, 300, 93, 28))
        self.clearBtn.setObjectName("clearBtn")

        self.retranslateUi(Form)
        self.clearBtn.clicked.connect(Form.clearResult)
        self.queryBtn.clicked.connect(Form.queryWeather)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.groupBox.setTitle(_translate("Form", "查询城市天气"))
        self.weatherComboBox.setItemText(0, _translate("Form", "北京"))
        self.weatherComboBox.setItemText(1, _translate("Form", "天津"))
        self.weatherComboBox.setItemText(2, _translate("Form", "上海"))
        self.label.setText(_translate("Form", "城市"))
        self.queryBtn.setText(_translate("Form", "查询"))
        self.clearBtn.setText(_translate("Form", "清空")).

五、调用主窗口类
在主窗口类MainWindow中调用界面类Ui_Form,然后在主窗口类中添加查询天气的业务逻辑代码,这样就做到了界面显示和业务逻辑的分离。
CallWeatherWin.py代码如下:

# -*- coding: utf-8 -*-

import sys     
from PyQt5.QtWidgets import QApplication , QMainWindow
from WeatherWin import Ui_Form
import requests

class MainWindow(QMainWindow ):
    def __init__(self, parent=None):    
        super(MainWindow, self).__init__(parent)
        self.ui = Ui_Form()
        self.ui.setupUi(self)
         
    def queryWeather(self):
        print('* queryWeather  ')
        cityName = self.ui.weatherComboBox.currentText()
        cityCode = self.transCityName(cityName)

        rep = requests.get('http://www.weather.com.cn/data/sk/' + cityCode + '.html')
        rep.encoding = 'utf-8'
        print( rep.json() ) 
        
        msg1 = '城市: %s' % rep.json()['weatherinfo']['city'] + '\n'
        msg2 = '风向: %s' % rep.json()['weatherinfo']['WD'] + '\n'
        msg3 = '温度: %s' % rep.json()['weatherinfo']['temp'] + ' 度' + '\n'
        msg4 = '风力: %s' % rep.json()['weatherinfo']['WS'] + '\n'
        msg5 = '湿度: %s' % rep.json()['weatherinfo']['SD'] + '\n'
        result = msg1 + msg2 + msg3 + msg4 + msg5
        self.ui.resultText.setText(result)
        
    def transCityName(self ,cityName):
        cityCode = ''
        if cityName == '北京' :
            cityCode = '101010100'
        elif cityName == '天津' :
            cityCode = '101030100'
        elif cityName == '上海' :
            cityCode = '101020100'
            
        return cityCode
                
    def clearResult(self):
        print('* clearResult  ')
        self.ui.resultText.clear()    
        
if __name__=="__main__":  
    app = QApplication(sys.argv)  
    win = MainWindow()  
    win.show()  
    sys.exit(app.exec_())  

运行脚本,显示效果如下图所示。

六、使用PyInstaller打包项目生成EXE文件
我们使用PyQt5开发的程序并不一定是给自己使用的,也可能是给用户或者朋友用,使用者可能并不知道如何运行.py文件,这时候就有了把.py文件编译成.exe文件的需求。
PyInstaller是一个很好用而且免费的打包工具,使用pip命令安装PyInstaller模块:

pip install PyInstaller

在命令行窗口中进入需要打包的代码所在的目录下,运行下面的命令:

pyinstaller [opts] yourprogram.py

可选的参数有:
-F, -onefile, 打包成一个EXE文件
-D, -onedir, 创建一个目录,包含EXE文件,但会依赖很多文件(默认选项)
-c, -console, -nowindowed, 使用控制台,无窗口(默认)
-w, -windowed, -noconsole,使用窗口,无控制台

对于本例,进入CallWeatherWin.py文件所在的目录下,运行:

pyinstaller -F -w CallWeatherWin.py

PyInstaller自动执行一系列的项目打包过程,最后生成EXE文件,在同目录下的dist子文件夹中生成了CallWeatherWin.exe文件。双击CallWeatherWin.exe文件,其运行效果与前面直接使用Python解释器运行CallWeatherWin.py的效果一样。
————————————————

                        版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                    

原文链接:https://blog.csdn.net/sinat_16020825/article/details/120724216

0

评论 (0)

取消