進入博客園已經有5個多月的時間了,自從開始寫第一篇博客,積分和排名有了很大的進步,排名從原來的24萬多名到了目前的10萬多名,時刻激勵着我為社區貢獻自己的微薄之力(雖然關注我的人很少)。於是為了以數字的形式記錄我再社區的成長,我決定用python寫一個小程序:每天記錄我的博客積分和排名,根據歷史記錄繪制成圖標,最后發送到我的個人郵箱中。
一、實現過程
- 用requests模塊獲取個人博客園中的所有信息
- 使用正則匹配出積分和排名的數據
- 將數據存入到某個文件中
- 使用matplotlib模塊根據文件中的歷史記錄繪制成一個折線圖
- 使用smtplib模塊將整理的內容和圖片發送到指定的郵箱中
- 編寫周期性計划任務執行
二、具體代碼
#!/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("\r\n")) 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 + "\n" else: fr.append(content + "\n") #將調整后的信息寫入歷史文件中 with open(file,"w") as f: f.writelines(fr) #將歷史文件中每行數據加上<p>html標識,作用是以段落的形式展現 summaryhtml="" for i in fr: i.strip(r"\n") 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)