检查天气似乎相当简单:打开 Web 浏览器,点击地址栏,输入天气网站的 URL(或搜索一个,然后点击链接),等待页面加载,跳过所有的广告等。其实, 如果有一个程序,下载今后几天的天气预报,并以纯文本打印出来,就可以跳过很多无聊的步骤。该程序利用 requests 模块,从网站下载数据。
总的来说,该程序将执行以下操作:
• 从命令行读取请求的位置。
• 从 OpenWeatherMap.org 下载 JSON 天气数据。
• 将 JSON 数据字符串转换成 Python 的数据结构。
• 打印今天和未来两天的天气。
因此,代码需要完成以下任务:
• 连接 sys.argv 中的字符串,得到位置。
• 调用 requests.get(),下载天气数据。
• 调用 json.loads(),将 JSON 数据转换为 Python 数据结构。
• 打印天气预报。
针对这个项目,打开一个新的文件编辑器窗口,并保存为 quickWeather.py。
从命令行参数获取位置
该程序的输入来自命令行。让 quickWeather.py 看起来像这样:
#! python3
# quickWeather.py - Prints the weather for a location from the command line.
import json, requests, sys
# Compute location from command line arguments.
if len(sys.argv) < 2:
print('Usage: quickWeather.py location')
sys.exit()
location = ' '.join(sys.argv[1:])
# TODO: Download the JSON data from OpenWeatherMap.org's API
# TODO: Load JSON data into a Python variable
在 Python 中,命令行参数存储在 sys.argv 列表里。 #!行和 import 语句之后,程序会检查是否有多个命令行参数(回想一下, sys.argv 中至少有一个元素 sys.argv[0],它包含了 Python 脚本的文件名)。如果该列表中只有一个元素,那么用户没有在命令行中提供位置,程序向用户提供“Usage(用法)”信息,然后结束。命令行参数以空格分隔。命令行参数 San Francisco, CA 将使 sys.argv 中保存['quickWeather.py', 'San', 'Francisco,', 'CA']。因此,调用 join()方法,将 sys.argv 中除第一个字符串以外的字符串连接起来。将连接的字符串存储在变量 location 中
下载 JSON 数据
OpenWeatherMap.org 提供了 JSON 格式的实时天气信息。你的程序只需要下载页面 http://api.openweathermap.org/data/2.5/forecast/daily?q=
#! python3
# quickWeather.py - Prints the weather for a location from the command line.
--snip--
# Download the JSON data from OpenWeatherMap.org's API
url = 'http://api.openweathermap.org/data/2.5/forecast/daily?q=%s&cnt=3' % (location)
response = requests.get(url)
response.raise_for_status()
# TODO: Load JSON data into a Python variable
我们从命令行参数中得到了 location。为了生成要访问的网址,我们利用%s 占位符,将 location 中保存的字符串插入 URL 字符串的那个位置。结果保存在 url 中,并将 url 传入 requests.get()。 requests.get()调用返回一个 Response 对象,它可以通过调用
raise_for_status()来检查错误。如果不发生异常,下载的文本将保存在 response.text 中。
加载 JSON 数据并打印天气
esponse.text 成员变量保存了一个 JSON 格式数据的大字符串。要将它转换为Python 值,就调用 json.loads()函数。 JSON 数据会像这样:
{'city': {'coord': {'lat': 37.7771, 'lon': -122.42},
'country': 'United States of America',
'id': '5391959',
'name': 'San Francisco',
'population': 0},
'cnt': 3,
'cod': '200',
'list': [{'clouds': 0,
'deg': 233,
'dt': 1402344000,
'humidity': 58,
'pressure': 1012.23,
'speed': 1.96,
'temp': {'day': 302.29,
'eve': 296.46,
'max': 302.29,
'min': 289.77,
'morn': 294.59,
'night': 289.77},
'weather': [{'description': 'sky is clear',
'icon': '01d',
--snip--
可以将 weatherData 传入 pprint.pprint,查看这个数据。你可能要查找 http://openweathermap.org/,找到关于这些字段含义的文档。例如,在线文档会告诉你, 'day'后面的 302.29 是白天的开尔文温度,而不是摄氏或华氏温度。你想要的天气描述在'main'和 'description'之后。为了整齐地打印出来,在quickWeather.py 中添加以下代码。
#! python3
# quickWeather.py - Prints the weather for a location from the command line.
--snip--
# Load JSON data into a Python variable
weatherData = json.loads(response.text)
# Print weather descriptions.
w = weatherData['list']
print('Current weather in %s: ' % (location))
print(w[0]['weather'][0]['main'], '-', w[0]['weather'][0]['description'])
print()
print('Tomorrow:')
print(w[1]['weather'][0]['main'], '-', w[1]['weather'][0]['description'])
print()
print('Day after tomorrow:')
print(w[2]['weather'][0]['main'], '-', w[2]['weather'][0]['description'])
注意,代码将 weatherData['list']保存在变量 w 中,这将节省一些打字时间。可以用 w[0]、 w[1]和 w[2]来取得今天、明天和后天天气的字典。这些字典都有'weather'键,其中包含一个列表值。你感兴趣的是第一个列表项(一个嵌套的字典,包含几个键), 下标是 0。这里,我们打印出保存在'main'和'description'键中的值,用连字符隔开。如果用命令行参数 quickWeather.py San Francisco, CA 运行这个程序,输出看起来是这样的:
Current weather in San Francisco, CA:
Clear - sky is clear
Tomorrow:
Clouds - few clouds
Day after tomorrow:
Clear - sky is clear
类似程序的想法
访问气象数据可以成为多种类型程序的基础。你可以创建类似程序,完成以下任务:
• 收集几个露营地点或远足路线的天气预报,看看哪一个天气最好。
• 如果需要将植物移到室内,安排一个程序定期检查天气并发送霜冻警报(
• 从多个站点获得气象数据,同时显示,或计算并显示多个天气预报的平均值。
完整代码
#! python3
# quickWeather.py - Prints the weather for a location from the command line.
import json, requests, sys
# Compute location from command line arguments.
if len(sys.argv) < 2:
print('Usage: quickWeather.py location')
sys.exit()
location = ' '.join(sys.argv[1:])
# Download the JSON data from OpenWeatherMap.org's API
url = 'http://api.openweathermap.org/data/2.5/forecast/daily?q=%s&cnt=3' % (location)
response = requests.get(url)
response.raise_for_status()
# Load JSON data into a Python variable
weatherData = json.loads(response.text)
# Print weather descriptions.
w = weatherData['list']
print('Current weather in %s: ' % (location))
print(w[0]['weather'][0]['main'], '-', w[0]['weather'][0]['description'])
print()
print('Tomorrow:')
print(w[1]['weather'][0]['main'], '-', w[1]['weather'][0]['description'])
print()
print('Day after tomorrow:')
print(w[2]['weather'][0]['main'], '-', w[2]['weather'][0]['description'])