Python正则提取多封邮件内容写入CSV仅保留最后一条数据问题
问题根因
- 初始代码的核心错误:文件打开操作放在了邮件遍历循环内部,且使用
"w"写入模式,该模式每次打开文件时会清空全部原有内容,每处理一封邮件就会覆盖之前写入的结果,最终文件只会保留最后一封邮件的匹配数据。 - 你调整后的版本存在3个问题:
- 缩进语法错误:
writer = csv.writer(f_out)没有缩进,不在with open()代码块的作用域内,运行会直接抛出作用域错误。 - 移除了邮件内容过滤逻辑:会遍历到邮件的HTML分片、附件分片,要么匹配不到有效数据,要么触发解码异常。
- 正则表达式放在循环内重复编译,存在不必要的性能损耗。
- 缩进语法错误:
修复后完整代码
修复点说明:
- 将文件打开、正则编译操作全部移到所有遍历循环外,仅执行一次
- 修正所有缩进错误,保证CSV写入操作在文件打开的作用域内
- 恢复纯文本非附件分片的过滤逻辑,增加解码异常兼容,避免任务意外中断
- 增加CSV编码、空行兼容配置,避免乱码和多余空行问题
import re import csv import imaplib import email from email.header import decode_header # -------------------------- 配置项 按需修改 -------------------------- IMAP_SERVER = "填写你的邮箱IMAP服务地址,比如imap.qq.com" EMAIL_ACCOUNT = "你的邮箱账号" EMAIL_PASSWORD = "你的邮箱IMAP授权码" SCAN_COUNT = 2 # 需要扫描的最近邮件数量,对应原代码的N # -------------------------------------------------------------------- # 正则仅编译一次 match_pattern = re.compile(r"([a-zA-Z]+[0-9]+) Line ([0-9]+) Seq ([0-9]) ([0-9]+/[0-9]+/[0-9]+)") # 循环外打开CSV文件,仅初始化清空一次 with open("result.csv", "w", encoding="utf-8-sig", newline="") as csv_file: csv_writer = csv.writer(csv_file) # 写入表头,不需要可删除 csv_writer.writerow(["标识ID", "行号", "序列号", "日期"]) # 连接邮箱、登录 imap_conn = imaplib.IMAP4_SSL(IMAP_SERVER) imap_conn.login(EMAIL_ACCOUNT, EMAIL_PASSWORD) imap_conn.select("INBOX") # 获取收件箱邮件总数 _, msg_index_list = imap_conn.search(None, "ALL") total_msg = int(msg_index_list[0].split()[-1]) # 倒序遍历指定数量的邮件 for msg_id in range(total_msg, total_msg - SCAN_COUNT, -1): _, fetch_res = imap_conn.fetch(str(msg_id), "(RFC822)") for res_item in fetch_res: if not isinstance(res_item, tuple): continue # 解析邮件内容 msg_obj = email.message_from_bytes(res_item[1]) # 解码邮件头 subj, subj_enc = decode_header(msg_obj["Subject"])[0] if isinstance(subj, bytes): subj = subj.decode(subj_enc if subj_enc else "utf-8", errors="ignore") sender, sender_enc = decode_header(msg_obj.get("From"))[0] if isinstance(sender, bytes): sender = sender.decode(sender_enc if sender_enc else "utf-8", errors="ignore") print(f"正在处理邮件:主题[{subj}] 发件人[{sender}]") # 遍历邮件分片 for part in msg_obj.walk(): content_type = part.get_content_type() disposition = str(part.get("Content-Disposition")) # 跳过非纯文本、附件分片 if content_type != "text/plain" or "attachment" in disposition: continue payload = part.get_payload(decode=True) if not payload: continue # 解码正文 body = payload.decode("utf-8", errors="ignore") # 匹配结果写入CSV match_res = match_pattern.finditer(body) csv_writer.writerows(map(lambda m: m.groups(), match_res)) # 控制台打印匹配结果 for item in match_res: print(item.groups()) # 关闭邮箱连接 imap_conn.close() imap_conn.logout()
额外说明
- 代码中
encoding="utf-8-sig"是为了兼容Excel打开CSV时的中文乱码问题,newline=""是为了避免csv模块写入时产生多余空行。 - 如果需要输出为Excel格式,直接将生成的CSV文件用Excel打开后另存为xlsx格式即可;如果需要直接生成xlsx,可以安装
openpyxl库替换对应的写入逻辑,CSV格式兼容性更强、写入效率更高,优先推荐使用。 - 代码增加了解码错误忽略逻辑,遇到编码异常的邮件不会直接中断整个扫描任务。
内容的提问来源于stack exchange,提问作者LaunchCoder33
相关产品推荐
相关产品推荐

