1. 项目背景与需求分析
去年接手了一个数据报表的活儿,每天要从十几个Excel里提取数据做汇总分析。刚开始手动操作还能应付,后来数据量越来越大,经常加班到深夜。终于在某天凌晨三点对着电脑屏幕崩溃后,我决定用Python把这个流程自动化。
这个自动化脚本的核心需求很明确:
- 自动遍历指定文件夹内的所有Excel文件
- 提取每个文件中特定工作表的关键数据列
- 按照预设规则进行数据清洗和计算
- 生成统一格式的汇总报表
- 通过邮件自动发送给相关责任人
2. 技术选型与方案设计
2.1 核心工具链选择
经过对比测试,最终确定的工具组合是:
- pandas:数据处理核心库,DataFrame结构非常适合表格操作
- openpyxl:处理新版xlsx格式的Excel文件
- smtplib + email:实现邮件自动发送功能
- schedule:定时任务调度
注意:早期尝试过xlrd库,但在处理xlsx格式时遇到兼容性问题。openpyxl虽然内存占用稍大,但对新格式支持更好。
2.2 程序架构设计
整个程序采用模块化设计,主要分为四个功能模块:
- 文件扫描模块(file_scanner.py)
- 数据处理模块(data_processor.py)
- 报表生成模块(report_generator.py)
- 邮件发送模块(mail_sender.py)
python复制# 主程序结构示例
def main():
files = scan_files('./data') # 扫描文件
raw_data = process_files(files) # 处理数据
report = generate_report(raw_data) # 生成报表
send_email(report) # 发送邮件
3. 核心实现细节
3.1 文件批量处理实现
文件扫描模块的关键点在于:
- 使用os.walk递归遍历目录
- 通过文件扩展名过滤非Excel文件
- 处理文件名编码问题(特别是中文路径)
python复制def scan_files(directory):
excel_files = []
for root, _, files in os.walk(directory):
for file in files:
if file.endswith(('.xlsx', '.xls')):
filepath = os.path.join(root, file)
try:
# 尝试打开文件验证有效性
pd.read_excel(filepath, nrows=1)
excel_files.append(filepath)
except Exception as e:
print(f"无效文件 {filepath}: {str(e)}")
return excel_files
3.2 数据清洗关键逻辑
数据清洗中最复杂的部分是处理各种异常情况:
- 空值处理:采用业务规则默认值填充
- 格式转换:统一日期、金额等字段格式
- 数据校验:检查数值范围是否合理
python复制def clean_data(df):
# 处理空值
df['销售额'].fillna(0, inplace=True)
# 统一日期格式
df['日期'] = pd.to_datetime(df['日期'], errors='coerce')
# 数据校验
mask = (df['单价'] > 0) & (df['数量'] > 0)
df = df.loc[mask].copy()
return df
4. 邮件自动发送实现
4.1 邮件内容构建
使用email库构建带附件的邮件:
- MIMEMultipart作为容器
- MIMEText添加正文内容
- MIMEApplication添加Excel附件
python复制def build_email(report_path):
msg = MIMEMultipart()
msg['From'] = 'auto_report@company.com'
msg['To'] = 'team@company.com'
msg['Subject'] = '每日销售报表 - ' + datetime.now().strftime('%Y-%m-%d')
# 添加正文
body = MIMEText('请查收今日自动生成的销售报表', 'plain')
msg.attach(body)
# 添加附件
with open(report_path, 'rb') as f:
part = MIMEApplication(f.read(), Name=os.path.basename(report_path))
part['Content-Disposition'] = f'attachment; filename="{os.path.basename(report_path)}"'
msg.attach(part)
return msg
4.2 邮件服务器配置
使用公司SMTP服务器发送邮件,关键配置参数:
- 服务器地址和端口
- TLS/SSL加密选项
- 认证信息(建议使用配置文件或环境变量存储)
重要提示:切勿在代码中硬编码密码!可以使用python-dotenv加载环境变量
5. 定时任务管理
使用schedule库实现每日定时执行:
- 设置每天上午9点执行
- 添加异常捕获和日志记录
- 支持手动立即执行
python复制def job():
try:
main()
logging.info('报表生成并发送成功')
except Exception as e:
logging.error(f'任务执行失败: {str(e)}')
# 设置定时任务
schedule.every().day.at("09:00").do(job)
# 主循环
while True:
schedule.run_pending()
time.sleep(60)
6. 踩坑经验与优化建议
6.1 性能优化技巧
-
内存管理:
- 使用chunksize参数分块读取大文件
- 及时del不再使用的DataFrame
- 禁用openpyxl的默认只读优化
-
并发处理:
- 对独立Excel文件使用多线程处理
- 注意GIL限制,IO密集型任务更适合多线程
python复制from concurrent.futures import ThreadPoolExecutor
def process_file(file):
# 单个文件处理逻辑
pass
with ThreadPoolExecutor(max_workers=4) as executor:
results = list(executor.map(process_file, file_list))
6.2 常见问题排查
-
编码问题:
- 遇到中文乱码时指定engine='openpyxl'
- 文件路径包含中文时使用os.path处理
-
格式兼容性:
- 旧版xls文件使用xlrd兼容模式
- 处理合并单元格时注意索引变化
-
邮件发送失败:
- 检查SMTP服务器是否需要特定端口
- 验证发件账号是否有足够权限
7. 项目扩展方向
这个基础框架可以进一步扩展:
- 数据可视化:用matplotlib自动生成图表插入邮件
- 异常检测:设置业务规则自动标记异常数据
- Web界面:用Flask添加手动触发和配置界面
- 数据库集成:将结果存入MySQL或MongoDB
python复制# 可视化扩展示例
def add_chart(report_path):
df = pd.read_excel(report_path)
plt.figure(figsize=(10,6))
df.groupby('品类')['销售额'].sum().plot.bar()
chart_path = '/tmp/chart.png'
plt.savefig(chart_path)
return chart_path
整个项目从构思到上线用了两周时间,现在每天节省了至少3小时的手工操作时间。最关键的是再也不用担心深夜加班处理数据时的手误问题了。自动化脚本运行半年多来,已经处理了超过5000份Excel文件,生成报表300多份,准确率100%。