Python从邮件提取表格写入CSV,移除\r\n等特殊字符
解决邮件表格提取后特殊字符无法去除的问题
嗨,很高兴能帮到你!看起来你已经成功抓取到邮件里的表格数据了,只是卡在清理特殊字符和规整格式这一步——这对新手来说太正常啦,别担心😉
问题根源
你当前用item.text直接获取单元格内容时,邮件HTML里的换行符(\r、\n)、多余空白,还有邮件编码残留的奇怪字符(比如你看到的=p>)都被保留了下来,导致内容分散、格式混乱。
解决方案:先清理文本,再调整格式
我们可以写一个专门的文本清理函数,把这些干扰字符去掉,再根据表格的实际结构调整输出格式。
1. 编写文本清理函数
这个函数会帮你移除换行符、多余空白,以及邮件里的奇怪编码残留:
def clean_text(text): # 移除\r和\n换行符 cleaned = text.replace('\r', '').replace('\n', '') # 去除首尾空白,同时把多个连续空格合并成一个 cleaned = ' '.join(cleaned.split()) # 清理邮件里的奇怪残留(比如=p>) cleaned = cleaned.replace('=p>', '') return cleaned
2. 修改表格数据提取逻辑
把原来的列表推导式改成用清理函数处理每个单元格的内容:
# 替换原来的tab_data生成代码 tab_data = [[clean_text(item.text) for item in row_data.select("td")] for row_data in table_tag.select("tr")]
3. 调整格式匹配预期结果
从你给出的当前结果来看,邮件里的表格可能是竖排结构(每行一个表头+对应值),而你需要的是横排的CSV格式。我们可以把表头和对应值分组整理:
# 先收集所有非空的表头和数据 all_cells = [cell for row in tab_data for cell in row if cell] # 观察到表头有9项(Quick No.到Additional Information),所以每9个单元格为一组 headers = all_cells[:9] # 按每组9个数据拆分并写入CSV for i in range(9, len(all_cells), 9): data_row = all_cells[i:i+9] writer.writerow(data_row)
完整修改后的代码示例
from bs4 import BeautifulSoup def clean_text(text): cleaned = text.replace('\r', '').replace('\n', '') cleaned = ' '.join(cleaned.split()) cleaned = cleaned.replace('=p>', '') return cleaned for emailid in items: # 获取邮件内容 resp, data = m.fetch(emailid, '(UID BODY[TEXT])') text = str(data[0][1]) tree = BeautifulSoup(text, "lxml") table_tag = tree.select("table")[0] # 提取并清理表格数据 tab_data = [[clean_text(item.text) for item in row_data.select("td")] for row_data in table_tag.select("tr")] # 整理成横排格式并写入CSV all_cells = [cell for row in tab_data for cell in row if cell] if len(all_cells) >= 9: # 可选:先写入表头 writer.writerow(all_cells[:9]) # 按每组9个数据拆分写入 for i in range(9, len(all_cells), 9): data_row = all_cells[i:i+9] writer.writerow(data_row) # 打印验证结果 print("表头:", ' '.join(all_cells[:9])) for i in range(9, len(all_cells), 9): print("数据行:", ' '.join(all_cells[i:i+9]))
额外提示
如果清理后还是有奇怪的字符,可以试试用正则表达式更全面地过滤:
import re def clean_text(text): cleaned = text.replace('\r', '').replace('\n', '') # 只保留字母、数字、空格和常见标点 cleaned = re.sub(r'[^\w\s.,/-]', '', cleaned) cleaned = ' '.join(cleaned.split()) return cleaned
你可以先运行带clean_text的代码,看看字符清理的效果,如果格式还是不符合预期,可以把print(table_tag)输出的HTML结构贴出来,这样能更精准地调整数据排列逻辑~
内容的提问来源于stack exchange,提问作者Chambo
相关产品推荐
相关产品推荐

