你想每天收到一封V2EX的今日热议主题的邮件么?</a />

背景

之前写过一个类似的获取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按天更新,一部分按照小时更新,可惜软件没有这种功能,所以只好自己实现了一个了。

测试

你想每天收到一封V2EX的今日热议主题的邮件么?