您的位置:首页 > 编程语言 > Python开发

python天气预报

2016-01-28 16:20 661 查看
注:我用的是和风天气的api

和风天气的接口说明

http://www.heweather.com/documents/api

以下为我目前用到的api及其结构

1、城市ID:https://api.heweather.com/x3/citylist?search=类型&key=你的认证key
返回一个字典:
{”city_info":[{城市1},{城市2}...],"status":"ok"}


2、城市天气预报:https://api.heweather.com/x3/weather?cityid=城市ID&key=你的认证key
同样返回一个字典,但由于返回的字典结构较复杂,直接选取官网中的说明(实际使用时结构可能与官网不同):
{
{
"HeWeather data service 3.0": [
{
"basic": {
"city": "大连",
"cnty": "中国",
"id": "CN101070201",
"lat": "38.944000",
"lon": "121.576000",
"update": {
"loc": "2015-07-15 10:43",
"utc": "2015-07-15 02:46:14"
}
},
"status": "ok",
"aqi": {
"city": {
"aqi": "71",
"co": "1",
"no2": "75",
"o3": "101",
"pm10": "89",
"pm25": "44",
"qlty": "良",
"so2": "27"
}
},
"alarms": [
{
"level": "橙色",
"stat": "预警中",
"title": "辽宁省大连市气象台发布高温橙色预警",
"txt": "大连市气象台2015年07月14日13时31分发布高温橙色预警信号:预计14日下午至傍晚,旅顺口区局部最高气温将达到37℃以上,请注意防范。
",
"type": "高温"
}
],
"now": {
"cond": {
"code": "100",
"txt": "晴"
},
"fl": "33",
"hum": "28",
"pcpn": "0",
"pres": "1005",
"tmp": "32",
"vis": "10",
"wind": {
"deg": "350",
"dir": "东北风",
"sc": "4-5",
"spd": "11"
}
},
"daily_forecast": [
{
"date": "2015-07-15",
"astro": {
"sr": "04:40",
"ss": "19:19"
},
"cond": {
"code_d": "100",
"code_n": "101",
"txt_d": "晴",
"txt_n": "多云"
},
"hum": "48",
"pcpn": "0.0",
"pop": "0",
"pres": "1005",
"tmp": {
"max": "33",
"min": "24"
},
"vis": "10",
"wind": {
"deg": "192",
"dir": "东南风",
"sc": "4-5",
"spd": "11"
}
},
{
"date": "2015-07-16",
"astro": {
"sr": "04:40",
"ss": "19:18"
},
"cond": {
"code_d": "104",
"code_n": "104",
"txt_d": "阴",
"txt_n": "阴"
},
"hum": "82",
"pcpn": "2.7",
"pop": "82",
"pres": "1008",
"tmp": {
"max": "27",
"min": "23"
},
"vis": "10",
"wind": {
"deg": "116",
"dir": "东南风",
"sc": "4-5",
"spd": "11"
}
},
{
"date": "2015-07-17",
"astro": {
"sr": "04:41",
"ss": "19:17"
},
"cond": {
"code_d": "101",
"code_n": "100",
"txt_d": "多云",
"txt_n": "晴"
},
"hum": "70",
"pcpn": "0.1",
"pop": "11",
"pres": "1006",
"tmp": {
"max": "28",
"min": "22"
},
"vis": "10",
"wind": {
"deg": "172",
"dir": "西风",
"sc": "4-5",
"spd": "11"
}
}
],
"hourly_forecast": [
{
"date": "2015-07-15 10:00",
"hum": "51",
"pop": "0",
"pres": "1006",
"tmp": "32",
"wind": {
"deg": "127",
"dir": "东南风",
"sc": "微风",
"spd": "4"
}
},
{
"date": "2015-07-15 13:00",
"hum": "49",
"pop": "0",
"pres": "1005",
"tmp": "34",
"wind": {
"deg": "179",
"dir": "南风",
"sc": "微风",
"spd": "7"
}
},
{
"date": "2015-07-15 16:00",
"hum": "54",
"pop": "0",
"pres": "1005",
"tmp": "31",
"wind": {
"deg": "216",
"dir": "西南风",
"sc": "微风",
"spd": "6"
}
},
{
"date": "2015-07-15 19:00",
"hum": "62",
"pop": "0",
"pres": "1005",
"tmp": "29",
"wind": {
"deg": "192",
"dir": "西南风",
"sc": "微风",
"spd": "4"
}
},
{
"date": "2015-07-15 22:00",
"hum": "62",
"pop": "0",
"pres": "1006",
"tmp": "26",
"wind": {
"deg": "154",
"dir": "东南风",
"sc": "微风",
"spd": "10"
}
}
],
"suggestion": {
"comf": {
"brf": "较舒适",
"txt": "白天天气晴好,您在这种天气条件下,会感觉早晚凉爽、舒适,午后偏热。"
},
"cw": {
"brf": "较不宜",
"txt": "较不宜洗车,未来一天无雨,风力较大,如果执意擦洗汽车,要做好蒙上污垢的心理准备。"
},
"drsg": {
"brf": "炎热",
"txt": "天气炎热,建议着短衫、短裙、短裤、薄型T恤衫等清凉夏季服装。"
},
"flu": {
"brf": "少发",
"txt": "各项气象条件适宜,发生感冒机率较低。但请避免长期处于空调房间中,以防感冒。"
},
"sport": {
"brf": "较适宜",
"txt": "天气较好,但风力较大,推荐您进行室内运动,若在户外运动请注意防风。"
},
"trav": {
"brf": "适宜",
"txt": "天气较好,是个好天气哦。稍热但是风大,能缓解炎热的感觉,适宜旅游,可不要错过机会呦!"
},
"uv": {
"brf": "强",
"txt": "紫外线辐射强,建议涂擦SPF20左右、PA++的防晒护肤品。避免在10点至14点暴露于日光下。"
}
}
}
]
}

编码阶段:

思路:1、由于免费账号查询次数每天有限制,可以将查询结果保存在当日的文件中(比如“cityID2016-2-1.txt”),

在查询前判断当天的文件是否存在,若存在则直接读取文件中的内容,若不存在,则从接口处获得

2、由于景点和城市查询时只有api的某些字段不同,所以可以将获取方法写在同一个函数中,只要为此函数增加

一个有默认值的参数即可(虽然现在免费账号无法查询景点天气,但这样方便日后再开发)

具体代码实现:

# -*- coding: utf-8 -*-
__author__ = 'yvonne'

import urllib2,json
from datetime import date
from os import path

def get_city_id(cityname, search_type=1):
ids = ''
if search_type == 1:# 查询城市ID
search = 'allchina'
fn0 = 'cityID'
elif search_type == 0:# 查询景点ID
fn0 = 'viewID'
search = 'allattractions'
else:
# 代表type值出错
return -1
fn = fn0+str(date.today())+'.txt'
try:
'''
查询是否存在当天的城市ID列表文件
若存在则直接读取文件里的信息
不存在则从接口再获取,景点也这么来
'''
if path.exists(fn):
fp = open(fn, 'r')
context = fp.read()
fp.close()
else:
fp = open(fn, 'w')
url_city = 'https://api.heweather.com/x3/citylist?search='+search+'&key=(改成您自己的Key)'
req = urllib2.Request(url_city)
resp = urllib2.urlopen(req)
context = resp.read()
# print True
fp.write(context)
fp.close()

city_json = json.loads(context, encoding='utf-8')
city_info = city_json["city_info"]
city_name = unicode(cityname, 'utf-8')
# print city_name
for index, cities in enumerate(city_info):
if city_name in cities['city']:
# 暂时不考虑有多个的情况(因为数据是从前端传入而不是用户手动输入的)
print cities['city']
ids = cities['id']
break
else:
# 之后将会返回-1
print '您输入的城市或景点不存在,请反馈给管理员'
except IOError, e:
print e
else:
pass
return ids

def get_city_weather(index, search_type=1):

if search_type == 1:
search = 'weather'
elif search_type == 0:
search = 'attractions'
else:
return -1
url_weather = 'https://api.heweather.com/x3/'+search+'?cityid='+index+'&key=(改成您自己的Key)'
req = urllib2.Request(url_weather)
resp = urllib2.urlopen(req)
context = resp.read()
weather_json = json.loads(context, encoding='utf-8')
fp = open("test.txt", 'w')
fp.write(context)
fp.close()
if search_type == 1:
weather = weather_json["HeWeather data service 3.0"][0]['daily_forecast'][0]
else:
weather = weather_json
return weather

if __name__:
# 测试代码
city = raw_input('请输入要查询的城市或景点:')
city_id = get_city_id(city)
print city_id
city_weather = get_city_weather(city_id)
print "最高温度", city_weather['tmp']['max']
print "最低温度", city_weather['tmp']['min']
print "日间天气", city_weather['cond']['txt_d']
print "夜间天气", city_weather['cond']['txt_n']

结果:



可以改进的地方:

若这是作为一个独立的应用的话,应该要提供模糊查询以及更丰富的天气预报信息,我现在用的是
if city_name in cities['city']:

模糊查询的效果可能还不是太过完美,而这个小demo是我根据现阶段我的需求写的。

遇到的问题:

编写过程中发现,json返回的数据都是用unicode编码的,在python解释器中无法正常显示中文,一直显示的是字符编码。
具体解决方法,请看我博客中的另一篇文章:python中json数据中文编码显示的问题
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: