You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用Python与Pandas解析Outlook *.msg邮件中的复杂表格?

还原带单元格内换行的Outlook邮件表格到Pandas DataFrame

首先,要解决这个问题,核心在于邮件表格的结构信息在纯文本中已经丢失——ExtractMsg的body属性返回的是纯文本内容,会把单元格内的硬换行和表格的行分隔符混在一起,导致直接拆分后无法正确分组。

最优方案是优先提取邮件的HTML正文(因为Outlook邮件的表格通常是HTML格式渲染的),通过HTML解析来完整保留表格结构,这比纯文本还原靠谱得多。下面是具体步骤:

方法1:解析HTML正文(推荐)

邮件的HTML版本会完整保留<table><td>等标签,能准确区分单元格和单元格内的换行。代码如下:

import ExtractMsg
from bs4 import BeautifulSoup
import pandas as pd

# 读取.msg文件
msg_file = "your_email.msg"  # 替换成你的文件路径
email = ExtractMsg.Message(msg_file)

# 获取HTML正文(如果邮件包含HTML内容)
html_content = email.htmlBody

if html_content:
    # 用BeautifulSoup解析HTML
    soup = BeautifulSoup(html_content, "html.parser")
    
    # 找到目标表格(假设是邮件中的第一个表格,可根据实际调整)
    target_table = soup.find("table")
    
    # 逐行解析表格
    table_rows = []
    for row in target_table.find_all("tr"):
        # 提取单元格内容,保留原始换行(把<br>转成换行符)
        cells = [cell.get_text(strip=False).replace("\r\n", "\n").replace("<br>", "\n") for cell in row.find_all(["td", "th"])]
        table_rows.append(cells)
    
    # 转换为Pandas DataFrame
    df = pd.DataFrame(table_rows[1:], columns=table_rows[0])
    print(df)
else:
    print("该邮件没有HTML正文,将尝试纯文本还原方案")

这个方法能100%还原表格结构,包括单元格内的换行,因为HTML本身就记录了哪些换行属于单元格内部。

方法2:纯文本内容还原(当没有HTML正文时)

如果邮件只有纯文本版本,我们需要根据内容规律手动识别单元格边界。从你提供的正文内容来看,能找到几个规律:

  • 表头是ABC
  • 每一行的起始是数字(1、2、3、4、5)
  • C列的内容通常以c结尾(1c、2c等)

基于这些规律,我们可以合并单元格内的换行:

import ExtractMsg
import pandas as pd

msg_file = "your_email.msg"
email = ExtractMsg.Message(msg_file)
email_body = email.body

# 清理纯文本:去掉空行和首尾空格
clean_lines = [line.strip() for line in email_body.split("\r\n") if line.strip()]

# 提取表头和数据部分
header = clean_lines[:3]
data_lines = clean_lines[3:]

# 找到所有行的起始索引(数字开头的行)
row_start_indices = [i for i, line in enumerate(data_lines) if line.isdigit()]
row_start_indices.append(len(data_lines))  # 添加末尾标记,方便切片

# 逐行合并单元格内容
processed_rows = []
for i in range(len(row_start_indices) - 1):
    start = row_start_indices[i]
    end = row_start_indices[i+1]
    current_row_parts = data_lines[start:end]
    
    # A列是第一个元素
    col_a = current_row_parts[0]
    
    # 找到C列的结束位置(最后一个以'c'结尾的元素)
    col_c_index = None
    for idx in range(len(current_row_parts)-1, 0, -1):
        if current_row_parts[idx].endswith("c"):
            col_c_index = idx
            break
    
    # 合并B、C列的内容(保留换行)
    if col_c_index:
        col_b = "\n".join(current_row_parts[1:col_c_index])
        col_c = "\n".join(current_row_parts[col_c_index:])
    else:
        # 兜底:如果没找到规律,按默认方式拆分
        col_b = "\n".join(current_row_parts[1:-1])
        col_c = current_row_parts[-1]
    
    processed_rows.append([col_a, col_b, col_c])

# 转换为DataFrame
df = pd.DataFrame(processed_rows, columns=header)
print(df)

运行后,你会得到还原后的表格,其中单元格内的换行被保留在对应的单元格中(显示为\n,在Pandas中查看时会自动换行)。

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

火山引擎 最新活动