你想收到V2ex新评论的即时邮件通知么

2020年03月13日 2623点热度 0人点赞 0条评论

背景

混V站好几年了,从上图可以看到我是14年入的国军(大雾->V站),经常在发完一个主题后迫不及待的想知道有没有人评论我,于是就一个劲儿的刷新v站,不得不说这样子实在浪费时间,而且感觉有点傻。

然后我就想到了一些v站的第三方客户端是否有通知功能,去Google play搜索了一下最终找到了一个叫V2ex+的客户端有通知功能,其实还有一种方法就是装一个叫feedly的安卓app,由于v站提供了评论的atom协议的feed流,添加一个订阅并设置一个小时刷新一下就行了,

以上两种方法呢都需要有个app在后台常驻才行,我不希望这样子,所以写了下面的python脚本来解决,这样可以只需要后台常驻一个邮箱app,所有的通知集中在一个地方推送,既节省后台资源省电,又不至于装太多app。

开发环境

  • Mac OSX 10.13.6
  • Python 3.6.4

脚本

#!/usr/bin/env python3
# coding=utf-8

import os
import time
import logging
import smtplib
import requests
from bs4 import BeautifulSoup
from email.mime.text import MIMEText
from apscheduler.schedulers.blocking import BlockingScheduler


HOST = 'smtp.qq.com'  #smtp服务的供应商
PORT = 587  # smtp服务供应商指定的端口
SENDER=''  # smtp服务的发件人,这里我用的是qq邮箱
RECEIVER=''  # 任意用来接收邮件的邮箱地址
PWD=''  # 提供smtp服务的邮箱的授权码,注意不是邮箱密码
INTERVAL=300  # 脚本每隔多少秒请求一下v站评论feed,检查是否有新评论
COMMENTS_FEED=''  # V站评论feed的url,点未读提醒可以看到

def dir_check():
    if not os.path.isdir('tmp'):
        os.mkdir('tmp')

def logger_getter():
    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 data_persistence(data):
	dir_check()
	with open('tmp/v2ex_timestamp','w') as f:
		f.write(data)
	logger_getter().debug("Persist the first comment's time stamp into file.")

def mail_send(subject, mail_body):
    try:
        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())
        s.quit()
    except smtplib.SMTPException as e:
        logger_getter().error(str(e))
        exit(1)

def get_soup():
	comment_feed_content=requests.get(COMMENTS_FEED).text
	soup=BeautifulSoup(comment_feed_content,'html5lib')
	return soup

def parser_and_processor():
	soup = get_soup()
	first_entry = soup.select_one('entry')
	title = first_entry.select_one('title').get_text()
	published_date=first_entry.select_one('published').get_text()
	content=first_entry.select_one('content').get_text()
	if not os.path.isfile('tmp/v2ex_timestamp'):
		# 此时持久化下来的时间戳所在的评论entry可能是一个收藏,但也要持久化一次
		data_persistence(published_date)
	with open('tmp/v2ex_timestamp') as f:
		old_published_date = f.read().strip()
	current_time = time.strftime("%m-%d|%H:%M", time.localtime())
	if old_published_date != published_date:
		# title为空说明这是一个收藏,暂不发送邮件
		if not title:
			mail_send(current_time + ' 您的V2EX有了一条新评论哦!', content)
		logger_getter().info('您发出了一封邮件哦!')
		# 此时要记得更新一下本地的数据
		data_persistence(published_date)
	else:
		logger_getter().debug('您的V2EX没有收到新评论哦!')

if __name__ == '__main__':
    scheduler = BlockingScheduler()
    scheduler.add_job(parser_and_processor, 'interval', seconds=INTERVAL)
    scheduler.start()

如何使用

将上述脚本复制粘贴到任意以.py为后缀的一个文件中,

然后修改脚本的前面几行配置,

HOST = 'smtp.qq.com'  #smtp服务的供应商
PORT = 587  # smtp服务供应商指定的端口
SENDER=''  # smtp服务的发件人,这里我用的是qq邮箱
RECEIVER=''  # 任意用来接收邮件的邮箱地址
PWD=''  # 提供smtp服务的邮箱的授权码,注意不是邮箱密码
INTERVAL=300  # 脚本每隔多少秒请求一下v站评论feed,检查是否有新评论
COMMENTS_FEED=''  # V站评论feed的url,点未读提醒可以看到

再然后在终端模拟器中执行下面的shell命令,安装依赖:

$ sudo pip3 install requests==2.22.0
$ sudo pip3 install APScheduler==3.6.3
$ sudo pip3 install html5lib==1.0.1
$ sudo pip3 install beautifulsoup4==4.6.0

然后再执行下面的命令:

$ python3 xxx.py &

最后关掉终端模拟器即可。

Sharp

"A Linux user and a Python{}".format('er')