基于Python批量获取过去某地某时的天气数据

目的:已知某一地址,获取过去某一时间该地的天气数据,并能够批量运行。

第一步:通过百度地图API获取该地址的经纬度坐标。

输入:

 此处因后续要画热力图,因此附带了字段count。

代码:

import json
from urllib.request import urlopen, quote
import csv

def getlnglat(address):
    url = 'http://api.map.baidu.com/geocoder/v2/'
    output = 'json'
    ak = 'your ak'
    add = quote(address)  # 防止乱码,用quote编码
    uri = url + '?' + 'address=' + add + '&output=' + output + '&ak=' + ak
    req = urlopen(uri)
    res = req.read().decode()  # 解码
    temp = json.loads(res)  # 对json数据解析
    return temp

with open('result.json', 'w') as file:  # 建立json数据文件
    with open('data.csv', 'r') as csvfile:  # 打开csv
        reader = csv.reader(csvfile)
        for line in reader:  # 逐行读取数据
            city = line[0].strip()  # 读取城市
            value = line[1].strip()  # 读取数值

            try:
                # 获取经纬度
                lng = getlnglat(city)['result']['location']['lng']
                lat = getlnglat(city)['result']['location']['lat']
            except KeyError:
                # 如果发生键错误,则将经纬度赋值为"error"
                lng = "error"
                lat = "error"

            str_temp = '{"lat":' + str(lat) + ',"lng":' + str(lng) + ',"count":' + str(value) + '},\r'
            file.write(str_temp)  # 写入文档

此段代码为经百度地图api官网样例后修改。

输出:

{"lat":45.58567523781376,"lng":84.89590053887504,"count":1}, {"lat":31.235929042252014,"lng":121.48053886017651,"count":1}, {"lat":26.032184521581936,"lng":105.7085407819862,"count":1}, {"lat":33.81734281915162,"lng":106.63566517540986,"count":1}, {"lat":37.41586507235288,"lng":117.32818631830014,"count":1}, {"lat":30.10533829713717,"lng":120.54517708011481,"count":1}, {"lat":29.243635896221726,"lng":118.37502510104238,"count":1}, {"lat":33.6238252167372,"lng":106.92741441351562,"count":1},

第二步:通过Visual Weather API获取天气数据。

输入:

此处因第一步有些位置获取坐标失败,因此为空白。

代码:

import pandas as pd
import math
import datetime
import urllib.request
import win32com.client
import winsound

# 读取原始事故数据
raw_accident_data = pd.read_csv('weatherdata.csv')

records = []
labels = ['Date', 'Latitude', 'Longitude', 'Number', 'temp', 'dew', 'humidity', 'wind speed', 'precip',
          'visibility', 'cloudcover', 'type', 'conditions']

# 遍历原始事故数据的每一行
for i, row in raw_accident_data.iterrows():

    latitude = row['lat']
    longitude = row['lon']
    documentNumber = row['number']
    datetimeStr = row['date']
    weather_api_endpoint = 'https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/weatherdata/history'

    # 检查经纬度是否为NaN或零值
    if math.isnan(latitude) or math.isnan(longitude) or (latitude == 0 and longitude == 0):
        print(i + 1, "Bad latlon {},{}".format(latitude, longitude))
        records.append(('','', '', documentNumber))
        continue

    try:
        date_time = datetime.datetime.strptime(datetimeStr, '%m/%d/%Y %H:%M')
    except ValueError:
        print("Bad date format {}".format(datetimeStr))
        records.append(('','', '', documentNumber))
        continue

    latitude = '{:.5f}'.format(latitude)
    longitude = '{:.5f}'.format(longitude)

    query_params = '&contentType=csv&aggregateMinutes=15&unitGroup=us&includeAstronomy=true&collectStationContributions=true&key={}&startDateTime={}&endDateTime={}&locations={},{}'
    query_params = query_params.format("your ak", date_time.isoformat(), date_time.isoformat(), latitude,longitude)

    try:
        response = urllib.request.urlopen(weather_api_endpoint + "?" + query_params)
        df = pd.read_csv(response)

        # 获取指定列的第一个数据
        Address = df.get('Address', [''])[0]
        Date = df.get('Date time', [''])[0]
        Temperature = df.get('Temperature', [''])[0]
        Dew_Point = df.get('Dew Point', [''])[0]
        Humidity = df.get('Relative Humidity', [''])[0]
        Wind_Speed = df.get('Wind Speed', [''])[0]
        Precipitation = df.get('Precipitation', [''])[0]
        Visibility = df.get('Visibility', [''])[0]
        Cloud_Cover = df.get('Cloud Cover', [''])[0]
        Weather_Type = df.get('Weather Type', [''])[0]
        Conditions = df.get('Conditions', [''])[0]

    except Exception:
        print("Error reading from {}".format(weather_api_endpoint + "?" + query_params))
        continue

    # 构造记录
    record = [date_time.isoformat(), latitude, longitude, documentNumber, Temperature, Dew_Point, Humidity, Wind_Speed,
              Precipitation, Visibility, Cloud_Cover, Weather_Type, Conditions]
    records.append(record)
    print("No.", i + 1, "Finished...")

# 创建输出DataFrame并保存为CSV文件
output_df = pd.DataFrame.from_records(records, columns=labels)
output_df.to_csv('output.csv', index=False)

# 结束播放提示音
speak = win32com.client.Dispatch('SAPI.SPVOICE')
winsound.MessageBeep()
speak.Speak('程序运行完毕!')

 此段代码为经Visual Weather API官网样例后修改。原代码返回数据格式为json,经测试json风速字段不可用,后改为返回数据格式为csv。

输出:

 这一步也会有获取不到的时间和地点,因此为空白。

获取到的字段包括:平均温度、露点、湿度、风速、降雨量、能见度、云量、天气类型等。

若修改weather_api_endpoint,还可获取该地点的预测数据,但返回数据字段可能发生变化,请以官网文档为准。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值