家里老人比较关注天气变化,但是又不会使用智能手机随时上网查看天气信息,只能观看天气预报或者拨打天气热线查看。何不写个程序,每天自动给老人发送短信,告诉天气信息呢?
Google 查询后,发现网上有很多已封装好的 API 接口,但试了试又不大满意,主要有以下两方面的问题:
- 地域范围太大,最低也是以县级市为单位预报天气
- 天气信息准确性不可知,数据来源未知,多久更新一次也未知
因此,决定自己动手写一个,部署到阿里云服务器上。主要有以下 3 个模块构成:
- 天气数据爬取模块:即从网上爬取天气信息,并存储到数据库中
- 数据调用模块:使用 Flask Web 模块,定制 API 接口,用来读取数据 http://api.yuenshui.cn/weather/。当然了,在短信发送模块中直接从数据库中调取数据也是可以的,但使用 API 的方法可以更加方便地复用,而且可随时通过网络查询爬虫数据有没有问题,甚至都不要设置邮件或者短信的异常提醒。
- 短信发送模块:使用阿里云的短信接口,调用 api 数据并发送短信。主要查看官方文档即可
本文源代码存储于 Github 上: https://github.com/enshui/weather_notice
天气数据爬取模块
天气预报数据,使用的是中央气象台官方网站,这能够保证数据的可靠性和及时性。根据个人需要,这里仅调取了未来 5 天的日期/天气情况/风向/风力/最高最低气温几个信息。而且,中央气象台的天气信息,是可以精确到乡镇的,非常契合我的需求。
由于网站未做任何反爬措施且爬取的内容较少,这里使用的requests
的方法,解析库使用的是 xpath。数据存储,使用的是mongodb
数据库。如下是爬虫部分的代码,可直接运行,爬取的是我家所在镇上每小时的天气信息~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
def get_information(): response = requests.get('http://forecast.weather.com.cn/town/weathern/101120504010.shtml') selector = etree.HTML(response.content) today_weather = selector.xpath('//li[@class="blue-item active"]') later_weather = selector.xpath('//li[@class="blue-item"]') weather_lists = today_weather + later_weather weather=[w.xpath('.//p[@class="weather-info"]/@title')[0] for w in weather_lists] wind_origin = [w.xpath('.//div[@class="wind-container"]/i[1]/@title')[0] for w in weather_lists] wind_final = [w.xpath('.//div[@class="wind-container"]/i[2]/@title')[0] for w in weather_lists] wind_info = [w.xpath('.//p[@class="wind-info"]/text()')[0].strip() for w in weather_lists] temperatures = selector.xpath('/html/body/div[4]/div[3]/div[1]/div/script/text()')[0].split() high_temperature = temperatures[8].replace(';', '').replace(']','').replace('[','').replace('"','').split(',')[1:6] low_temperature = temperatures[12].replace(';', '').replace(']','').replace('[','').replace('"','').split(',')[1:6] today_date = selector.xpath('//ul[@class="date-container"]//li[@class="date-item active"]//p[@class="date"]//text()') later_date = selector.xpath('//ul[@class="date-container"]//li[@class="date-item"]//p[@class="date"]//text()')[1:] date_lists=today_date + later_date #以下代码,将爬取到的数据,存储为字典的形式。每天的日期,存储为一个key值 result = dict() for i in range(5): data = dict() data['weather'] = weather[i] data['wind_origin'] = wind_origin[i] data['wind_final'] = wind_final[i] data['wind_info'] = wind_info[i] data['high_temperature'] = high_temperature[i] data['low_temperature'] = low_temperature[i] result[date_lists[i]] = data print(result) return result |
API 调用模块
该模块的作用是,将调取的数据制作成自己的 api,用于进一步的使用。 我做的 api 网址是:http://api.yuenshui.cn/weather/