Python基于两个DataFrame匹配查询数据并按邮箱生成Excel分发
基于Pandas DataFrame的定向数据分发实现方案
前置依赖
先安装需要用到的第三方库:
pip install pandas openpyxl
发邮件用到的smtplib、email模块为Python标准库,无需额外安装。
完整实现代码
import pandas as pd import smtplib import time from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.mime.application import MIMEApplication from datetime import datetime # -------------------------- 配置区 -------------------------- # 邮件发送配置,根据自身邮箱服务商修改 SMTP_SERVER = "smtp.exmail.qq.com" # 示例为企业微信邮箱SMTP地址 SMTP_PORT = 465 SENDER_EMAIL = "你的发件邮箱@company.com" SENDER_PASSWORD = "你的邮箱SMTP授权码" # 非登录密码,需在邮箱后台开启SMTP后获取 # 可选配置:批量发送时的延迟时间,单位秒,避免被限流 SEND_DELAY = 2 # 假设此处已经通过SQL查询得到了两个DataFrame:TableA、TableB # TableA字段:姓名、邮箱、Code(逗号分隔) # TableB字段:Info1、Code、Info2 # ----------------------------------------------------------- # 预处理TableA:拆分逗号分隔的Code,去除前后空格,过滤空Code TableA["code_list"] = TableA["Code"].str.split(",").apply( lambda codes: [c.strip() for c in codes if c.strip()] ) # 遍历每个收件人生成数据并发送邮件 for _, row in TableA.iterrows(): user_name = row["姓名"] user_email = row["邮箱"] user_codes = row["code_list"] # 跳过无有效Code的用户 if not user_codes: print(f"用户 {user_name} 无有效Code,跳过发送") continue # 过滤TableB中该用户可查看的全部数据 user_filter_data = TableB[TableB["Code"].isin(user_codes)].copy() # 生成Excel文件,自定义文件名 excel_file_name = f"{user_name}_业务数据_{datetime.now().strftime('%Y%m%d')}.xlsx" user_filter_data.to_excel(excel_file_name, index=False, engine="openpyxl") # 构造邮件 msg = MIMEMultipart() msg["From"] = SENDER_EMAIL msg["To"] = user_email msg["Subject"] = f"{user_name} 您好,您的业务数据已生成" # 邮件正文,可自定义内容 mail_body = f"{user_name} 您好:\n\n附件为您权限范围内的最新业务数据,请查收。\n\n如有问题请联系数据运营组。" msg.attach(MIMEText(mail_body, "plain", "utf-8")) # 添加Excel附件 with open(excel_file_name, "rb") as f: attach_part = MIMEApplication(f.read(), Name=excel_file_name) attach_part["Content-Disposition"] = f"attachment; filename={excel_file_name}" msg.attach(attach_part) # 发送邮件 with smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT) as server: server.login(SENDER_EMAIL, SENDER_PASSWORD) server.sendmail(SENDER_EMAIL, user_email, msg.as_string()) print(f"已成功发送数据至 {user_name} <{user_email}>") # 批量发送时加延迟,避免触发限流 time.sleep(SEND_DELAY)
常见优化点
- 若Code匹配对大小写不敏感,可以在过滤前统一将
TableB["Code"]和user_codes内的元素转为大写/小写,避免匹配遗漏 - 若需要自定义Excel的样式(比如列宽、单元格格式),可以使用
openpyxl的接口对生成的Excel文件做二次处理 - 若数据量较大,可以将生成的Excel压缩为zip包后再作为附件发送,减少传输体积
- 可以添加异常捕获逻辑,记录发送失败的用户,后续重试
内容的提问来源于stack exchange,提问作者ririri
相关产品推荐
相关产品推荐

