我用Python自動生成報表以郵件發(fā)送,減輕了我的工作壓力
數(shù)據(jù)分析師肯定每天都被各種各樣的數(shù)據(jù)數(shù)據(jù)報表搞得焦頭爛額,老板的,運營的、產(chǎn)品的等等。而且大部分報表都是重復性的工作,這篇文章就是幫助大家如何用Python來實現(xiàn)報表的自動發(fā)送,解放你的勞動力,可以讓你有時間去做更有意思的事情。
首先來介紹下實現(xiàn)自動報表要使用到的Python庫:
- pymysql 一個可以連接MySQL實例并且實現(xiàn)增刪改查功能的庫
- datetime Python標準庫中自帶的關于時間的庫
- openpyxl 一個可以讀寫07版以后的Excel文檔(.xlsx格式也支持)的庫
- smtplib SMTP即簡單郵件傳輸協(xié)議,Python簡單封裝成了一個庫
- email 一個用來處理郵件消息的庫
為什么使用openpyxl庫來處理Excel呢?因為它支持每個sheet的行數(shù)為100W+,也是支持xlsx格式的文件。如果你接受xls文件,并且每個sheet的行數(shù)小于6W,也是可以使用xlwt庫,它對大文件的讀取速度要大于openpyxl。
接下來我們就進入實戰(zhàn)部分,來正式實現(xiàn)這個過程。我把整個實現(xiàn)過程分成幾個函數(shù)的方式來實現(xiàn),這樣看著會比較有結構感。
一、首先導入所有要用到的庫
- # encoding=utf-8
- import pymysql as pms
- import openpyxl
- import datetime
- from email.mime.text import MIMEText
- from email.mime.multipart import MIMEMultipart
- from email.header import Header
- import smtplib
二、 編寫一個傳入sql就返回數(shù)據(jù)的函數(shù)get_datas(sql)
- def get_datas(sql):
- # 一個傳入sql導出數(shù)據(jù)的函數(shù)
- # 跟數(shù)據(jù)庫建立連接
- conn = pms.connect(host='實例地址', user='用戶',
- passwd='密碼', database='庫名', port=3306, charset="utf8")
- # 使用 cursor() 方法創(chuàng)建一個游標對象 cursor
- cur = conn.cursor()
- # 使用 execute() 方法執(zhí)行 SQL
- cur.execute(sql)
- # 獲取所需要的數(shù)據(jù)
- datas = cur.fetchall()
- #關閉連接
- cur.close()
- #返回所需的數(shù)據(jù)
- return datas
三、 編寫一個傳入sql就返回數(shù)據(jù)的字段名稱的函數(shù)get_datas(sql),因為一個函數(shù)只能返回一個值,這邊就用2個函數(shù)來分別返回數(shù)據(jù)和字段名稱(也就是excel里的表頭)
- def get_fields(sql):
- # 一個傳入sql導出字段的函數(shù)
- conn = pms.connect(host='rm-rj91p2yhl9dm2xmbixo.mysql.rds.aliyuncs.com', user='bi-analyzer',
- passwd='pcNzcKPnn', database='kikuu', port=3306, charset="utf8")
- cur = conn.cursor()
- cur.execute(sql)
- # 獲取所需要的字段名稱
- fields = cur.description
- cur.close()
- return fields
四、 編寫一個傳入數(shù)據(jù)、字段名稱、存儲地址返回一個excel 的函數(shù)et_excel(data, field, file)
- def get_excel(data, field, file):
- # 將數(shù)據(jù)和字段名寫入excel的函數(shù)
- #新建一個工作薄對象
- new = openpyxl.Workbook()
- #激活一個新的sheet
- sheet = new.active
- #給sheet命名
- sheet.title = '數(shù)據(jù)展示'
- #將字段名稱循環(huán)寫入excel***行,因為字段格式列表里包含列表,每個列表的***元素才是字段名稱
- for col in range(len(field)):
- #row代表行數(shù),column代表列數(shù),value代表單元格輸入的值,行數(shù)和列數(shù)都是從1開始,這點于python不同要注意
- _ = sheet.cell(row=1, column=col+1, value=u'%s' % field[col][0])
- #將數(shù)據(jù)循環(huán)寫入excel的每個單元格中
- for row in range(len(data)):
- for col in range(len(field)):
- #因為***行寫了字段名稱,所以要從第二行開始寫入
- _ = sheet.cell(row=row+2, column=col + 1, value=u'%s' % data[row][col])
- #將生成的excel保存,這步是必不可少的
- newworkbook = new.save(file)
- #返回生成的excel
- return newworkbook
五、 編寫一個自動獲取昨天日期字符串格式的函數(shù)getYesterday()
- def getYesterday():
- # 獲取昨天日期的字符串格式的函數(shù)
- #獲取今天的日期
- today = datetime.date.today()
- #獲取一天的日期格式數(shù)據(jù)
- oneday = datetime.timedelta(days=1)
- #昨天等于今天減去一天
- yesterday = today - oneday
- #獲取昨天日期的格式化字符串
- yesterdaystr = yesterday.strftime('%Y-%m-%d')
- #返回昨天的字符串
- return yesterdaystr
六、編寫一個生成郵件的函數(shù)create_email(email_from, email_to, email_Subject, email_text, annex_path, annex_name)
- def create_email(email_from, email_to, email_Subject, email_text, annex_path, annex_name):
- # 輸入發(fā)件人昵稱、收件人昵稱、主題,正文,附件地址,附件名稱生成一封郵件
- #生成一個空的帶附件的郵件實例
- message = MIMEMultipart()
- #將正文以text的形式插入郵件中
- message.attach(MIMEText(email_text, 'plain', 'utf-8'))
- #生成發(fā)件人名稱(這個跟發(fā)送的郵件沒有關系)
- message['From'] = Header(email_from, 'utf-8')
- #生成收件人名稱(這個跟接收的郵件也沒有關系)
- message['To'] = Header(email_to, 'utf-8')
- #生成郵件主題
- message['Subject'] = Header(email_Subject, 'utf-8')
- #讀取附件的內容
- att1 = MIMEText(open(annex_path, 'rb').read(), 'base64', 'utf-8')
- att1["Content-Type"] = 'application/octet-stream'
- #生成附件的名稱
- att1["Content-Disposition"] = 'attachment; filename=' + annex_name
- #將附件內容插入郵件中
- message.attach(att1)
- #返回郵件
- return message
七、 生成一個發(fā)送郵件的函數(shù)send_email(sender, password, receiver, msg)
- def send_email(sender, password, receiver, msg):
- # 一個輸入郵箱、密碼、收件人、郵件內容發(fā)送郵件的函數(shù)
- try:
- #找到你的發(fā)送郵箱的服務器地址,已加密的形式發(fā)送
- server = smtplib.SMTP_SSL("smtp.mxhichina.com", 465) # 發(fā)件人郵箱中的SMTP服務器
- server.ehlo()
- #登錄你的賬號
- server.login(sender, password) # 括號中對應的是發(fā)件人郵箱賬號、郵箱密碼
- #發(fā)送郵件
- server.sendmail(sender, receiver, msg.as_string()) # 括號中對應的是發(fā)件人郵箱賬號、收件人郵箱賬號(是一個列表)、郵件內容
- print("郵件發(fā)送成功")
- server.quit() # 關閉連接
- except Exception:
- print(traceback.print_exc())
- print("郵件發(fā)送失敗")
八、建立一個main函數(shù),把所有的自定義內容輸入進去,***執(zhí)行main函數(shù)
- def main():
- print(datetime.datetime.now())
- my_sql = sql = "SELECT a.id '用戶ID',
- a.gmtCreate '用戶注冊時間',
- af.lastLoginTime '***登錄時間',
- af.totalBuyCount '歷史付款子單數(shù)',
- af.paidmountUSD '歷史付款金額',
- af.lastPayTime '用戶***支付時間'
- FROM table a
- LEFT JOIN tableb af ON a.id= af.accountId ;"
- # 生成數(shù)據(jù)
- my_data = get_datas(my_sql)
- # 生成字段名稱
- my_field = get_fields(my_sql)
- # 得到昨天的日期
- yesterdaystr = getYesterday()
- # 文件名稱
- my_file_name = 'user attribute' + yesterdaystr + '.xlsx'
- # 文件路徑
- file_path = 'D:/work/report/' + my_file_name
- # 生成excel
- get_excel(my_data, my_field, file_path)
- my_email_from = 'BI部門自動報表機器人'
- my_email_to = '運營部'
- # 郵件標題
- my_email_Subject = 'user' + yesterdaystr
- # 郵件正文
- my_email_text = "Dear all,
- 附件為每周數(shù)據(jù),請查收!
- BI團隊 "
- #附件地址
- my_annex_path = file_path
- #附件名稱
- my_annex_name = my_file_name
- # 生成郵件
- my_msg = create_email(my_email_from, my_email_to, my_email_Subject,
- my_email_text, my_annex_path, my_annex_name)
- my_sender = '阿里云郵箱'
- my_password = '我的密碼'
- my_receiver = [10001@qq.com']#接收人郵箱列表
- # 發(fā)送郵件
- send_email(my_sender, my_password, my_receiver, my_msg)
- print(datetime.datetime.now())
- if __name__ == "__main__":
- main();