我討厭下雨天跪帝,尤其是出門卻沒帶傘的下雨天猪杭。每到這個(gè)時(shí)候,就特羨慕大頭兒子纠亚,“人家有傘塘慕,我有大頭”。蒂胞。图呢。既然沒有大頭兒子的天賦異稟,就只能老老實(shí)實(shí)地帶傘了骗随。
蛋蛤织,總是忘了帶腫么破!:枞尽指蚜!
在多次被北京的大雨拍在路上之后,我痛定思痛涨椒,決定要想個(gè)法子解決忘帶傘這一世紀(jì)難題摊鸡。。蚕冬。
其實(shí)這個(gè)問題很好解決嘛免猾,早晨出門前看下天氣預(yù)報(bào)不就行了。對(duì)于像我這種每天能夠早早起床囤热、舒展一會(huì)兒身體猎提、做一頓營養(yǎng)早餐、看一個(gè)小時(shí)書旁蔼、在上班路上欣賞北京美景的人來說so easy锨苏。
才怪。
每天睡的比豬晚棺聊、起的比豬早伞租,早晨急忙爬起來刷個(gè)牙洗個(gè)臉,連個(gè)飯都吃不上就要去擠地鐵躺屁,這還天天遲到呢肯夏!哪還能想起來去看天氣預(yù)報(bào)啊O睢!烁兰!
主動(dòng)去看天氣預(yù)報(bào)這個(gè)方案對(duì)我來基本無解耐亏。。沪斟。
那广辰,就被動(dòng)好了暇矫,讓基友在我需要帶傘的時(shí)候,主動(dòng)提醒我一下吧择吊。
好李根,祭出基友之友--Python!<妇Α房轿!
我想讓python做以下事情:
所以,要實(shí)現(xiàn)以下三部分:
- 爬取天氣數(shù)據(jù)
- 判斷是否有雨
- 發(fā)送提醒
嗯所森,開搞囱持。
爬天氣預(yù)報(bào)數(shù)據(jù)
先找個(gè)靠譜的天氣預(yù)報(bào)網(wǎng)站,看了一圈焕济,感覺這個(gè)中國天氣預(yù)報(bào)挺靠譜的纷妆,畢竟敢用“中國”命名呢。下圖就是目標(biāo)數(shù)據(jù)了:
打開瀏覽器控制臺(tái)晴弃,找到數(shù)據(jù)在html中的位置:
可以看到掩幢,7天的天氣數(shù)據(jù)位于 id="7d"的div標(biāo)簽 -> ul標(biāo)簽 -> li標(biāo)簽 中。
再看看li中的具體結(jié)構(gòu):
- 日期位于 li標(biāo)簽 -> h1標(biāo)簽 中上鞠;
- 天氣位于 li標(biāo)簽 ->** class="wea"**的p標(biāo)簽 中际邻;
- 最高溫度位于 li標(biāo)簽 -> class="tem"的p標(biāo)簽 ->span標(biāo)簽 中;
- 最低溫度位于 li標(biāo)簽 -> class="tem"的p標(biāo)簽 -> i標(biāo)簽 中旗国。
數(shù)據(jù)找好了枯怖,開始爬數(shù)據(jù)出來。鑒于爬數(shù)據(jù)的邏輯簡單能曾,直接用urllib2和BeautifulSoup來做度硝。
# 爬取7天內(nèi)的天氣數(shù)據(jù)
from bs4 import BeautifulSoup
import urllib2
def fetch_weather_datas():
# 請(qǐng)求頁面數(shù)據(jù)
response = urllib2.urlopen(url='http://www.weather.com.cn/weather/101010100.shtml')
body = response.read()
# 用BeautifulSoup解析,取出7天的天氣數(shù)據(jù)
soup = BeautifulSoup(body, "lxml")
tags = soup.select('#7d > ul > li')
return ['%s\t%s\t%s\t%s' % # 對(duì)七天的數(shù)據(jù)分別解析寿冕,將解析后的每天的數(shù)據(jù)拼接成“日期+天氣+最高氣溫+最低氣溫”的字符串蕊程,\t分隔
(
tag.select('h1')[0].string, # 取時(shí)間數(shù)據(jù)
tag.select('.wea')[0]['title'], # 取天氣數(shù)據(jù)
tag.select('.tem > span')[0].string, # 取最高氣溫
tag.select('.tem > i')[0].string # 取最低氣溫
)
for tag in tags] # 返回結(jié)果為List
今天是否有雨?
拿到天氣數(shù)據(jù)之后驼唱,要看下今天的天氣如何藻茂,是否需要提醒我?guī)恪?/p>
# 傳入爬到的天氣數(shù)據(jù),判斷今天是否是雨天
def is_rainy_day(weather_data):
return '雨' in weather_data
發(fā)送提醒
因?yàn)槲沂謾C(jī)上的郵件客戶端始終在后臺(tái)開啟,選擇用郵件的方式來做提醒比較合適玫恳,所以使用了Python自帶的郵件發(fā)送工具:smtplib辨赐。
需要有一個(gè)發(fā)送提醒郵件的郵箱賬號(hào),我用的是新浪的郵箱京办。
# 發(fā)送郵件
import smtplib
from email.mime.text import MIMEText
from email.header import Header
def send_mail(receivers, datas):
mail_host = 'smtp.sina.com' # 設(shè)置服務(wù)器掀序,不同的郵箱對(duì)應(yīng)的smtp服務(wù)器地址不同
mail_user = 'username' # 用戶名,發(fā)送郵件的郵箱賬號(hào)的用戶名
mail_pass = 'password' # 密碼惭婿,發(fā)送郵件的郵箱密碼
# 定義郵件內(nèi)容
message = MIMEText('\n'.join(datas), 'plain', 'utf-8') # 郵件內(nèi)容為爬取到的近7天天氣數(shù)據(jù)
message['From'] = Header(mail_user) # 郵件的發(fā)送方
message['To'] = Header(','.join(receivers), 'utf-8') # 郵件的接受方不恭,逗號(hào)分隔
message['Subject'] = Header('天氣提醒', 'utf-8') # 郵件主題
try:
smtpObj = smtplib.SMTP()
smtpObj.connect(mail_host, 25) # 連接服務(wù)器叶雹, 25 為新浪郵箱 SMTP 端口號(hào)
log('連接服務(wù)器成功..')
smtpObj.login(mail_user, mail_pass) # 登錄服務(wù)器
log('登錄郵箱服務(wù)器成功..')
smtpObj.sendmail(from_addr=mail_user, to_addrs=receivers, msg=message.as_string()) # 發(fā)送郵件
log('郵件發(fā)送成功..')
except smtplib.SMTPException as e:
log('無法發(fā)送郵件...' + e.message)
# 日志打印
import time
def log(msg):
timestamp = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
print '[%s] %s' % (timestamp, msg)
整合
將上邊編寫完成的方法按下邊的方式整合到一起,就是一個(gè)能夠發(fā)送天氣提醒的腳本了:
try:
weather_datas = fetch_weather_datas() # 爬取天氣數(shù)據(jù)
if is_rainy_day(weather_datas[0]): # 今天是否是雨天
send_mail('xxxx@sina.com', weather_datas) # 發(fā)送天氣數(shù)據(jù)到目標(biāo)郵箱
else:
log('今天天氣良好..')
except:
log('出錯(cuò)..')
定時(shí)執(zhí)行
寫完腳本后换吧,我希望這個(gè)腳本能在每天早晨6點(diǎn)30分執(zhí)行折晦,這樣我就能在醒來的第一時(shí)間就能看到提醒郵件并帶上雨傘了。
首先需要一個(gè)能聯(lián)網(wǎng)的服務(wù)器沾瓦,將腳本放在服務(wù)器中满着。
然后,用crontab來做定時(shí)的任務(wù)(linux環(huán)境)暴拄。執(zhí)行:
crontab -e
此時(shí)會(huì)進(jìn)入vim界面漓滔,進(jìn)入編輯模式,輸入:
30 6 * * * /usr/bin/python xxxx/weather.py >> run.log
保存乖篷,此時(shí)定時(shí)任務(wù)就跑起來了响驴,日志記錄在run.log文件中。
具體的cron表達(dá)式語法在網(wǎng)上有很多教程撕蔼,就不細(xì)說了豁鲤。
完成
不必再羨慕大頭兒子了!雖然他有大頭鲸沮,但是我有傘啊~
Tip
完整的代碼可以看這里琳骡。
如有問題,歡迎交流~