使用python获取天气预报
-
工具:python3.4 (配合
re
或BeautifulSoup
) -
目标:获取天气预报,内容包括【时间】+【天气】+【气温】
有了之前的36kr新闻阅读器作为基础,我们不难写出更多基于python网络库的小程序。这次我们来写一个简单实用的脚本来获取天气预报,数据来源是中国天气网。最终呈现在终端或者命令行的内容类似于:
6号(今天) 多云 23 ~ 16℃
7号(明天) 小雨转中雨 22 ~ 15℃
1. 分析网页
这次的脚本也是一个Spider,所以第一步当然也是分析网页结构。打开中国天气网
在搜索栏输入城市,这里以上海为例,可以看到地址栏变成了http://www.weather.com.cn/weather/101020100.shtml
. 接着右键点击7天
预报中的今天
,选择Inspect
(检查元素(N)),可以看到这段代码
<ul class="t clearfix">
<li class="sky skyid lv2 on">
<h1>6日(今天)</h1>
<big class="png40 d00"></big>
<big class="png40 n00"></big>
<p title="多云" class="wea">多云</p>
<p class="tem">
<span>23</span>/<i>16℃</i>
</p>
...
...
</li>
第2~7天的内容结构也是这样。
2. 获取网页内容
2.1 利用正则表达式
我们利用urllib.request
获取网页内容,然后用36kr新闻阅读器中提到的re
模块来”暴力”提取关键信息。所谓re
,就是Regular Expression,即正则表达式。它可以被分为很多类,差异比较可以看这里。对于python所用的正则表达式,可以参考官方文档,以及这里。
首先,我们引入两个模块:
#!/urs/bin/enc python3
# -*- coding: utf-8 -*-
from urllib import request
import re
接着,下载网页内容:
url = 'http://www.weather.com.cn/weather/101020100.shtml'
req = request.Request(url)
weekly_weather = request.urlopen(req).read().decode('utf-8')
这样,我们就把内容保存在了weekly_weather
。接下来,我们分析第1节中的网页源码,进行正则匹配。观察以后可以发现:
-
对于
时间
,其结构是这样的:<h1>([1-9].*)</h1>
。其中[1-9]
表示匹配1~9开头的任意数字,.*
表示匹配任意字符串。由此可以匹配出这一天是几号,如(11月)6号
。 -
对于
天气
,其结构是这样的:.*class="wea">(.*)</p>
,可以匹配出这一天是晴天、多云,或者其他天气。 -
对于
气温
,其结构是这样的:<span>([0-9]*)</span>/<i>([0-9].*)</i>
。这样可以匹配出这一天是几度到几度,如23~16℃
。
因此可以利用python的re.findall()
提取出以上三项内容,并保存于seven_days
,注意不要遗漏换行符\n
:
seven_days = re.findall(r'\<h1\>([1-9].*)\</h1>\n.*\n.*\n.*\>(.*)\</p>\n.*\n\<span\>([0-9]*).*\>([0-9].*)\</i\>\n', weekly_weather)
re.findall()
会以list
的形式返回所有匹配的字符串。由于每一天有三个匹配项,因此seven_days
是一个list
,而其每一个元素都是一个元组tuple
。
最后就是将结果打印在屏幕上了:
for day in seven_days:
print(day[0], day[1], day[2], day[3], '\n')
2.2 使用BeautifulSoup
此外,还可以使用BeautifulSoup这一利器来帮我们解析html,进而得到我们想要的内容。 BeautifulSoup
的特点就是直观,可以通过标签类别、名字和属性等方式获得内容。
要使用BeautifulSoup
,首先要安装必要的包:
$ pip3 install beautifulsoup4
接着引入模块:
#!/urs/bin/enc python3
# -*- coding: utf-8 -*-
from urllib import request
from bs4 import BeautifulSoup
然后和之前一样,下载资源:
url = 'http://www.weather.com.cn/weather/101020100.shtml'
req = request.Request(url)
weekly_weather = request.urlopen(req).read().decode('utf-8')
下一步,我们生成一个实例化一个BeautifulSoup对象,用html.parser去解析下载到的html资源,保存为一个有层次结构的soup:
soup = BeautifulSoup(weekly_weather, 'html.parser')
如果分析一下上一节的html代码,我们可以发现class="t clearfix"
是独一无二的。因此我们可以利用它来寻找7天的天气数据。需要注意的是里面的参数名是class_
而非class
:
seven_days = soup.find('ul', class_='t clearfix').get_text()
现在seven_days的内容就变成了那一段html代码中去掉所有标签的内容,由于比较长,这里就不贴出来了。直接用print(seven_days)
就能看到。
观察其特点,我们根据\n
将其拆分,并舍去空白段,将有用信息存到一个list
里面:
seven_days = seven_days.split('\n')
days = []
for day in seven_days:
if day != '':
days.append(day)
else:
pass
至此,我们就可以在屏幕上输出天气信息了:
for i in range(2):
print(days[i*4])
print(days[i*4+1])
print(days[i*4+2])
print(days[i*4+3])
print('\n')
2.3 练习
以上,我们用两种方式完成了获取天气预报的小程序,作为脚本它是足够用了,不过我们还可以稍作改进,在参考github上的代码之前,以下几点就作为练习啦~
-
简化优化代码,抽象成函数,模块化。
-
如果在晚上使用,可以发现屏幕上输出的是明天加后天的天气。那么,如何获取今晚的天气(如气温)呢?
(END)