数据分析师每天都要被各种各样的数据报表压得喘不过气来,老板、运营、产品等等,而且大部分报表都是重复性的工作。本文就是帮助你如何使用Python实现报表的自动发送,解放你的劳动力,让你有时间做更多有趣的事情。首先介绍一下实现自动上报要用到的Python库:pymysql一个可以连接MySQL实例,实现增删改查功能的库。文档(也支持.xlsx格式)库smtplibSMTP是SimpleMailTransferProtocol,Python简单封装成一个库email一个处理邮件信息的库为什么要用openpyxl库来处理Excel?因为支持100W+rowspersheet,所以也支持xlsx格式的文件。如果接受xls文件,每张行数小于6W,也可以使用xlwt库,读取大文件速度比openpyxl快。接下来,我们将进入实战部分,正式实现这个过程。我把整个实现过程分成了几个函数来实现,这样看起来会更有条理。1.首先导入所有要用到的库#encoding=utf-8importpymysqlaspmsimportopenpyxlimportdatetimefromemail.mime.textimportMIMETextfromemail.mime.multipartimportMIMEMultipartfromemail.headerimportHeaderimportsmtplib2.写一个函数get_datas(sql)defget_datas(sql)传入sql后返回数据:#apass导入sql导出数据的函数#与数据库建立连接conn=pms.connect(host='实例地址',user='用户',passwd='密码',database='库名',port=3306,charset="utf8")#使用cursor()方法创建游标对象cursorcur=conn.cursor()#使用execute()方法执行SQLcur.execute(sql)#获取需要的数据datas=cur.fetchall()#关闭连接cur.close()#返回需要的数据returndatas3.写一个函数get_datas(sql),传入sql,返回数据的字段名,因为一个函数只能返回一个值,这里使用2个函数分别返回数据和字段名(即thetableheaderinexcel)defget_fields(sql):#传入sql导出字段的函数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.descriptioncur.close()returnfields4.写一个函数,传入数据,字段名,存储地址,返回一个excelet_excel(data,field,file)defget_excel(data,field,file):#将数据和字段名写入excel的函数#新建一个workbook对象new=openpyxl.Workbook()#激活一个新的sheetsheet=new.active#给sheet命名sheet.title='数据显示'#将字段名循环写入excel的行中,因为字段格式列表包含列表,每个列表的第一个元素是字段名forcolinrange(len(field)):#row代表行数,column代表列数,value代表单元格中输入的值,行数和列数从1开始,这点和python不同。注意_=sheet.cell(row=1,column=col+1,value=u'%s'%field[col][0])#将数据循环写入excel的每个单元格forrowinrange(len(data)):forcolinrange(len(field)):#因为***行写的是字段名,所以从第二行开始写_=sheet.cell(row=row+2,column=col+1,value=u'%s'%data[row][col])#保存生成的excel,这一步必不可少newworkbook=new.save(file)#返回生成的excelreturnnewworkbook5.写一个自动获取字符串的函数formatofyesterday'sdategetYesterday()defgetYesterday():#获取昨天日期的字符串格式Function#获取今天的日期today=datetime.date.today()#获取一天的日期格式数据oneday=datetime.timedelta(days=1)#昨天等于今天减去一天昨天=今天-oneday#得到昨天日期的格式将字符串进行转换yesterdaystr=yesterday.strftime('%Y-%m-%d')#返回昨天的字符串returnyesterdaystr六、编写一个函数来生成电子邮件create_email(email_from,email_to,email_Subject,email_text,annex_path,annex_name)defcreate_email(email_from,email_to,email_Subject,email_text,annex_path,annex_name):#输入发件人昵称、收件人昵称、主题、正文、附件地址、附件名称,生成邮件#生成带附件的空邮件实例message=MIMEMultipart()#将文本插入短信形式的邮件message.attach(MIMEText(email_text,'plain','utf-8'))#生成发件人姓名(这与发送的邮件无关)message['From']=Header(email_from,'utf-8')#生成收件人姓名(这与收到的邮件无关)message['To']=Header(email_to,'utf-8')#生成邮件主题emailmessage['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)#回邮returnmessage7.生成一个发送邮件的函数send_email(sender,password,receiver,msg)defsend_email(sender,password,receiver,msg):#一个发送邮件的函数,输入邮箱,密码,收件人和邮件内容try:#Find你发送邮箱的服务器地址,并以加密形式发送server.login(sender,password)#括号对应发件人邮箱账号和邮箱密码#发送邮件server.sendmail(sender,receiver,msg.as_string())#括号对应发件人邮箱,收件人邮箱(一个列表),邮件内容print("邮件发送成功")server.quit()#关闭连接exceptException:print(traceback.print_exc())print("Mailsendingfailed")8、创建一个main函数,输入所有的自定义内容,最后执行main函数defmain():print(datetime.datetime.now())my_sql=sql="SELECTa.id'用户ID',a.gmtCreate'用户注册时间',af.lastLoginTime'***登录时间',af.totalBuyCount'历史支付子单号',af.paidmountUSD'历史支付金额',af.lastPayTime'用户***支付时间'FROMtableaLEFTJOINtablebafONa.id=af.accountId;"#生成数据my_data=get_datas(my_sql)#生成字段名my_field=get_fields(my_sql)#获取昨天的日期yesterdaystr=getYesterday()#文件名my_file_name='userattribute'+yesterdaystr+'.xlsx'#文件路径file_path='D:/work/report/'+my_file_name#生成excelget_excel(my_data,my_field,file_path)my_email_from='BI部门自动上报机器人'my_email_to='运营部'#邮件标题my_email_Subject='user'+yesterdaystr#邮件正文my_email_text="亲爱的,附件是周数据,请查收!BIteam》#附件地址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']#收件人邮箱列表#发送邮件send_email(my_sender,my_password,my_receiver,my_msg)print(datetime.datetime.now())if__name__=="__main__":main();
