每天自动发送天气预报到女朋友邮箱

Posted by He Zongjiang on 2020-07-27

手机上每天都会收到天气预报的提醒,但都是出门后才发过来,我都出门,你再跟我说今天的天气预报,该没带伞还是没带伞,有啥用?于是琢磨自己写一个天气预报,顺便还可以撩妹,嘿嘿😊。先上最终成果图:

为了简单起见,代码使用 Python3 编写,天气数据直接从网上拿。整个过程主要分 3 步:

  1. 获取天气数据
  2. coding
  3. 打开浏览器截图
  4. 部署到服务器

废话不多说,直接开始。

一、获取天气数据

这里的天气数据是在 和风天气 上获取的,通过 注册 -> 登录 -> 控制台 -> 应用管理 -> 创建应用。通过这些步骤,就可以免费获取到 Key。可能界面会更新,以后创建流程可能会不一样,但无论如何,拿到 Key 就可以了。我们最终的目的是获取天气数据,无论怎么变动,拿到天气数据就行。

获取Key

获取到 Key 之后,打开 和风天气的开发文档,使用免费版接口。

知道这些,就可以开始请求 API,获取数据,解析天气信息了。

二、解析天气数据

发起请求,获取天气数据,URL 中的 location 修改为需要获取地点的参数,key 为上一步申请的 Key。

1
2
3
4
5
import requests

url = 'https://free-api.heweather.net/s6/weather/forecast?location=深圳&key=your_key'
res = requests.get(url).json()
print(res)

这样就已经获取到天气数据了。

为了简单起见,下面只解析天气和温度,解析其他数据方法是一样的。

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
import requests

def get_weather():

url = 'https://free-api.heweather.net/s6/weather/forecast?location=深圳&key=your_key'
res = requests.get(url).json()
print(res)
result = res['HeWeather6'][0]['daily_forecast']

# 今天的天气
today_date = result[0]['date'] # 日期
today_day = result[0]['cond_txt_d'] # 白天天气
today_night = result[0]['cond_txt_n'] # 晚上天气
today_max_tmp = result[0]['tmp_max'] # 最高温度
today_min_tmp = result[0]['tmp_min'] # 最低温度

# 明天的天气
tomorrow_date = result[1]['date']
tomorrow_day = result[1]['cond_txt_d']
tomorrow_night = result[1]['cond_txt_n']
tomorrow_max_tmp = result[1]['tmp_max']
tomorrow_min_tmp = result[1]['tmp_min']

weather_msg = '天气预报来啦~\n深圳今天(' + today_date + ')' + today_day + '转' + today_night + ',' + today_min_tmp + '℃ ~ ' + today_max_tmp + '℃。\n'
weather_msg += '深圳明天(' + tomorrow_date + ')' + tomorrow_day + '转' + tomorrow_night + ',' + tomorrow_min_tmp + '℃ ~ ' + tomorrow_max_tmp + '℃。'

# print(weather_msg)
return weather_msg

关于每个字段的具体含义,和风天气的开发文档中有具体描述。这样天气信息就准备好了。

三、天气截图

关于天气截图还是用的和风天气。进入控制台 -> 插件管理 -> 添加插件 -> H5插件。然后根据自己喜好,生成代码即可。然后会得到一个 URL,用浏览器打开是下面这样的:

我们要做的就是用 Python 对浏览器截图。

最终需要部署到服务器,如果你没有服务器也不要紧,买一个就可以了,呃,跳过这一小结,直接发邮件也是没问题的,只是少张图片而已。当然也可以直接把连接附在邮件里,点击邮件中的链接也可以,下一小结会说到。

大部分服务器是没有图形界面的,这里使用 Google 的无头浏览器。

所谓的无头浏览器模式也就是不需要打开浏览器,但是却可以起到模拟打开浏览器的执行效果,一切无界面执行。

我用的是 Centos7 的服务器,安装 Google 无头浏览器具体操作如下:

  1. 添加 google 的 repo 源
1
$ vim /etc/yum.repos.d/google.repo

在打开的空文件中填入以下内容

1
2
3
4
5
6
[google]
name=Google-x86_64
baseurl=http://dl.google.com/linux/rpm/stable/x86_64
enabled=1
gpgcheck=0
gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub
  1. 使用 yum 安装 chrome 浏览器
1
2
$ sudo yum makecache
$ sudo yum install google-chrome-stable -y
  1. 查看 chrome 的版本
1
2
$ google-chrome --version
Google Chrome 81.0.4044.122
  1. 下载 chromedriver

打开国内淘宝镜像地址,根据 chrome 版本下载对应的驱动。例如,我的 chrom 版本是 81.0.4044.122。

下载驱动,然后解压:

1
2
$ wget https://npm.taobao.org/mirrors/chromedriver/81.0.4044.138/chromedriver_linux64.zip
$ unzip chromedriver_linux64.zip

好了,浏览器完毕。接下来使用 selenium 来帮忙打开网页。当然你的服务器上得有 Python3 才行,如果没有可以看看《Linux 安装 Python 3.x》,简单几步就行。

先安装 selenium:

1
$ pip3 install selenium

安装完之后,终于可以开始截图了,不容易……

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
35
36
37
38
39
40
from selenium.webdriver import Chrome
from selenium.webdriver.chrome.options import Options
import time
import os.path

# 配置驱动路径
DRIVER_PATH = '/your/chromedriver/path'

if __name__ == "__main__":
# 设置浏览器
options = Options()
options.add_argument('--no-sandbox')
options.add_argument('--headless') # 无头参数
options.add_argument('--disable-gpu')
# 启动浏览器
driver = Chrome(executable_path=DRIVER_PATH, options=options)
driver.maximize_window()

try:
# 配置你的和风天气H5界面的url
url = 'https://your/hefeng/weather/url'
driver.get(url)
time.sleep(3)

# 设置截屏整个网页的宽度以及高度
scroll_width = 300
scroll_height = 700
driver.set_window_size(scroll_width, scroll_height)

# 保存图片,自定义图片命名和路径,注意:发送邮件时需要用到
img_name = time.strftime('%Y-%m-%d', time.localtime(time.time())) # 获取今天的日期
img = '/user/weather/' + img_name + '.png'
driver.get_screenshot_as_file(img)

# 关闭浏览器
driver.close()
driver.quit()

except Exception as e:
print(e)

运行代码,然后你就可以在代码中配置的路径下找到一张截图,注意路径需要自己配置,这个路径后面还要用到,图片命名是根据时间来的,也方便后面使用。

小插曲,如果图片中的中文都会显示x,这是由于服务器没有配置中文字体,上传个中文字体到服务器就行,很简单,不多说了。

准备了这么这么一大串,终于要发邮件了。

四、发送天气到邮箱

要发邮件,首先需要获取邮箱授权码。无论什么邮箱,操作过程大同小异,这里以 QQ 邮箱为例。

登录邮箱 -> 设置 -> 账户。开启 POP3/SMTP服务,获取授权码。

获取到的授权码如下图,是个字符串串。有了这个就可以通过代码来发邮件了。

授权码

发送邮件:

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import smtplib
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
import datetime # 导入日期时间模块
import os

def send_email(msg):
"""
发送邮件
"""
# 设置邮箱的域名
HOST = 'smtp.qq.com'
# 设置邮件标题
SUBJECT = '叮咚~ 明儿的天气到账啦~'
# 设置发件人邮箱
FROM = 'xxxx@qq.com'
# reciver
TO = 'xxxx@qq.com' # 可以同时发送到多个邮箱,逗号分割

message = MIMEMultipart('related')

msg_alternative = MIMEMultipart('alternative')
message.attach(msg_alternative)

mail_msg = msg + '<br>'

# 指定图片为当前目录
today = datetime.date.today() # 获得今天的日期
# 注意这里的图片路径,需要和上一步截图中的路径一致
img_path = '/user/weather/' + str(today) + '.png'

# 如果图片存在,则使用图片
if os.path.exists(img_path):
mail_msg = mail_msg + '<p><img src="cid:image1"></p>'
msg_alternative.attach(MIMEText(mail_msg, 'html', 'utf-8'))
with open(img_path, 'rb') as fp:
msg_image = MIMEImage(fp.read())
# 定义图片 ID,在 HTML 文本中引用
msg_image.add_header('Content-ID', '<image1>')
message.attach(msg_image)
fp.close()
else: # 如果图片不存在,则使用链接
mail_msg = mail_msg + '<a href="https://your/hefeng/weather/url">🎈爱心天气❤</a>'
msg_alternative.attach(MIMEText(mail_msg, 'html', 'utf-8'))

# 设置邮件发件人
message['From'] = FROM
# 设置邮件收件人
message['To'] = TO
# 设置邮件标题
message['Subject'] = SUBJECT

# 获取简单邮件传输协议的证书
email_client = smtplib.SMTP_SSL(host=HOST)
# 设置发件人邮箱的域名和端口,端口为465
email_client.connect(HOST, '465')
# 登录邮箱
login_result = email_client.login(FROM, 'your authorization code')
print('login result: ' + login_result)
# 发送邮件
email_client.sendmail(from_addr=FROM, to_addrs=TO.split(','), msg=message.as_string())
# 关闭邮件发送客户端
email_client.close()

五、部署到服务器

现在需要把写好的代码部署到服务器,让服务器每天定时发送。完整代码可以在我的 Github 上查看。

首先上传文件到服务器,weather.py 文件是发送天气信息到邮箱,screenshot.py 文件是对浏览器进行截图:

1
2
$ scp /your/path/weather.py user@ip.address:/usesr/weather/
$ scp /your/path/screenshot.py user@ip.address:/usesr/weather/

然后这两个文件需要有可执行权:

1
2
$ chomd chmod a+x weather.py
$ chomd chmod a+x screenshot.py

接着使用 Python3 来执行这两个文件,但你需要知道 Python3 在哪,例如我的在/usr/bin/python3

1
2
$ which python3
/usr/bin/python3

最后配置 crontab 文件,定时发送就可以了:

1
$ vim /etc/crontab

我的配置信息如下,每天19:50开始天气截图,20:00发送邮件。

现在,妈妈再也不用担心我不知道明天的天气了。

当然,还可以改吧改吧,弄一下花哨的东西去撩妹了。