用Python实现可视化天气预报

Python
193
0
0
2024-06-09
标签   Python实践

我们用Python来做一个天气时钟。也就是既能显示时间,也能显示未来12小时天气。我们的产品设计效果如下图:

一、时钟部分

这个天气时钟首先我们先做时钟部分。

时钟有时针、分针和秒针。这里用来绘制用到了Python Trutle库。以小时针为例。我们先

  • 拿起画笔pen.penup()
  • 笔移动到表盘中心点pen.goto(global_x_shift, global_y_shift)
  • 带上笔的颜色, pen.color(hour_color)
  • 设置笔的初始方向 pen.setheading(90)
  • 设置笔的顺时针选择角度angle,对于时针来说就是angele=(hour /12)*360+(minute/60)*30
  • 然后向右旋转角度pen.rt(angle)
  • pen.pendown()放下笔开始绘画
  • pen.fd(hour_hand) 向前绘制长度hour_hand。
# draw a clock using the pen i created
def draw_clock(hour, minute, second, pen):
    pen.hideturtle()

    # Draw the hour han
    # 有关Python Turtle常用的操作见http://www.cse.msu.edu/~ldillon/cse-ctl/Spring2015/Meeting07/turtleCheatSheet.pdf 
    pen.penup()  # 暂停绘画,和底下的pendown是一对
    pen.goto(global_x_shift, global_y_shift)
    pen.color(hour_color)
    pen.pensize(6)  # 小时针的宽度
    pen.setheading(90)  # 设置角度,0(east), 90(north), 180(west), 270(south)
    angle = (hour / 12) * 360 + (minute/60) * 30  # 根据当前时间,小时针应该便宜的角度
    pen.rt(angle)  # 向右/顺时针旋转角度,turtle.rt和turtle.right一样
    pen.pendown()  # 开始绘画,和上面的penup是一对
    pen.fd(hour_hand)  # 小时针的长度,向前绘制,turtle.fd同turtle.forward

    # Draw the minute hand
    pen.penup()
    pen.goto(global_x_shift, global_y_shift)
    pen.color(minute_color)
    pen.setheading(90)
    angle = (minute / 60.0) * 360  # optional + (s/60) * 6
    pen.rt(angle)
    pen.pendown()
    pen.fd(minute_hand)

    # Draw the second hand
    pen.penup()
    pen.goto(global_x_shift, global_y_shift)
    pen.color(second_color)
    pen.setheading(90)
    angle = (second / 60) * 360
    pen.rt(angle)
    pen.pendown()
    pen.fd(second_hand)

二、未来12小时天气

获取未来12小时天气预报这个update_forecast函数,我们通过拉取openweathermap的接口,得到了温度,体感温度,风速和天气类型图标。

这些天气数值和图标准备好之后。会放在数组待用。

def update_forecast():

    global hour_cursor

    # weather ID breakdown https://openweathermap.org/weather-conditions
    # use https://ezgif.com/maker for gif conversion

    logging.debug("---- update_forecast() ----")

    hour_cursor = int(time.strftime("%I"))  # %I表示12小时制
    meridiem = time.strftime('%p')  # %p表示上午AM或者下午PM

    logging.debug("hour_cursor: " + str(hour_cursor))

    for num in range(12):
        # current hour
        logging.debug("current hour: " + str(hour_cursor) + " " + meridiem)
        # forecast hour
        logging.debug("forecast hour: " + str(int(hour_cursor)+num))
        logging.debug("temperature: " + str(data["hourly"][num]["temp"]))
        logging.debug("feels like: " + str(data["hourly"][num]["feels_like"]))
        logging.debug("wind speed: " + str(data["hourly"][num]["wind_speed"]))
        logging.debug(data["hourly"][num]["weather"][0]["description"])
        logging.debug("weather ID: " + str(data["hourly"][num]["weather"][0]["id"]))
        logging.debug("POP: " + str(data["hourly"][num]["pop"]))

        if 'rain' not in data["hourly"][num]:
            logging.debug("no rain data")
        else:
            logging.debug("rain: " + str(data["hourly"][num]["rain"]))

        temp_array[num] = data["hourly"][num]["temp"]  # 温度
        temp_feel_array[num] = data["hourly"][num]["feels_like"]  # 体感温度
        wind_array[num] = data["hourly"][num]["wind_speed"]  # 风速
        id_array[num] = data["hourly"][num]["weather"][0]["id"]  # 天气icon id,见https://openweathermap.org/weather-conditions

        path_theme = os.path.join(path, theme)

        if 232 >= id_array[num] >= 200:
            idImage_array[num] = os.path.join(path_theme, "11d@2x.gif")
        elif 321 >= id_array[num] >= 300:
            idImage_array[num] = os.path.join(path_theme, "09d@2x.gif")
        elif 504 >= id_array[num] >= 500:
            idImage_array[num] = os.path.join(path_theme, "10d@2x.gif")
        elif id_array[num] == 511:
            idImage_array[num] = os.path.join(path_theme, "13d@2x.gif")
        elif 531 >= id_array[num] >= 520:
            idImage_array[num] = os.path.join(path_theme, "09d@2x.gif")
        elif 622 >= id_array[num] >= 600:
            idImage_array[num] = os.path.join(path_theme, "13d@2x.gif")
        elif 781 >= id_array[num] >= 701:
            idImage_array[num] = os.path.join(path_theme, "50d@2x.gif")
        elif id_array[num] == 800:
            idImage_array[num] = os.path.join(path_theme, "01d@2x.gif")
        elif id_array[num] == 801:
            idImage_array[num] = os.path.join(path_theme, "02d@2x.gif")
        elif id_array[num] == 802:
            idImage_array[num] = os.path.join(path_theme, "03d@2x.gif")
        elif id_array[num] == 803 or id_array[num] == 804:
            idImage_array[num] = os.path.join(path_theme, "04d@2x.gif")
        else:
            logging.error("Invalid weather ID")

    logging.debug(temp_array)
    logging.debug(id_array)
    logging.debug(idImage_array)

    for image in idImage_array:
        wn.addshape(image)  # 画布上画上天气图标

天气icon放置的位置就是原本时钟上的小时数位置。也就是x和y坐标通过公式计算:

hour_x = []
hour_y = []

for i in range(60, -300, -30):
    i_r = math.radians(i)
    hour_x.append((math.cos(i_r)*radius))
    hour_y.append((math.sin(i_r)*radius))

三、总结

完整的程序我放在了这里:weatherClock/weatherClock.py at master · lumanyu/weatherClock (github.com)

本程序通过小时和天气的创新融合,运用程序员的技能做了一个实用工具。