Python-定時(shí)爬取指定城市天氣(二)-郵件提醒

[TOC]

一、概述

上一篇文章python-定時(shí)爬取指定城市天氣(一)-發(fā)送給關(guān)心的微信好友中我們講述了怎么定時(shí)爬取城市天氣折晦,并發(fā)送給指定微信好友,文末遺留兩個(gè)問(wèn)題

  • 定時(shí)任務(wù)做成windows服務(wù),這樣更優(yōu)雅在抛,隨開(kāi)機(jī)啟動(dòng)
  • 發(fā)送消息給微信好友換成發(fā)送郵件給指定郵箱

本篇文章我們?cè)谠瓉?lái)代碼的基礎(chǔ)上進(jìn)行了一定的模塊拆分,并處理以上兩個(gè)問(wèn)題

二萧恕、模塊重新劃分

  1. 新增my_job.py文件刚梭,把任務(wù)模塊單獨(dú)劃分出來(lái)

之前的定時(shí)任務(wù)使用的是apscheduler庫(kù)做的,并且任務(wù)類在main函數(shù)所在py文件中票唆,這樣導(dǎo)致主py文件很難進(jìn)行修改

  1. 新增util.py文件

包含公用的方法朴读,比如目前的字典轉(zhuǎn)字符串

  1. 新增weather_service.py文件

主要負(fù)責(zé)構(gòu)造windows服務(wù),也是一個(gè)主py文件走趋,不同于第一篇文章的主py文件weath_report.py衅金,這是我們實(shí)現(xiàn)的兩種定時(shí)任務(wù),可分別運(yùn)行簿煌,如果想把天氣信息通知微信好友則啟動(dòng)weath_report.py典挑,可參考文章ython-定時(shí)爬取指定城市天氣(一)-發(fā)送給關(guān)心的微信好友,如果是通過(guò)發(fā)送郵件的方式則直接把weather_service.py安裝成windows服務(wù)啦吧,并啟動(dòng)即可您觉,記住需要配置運(yùn)行的任務(wù)列表,下邊會(huì)講述怎么配置任務(wù)

  1. 新增timing_task.py文件

包含任務(wù)方法executeJob()授滓,主要是在服務(wù)中循環(huán)跑琳水,然后在合適的時(shí)間爬取天氣并發(fā)送到指定郵箱肆糕,任務(wù)的參數(shù)是通過(guò)配置json串來(lái)實(shí)現(xiàn)

三、優(yōu)化定時(shí)任務(wù)

本篇文章的定時(shí)任務(wù)是運(yùn)行在windows服務(wù)中的在孝,因此我們首先需要安裝pywin32模塊

  1. 安裝pywin32
pip install pywin32
  1. 服務(wù)操作相關(guān)命令
1.安裝服務(wù) python PythonService.py install
2.讓服務(wù)自動(dòng)啟動(dòng) python PythonService.py --startup auto install
3.啟動(dòng)服務(wù) python PythonService.py start
4.重啟服務(wù) python PythonService.py restart
5.停止服務(wù) python PythonService.py stop
6.刪除/卸載服務(wù) python PythonService.py remove
  1. 啟動(dòng)服務(wù)時(shí)被拒絕
Installing service timingTaskDaemon
Error installing service: 拒絕訪問(wèn)诚啃。 (5)

a.大多數(shù)原因是由于python環(huán)境配置的問(wèn)題,python默認(rèn)安裝時(shí)配置的pah是用戶環(huán)境變量私沮,這里我們需要改成系統(tǒng)環(huán)境變量始赎,具體可以參考Python 寫(xiě)windows service 及 start service 出現(xiàn)錯(cuò)誤 1053:服務(wù)沒(méi)有及時(shí)響應(yīng)啟動(dòng)或控制請(qǐng)求
b.考慮命令行是否有權(quán)限,我自己的win8系統(tǒng)默認(rèn)權(quán)限就不夠仔燕,需要右鍵管理員啟動(dòng)才可以

  1. 實(shí)現(xiàn)windows服務(wù)功能造垛,我們需要繼承win32serviceutil.ServiceFramework這個(gè)類,把需要執(zhí)行的業(yè)務(wù)邏輯放入SvcDoRun函數(shù)中晰搀,如下代碼中executeJob()函數(shù)即為我們定時(shí)執(zhí)行的任務(wù)
class WeatherPythonService(win32serviceutil.ServiceFramework):
    _svc_name_ = "weather_service_test4"
    _svc_display_name_ = "weather_service_test4"
    _svc_description_ = "i am a test weather_service_test"
    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self, args)
        # Create an event which we will use to wait on.
        # The "service stop" request will set this event.
        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
        self.run = True
    def SvcStop(self):
        # Before we do anything, tell the SCM we are starting the stop process.
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        # And set my event.
        win32event.SetEvent(self.hWaitStop)
        self.run = False
    def SvcDoRun(self):
        #what to do#
        while self.run:
            executeJob()
            time.sleep(5)
        #win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE)
if __name__ == '__main__':
    #executeJob()
    win32serviceutil.HandleCommandLine(WeatherPythonService)
  1. 任務(wù)執(zhí)行函數(shù)
def executeJob():
    now_time = time.localtime(time.time())
    now_hour = now_time.tm_hour
    now_minute = now_time.tm_min
    for job in my_jobs:
        ts = job['time']
        for t in ts.split(','):
            jobtime = t.split('.')
            h = jobtime[0]
            m = jobtime[1]
            if (now_hour != h and now_minute != m):
                code = city_code.find_code(job['city'])
                wea = getWeath(code)
                strWea = strDic(wea)
                title = '{}天氣預(yù)報(bào)'.format(job['city'])
                send_email(job['receivers'], 'title', title + ":\n" + strWea)

任務(wù)執(zhí)行時(shí)五辽,需要配置任務(wù)執(zhí)行列表,即上述代碼中my_jobs對(duì)象外恕,該對(duì)象是一個(gè)標(biāo)準(zhǔn)的json串杆逗,不同于上一篇文章的json格式,本篇文章的任務(wù)參數(shù)如下鳞疲,任務(wù)整體是一個(gè)數(shù)組罪郊,數(shù)組中包含了任務(wù)對(duì)象,每一個(gè)對(duì)象由3個(gè)字段組成尚洽,分別是郵件接收者郵箱receivers排龄、爬取城市city和爬取時(shí)間time

my_jobs = [{
    "receivers":['1134024095@qq.com'],
    "city":"昌平",
    "time":"6.30,17.30"
    },{
    "receivers":['1134024095@qq.com'],
    "city":"海淀",
    "time":"6.30,17.30"
    }]
  1. 安裝服務(wù),成功啟動(dòng)后翎朱,但是任務(wù)沒(méi)有正常執(zhí)行,可以通過(guò)查看系統(tǒng)任務(wù)事件來(lái)確定錯(cuò)誤的原因尺铣,如下圖所示拴曲,這是我在排查錯(cuò)誤的時(shí)候截圖

查詢系統(tǒng)日志:win+r 回車輸入 eventvwr.exe 在回車

look_log.png

四、發(fā)送郵件

這里我們使用QQ郵箱作為示例進(jìn)行演示凛忿,發(fā)送郵件使用smtplib庫(kù)

  1. QQ郵箱發(fā)送需要申請(qǐng)口令澈灼,申請(qǐng)方式

  2. 選擇郵箱發(fā)送服務(wù)器smtp.qq.com和端口號(hào)465

  3. 構(gòu)造發(fā)件人、收件人和郵件內(nèi)容

message = MIMEText(text, 'plain', 'utf-8')
message['From'] = formataddr(["就差一點(diǎn)兒", sender])  # 括號(hào)里的對(duì)應(yīng)發(fā)件人郵箱昵稱店溢、發(fā)件人郵箱賬號(hào)
message['To'] = Header(','.join(receivers), 'utf-8')#接受者
message['Subject'] = Header(title, 'utf-8')

text為郵件內(nèi)容叁熔,通過(guò)From構(gòu)造發(fā)件人信息,To構(gòu)造收件人信息床牧,這個(gè)構(gòu)造的只是顯示的文本串荣回,如本小節(jié)底部截圖所示的收件人和發(fā)件人等,真正的接受郵件的賬號(hào)在發(fā)送郵件時(shí)指定戈咳。

  1. 連接郵箱服務(wù)器心软、登陸
smtpObj = smtplib.SMTP_SSL()
smtpObj.connect(mail_host, mail_port)    # mail_port 為 SMTP 端口號(hào)
smtpObj.login(mail_user, mail_pass)  
  1. 發(fā)送郵件
smtpObj.sendmail(sender, receivers, message.as_string())
  1. 郵件發(fā)送成功


    success.png
  1. 完整發(fā)送郵件代碼
# 三個(gè)參數(shù):第一個(gè)為文本內(nèi)容壕吹,第二個(gè) plain 設(shè)置文本格式,第三個(gè) utf-8 設(shè)置編碼
def send_email(receivers, title, text):
    message = MIMEText(text, 'plain', 'utf-8')
    message['From'] = formataddr(["就差一點(diǎn)兒", sender])  # 括號(hào)里的對(duì)應(yīng)發(fā)件人郵箱昵稱删铃、發(fā)件人郵箱賬號(hào)
    message['To'] = Header(','.join(receivers), 'utf-8')#接受者

    message['Subject'] = Header(title, 'utf-8')
    
    ret = True
    try:
        smtpObj = smtplib.SMTP_SSL()
        smtpObj.connect(mail_host, mail_port)    # mail_port 為 SMTP 端口號(hào)
        smtpObj.login(mail_user, mail_pass)  
        smtpObj.sendmail(sender, receivers, message.as_string())
    except smtplib.SMTPException:
        ret = False
    
    f = open('./sendemail_weather.log', 'a', encoding = 'utf-8')
    if ret:
        f.write(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + ':郵件發(fā)送成功\n')
    else:
        f.write(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') +':無(wú)法發(fā)送郵件\n')
    f.close()
  1. 測(cè)試發(fā)送郵件
send_email(['1134024095@qq.com','1024068757@qq.com'], "昌平", "6.30")

五耳贬、源代碼

以前寫(xiě)博客測(cè)試程序都是放在csdn,最近幾次發(fā)現(xiàn)csdn審核流程太慢了猎唁,導(dǎo)致和博客發(fā)布時(shí)間不統(tǒng)一咒劲,因此后續(xù)測(cè)試程序代碼我都盡量放在git上,本篇文章的測(cè)試程序有需要的朋友可以去weather_report_service下載




轉(zhuǎn)載聲明:本站文章無(wú)特別說(shuō)明诫隅,皆為原創(chuàng)腐魂,版權(quán)所有,轉(zhuǎn)載請(qǐng)注明:朝十晚八 or Twowords


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末阎肝,一起剝皮案震驚了整個(gè)濱河市挤渔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌风题,老刑警劉巖判导,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異沛硅,居然都是意外死亡眼刃,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)摇肌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)擂红,“玉大人,你說(shuō)我怎么就攤上這事围小£侵瑁” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵肯适,是天一觀的道長(zhǎng)变秦。 經(jīng)常有香客問(wèn)我,道長(zhǎng)框舔,這世上最難降的妖魔是什么蹦玫? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮刘绣,結(jié)果婚禮上樱溉,老公的妹妹穿的比我還像新娘。我一直安慰自己纬凤,他們只是感情好福贞,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著停士,像睡著了一般肚医。 火紅的嫁衣襯著肌膚如雪绢馍。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天肠套,我揣著相機(jī)與錄音舰涌,去河邊找鬼。 笑死你稚,一個(gè)胖子當(dāng)著我的面吹牛瓷耙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播刁赖,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼搁痛,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了宇弛?” 一聲冷哼從身側(cè)響起鸡典,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎枪芒,沒(méi)想到半個(gè)月后彻况,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡舅踪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年纽甘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抽碌。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡悍赢,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出货徙,到底是詐尸還是另有隱情左权,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布痴颊,位于F島的核電站赏迟,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏祷舀。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一烹笔、第九天 我趴在偏房一處隱蔽的房頂上張望裳扯。 院中可真熱鬧,春花似錦谤职、人聲如沸饰豺。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)冤吨。三九已至蒿柳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間漩蟆,已是汗流浹背垒探。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留怠李,地道東北人圾叼。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像捺癞,于是被迫代替她去往敵國(guó)和親夷蚊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354