共计 2881 个字符,预计需要花费 8 分钟才能阅读完成。
背景
之前写过一个类似的获取 V2EX 今日热议话题的脚本,只不过那个脚本是为 cron job 优化过的脚本,用来每隔一段时间获取一下当前的最热主题并发送邮件,但是现在我想每天只在指定的时间点收到一封邮件,比如说每天稍微晚一点的时间 23:00 收到一封汇总的邮件,之前的脚本就不适用了,于是就花了几分钟重写了一份,这次引入了高级的 python 第三方定时任务库 apscheduler,摆脱了对 Linux 系统自带的 cron 工具的依赖 (实际原因是,在我习惯用的 Ubuntu server 上 cron 一直工作不正常,各种调试都搞不定,遂弃之,centos 上 cron 就挺好的)
开发环境
- Linuxmint 19.3(基于 ubuntu desktop 18.04)
- Python 3.6.8
运行环境
- Ubuntu server 18.04
- Python 3.6
实际代码
#!/usr/bin/env python3
# coding=utf-8
import os
import json
import time
import logging
import requests
import smtplib
from email.mime.text import MIMEText
from apscheduler.schedulers.blocking import BlockingScheduler
HOUR=23 # 一天的第几小时运行
MINUTE=0 # 一个小时的第多少分钟运行
HOST = 'smtp.126.com' #smtp 服务的供应商
PORT = 25 # smtp 服务供应商指定的端口
SENDER='' # smtp 服务的发件人,这里我用的是 126 邮箱
RECEIVER='' # 任意用来接收邮件的邮箱地址
PWD='' # 提供 smtp 服务的邮箱的授权码,一般不是邮箱密码
def logger_getter():
def dir_check():
if not os.path.isdir('tmp'):
os.mkdir('tmp')
logger = logging.getLogger()
if not len(logger.handlers):
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter("%(filename)s - %(asctime)s - %(levelname)s -%(message)s",
datefmt='%Y-%m-%d %H:%M:%S')
dir_check()
file_handler = logging.FileHandler('tmp/record.log')
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
return logger
def mail_send(subject, mail_body):
try:
host = HOST
port = PORT
msg = MIMEText(mail_body, 'plain', 'utf-8')
msg['Subject'] = subject
msg['From'] = SENDER
msg['To'] = RECEIVER
s = smtplib.SMTP(host, port)
s.debuglevel = 0
s.login(SENDER, PWD)
s.sendmail(SENDER, RECEIVER, msg.as_string())
logger_getter().debug('成功发送了一封邮件!')
s.quit()
except smtplib.SMTPException as e:
logger_getter().error(str(e))
exit(1)
def get_mail_body():
url='https://www.v2ex.com/api/topics/hot.json'
reponse_data = requests.get(url).text
dict_data = json.loads(reponse_data)
mail_body = [post['title'] + '' + post['url'] for post in dict_data]
mail_body_formated = '\n'.join(mail_body)
return mail_body_formated
def main():
curr_date = time.strftime('%Y-%m-%d',time.localtime(time.time()))
subject = curr_date + 'V2EX 今日热议主题'
mail_send(subject, get_mail_body())
if __name__ == '__main__':
try:
scheduler = BlockingScheduler()
scheduler.add_job(main, 'cron', hour=HOUR,minute=MINUTE)
scheduler.start()
logger_getter().info('The email has sent to the receiver.')
except Exception as e:
logger_getter().debug('An exception occurred as below:')
logger_getter().debug(str(e))
如何使用
将上述代码复制粘贴到一个任意命名但后缀为.py 的文件中,然后修改代码开头的几行配置,如下所示:
HOUR=23 # 一天的第几小时运行
minute=0 # 一个小时的第多少分钟运行
HOST = 'smtp.126.com' #smtp 服务的供应商
PORT = 25 # smtp 服务供应商指定的端口
SENDER='' # smtp 服务的发件人, 这里我用的是 126 邮箱
RECEIVER='' # 任意用来接收邮件的邮箱地址
PWD='' # 提供 smtp 服务的邮箱的授权码,一般不是邮箱密码
然后运行下面两行命令安装依赖:
$ pip3 install requests==2.22.0
$ pip3 install APScheduler==3.6.3
最后运行
$ python3 xxx.py &
运行完上面的代码后可以直接关掉终端了,更优雅的解决方案请自行百度 Linux screen。
写在最后
其实安卓有个叫 feedly 的 RSS 订阅应用可以在里面搜到一个 V2ex 每日热议主题的 feed,但是有个问题,我现在只想每日看到一次汇总的结果就行了,可我还有其它的 feed 订阅是按照小时更新的,二者不能分开设置,也即是一部分 feed 按天更新,一部分按照小时更新,可惜软件没有这种功能,所以只好自己实现了一个了。
测试
正文完