gpt4 book ai didi

python制作的天气预报小工具(gui界面)

转载 作者:qq735679552 更新时间:2022-09-27 22:32:09 28 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章python制作的天气预报小工具(gui界面)由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

一.准备工作

不需要准备.

二.预览

1.启动

启动以后自动定位所在城市,展示定位城市的天气.

python制作的天气预报小工具(gui界面)

2.添加城市

python制作的天气预报小工具(gui界面)

3.展示多个城市天气

添加天气之后能够显示多个城市天气信息.

python制作的天气预报小工具(gui界面)

三.设计流程

1.获取城市天气信息过程

用此流程图展示定位城市信息到获取城市天气信息过程.

python制作的天气预报小工具(gui界面)

四.源代码

1.Weather_Tool-v1.0.py

from tkinter import *from tkinter import ttkfrom PIL import Image,ImageTkfrom tkinter import messageboxfrom Weather_Spider import Weather_Getfrom threading import Threadimport datetimeimport time"""5-11.打开首页定位当前位置获取天气    (ip定位+jieba分词+城市号+城市天气) **5.11实现**2.用户手动选择,查看当前所选城市天气 (Toplevel+Combobox) **已实现**5-141.加入notepad,显示多个城市天气    (notebook Frame)    **已实现**2.频繁刷新检测(线程计时10秒)   **已实现**3.用户选择主题    (Menu.add_radiobutton())    **已实现**4.一个窗口多个Combobox,怎样处理选择事件	**已实现**5-151.右击notebook frame标题出现“关闭”菜单	**已砍掉**2.用户添加了城市后,label出现在了最后的Frame中	**未实现**"""imgs=["./img/loading.png"]class App:    def __init__(self):        self.w=Tk()        self.w.title("天气预报小工具-v1.0")        width=600        height=282        left=(self.w.winfo_screenwidth()-width)/2        top=(self.w.winfo_screenheight()-height)/2        self.w.geometry("%dx%d+%d+%d"%(width,height,left,top))        self.w.iconbitmap("biticon.ico")        self.w.resizable(False,False)        self.cerate_widgets()        self.first_launch()        self.set_widgets()        self.place_widgets()        self.thread_it(self.show_local_weather)        self.w.mainloop()    def cerate_widgets(self):        self.note=ttk.Notebook()        self.f1=Frame()        self.tree=ttk.Treeview(self.f1)        self.l1_var=StringVar()        self.l1=ttk.Label(self.f1,textvariable=self.l1_var)        self.m=Menu(self.w)        self.w["menu"]=self.m        self.s1=Menu(self.m,tearoff=False)        self.s2=Menu(self.m,tearoff=False)        self.s3=Menu(self.m,tearoff=False)    def set_widgets(self):        self.location=[]        style = ttk.Style(self.w)        style.theme_use("default")        columns=("rq","tq","flfx","zdqw","zgqw")        self.tree.config(show="headings",columns=columns)        self.tree.column(columns[0],anchor=CENTER,minwidth=95,width=110)        self.tree.column(columns[1],anchor=CENTER,minwidth=60,width=70)        self.tree.column(columns[2],anchor=CENTER,minwidth=90,width=100)        self.tree.column(columns[3],anchor=CENTER,minwidth=90,width=100)        self.tree.column(columns[4],anchor=CENTER,minwidth=90,width=100)        self.tree.heading("rq", text="日期")        self.tree.heading("tq", text="天气")        self.tree.heading("flfx", text="风向风力")        self.tree.heading("zdqw", text="最低气温")        self.tree.heading("zgqw", text="最高气温")        self.m.add_cascade(label="开始",menu=self.s1)        self.s1.add_command(label="aaa",command="")        self.s1.add_separator()        self.s1.add_command(label="退出",command=self.quit_window)        self.m.add_cascade(label="操作",menu=self.s2)        self.s2.add_command(label="刷新",command=lambda:self.thread_it(self.refresh_weather))        self.s2.add_command(label="添加城市",command=lambda:self.thread_it(self.select_city),state="disable")        s2_sub = Menu(self.s2, tearoff=0)        self.s2.add_separator()        self.s2.add_cascade(label="更换主题",menu=s2_sub)        self.m.add_cascade(label="关于",menu=self.s3)        self.s3.add_command(label="关于作者",command=lambda :messagebox.showinfo("关于作者","作者很神秘,什么都没留下"))        self.tree.tag_configure("evenColor",background="lightblue")        self.w.protocol("WM_DELETE_WINDOW",self.quit_window)        themes=[ "default","clam", "alt", "classic"]        self.themevar=StringVar()        for i,t in enumerate(themes):            s2_sub.add_radiobutton(label=t,variable=self.themevar,command=lambda:self.thread_it(self.change_theme),value=t)        self.themevar.set("default")    def place_widgets(self):        self.note.place(x=0,y=0,width=600,height=282)        self.tree.place(x=0,y=0,width=600,height=150)        self.l1.place(x=0,y=150,height=85,width=600)    def first_launch(self):        """        第一次启动,展示加载图片提示信息        :return:        """        self.start_time=time.time()        paned = PanedWindow(self.w)        self.img = imgs        img = Image.open(self.img[0])        paned.image = ImageTk.PhotoImage(img)        self.load_img = Label(self.w, image=paned.image)        self.load_lab = Label(self.w, text="Loading...")        self.load_img.pack()        self.load_lab.pack()    def show_local_weather(self):        """        展示定位天气信息        :return:        """        self.l1_var.set("正在刷新天气......")        items = self.tree.get_children()        for item in items:            self.tree.delete(item)        try:            city,item=Weather_Get().get_local_weather()            self.load_img.destroy()            self.load_lab.destroy()            self.s2.entryconfig("添加城市", state="normal")            self.note.add(self.f1,text=city)            i=0            for data in item["recent"]:                self.tree.insert("", i, values=(                data.get("日期"), data.get("天气"), data.get("风力风向"), data.get("最低气温"), data.get("最高气温")))                i+=1            self.l1_var.set(f"今天:{self.show_date()}当前所在地区:{city}当前气温:{item["now"]}感冒指数:{item["ganmao"]}")        except TypeError:            messagebox.showerror("错误","天气信息加载失败!")            self.l1_var.set("天气信息加载失败!")            self.s2.entryconfig("添加城市", state="normal")    def refresh_weather(self):        """        刷新天气后,10秒内不能点击刷新        :return:        """        self.s2.entryconfig("刷新", state="disable")        self.show_local_weather()        self.thread_it(self.wait_time)    def wait_time(self):        """        线程计时10s,十秒后刷新按钮可点击        :return:        """        time.sleep(10)        self.s2.entryconfig("刷新", state="normal")    def show_date(self):        """        展示日期信息,便于天气展示        :return:        """        date = str(datetime.date.today())        year,month,day=date.split("-")        week_day_dict = {            0: "星期一",            1: "星期二",            2: "星期三",            3: "星期四",            4: "星期五",            5: "星期六",            6: "星期日 ",        }        now=datetime.datetime.now()        date_index = now.weekday()        return f"{year}年{month}月{day}日 {week_day_dict[date_index]}"    def select_city(self):        """        Toplevel让用户选择城市,后台获取城市号        :return:        """        self.t=Toplevel()        self.t.resizable(0,0)        width=300        height=140        left=(self.t.winfo_screenwidth()-width)/2        top=(self.t.winfo_screenheight()-height)/2        self.t.geometry("%dx%d+%d+%d"%(width,height,left,top))        self.t.title("选择城市")        self.tl1=ttk.Label(self.t,text="请选择城市:")        self.tl1.pack()        provinces=Weather_Get().get_provinces()        self.tc1=ttk.Combobox(self.t,justify="center",state="readonly",value=provinces)        self.tc2=ttk.Combobox(self.t,justify="center",state="readonly")        self.tc1.pack()        self.tc1.bind("<<ComboboxSelected>>",self.show_tc2_value)        self.tc2.bind("<<ComboboxSelected>>",self.show_tc3_value)        self.tc2.pack()        self.tc3=ttk.Combobox(self.t,justify="center",state="readonly")        self.tc3.pack()        self.tb1=ttk.Button(self.t,text="选择",command=lambda :self.thread_it(self.ack_city))        self.tb1.pack(pady=10)#----待完善    def ack_city(self):        """        Toplevel中选择了城市,选择使用notebook中建立Frame展示所选城市信息        :return:        """        cityno=self.get_city_no()        weather_item=Weather_Get().get_weather(cityno)        location=self.province_name+self.city_name+self.region        if location in self.location:            messagebox.showwarning("警告","此城市已添加,请勿重复添加!")        else:            self.location.append(location)            self.f2= Frame(takefocus=True)            self.note.add(self.f2, text=location)            self.tree2 = ttk.Treeview(self.f2)            columns = ("rq", "tq", "flfx", "zdqw", "zgqw")            self.tree2.config(show="headings", columns=columns)            self.tree2.column(columns[0], anchor=CENTER, minwidth=95, width=110)            self.tree2.column(columns[1], anchor=CENTER, minwidth=60, width=70)            self.tree2.column(columns[2], anchor=CENTER, minwidth=90, width=100)            self.tree2.column(columns[3], anchor=CENTER, minwidth=90, width=100)            self.tree2.column(columns[4], anchor=CENTER, minwidth=90, width=100)            self.tree2.heading("rq", text="日期")            self.tree2.heading("tq", text="天气")            self.tree2.heading("flfx", text="风向风力")            self.tree2.heading("zdqw", text="最低气温")            self.tree2.heading("zgqw", text="最高气温")            self.tree2.place(x=0,y=0,width=600,height=150)            # label_="label"+str(self.click_no)            # label_var="label"+str(self.click_no)+"_var"            self.fl1_var=StringVar()            self.fl1=ttk.Label(self.f2,textvariable=self.fl1_var)            self.fl1.place(x=0,y=150,height=85,width=600)            items = self.tree2.get_children()            for item in items:                self.tree2.delete(item)            try:                item = weather_item                city=location                i = 0                for data in item["recent"]:                    self.tree2.insert("", i, values=(                        data.get("日期"), data.get("天气"), data.get("风力风向"), data.get("最低气温"), data.get("最高气温")))                    i += 1                self.fl1_var.set(f"今天:{self.show_date()}当前所在地区:{city}当前气温:{item["now"]}感冒指数:{item["ganmao"]}")            except TypeError:                messagebox.showerror("错误","天气信息加载失败!")                self.fl1_var.set(f"{city}天气信息加载失败!")        self.t.destroy()    def change_tab(self,*args):        pass    def show_tc2_value(self,event):        """        展示"市"级信息        :param event:        :return:        """        self.tc2.config(value=[])        self.tc3.config(value=[])        self.province_name=self.tc1.get()        cities=Weather_Get().get_cities(self.province_name)        self.tc2.config(value=cities)    def show_tc3_value(self,event):        """        展示"区/县"级信息        :param event:        :return:        """        self.city_name=self.tc2.get()        regions=Weather_Get().get_regions(self.province_name,self.city_name)        self.tc3.config(value=regions)    def get_city_no(self):        """        根据省、市、区、县 获取城市号        :return: 城市号        """        self.region=self.tc3.get()        city_no=Weather_Get().get_city_id_by_add(self.province_name,self.city_name,self.region)        return city_no    def change_theme(self,):        """        更换主题        :return:        """        theme=self.themevar.get()        style = ttk.Style(self.w)        style.theme_use(theme)    def quit_window(self):        ret=messagebox.askyesno("退出","是否要退出?")        if ret:            self.w.destroy()    def thread_it(self,func,*args):        """        防止线程冲突        :param func:        :param args:        :return:        """        t=Thread(target=func,args=args)        t.setDaemon(True)        t.start()if __name__ == "__main__":    a=App()

2.Weather_Spider.py

#coding:utf-8import requestsimport jsonfrom lxml import etreeimport jiebaclass Weather_Get():    def __init__(self):        self.base_ip_url="http://ip-api.com/json"        self.location_url="https://ip.tool.chinaz.com/"        #获取中国国内城市--number接口        self.city_number_url="http://static.2ktq.com/sktq/common/city_China.json"        #天气查询接口        self.base_weather_url="http://wthrcdn.etouch.cn/weather_mini?citykey={}"        self.headers={            "user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36",        }        self.item=self.get_city_item()    def request(self,url,headers):        """        请求url,可自定义请求头        :param url: 请求的url        :param headers: 自定义的请求头        :return: 网页文本数据        """        s=requests.session()        s.keep_alive=False        try:            r=s.get(url,headers=headers)            r.encoding="utf-8"            if r.status_code==200:                r.encoding = r.apparent_encoding                return r.text            else:                return None        except requests.exceptions.ConnectionError:            return None    def get_city(self):        """        通过ip定位到当前城市        :return:所在省市位置信息        """        my_headers={            "Connection": "keep-alive",            "Host": "ip.tool.chinaz.com",            "sec-ch-ua": ""Google Chrome";v="89", "Chromium";v="89", ";Not A Brand";v="99"",            "user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36",            "Upgrade-Insecure-Requests": "1"        }        res = etree.HTML(self.request(self.location_url,headers=my_headers))        location = res.xpath("//div[@class="WhoIpWrap jspu"]//span[@class="Whwtdhalf w30-0 lh24 tl ml80"]/em/text()")        #结巴分词好费时间啊        jieba_cut_result = jieba.lcut("".join(location))        try:            #去除首位的国家和网络类型            del jieba_cut_result[0]            del jieba_cut_result[-1]            item = {}            # 如果结果为类似 石家庄裕华 则自动加入市区            if jieba_cut_result[0]!=jieba_cut_result[1]:                item["province"] = jieba_cut_result[0] + "市"                item["city"] = jieba_cut_result[1] + "区"                return item            else:                # 如果结果为类似 北京北京 则自动加入市                item["province"] = jieba_cut_result[0] + "市"                item["city"] = jieba_cut_result[1] + "市"                return item        except IndexError:            return False    def get_city_item(self):        res =self.request(self.city_number_url,headers=self.headers)        item=eval("{"cities":"+res+"}")        return item    def get_provinces(self):        province=[p for p in self.item["cities"]]        #print(province)        return province    def get_cities(self,province):        cities_=self.item["cities"][province]        cities=[city for city in cities_.keys()]        return cities    def get_regions(self,province,city):        regions_=self.item["cities"][province][city]        regions=[region for region in regions_.keys()]        #print(province,city,regions)        return regions    def get_city_id_by_add(self,province,city,region=""):        if region=="":            city_no=self.item["cities"][province][city][city].replace("CN","")        else:            city_no=self.item["cities"][province][city][region].replace("CN","")        return city_no    def get_cityid(self,province,city):        """        通过省、市在字典中查找对应的城市号        :param province: 省        :param city: 市        :return: 城市号        """        if province in self.item["cities"].keys():            try:                #河北省唐山市唐山市(通常的省市)                number=self.item["cities"][province].get(city).get(city).replace("CN","")                return number            except AttributeError:                number=self.item["cities"][province].get(province).get(city).replace("CN","")                return number        else:            print("未检索到关于{}{}的信息!".format(province,city))    def get_weather(self,number):        weather_data = json.loads(self.request(self.base_weather_url.format(number),self.headers))        # pprint.pprint(weather_data)        data=weather_data["data"]        item={}        yesterday={}        item_list=[]        yesterday["日期"]=data["yesterday"]["date"]+"(昨天)"        item["now"]=data["wendu"]+"℃"        item["ganmao"]=data["ganmao"]        yesterday["天气"]=data["yesterday"]["type"]        yesterday["风力风向"]=data["yesterday"]["fx"]+data["yesterday"]["fl"].replace("<![CDATA[","").replace("]]>","")        yesterday["最低气温"]=data["yesterday"]["low"].replace("低温 ","")        yesterday["最高气温"]=data["yesterday"]["high"].replace("高温 ","")        item_list.append(yesterday)        count=0        for weateher in data["forecast"]:            item2={}            if count==0:                date=weateher["date"]+"(今天)"            elif count==1:                date=weateher["date"]+"(明天)"            elif count==2:                date=weateher["date"]+"(后天)"            else:                date=weateher["date"]+f"({count-1}天后)"            item2["日期"]=date            item2["天气"] = weateher["type"]            item2["风力风向"]=weateher["fengxiang"]+weateher["fengli"].replace("<![CDATA[","").replace("]]>","")            item2["最低气温"] = weateher["low"].replace("低温 ", "")            item2["最高气温"] = weateher["high"].replace("高温 ", "")            item_list.append(item2)            count+=1        item["recent"]=item_list        return item    def get_local_weather(self):        item=Weather_Get().get_city()        if item:            p=item["province"]            c=item["city"]            number=Weather_Get().get_cityid(p,c)            weather=Weather_Get().get_weather(number)            return p+c,weather        else:            return False

五.总结

本次使用Tkinter写了一款天气预报小工具,基本支持全国每个省市的天气预报,支持历史天气(昨天)查看,虽然基本功能能够实现,但是仍旧存在两个小问题: 1.添加超过两个城市天气后,具体城市信息会显示在最新添加的Freame中。 2.ip定位不准确.

本程序还有两个特色:

1.支持更换主题。 2.程序首次启动加入了加载过渡。 其他的彩蛋,您自己去发现吧! 程序放在了蓝奏云。思路、代码方面有什么不足欢迎各位大佬指正、批评! 。

以上就是python制作的天气预报小工具(gui界面)的详细内容,更多关于python 天气预报工具的资料请关注我其它相关文章! 。

原文链接:https://blog.csdn.net/a1397852386/article/details/116947547 。

最后此篇关于python制作的天气预报小工具(gui界面)的文章就讲到这里了,如果你想了解更多关于python制作的天气预报小工具(gui界面)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com