使用XLWings将爬取的邮件文本导出至Excel的问题排查求助
问题排查及修复方案
核心问题列表
- 重复调用
getEmail():imap协议默认抓取seen=False的未读邮件后,会自动将邮件标记为已读。你在全局先调用了一次getEmail(),执行exportExcel()时再次调用该函数已经找不到符合条件的未读邮件,导致todays_ps为空值。 - xlwings打开已打开工作簿的写法不严谨:如果
ExportEmailTest.xlsm已经处于打开状态,使用xw.Book()可能因为工作路径不匹配、Excel实例不统一导致找不到文件,优先用xw.books['文件名']定位已打开的工作簿。 - 冗余参数问题:
index=False是针对DataFrame类型数据写入的参数,纯字符串写入不需要加该参数。 getEmail()返回逻辑限制:当前函数只要匹配到第一封邮件就直接return,只会返回1封邮件内容,如果需要抓取所有符合条件的未读邮件需要调整返回逻辑。
修复后代码
import xlwings as xw from imap_tools import MailBox, AND def getEmail(): with MailBox('imap.gmail.com').login('*****@gmail.com', '*****.', 'INBOX') as mailbox: # 加mark_seen=False参数可以避免抓取后自动标记已读,按需开启 for msg in mailbox.fetch(AND(from_='*****@gmail.com', seen=False)): print(msg.subject) body = msg.text or msg.html print(body.strip()) # 只取第一封的逻辑保留,需要多封的话改成append到列表返回 return body.strip() def exportExcel(): todays_ps = getEmail() # 优先定位已打开的工作簿,找不到再读本地文件 try: wb = xw.books['ExportEmailTest.xlsm'] except: wb = xw.Book('ExportEmailTest.xlsm') sht2 = wb.sheets['Sheet2'] sht2.range('A1').value = todays_ps # 可选:写完自动保存 wb.save() # 删掉全局的getEmail()调用,只在exportExcel里调用一次 exportExcel()
额外注意事项
- 如果抓取邮件时不想自动标记为已读,可以在
mailbox.fetch()的参数里加mark_seen=False - 写入的内容如果含html标签,需要提前用
beautifulsoup等库过滤后再写入Excel - 若Excel文件处于被其他进程占用的状态,也会导致xlwings写入失败,确认文件仅被当前Excel实例打开
内容的提问来源于stack exchange,提问作者Andy
相关产品推荐
相关产品推荐

