一、需求
定时自动发送邮件,邮件内容包含:
- 通过接口爬取每日一句,作为正文
- 通过接口爬取每日天气,作为正文
- 通过接口爬取随机图片,并作为附件
最终效果图:
二、代码实现
1、Python代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2023/6/3 20:37
# @Author : Maple
# @File : sendemail.py
import smtplib
import email
import datetime
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.header import Header
import requests
from bs4 import BeautifulSoup
from lxml import etree
import os
# 获取当前路径
current_directory = os.path.dirname(os.path.abspath(__file__))
# 通过接口获取城市code
def get_city_code(city):
response = requests.get(url="http://toy1.weather.com.cn/search?cityname=" + city)
res = response.content.decode('utf-8')
city_code = eval(res)[0]["ref"].split('~')[0]
return city_code
# 通过接口获取城市天气
def get_Weather(city_code):
url = f'http://www.weather.com.cn/weather/{city_code}.shtml'
req = requests.get(url= url)
req.encoding = 'utf-8'
soup = BeautifulSoup(req.text,'html.parser')
ul_tag = soup.find('ul','t clearfix')
li_tag = ul_tag.findAll('li')[0] # 获取当日数据
# print(li_tag)
#获取气温、低温、高温和风力
weather = li_tag.find('p','wea').string
low_temp = li_tag.find('p', 'tem').find('i').string if li_tag.find('p', 'tem').find('i') else None
high_temp = li_tag.find('p','tem').find('span').string if li_tag.find('p', 'tem').find('span') else None
wind = li_tag.find('p','win').find('i').string
return weather,low_temp,high_temp,wind
# 通过接口获取每日一句
def get_one_sentence():
get_request = requests.get('https://v.api.aa1.cn/api/yiyan/index.php')
html = etree.HTML(get_request.text)
sentence = html.xpath('/html/body/p/text()')[0]
return sentence
# 通过接口获取随机图片
def get_random_pic():
res = requests.get(url='https://api.thecatapi.com/v1/images/search?size=full')
print(res.content.decode('utf-8'))
# pic = res.content.decode('utf-8')[0]['url']
pic_url = eval(res.content.decode('utf-8'))[0]['url']
pic_name = pic_url.split('/')[-1]
pic_id = eval(res.content.decode('utf-8'))[0]['id']
print(pic_url)
buf = requests.get(pic_url).content
with open(current_directory + '/sources/' + pic_name, 'wb+') as f:
f.write(buf)
return pic_name
def get_email_content(city):
my_date = datetime.datetime.now().strftime('%Y-%m-%d')
city_code = get_city_code(city)
weather,low_temp,high_temp,wind = get_Weather(city_code)
if low_temp is None or high_temp is None:
tmp = high_temp if low_temp is None else low_temp
else:
tmp = low_temp + '~' + high_temp
sentense = get_one_sentence()
out_str = "{}\n\n今日日期:{}\n|城市:{}\n|天气:{}\n|气温:{}\n|风力:{}".format(sentense,my_date,city,weather,tmp,wind)
return out_str
def sendEmail(from_email,reciver_email,content):
user = "353511235@qq.com"
password = "yqzmyivsrpkvcbae"
# smtp = smtplib.SMTP_SSL("smtp.qq.com", port=587)
# Linux上只能用SMTP,不知为何,否则会报[SSL: WRONG_VERSION_NUMBER]错误
smtp = smtplib.SMTP("smtp.qq.com",port=587)
# 打印与服务器交互信息
smtp.set_debuglevel(1)
smtp.login(user= user,password=password)
mm = MIMEMultipart('related')
mm['From'] = Header('Maple2 <353511235@qq.com>')
mm['To'] = Header('KK <maplea2012@gmail.com>', 'utf-8')
#设置邮件标题
subject_content = "来自你最好的朋友Maple的每日温馨祝福"
mm['Subject'] = Header(subject_content,'utf-8')
# 添加正文文本
message_text = MIMEText(content, 'plain', 'utf-8')
# 添加图片-1:专属头像
with open(current_directory + '/sources/头像.jpg', 'rb') as r:
img = r.read()
message_img1 = MIMEImage(img)
# 添加图片-2:随机图片
pic_name = get_random_pic()
with open(current_directory + '/sources/' + pic_name, 'rb') as r:
img2= r.read()
message_img2 = MIMEImage(img2)
mm.attach(message_text)
mm.attach(message_img1)
mm.attach(message_img2)
# 发送邮件
try:
smtp.sendmail(from_addr= from_email,to_addrs= reciver_email,msg= mm.as_string())
print('发送成功')
except smtplib.SMTPException:
print("发送失败")
if __name__ == '__main__':
city_code = get_city_code('广州')
weather, low_temp, high_temp, wind = get_Weather(city_code)
# print(weather)
# print(low_temp)
# print(high_temp)
# print(wind)
# sentense = get_one_sentence()
# print(sentense)
content = get_email_content('广州')
print(content)
sendEmail("353511235@qq.com","maplea2012@gmail.com",content)
# print(city_code)
2、定时调度-使用Linux中的crontab
(1) 进入编辑页面
crontab -e
(2) 编写定时调度语句
- 测试用:每2分钟调度一次
- 注意:在anaconda3 中创建了一个名叫study的虚拟环境,并在该环境中运行上述python脚本。关于如何在anaconda中创建虚拟环境,以及pycharm编辑器本地代码如何上传到Linux,可阅读第三部分-补充内容
*/2 * * * * /opt/module/anaconda3/envs/study/bin/python /opt/code/python/sendemail3.py
(3) 重启crontab 使调度配置生效
(base) [root@master ~]# service crond restart
(4) 观察调度进度
(base) [root@master python]# tail -f /var/log/cron
(5) 查看调度执行日志
(base) [root@master python]# vim /var/spool/mail/root
三、补充知识
1、Linux 中安装Anaconda3
(1)Anaconda3-2021.05-Linux-x86_64.sh安装包上传到/opt/software
(2)一路enter
(3)设置安装路径
/opt/module/anaconda3
(4)完成安装
(5)初始化
(6)退出ssh并重新连接
(7)安装环境验证
(8)配置镜像源
vim ~/.condarc
--------------------------------------------------------------------
channels:
- defaults
show_channel_urls: true
default_channels:
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2
custom_channels:
conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
msys2: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
bioconda: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
menpo: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
pytorch: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
simpleitk: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
2、Anaconda3中创建虚拟环境
(1)创建一个名为study的虚拟环境
(base) [root@master ~]# conda create -n study python=3.8
(2)切换到study 虚拟环境
conda activate study
3、pycharm本地编辑器代码上传Linux
(1)添加Linux上的远程study 虚拟环境,并配置本地代码远程同步的路径
(2)代码的远程部署配置
(3)配置完成后,本地代码会自动同步到远程[当然也可以选择手动upload],比如本文设置的远程代码路径是:opt/code/python
手动上传:右键-> deployement->upload to xx
4、利用远程环境执行Python脚本
(1) 方式1:pycharm端提交执行脚本,会连接到远程环境执行
(2) 方式2:直接在Linux端执行python脚本