当前位置:首页>python>告别手动发周报:Python自动发邮件完整方案

告别手动发周报:Python自动发邮件完整方案

  • 2026-10-11 05:42:43
告别手动发周报:Python自动发邮件完整方案

告别手动发周报:Python自动发邮件完整方案

周一早上的"至暗时刻"

以前每周一一大早的"标准动作"是:打开邮箱、打开Excel、跑SQL、把数据贴到Excel里、做几张图、调格式、写分析、转PDF、写邮件内容、挨个加抄送......

这一套下来,保底两小时,遇到数据异常特殊情况的,3-5个小时就搭进去了。

更崩溃的是,每周一都是一样的套路,连改都没法改,纯硬活

现在我用AI辅助写Python把整个流程写成脚本,每周一早8点,报表自己生成、自己出图、自己整理邮件,等我到公司,点上杯瑞幸,然后过一遍数据和邮件内容就行了。

整体工作流程没有想象的复杂,今天给大家分享一下整体方案

整体方案:四个模块串成一条线

整条自动化流程,差不多四个模块:

取数:pandas读SQL/Excel/中间表,输出DataFrame

出图:matplotlib生成销售趋势、Top门店、品类分布三张图

发邮件:yagmail或smtplib发HTML邮件,附件带图片和Excel

定时:schedule库每周一8点自动触发,全程零人工

第一步:取数(pandas读数据)

我用pandas从SQL直接拉数据,示例代码:

import pandas as pd

from sqlalchemy import create_engine

# 引擎配置,按自己公司改

engine = create_engine('mysql+pymysql://user:pwd@host:3306/db')

# 每周一跑上周数据

sql = """

SELECT

    store_name,

    SUM(sales) AS total_sales,

    COUNT(DISTINCT member_id) AS member_cnt

FROM daily_sales

WHERE sale_date BETWEEN DATE_SUB(CURRENT_DATE, INTERVAL 7 DAY)

                    AND DATE_SUB(CURRENT_DATE, INTERVAL 1 DAY)

GROUP BY store_name

ORDER BY total_sales DESC

"""

df = pd.read_sql(sql, engine)

注意一个小坑:任务最好放在凌晨跑,用`DATE_SUB`比写死日期省心,跨月跨年都不会出错。

第二步:出图(matplotlib三张图)

用matplotlib生成三张关键图,存到本地临时目录:

import matplotlib.pyplot as plt

import os

# 中文字体配置(Mac/Win不一样,按你电脑改)

plt.rcParams['font.sans-serif'] = ['PingFang SC', 'Hiragino Sans GB']

plt.rcParams['axes.unicode_minus'] = False

os.makedirs('/tmp/report_img', exist_ok=True)

# 图1:门店销售Top10

top10 = df.head(10)

plt.figure(figsize=(10, 6))

plt.barh(top10['store_name'], top10['total_sales'], color='#E74C3C')

plt.title('门店销售Top10', fontsize=16)

plt.gca().invert_yaxis()

plt.tight_layout()

plt.savefig('/tmp/report_img/top10.png', dpi=120)

plt.close()

剩下两张图(趋势图、品类分布)写法一样,就是改下数据和颜色。这块代码是死的,跑一次就能复用。

第三步:发邮件(yagmail最省事)

我对比过smtplib和yagmail。yagmail就够用,比smtplib少写一半代码,附件、内嵌图片、HTML正文都一行搞定。

import yagmail

# 一次性配好(密码用QQ邮箱授权码,不是登录密码)

yag = yagmail.SMTP(

    user='your@qq.com',

    password='你的QQ邮箱授权码',  # QQ邮箱设置里生成

    host='smtp.qq.com'

)

# HTML正文

html = f"""

<h2>上周销售周报(自动生成)</h2>

<p>本周总销售额:<b>{df['total_sales'].sum():,.0f}元</b></p>

<p>活跃会员数:<b>{df['member_cnt'].sum():,}人</b></p>

<p>详见附件和图片。</p>

"""

# 发送(收件人+抄送+附件+正文,一行搞定)

yag.send(

    to=['leader@company.com'],

    cc=['me@company.com'],

    subject='【周报】上周销售数据',

    contents=[yagmail.inline('/tmp/report_img/top10.png'), html],

    attachments=['/tmp/report_img/top10.png', '/tmp/report_img/趋势.png']

)

几个容易踩的坑:

• 授权码不是密码:QQ/163/企业邮箱都要去后台单独开授权码

• 图片内嵌用yagmail.inline():不然图片在收件人那边是裂的

• 抄送cc和密送bcc要分清:cc所有人可见,bcc不可见

第四步:定时(schedule最简单)

定时方案我试过三个,schedule、cron、APScheduler——个人推荐schedule,10行代码搞定:

import schedule

import time

def job():

    # 把前三步打包成一个函数

    run_full_pipeline()

# 每周一早8点跑

schedule.every().monday.at('08:00').do(job)

while True:

    schedule.run_pending()

    time.sleep(60)  # 每分钟检查一次

这个脚本扔到服务器后台跑(用`nohup python script.py &`),周一早上你还没到工位,报表已经躺在领导邮箱里了。

我自己用的时候,还多了两块活儿

基础版能节约2小时。我自己用的版本还多了两块:

多门店报表自动拆分,用`groupby('store_name')`拆分数据,每个店长只看自己店的数据,邮件正文用f-string动态插入店长名字,加个`for`循环解决。

写在最后:数据人最该先自动化什么

个人认为,最该自动化的不是分析环节,是"交付环节"。

分析再花哨,最后一公里是"让该看的人看到"。Excel再漂亮,没有触达到目标用户手上就是零。Python这玩意儿最大的价值不是帮你算数据,是把"算完数据→送到决策者手里"这条链路打通。

额外再插一嘴,现在各种AI工具已经基本成熟了,推荐使用workbuddy创建自动任务,可以帮助0编程基础的数据员,从头梳理各种卡点,它会帮你调试代码搭建自动任务,不过需要警惕的是AI出的数据结果一定要自己复核一遍,我被坑了好多次了,唉......

最新文章

随机文章