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

pd.read_table读取非表格内容且数据全存入单列如何解决

问题原因
  • 内容未做范围截取:直接传入全量邮件正文给解析函数,开头提示语、末尾落款等非表格内容会被全部读入
  • 解析逻辑失效:预先定义的表格行匹配正则未被调用,使用\s+作为分隔符会将所有空白字符识别为列分割标记,直接导致字段错位、内容合并
  • 写入逻辑错误:文件在循环中被反复覆盖,仅会保留最后一封邮件的解析结果,初始化的csv.writer对象未被实际使用
  • 正文提取不严谨:未过滤HTML、附件类part,容易引入非正文冗余内容
修复后完整代码
import csv
import re
import io
import email
from email.header import decode_header
import pandas as pd
import smtplib

# 常量统一定义在循环外
SENDER_EMAIL = '***@outlook.com'
SENDER_PASSWORD = '***'
ALERT_RECEIVER = '***@gmail.com'
PO_TABLE_PATTERN = re.compile(r"([a-zA-Z]{3}[0-9]+) Line ([0-9]+) Seq ([0-9]+) ([0-9]+/[0-9]+/[0-9]+)")

# 初始化CSV文件,写入表头
with open("data.csv", "w", newline='', encoding='utf-8') as f_out:
    writer = csv.writer(f_out)
    writer.writerow(["PO#", "Line#", "Seq", "Date"])

    for i in range(messages, messages-N, -1):
        res, msg = imap.fetch(str(i), "(RFC822)")
        for response in msg:
            if not isinstance(response, tuple):
                continue
            # 解析邮件内容
            msg = email.message_from_bytes(response[1])
            # 解码邮件主题
            subject, encoding = decode_header(msg["Subject"])[0]
            if isinstance(subject, bytes):
                subject = subject.decode(encoding if encoding else 'utf-8')
            # 解码发件人
            From, encoding = decode_header(msg.get("From"))[0]
            if isinstance(From, bytes):
                From = From.decode(encoding if encoding else 'utf-8')
            print("Subject:", subject)
            print("From:", From)

            body = ""
            # 仅提取纯文本正文,跳过附件、HTML内容
            for part in msg.walk():
                content_type = part.get_content_type()
                content_disposition = str(part.get("Content-Disposition"))
                if content_type != 'text/plain' or content_disposition.startswith('attachment'):
                    continue
                payload = part.get_payload(decode=True)
                if payload:
                    body = payload.decode(encoding if encoding else 'utf-8', errors='ignore')
                    break

            try:
                # 预处理表头空格,用正则提取所有有效表格行,自动过滤无关文本
                processed_body = body.replace(' #', '#')
                table_records = PO_TABLE_PATTERN.findall(processed_body)
                if not table_records:
                    raise ValueError("未匹配到有效订单表格内容")
                # 追加写入CSV
                writer.writerows(table_records)
                print(f"邮件解析完成,共写入{len(table_records)}条订单记录")
            except Exception as e:
                # 解析失败发送告警邮件
                mail_content = 'Subject: {}\n\n{}'.format(subject, body)
                server = smtplib.SMTP('smtp-mail.outlook.com', 587)
                server.starttls()
                server.login(SENDER_EMAIL, SENDER_PASSWORD)
                server.sendmail(SENDER_EMAIL, ALERT_RECEIVER, mail_content)
                server.quit()
                print(f"解析失败,已发送告警邮件,错误:{str(e)}")

imap.close()
imap.logout()
关键改动说明
  • 正文提取阶段仅保留text/plain类型的非附件内容,从源头过滤HTML代码、附件内容等冗余数据
  • 调用预先定义的正则做全正文匹配,仅提取符合PO行格式的内容,自动过滤前后的提示语、落款等无关文本;正则分组返回结果直接对应PO#/Line#/Seq/Date四个目标字段,不会出现列错位、内容合并到同一列的问题
  • 调整CSV写入逻辑,文件打开后先写入固定表头,后续解析到的订单行直接追加写入,不会出现循环覆盖文件的问题
  • 补全编码兜底、SMTP连接关闭等边缘逻辑,避免因编码异常、连接泄漏导致的运行错误

内容的提问来源于stack exchange,提问作者LaunchCoder33

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 18:42:33