有了这个脚本,妈妈再也不用担心我下雨天忘带伞了!

伞.jpeg

我讨厌下雨天,尤其是出门却没带伞的下雨天。每到这个时候,就特羡慕大头儿子,“人家有伞,我有大头”。。。既然没有大头儿子的天赋异禀,就只能老老实实地带伞了。

蛋,总是忘了带肿么破!!!

在多次被北京的大雨拍在路上之后,我痛定思痛,决定要想个法子解决忘带伞这一世纪难题。。。

其实这个问题很好解决嘛,早晨出门前看下天气预报不就行了。对于像我这种每天能够早早起床、舒展一会儿身体、做一顿营养早餐、看一个小时书、在上班路上欣赏北京美景的人来说so easy。

才怪。

每天睡的比猪晚、起的比猪早,早晨急忙爬起来刷个牙洗个脸,连个饭都吃不上就要去挤地铁,这还天天迟到呢!哪还能想起来去看天气预报啊!!!

主动去看天气预报这个方案对我来基本无解。。。

那,就被动好了,让基友在我需要带伞的时候,主动提醒我一下吧。

好,祭出基友之友--Python!!!

我想让python做以下事情:

流程图.png

所以,要实现以下三部分:

  1. 爬取天气数据
  2. 判断是否有雨
  3. 发送提醒

嗯,开搞。

爬天气预报数据

先找个靠谱的天气预报网站,看了一圈,感觉这个中国天气预报挺靠谱的,毕竟敢用“中国”命名呢。下图就是目标数据了:

天气数据.png

打开浏览器控制台,找到数据在html中的位置:

html1.png

可以看到,7天的天气数据位于 id="7d"div标签 -> ul标签 -> li标签 中。

再看看li中的具体结构:

html2.png
  • 日期位于 li标签 -> h1标签 中;
  • 天气位于 li标签 ->** class="wea"**的p标签 中;
  • 最高温度位于 li标签 -> class="tem"p标签 ->span标签 中;
  • 最低温度位于 li标签 -> class="tem"p标签 -> i标签 中。

数据找好了,开始爬数据出来。鉴于爬数据的逻辑简单,直接用urllib2BeautifulSoup来做。

# 爬取7天内的天气数据
from bs4 import BeautifulSoup
import urllib2
def fetch_weather_datas():
    # 请求页面数据
    response = urllib2.urlopen(url='http://www.weather.com.cn/weather/101010100.shtml') 
    body = response.read()

    # 用BeautifulSoup解析,取出7天的天气数据
    soup = BeautifulSoup(body, "lxml")
    tags = soup.select('#7d > ul > li')

    return ['%s\t%s\t%s\t%s' %  # 对七天的数据分别解析,将解析后的每天的数据拼接成“日期+天气+最高气温+最低气温”的字符串,\t分隔
        (
            tag.select('h1')[0].string, # 取时间数据
            tag.select('.wea')[0]['title'],  # 取天气数据
            tag.select('.tem > span')[0].string, # 取最高气温
            tag.select('.tem > i')[0].string # 取最低气温
        ) 
        for tag in tags] # 返回结果为List

今天是否有雨?

拿到天气数据之后,要看下今天的天气如何,是否需要提醒我带伞。

# 传入爬到的天气数据,判断今天是否是雨天
def is_rainy_day(weather_data):
    return '雨' in weather_data

发送提醒

因为我手机上的邮件客户端始终在后台开启,选择用邮件的方式来做提醒比较合适,所以使用了Python自带的邮件发送工具:smtplib
需要有一个发送提醒邮件的邮箱账号,我用的是新浪的邮箱。

# 发送邮件
import smtplib
from email.mime.text import MIMEText
from email.header import Header
def send_mail(receivers, datas):
    mail_host = 'smtp.sina.com'  # 设置服务器,不同的邮箱对应的smtp服务器地址不同
    mail_user = 'username'  # 用户名,发送邮件的邮箱账号的用户名
    mail_pass = 'password'  # 密码,发送邮件的邮箱密码

    # 定义邮件内容
    message = MIMEText('\n'.join(datas), 'plain', 'utf-8') # 邮件内容为爬取到的近7天天气数据
    message['From'] = Header(mail_user) # 邮件的发送方
    message['To'] = Header(','.join(receivers), 'utf-8') # 邮件的接受方,逗号分隔
    message['Subject'] = Header('天气提醒', 'utf-8') # 邮件主题

    try:
        smtpObj = smtplib.SMTP()
        smtpObj.connect(mail_host, 25)  # 连接服务器, 25 为新浪邮箱 SMTP 端口号
        log('连接服务器成功..')
        smtpObj.login(mail_user, mail_pass) # 登录服务器
        log('登录邮箱服务器成功..')
        smtpObj.sendmail(from_addr=mail_user, to_addrs=receivers, msg=message.as_string()) # 发送邮件
        log('邮件发送成功..')
    except smtplib.SMTPException as e:
        log('无法发送邮件...' + 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)

整合

将上边编写完成的方法按下边的方式整合到一起,就是一个能够发送天气提醒的脚本了:

try:
    weather_datas = fetch_weather_datas() # 爬取天气数据
    if is_rainy_day(weather_datas[0]):  # 今天是否是雨天
        send_mail('xxxx@sina.com', weather_datas) # 发送天气数据到目标邮箱
    else:
        log('今天天气良好..')
except:
    log('出错..')

定时执行

写完脚本后,我希望这个脚本能在每天早晨6点30分执行,这样我就能在醒来的第一时间就能看到提醒邮件并带上雨伞了。

首先需要一个能联网的服务器,将脚本放在服务器中。

然后,用crontab来做定时的任务(linux环境)。执行:

crontab -e

此时会进入vim界面,进入编辑模式,输入:

30 6 * * * /usr/bin/python xxxx/weather.py >> run.log

保存,此时定时任务就跑起来了,日志记录在run.log文件中。

具体的cron表达式语法在网上有很多教程,就不细说了。

完成

不必再羡慕大头儿子了!虽然他有大头,但是我有伞啊~


Tip

完整的代码可以看这里

如有问题,欢迎交流~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,014评论 19 139
  • 一 在外漂泊时间久了,就会发现,回家不过是过年的例行公事,不回家却是自由舒服的常态。 中秋节,你回不回家?有人如是...
    是喵儿啊阅读 664评论 3 0
  • 目标明确了,计划也制定好了,该去实践了,可是仅仅依靠“实践”并不能保证成功,那么如何去实践呢,这是第7章解决的问题...
    kelinda阅读 217评论 0 1
  • 感觉早早田的每个人都在努力让自己向上做好,但有时候太走进内在了,学的东西感觉一直是理论层面的,当我们从理论探索出实...
    凤飞飞1阅读 195评论 0 0
  • -1- 没错,那时候车马很慢,邮件很慢,时光很慢,慢到这辈子只够爱一个人。 爸爸妈妈自小认识但不熟悉,结婚二十多年...
    超级带感的狗狗草阅读 574评论 2 2