[ python ] 查詢數據庫生成Excel並發送郵件


開發要求:

  由於管理后台導出數據非常緩慢,找程序員解決無果后,自己動手寫了一個腳本,每天定時將報表發送給業務部門。


     1. 通過條件查詢MySQL獲取數據
       2. 將獲取的數據寫入到Excel中,對應字段名
       3. 將Excel作為附件內容,將郵件發送至相關人員

 

程序:

1. README

# 作者:hkey

# 博客地址:hukey.cnblogs.com

# http://www.cnblogs.com/hukey/p/8983831.html

# 目錄結構:

    PS: 功能比較單一,為了方便管理寫入了一個文件中,有如下兩個類:
    
        CreateExcel: 查詢數據庫並生成Excel
        SendMail: 將Excel作為附件內容,將郵件發送至相關人員
    
# 使用說明:
    
    數據庫信息和郵件信息內容都需要手動填寫,確保無誤;
    可實現發送至多人;
README

 

2. 數據庫腳本:

-- MySQL dump 10.14  Distrib 5.5.56-MariaDB, for Linux (x86_64)
--
-- Host: localhost    Database: user_info
-- ------------------------------------------------------
-- Server version    5.5.56-MariaDB

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Table structure for table `user`
--
DROP TABLE IF EXISTS `user`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `user` (
  `id` int(16) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `city` varchar(255) DEFAULT NULL,
  `class` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `user`
--

LOCK TABLES `user` WRITE;
/*!40000 ALTER TABLE `user` DISABLE KEYS */;
INSERT INTO `user` VALUES (1,'小飛','北京','三年二班'),(2,'小四','上海','三年一班'),(3,'小K','西安','三年三班');
/*!40000 ALTER TABLE `user` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

-- Dump completed on 2018-05-03  9:45:06
user_info.sql

 

3. 程序代碼

# -*- coding: utf-8 -*-
# Author: hkey
from email.header import Header
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
# from email.utils import parseaddr, formataddr
from email import encoders
from email.mime.base import MIMEBase
import smtplib, os
import pymysql, xlwt

class CreateExcel(object):
    '''查詢數據庫並生成Excel文檔'''
    def __init__(self, mysql_info):
        self.mysql_info = mysql_info
        self.conn = pymysql.connect(host = self.mysql_info['host'], port = self.mysql_info['port'],
                               user = self.mysql_info['user'], passwd = self.mysql_info['passwd'],
                               db = self.mysql_info['db'], charset='utf8')
        self.cursor = self.conn.cursor()
    def getUserData(self, sql):
        # 查詢數據庫
        self.cursor.execute(sql)
        table_desc = self.cursor.description
        result = self.cursor.fetchall()
        if not result:
            print('沒數據。')
            # 返回查詢數據、表字段
        print('數據庫查詢完畢'.center(30, '#'))
        return result, table_desc

    def writeToExcel(self, data, filename):
        # 生成Excel文檔
        # 注意:生成Excel是一列一列寫入的。
        result, fileds = data
        wbk = xlwt.Workbook(encoding='utf-8')
        # 創建一個表格
        sheet1 = wbk.add_sheet('sheet1', cell_overwrite_ok=True)
        for filed in range(len(fileds)):
            # Excel插入第一行字段信息
            sheet1.write(0, filed, fileds[filed][0]) # (行,列,數據)

        for row in range(1, len(result)+1):
            # 將數據從第二行開始寫入
            for col in range(0, len(fileds)):
                sheet1.write(row, col, result[row-1][col]) #(行, 列, 數據第一行的第一列)
        wbk.save(filename)
    def close(self):
        # 關閉游標和數據庫連接
        self.cursor.close()
        self.conn.close()
        print('關閉數據庫連接'.center(30, '#'))
class SendMail(object):
    '''將Excel作為附件發送郵件'''
    def __init__(self, email_info):
        self.email_info = email_info
        # 使用SMTP_SSL連接端口為465
        self.smtp = smtplib.SMTP_SSL(self.email_info['server'], self.email_info['port'])
        # 創建兩個變量
        self._attachements = []
        self._from = ''
    def login(self):
        # 通過郵箱名和smtp授權碼登錄到郵箱
        self._from = self.email_info['user']
        self.smtp.login(self.email_info['user'], self.email_info['password'])
    # def _format_addr(self, s):
    #     name, addr = parseaddr(s)
    #     return formataddr((Header(name, 'utf-8').encode(), addr))

    def add_attachment(self):
        # 添加附件內容
        # 注意:添加附件內容是通過讀取文件的方式加入
        file_path = self.email_info['file_path']
        with open(file_path, 'rb') as file:
            filename = os.path.split(file_path)[1]
            mime = MIMEBase('application', 'octet-stream', filename=filename)
            mime.add_header('Content-Disposition', 'attachment', filename=('gbk', '', filename))
            mime.add_header('Content-ID', '<0>')
            mime.add_header('X-Attachment-Id', '0')
            mime.set_payload(file.read())
            encoders.encode_base64(mime)
            # 添加到列表,可以有多個附件內容
            self._attachements.append(mime)

    def sendMail(self):
        # 發送郵件,可以實現群發
        msg = MIMEMultipart()
        contents = MIMEText(self.email_info['content'], 'plain', 'utf-8')
        msg['From'] = self.email_info['user']
        msg['To'] = self.email_info['to']
        msg['Subject'] = self.email_info['subject']

        for att in self._attachements:
            # 從列表中提交附件,附件可以有多個
            msg.attach(att)
        msg.attach(contents)
        try:
            self.smtp.sendmail(self._from, self.email_info['to'].split(','), msg.as_string())
            print('郵件發送成功,請注意查收'.center(30, '#'))
        except Exception as e:
            print('Error:', e)

    def close(self):
        # 退出smtp服務
        self.smtp.quit()
        print('logout'.center(30, '#'))


if __name__ == '__main__':
    # 數據庫連接信息
    mysql_dict = {
        'host': '192.168.118.13',
        'port': 3306,
        'user': 'root',
        'passwd': '123456',
        'db': 'user_info'
    }
    # 郵件登錄及內容信息
    email_dict = {
    # 手動填寫,確保信息無誤
        "user": "xxx@126.com",    
        "to": "xxx@qq.com, xxx@qq.com", # 多個郵箱以','隔開;
        "server": "smtp.126.com",
        'port': 465,    # values值必須int類型
        "username": "xxx@126.com",
        "password": "xxxx",
        "subject": "user測試表",
        "content": '用戶測試數據',
        'file_path': 'example.xls'
    }

    sql = 'select * from user'
    # filename = 'example.xls'
    create_excel = CreateExcel(mysql_dict)
    sql_res = create_excel.getUserData(sql)
    create_excel.writeToExcel(sql_res,email_dict['file_path'])
    create_excel.close()
    sendmail = SendMail(email_dict)
    sendmail.login()
    sendmail.add_attachment()
    sendmail.sendMail()
    sendmail.close()
SendToExcel.py

 

運行結果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM