绘制台风路径(一)

python爬取台风路径

# 导入所需模块
import requests
import json
import re
import time
import pandas as pd
import datetime
 
# 设置请求头,模仿浏览器行为
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'}
 
# 定义函数来显示某一年的所有台风编号和名称
def show_tc_nums_and_names_by_year(year):
    # 构建URL以获取JSON数据
    url = f"http://typhoon.nmc.cn/weatherservice/typhoon/jsons/list_{year}?callback=typhoon_jsons_list_{year}"
    # 发送GET请求并获取响应文本
    html_obj = requests.get(url, headers=headers).text
    
    # 处理字符串以提取有用的JSON部分
    json_obj = html_obj[html_obj.index("(") + 1:html_obj.rindex(")")]
    # 将JSON字符串转换为字典
    json_dict = json.loads(json_obj)
    
    # 解析JSON数据中的台风编号和名称
    typhoon_list = json_dict.get("typhoonList", [])
    if typhoon_list:
        print(f"Year {year} has the following typhoons:")  # 打印年份和台风信息提示
        for typhoon in typhoon_list:
            # 格式化台风编号
            num = f"TC{typhoon[3]}"
            # 获取或生成中文名称
            name_cn = typhoon[2] if typhoon[2] != "null" else ""
            # 获取英文名称
            name_en = typhoon[1]
            # 打印台风编号及名称
            print(f"{num} ({name_en}, {name_cn})")
    else:
        print(f"No typhoon information found for year {year}")  # 如果没有找到台风信息,则打印提示
 
# 定义函数预测给定日期加上小时增量后的日期
def date_pred(date, deltahour):
    # 解析日期字符串为datetime对象
    time = datetime.datetime.strptime(date, "%Y%m%d%H%M")
    # 计算新日期
    new_date = (time + datetime.timedelta(hours=deltahour)).strftime("%Y%m%d%H%M")
    # 返回新日期字符串
    return new_date
 
# 定义函数根据类型字符串返回台风强度描述
def get_type(date_type):
    # 定义类型映射
    item = {'TC': '热带气旋', 'TD': '热带低压', 'TS': '热带风暴', 'STS': '强热带风暴',
            'TY': '台风', 'STY': '强台风', 'SuperTY': '超强台风', '': '',}
    # 返回对应描述或默认值
    return item.get(date_type, '')
 
# 定义函数获取特定台风的详细信息
def get_tc_info(item):
    # 创建13位时间戳
    t = int(round(time.time() * 1000))
    # 构建URL并发送GET请求
    url = 'http://typhoon.nmc.cn/weatherservice/typhoon/jsons/view_%s?t=%s&callback=typhoon_jsons_view_%s' % (item['id'], t, item['id'])
    html_obj = requests.get(url, headers=headers, verify=False).text
    # 提取JSON数据
    data = json.loads(re.match(".*?({.*}).*", html_obj, re.S).group(1))['typhoon']
 
    # 创建字典存储台风信息
    info_dicts = { 
        'tc_num':item['tc_num'],  # 台风编号
        'name_cn':item['name_cn'], # 中文名称
        'name_en':item['name_en'], # 英文名称
        'dateUTC':[],    # UTC日期
        'dateCST':[],    # CST日期
        'vmax':[],    # 最大风速 m/s
        'grade':[],   # 强度等级
        'lat':[],   # 纬度
        'lon':[],   # 经度
        'mslp':[],    # 中心气压 hPa
        'attr':[]   # 属性:预报或分析
    }
 
    # 遍历分析数据
    for v in data[8]:
        info_dicts['dateUTC'].append(v[1])
        info_dicts['dateCST'].append(date_pred(v[1], 8))  # 将UTC时间转换为CST时间
        info_dicts['vmax'].append(v[7])
        info_dicts['grade'].append(get_type(v[3]))
        info_dicts['lon'].append(v[4])
        info_dicts['lat'].append(v[5])
        info_dicts['mslp'].append(v[6])
        info_dicts['attr'].append('analysis')
 
    # 获取最新预报时间
    dateUTC0 = info_dicts['dateUTC'][-1]
 
    # 处理最新预报
    if len(data[8][-1]) > 11 and data[8][-1][11] is not None and 'BABJ' in data[8][-1][11]:
        BABJ_list = data[8][-1][11]['BABJ']
        for i in range(len(BABJ_list)):
            # 获取预报前置时间(小时)
            pred_hour = int(BABJ_list[i][0])
            # 预测UTC时间
            dateUTC_pred = date_pred(dateUTC0, pred_hour)
            info_dicts['dateUTC'].append(dateUTC_pred)
            info_dicts['dateCST'].append(date_pred(dateUTC_pred, 8))
            info_dicts['vmax'].append(BABJ_list[i][5])
            info_dicts['grade'].append(get_type(BABJ_list[i][7]))
            info_dicts['lon'].append(BABJ_list[i][2])
            info_dicts['lat'].append(BABJ_list[i][3])
            info_dicts['mslp'].append(BABJ_list[i][4])
            info_dicts['attr'].append('forecast')
 
    # 将字典转换为DataFrame
    tc_info = pd.DataFrame(info_dicts)
    # 返回DataFrame
    return tc_info
 
# 定义函数根据年份和编号获取台风信息
def get_tc_info_by_year_and_num(year, num):
    # 构建URL并发送GET请求
    url = f"http://typhoon.nmc.cn/weatherservice/typhoon/jsons/list_{year}?callback=typhoon_jsons_list_{year}"
    
    html_obj = requests.get(url, headers=headers, verify=False).text
    # 打印响应文本(调试用途)
    print(html_obj)
    # 提取JSON数据
    data = json.loads(re.match(".*?({.*}).*", html_obj, re.S).group(1))
 
    # 检查是否存在台风列表
    if data.get('typhoonList'):
        for item in data['typhoonList']:
            # 如果找到了匹配的台风编号
            if item[4] == num:
                # 创建包含台风ID、编号、中文名和英文名的字典
                tc = {
                    'id': item[0],
                    'tc_num': str(item[4]),
                    'name_cn': item[2],
                    'name_en': item[1]
                }
                # 返回台风详细信息
                return get_tc_info(tc)
    # 如果没有找到匹配的台风,则返回None
    return None
 
# 主程序入口
if __name__ == "__main__":
    # 设置请求头(重复,应避免)
    headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'}
 
    # 输入年份
    year = input("请输入年份: ")
    # 显示该年份的台风编号和名称
    show_tc_nums_and_names_by_year(year)
    # 输入台风TC编号(四位数字)
    num = input("请输入台风TC编号(TC后面四位数字): ")
 
    # 获取台风信息
    data = get_tc_info_by_year_and_num(year, num)
 
    # 如果数据存在,则打印并保存到CSV和Excel文件
    if data is not None:
        print(data)
        data.to_csv(rf'{year}_TC{num}.csv', index=False)
        print(f"台风{num}的数据已保存到文件{year}_TC{num}.csv")
        data.to_excel(rf'{year}_TY{num}.xlsx', index=False, engine='openpyxl')
        print(f"台风{num}的数据已保存到文件{year}_TC{num}.xlsx")
    # 如果未找到数据,则打印提示
    else:
        print(f"在{year}年未找到台风{num}的数据。")

加载函数库

import os  
import pandas as pd  
import numpy as np  
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']  # 指定默认字体  
plt.rcParams['axes.unicode_minus'] = False  # 解决保存图像时负号'-'显示为方块的问题    
import cartopy.crs as ccrs  
import cartopy.feature as cfeat
from matplotlib.lines import Line2D  
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter  

 读取文件

df = pd.read_csv('D:/data/2024_TY2403.csv')  

完整代码 

import os  
import pandas as pd  
import numpy as np  
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']  # 指定默认字体  
plt.rcParams['axes.unicode_minus'] = False  # 解决保存图像时负号'-'显示为方块的问题    
import cartopy.crs as ccrs  
import cartopy.feature as cfeat
from matplotlib.lines import Line2D  
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter  
  
# 读取数据  
df = pd.read_csv('D:/data/2024_TY2403.csv')  
  
# 定义颜色函数  
def get_color(grade):  
    if grade == '热带低压' or grade == '热带扰动':  
        return '#FFFF00'  
    elif grade == '热带风暴':  
        return '#6495ED'  
    elif grade == '强热带风暴':  
        return '#3CB371'  
    elif grade == '台风':  
        return '#FFA500'  
    elif grade == '强台风':  
        return '#FF00FF'  
    elif grade == '超强台风':  
        return '#DC143C'  
  
# 创建地图并绘制台风路径  
def plot_typhoons(df, extent):  
    fig = plt.figure(figsize=(12, 8))  
    ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())  
  
    # 添加底图(这里以简单的海岸线为例,您可以根据需要添加其他底图)  
    ax.add_feature(cfeat.COASTLINE)  
  
    # 设置地图范围  
    ax.set_extent(extent, crs=ccrs.PlateCarree())  
  
    # 添加网格线  
    gl = ax.gridlines(draw_labels=True, linewidth=1, color='gray', alpha=0.5, linestyle='--')  
    gl.xlabels_top = gl.ylabels_right = False  
  
    # 设置经纬度格式和刻度  
    ax.xaxis.set_major_formatter(LongitudeFormatter())  
    ax.yaxis.set_major_formatter(LatitudeFormatter())  
  
    # 绘制台风路径  
    for tc_num, group in df.groupby('tc_num'):  
        points = np.array(list(zip(group['lon'], group['lat'])))  
        x, y = points.T  
        color = get_color(group['grade'].iloc[-1])  # 使用最后一个强度级别作为颜色  
        ax.plot(x, y, color=color, marker='o', markersize=5, linestyle='-', linewidth=1, transform=ccrs.PlateCarree())  
  
    # 添加图例(这里需要手动指定,因为使用了循环绘制)  
    legend_elements = [  
    Line2D([], [], color='#FFFF00', marker='o', label='热带低压/扰动', markersize=5),  
    Line2D([], [], color='#6495ED', marker='o', label='热带风暴', markersize=5),  
    Line2D([], [], color='#3CB371', marker='o', label='强热带风暴', markersize=5),  
    Line2D([], [], color='#FFA500', marker='o', label='台风', markersize=5),  
    Line2D([], [], color='#FF00FF', marker='o', label='强台风', markersize=5),  
    Line2D([], [], color='#DC143C', marker='o', label='超强台风', markersize=5),  
]  
    ax.legend(handles=legend_elements, loc='upper left')  
  
    # 设置标题  
    plt.title('台风路径')  
  
    # 显示地图  
    plt.show()  
  
# 调用函数  
plot_typhoons(df, extent=[100, 180, 0, 40])  # 根据需要设置extent
### 使用Python实现台风中心定位的方法 对于台风中心的精确定位,通常依赖于气象观测数据和数值天气预报模式的结果。在实践中,可以利用多种方法来估计台风的位置,包括但不限于最小风速法、气压场分析以及卫星云图识别技术。 #### 方法:基于最低海平面气压位置 种简单而常用的方式是从给定时间段内的多个站点获取海平面气压读数,并找到其中最低的那个作为潜在的风暴眼所在之处。这种方法假设低压区即为热带气旋的核心部位。 ```python import numpy as np def find_lowest_pressure_center(pressures): """ 寻找最低压力点以确定可能存在的台风中心。 参数: pressures (list of tuples): [(latitude, longitude, pressure), ...] 返回: tuple: 台风中心坐标 (lat, lon),如果未发现合适的候选,则返回None """ min_press = float('inf') center_location = None for lat, lon, press in pressures: if press < min_press: min_press = press center_location = (lat, lon) return center_location ``` 此段代码定义了个名为`find_lowest_pressure_center()` 的函数,它接收系列包含纬度、经度及其对应的海平面气压值组成的三元组列表作为输入参数,并输出最有可能代表当前时刻台风中心坐标的二元组[^1]。 #### 方法二:应用图像处理算法到可见光/红外线遥感影像上 另种更为复杂但也更精确的技术涉及使用计算机视觉库(如OpenCV)配合机器学习框架对来自地球同步轨道卫星拍摄得到的高分辨率图片序列执行边缘检测、形态学变换等系列操作后提取出涡旋结构特征并据此推断出台风的具体方位。 ```python import cv2 from skimage import io def detect_eye_from_satellite_image(image_path): """ 利用图像处理手段从未知状态下的静止卫星图像中自动辨识出飓风水汽漩涡核心部分。 参数: image_path (str): 卫星图像文件路径 返回: tuple or NoneType: 如果成功找到了疑似眼睛区域,则给出其边界矩形左上角顶点坐标(x,y)及宽高等几何属性; 否则返回None表示未能完成匹配过程。 """ img = io.imread(image_path) gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) _, threshed = cv2.threshold(gray_img, 170, 255, cv2.THRESH_BINARY_INV|cv2.THRESH_OTSU) contours,hierarchy=cv2.findContours(threshed,cv2.RETR_EXTERNAL ,cv2.CHAIN_APPROX_SIMPLE)[-2:] eye_candidate=None max_area=0 for cnt in contours: area=cv2.contourArea(cnt) if area>max_area and area<image.shape[0]*image.shape[1]/8 : # 过滤掉过大的轮廓以防误判陆地等非目标物体 rect=cv2.boundingRect(cnt) max_area=area eye_candidate=(rect[0],rect[1],rect[2],rect[3]) return eye_candidate ``` 上述脚本展示了如何加载张JPEG格式的卫星照片并通过设定阈值得到黑白两色版本以便后续计算;接着调用了 OpenCV 库里的 API 来寻找所有封闭曲线并将面积最大的那个视为可能是我们感兴趣的对象——也就是所谓的“眼睛”。最后步则是根据这个最大连通分量绘制包围盒从而直观展示出结果[^2]。 #### 结合深度学习模型提高准确性 随着人工智能的发展,越来越多的研究人员尝试构建专门针对特定应用场景设计过的卷积神经网络(CNNs)或其他类型的深层架构来进行更加精准高效的自动化分类任务。这类方案往往需要大量标注样本支持训练阶段的工作,但在测试环境下却能展现出超越传统统计物理建模的优势特性。 例如,在某些情况下,即使当常规探测设备失效或者无法覆盖整个影响范围时,经过良好训练后的AI系统仍然可以从有限的信息源里挖掘出有用线索进而辅助决策者做出科学合理的判断[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值