You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python正则提取多封邮件内容写入CSV仅保留最后一条数据问题

问题根因
  • 初始代码的核心错误:文件打开操作放在了邮件遍历循环内部,且使用"w"写入模式,该模式每次打开文件时会清空全部原有内容,每处理一封邮件就会覆盖之前写入的结果,最终文件只会保留最后一封邮件的匹配数据。
  • 你调整后的版本存在3个问题:
    1. 缩进语法错误:writer = csv.writer(f_out)没有缩进,不在with open()代码块的作用域内,运行会直接抛出作用域错误。
    2. 移除了邮件内容过滤逻辑:会遍历到邮件的HTML分片、附件分片,要么匹配不到有效数据,要么触发解码异常。
    3. 正则表达式放在循环内重复编译,存在不必要的性能损耗。
修复后完整代码

修复点说明:

  • 将文件打开、正则编译操作全部移到所有遍历循环外,仅执行一次
  • 修正所有缩进错误,保证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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 01:21:47