• 监控个人博客园的积分与排名并定时发送邮件


    进入博客园已经有5个多月的时间了,自从开始写第一篇博客,积分和排名有了很大的进步,排名从原来的24万多名到了目前的10万多名,时刻激励着我为社区贡献自己的微薄之力(虽然关注我的人很少)。于是为了以数字的形式记录我再社区的成长,我决定用python写一个小程序:每天记录我的博客积分和排名,根据历史记录绘制成图标,最后发送到我的个人邮箱中。


    一、实现过程

    1. 用requests模块获取个人博客园中的所有信息
    2. 使用正则匹配出积分和排名的数据
    3. 将数据存入到某个文件中
    4. 使用matplotlib模块根据文件中的历史记录绘制成一个折线图
    5. 使用smtplib模块将整理的内容和图片发送到指定的邮箱中
    6. 编写周期性计划任务执行

    二、具体代码

    #!/usr/bin/python3
    
    import matplotlib.pyplot as plt
    import matplotlib
    import requests
    import re
    import time
    import smtplib
    from email.mime.multipart import MIMEMultipart
    from email.mime.text import MIMEText
    from email.mime.image import MIMEImage
    
    #指定将数据存放到哪个文件下
    file = "/home/bill/myscript/exportfile/cnblogs.log"
    #个人博客园主页url
    url = "https://www.cnblogs.com/zqj-blog/mvc/blog/sidecolumn.aspx?blogApp=zqj-blog"
    
    # 用正则获取积分和排名的数据
    r = requests.get(url)
    str = "".join(r.text.split("
    "))
    pattern = re.compile(r"积分 -.*?(d+).*?(d+)")
    match  = pattern.findall(str)
    score = match[0][0]
    rank = match[0][1]
    
    #自定义写入历史文件的格式
    date = time.strftime("%Y-%m-%d")
    content = "%s       score: %s       rank: %s     " % (date,score,rank)
    
    #以列表的形式读取文件内容
    with open(file,"r") as f:
        fr = f.readlines()
    
    #为避免脚本多次执行产生过多的历史记录,以下逻辑是为了保证一天只存最后一条记录
    if (fr[-1].find(date) != -1):
        fr[-1] = content + "
    "
    else:
        fr.append(content + "
    ")
    
    #将调整后的信息写入历史文件中
    with open(file,"w") as f:
        f.writelines(fr)
    
    #将历史文件中每行数据加上<p>html标识,作用是以段落的形式展现
    summaryhtml=""
    for i in fr:
        i.strip(r"
    ")
        summaryhtml = summaryhtml + "<p>" + i + "</p>"
    
    #获取最后两天的数据,计算数值的差值,便于展现出每次进步了多少
    s1 = fr[-1]
    s2 = fr[-2]
    p = re.compile(r".*score: (d+).*rank: (d+)")
    m1 = p.findall( s1 )
    m2 = p.findall( s2 )
    score1 = m1[0][0]
    rank1 = m1[0][1]
    score2 = m2[0][0]
    rank2 = m2[0][1]
    S = int(score1) - int(score2)
    R = int(rank2) - int(rank1)
    
    #在写入邮件的html中加上每次分数、排名变化情况
    summaryhtml = summaryhtml + "<p> The <big>SCORE</big> increased <strong><big> %d </big></strong></p> <p>The <big>RANK</big> increased <strong><big> %d </big></strong></p>" % (S,R)
    
    # 使用matplotlib模块绘制折线图,并保持下来
    #‘agg’表示不显示图片
    matplotlib.use('Agg')
    pattern = re.compile(r"(d+-d+-d+).*score: (d+).*rank: (d+)")
    date = []
    score = []
    rank = []
    with open(file,'r') as f:
        lines = f.readlines()
        for line in lines:
            match = pattern.findall( line )
            if(len(match[0]) == 3 ):
                date.append(match[0][0])
                score.append(int(match[0][1]))
                rank.append(int(match[0][2]))
    			
    #由于折线图显示的问题,因此最多绘制30天的数据
    if(len(date) > 30 ):
        date = date[-30:]
    if( len(score) > 30 ):
        date = score[-30:]
    if(len(rank) > 30 ):
        date = rank[-30:]
    
    	
    #绘制分数排名的折线图
    day = date 
    plt.plot( day , rank ,'o-',color = 'r' ,label = "rank")
    #设置x洲字体大小 plt.xticks(fontsize=8) plt.ylabel("rank") #显示最后一个点的数值 plt.text(day[-1],rank[-1],rank[-1],ha='center',va='bottom',fontsize=8) #图示的显示位置 plt.legend(loc=3)
    #自动调整横坐标摆放
    plt.gcf().autofmt_xdate() plt.savefig("./rank.jpg") #清除缓存,便于保存下一张图片 plt.close() #绘制积分排名的折线图 plt.plot( day , score ,'--*b',color = 'g' ,label = "score")
    plt.xticks(fontsize=8) plt.ylabel("score") plt.text(day[-1],score[-1],score[-1],ha='center',va='bottom',fontsize=8) plt.legend(loc=4)
    plt.gcf().autofmt_xdate() plt.savefig("./score.jpg") plt.close() #发送邮件 #其中smtplib是用来发送邮件的,email模块是构造邮件的 #由于一般的邮箱都会禁止外链图片,因此想实现在邮件中直接添加图片是不太现实的。 #可以先将图片添加到附件中,然后设定邮件的格式是html,在文件中引用图片。 #cid:image1 表示引用的是ID为image1的图片 msg = MIMEMultipart() mail_msg = """ <h2>summary:</h2> <p>%s</p> <p><img src="cid:image1"></p> <p><img src="cid:image2"></p> """ % summaryhtml msg.attach(MIMEText(mail_msg, 'html', 'utf-8')) #以二进制的形式读取第一张图片 with open(r'./rank.jpg','rb') as f: msgimage = MIMEImage(f.read()) # 设置图片ID,在 HTML 文本中引用 msgimage.add_header('Content-ID', '<image1>') msg.attach(msgimage) #读取第二张图片,并设置图片的ID with open(r'./score.jpg','rb') as f: msgimage = MIMEImage(f.read()) msgimage.add_header('Content-ID', '<image2>') msg.attach(msgimage) ctype = 'application/octet-stream' maintype, subtype = ctype.split('/', 1) #添加第一个附件 image1 = MIMEImage(open(r'rank.jpg', 'rb').read(),_subtype=subtype ) image1.add_header('Content-Disposition', 'attachment', filename='rank.jpg') msg.attach(image1) #添加第二个附件 image2 = MIMEImage(open(r'score.jpg', 'rb').read(),_subtype=subtype ) image2.add_header('Content-Disposition', 'attachment', filename='score.jpg') msg.attach(image2) #发送 sender = "mail@mail.com" receive = 'mail@mail.com' msg['Subject'] = '监控博客访问量以及排名情况.' msg['From'] = sender msg['To'] = receive smtpobj = smtplib.SMTP("邮件服务器",25) server.login("发件人", "密码") smtpobj.sendmail(sender,[receive],msg.as_string())

      

        以上就是具体的代码,最直接的确定是“没有函数化”,以后有时间可以再做修改,将每个功能函数化。

    接下来,

        按脚本中用到的模块,将所有使用到的模块以每行的形式写入一个文件,比如说是a.txtx,我们可以批量安装某个文件下的所有模块。

    sudo apt-get update
    sudo apt-get install python3-pip
    sudo pip3 install --upgrade pip
    sudo pip3 install -r a.txt  

        将脚本放到linux服务器上(windows也可以,添加计划任务,自行百度),我使用的服务器是ubuntu18.04。python是3以上的版本

    sudo crontab -e      #编辑周期性计划任务
    

      

    周期性计划任务内容是:在每天的8:30 执行后续命令,因此每天8:30就能收到邮件

    【注意】

      1、ubuntu 18.04中默认是没有安装smtp服务器的,因此可能会出现邮件收不到的问题,查看日志

    /var/log/syslog

    上述原因很有可能是没有安装smtp服务器,执行下述命令即可解决。

    sudo apt-get install -y smtp
    

      2、在我查看邮件日志(/var/mail/root)看到提示,但是在命令行执行时有很正常,苦思冥想很久很久之后,意识到,这个模块是用windows上的pycharm软件安装的,此时模块默认的安装位置是:~/.local/lib/python3/site-packages目录下,并没有安装到python3指定的模块目录下。

        于是重新安装,需要加一个参数“-H”,即可

    sudo -H pip3 install matplotlib
    

    结果展示:

     (over)

  • 相关阅读:
    FindWindowEx使用方法
    什么是VSync
    getParameter
    高等数学积分公式大全
    为什么没有好用的Android游戏引擎?
    Best Time to Buy and Sell Stock III
    5.3 适配器模式(4.1)
    在动态网络下实现分布式共享存储
    人类智商一般在多少左右?爱因斯坦的智商是多少?
    海量数据处理面试题集锦
  • 原文地址:https://www.cnblogs.com/zqj-blog/p/10497107.html
Copyright © 2020-2023  润新知