2026/10/5 12:50:30

Python读取163邮箱邮件:requests、selenium与IMAP三种方案对比与实战

Python读取163邮箱邮件:requests、selenium与IMAP三种方案对比与实战 做邮件自动化的朋友应该都遇到过这个需求想把163邮箱收件箱里的邮件列表抓下来或者进一步提取正文、附件用于自动收验证码、整理订阅邮件、做邮件监控。我早期接到这个需求时第一反应就是写爬虫但163邮箱网页版的登录和渲染远比想象中麻烦试过 urllib、requests、selenium 三种方案后发现它们各有各的适用场景也存在各自的坑。这篇文章把三种方案的路数和取舍讲清楚另外附上一个我后来才意识到的更优解直接用 IMAP 协议读邮件从根本上绕开网页爬取的各种麻烦。如果你正准备用 Python 处理 163 邮箱或者对 Web 自动化的技术选型感兴趣这篇总结应该能帮你省下不少时间。我会直接贴出可用代码和踩坑记录也会说明哪些地方需要你根据当前页面结构做适配。1. 先把趋势看明白爬邮箱网页版的本质是什么1.1 邮件系统的动态渲染趋势纯请求越来越难很多人的第一反应是收件箱不就是个列表页面吗直接拿 requests 请求 HTML 再解析不就行了理论上确实是这样但实际操作中你会发现 163 邮箱网页版经过了多次改版页面大量使用异步加载。你请求回来的 HTML 里邮件列表的数据可能并不完整需要在浏览器中执行 JavaScript 后才会渲染出来。这就引出了 Web 爬虫里最核心的分水岭目标页面是服务端渲染还是客户端渲染。早年的邮箱 Web 端会在 HTML 里直接输出邮件表格requests 一把梭就能搞定现在的邮箱页面普遍是前后端分离列表数据往往通过内部的 JSON 接口异步返回或者用类似 iframe 内嵌子页面的方式组织。用 requests 抓回来的 HTML要么只是个骨架要么数据结构复杂到你怀疑人生。所以在动手之前先花几分钟打开浏览器开发者工具看 Network 面板里页面加载了哪些真实请求HTML 里到底包不包含邮件列表数据。这一步决定了你后面选择哪条技术路线也避免你写完一版 regex 解析后页面一改就全线崩溃。1.2 三种 Web 方案的横向对比urllib、requests、selenium 是处理 Web 自动化的三个典型层级urllib 是 Python 标准库自带的 HTTP 客户端功能最底层几乎所有细节都要手动处理比如 Cookie 存储、请求头拼接、重定向跟随等。适合用来理解 HTTP 协议工作原理但写业务代码效率低。requests 是对 HTTP 的极佳封装Session 自动管理 Cookie代码简洁直观是目前爬虫脚本的主力。适合接口调试、服务端渲染页面的抓取以及配合内部 JSON 接口使用。selenium 直接驱动真实浏览器能完整执行页面 JavaScript处理复杂交互几乎可以模拟真人操作。缺点是重、慢且依赖 ChromeDriver 等浏览器驱动版本匹配。三者不是替代关系而是递进关系。能不用浏览器就不用在浏览器里跑这是爬虫工程师的基本素养因为浏览器的开销和稳定性问题会让你在批量任务里吃尽苦头。1.3 有一条更优路径IMAP 协议在继续讲三种 Web 方案之前我必须先剧透一个结论如果你只是想读自己的邮件那 IMAP 协议才是更合理的方案。IMAP 是邮件客户端与邮件服务器之间的标准协议163 邮箱本来就支持。你在网页上看到的“收件箱”其实就是 IMAP 服务器上的 INBOX 文件夹。用 Python 标准库 imaplib 就能直接连上去像操作本地队列一样拉取主题、发件人、时间、正文代码量只有 Web 爬虫的三分之一还不用担心登录加密、验证码、页面改版之类的问题。我把 Web 方案放在前面讲是因为很多人明确要求“用爬虫”或者需要适配的不是邮件协议而是网页端功能比如标记已读、管理文件夹。但从选型角度你至少应该知道 IMAP 这条路的存在具体对比我会在第 5 部分展开。2. 方案一urllib——最原始的 HTTP 模拟适合理解原理2.1 核心思路CookieJar 保持会话 POST 表单登录urllib 做爬虫的思路其实和 requests 类似只是所有事情都要自己动手。核心是两件事第一用 http.cookiejar.CookieJar 构造一个带有 Cookie 管理能力的 opener因为登录后服务器会通过 Set-Cookie 头下发会话凭证后续请求必须携带这个 Cookie 才能被识别为登录状态第二向登录接口提交表单数据模拟用户在网页上的登录动作。163 邮箱的登录页面向来不是单纯 POST 用户名密码就能过的中间还有加密和验证码环节。我在最初用 urllib 实战时卡得最久的就是这一步。网易统一登录页会通过 JavaScript 对密码做 RSA 加密后再提交密钥由服务端动态下发。这意味着你光靠 urllib 发请求是不够的还得先抓取页面上的加密公钥然后在 Python 里复刻一遍加密算法。这里我给一个折中思路可以先手动在浏览器登录 163 邮箱然后把登录后的 Cookie 字符串提取出来直接塞进 urllib 的请求头里。这种方式对个人脚本来说完全够用虽然登录这一步还是手动的但之后抓取收件箱列表的过程是自动化的。2.2 urllib 实现收件箱列表解析的完整代码我直接贴一段基于手动 Cookie 的 urllib 获取收件箱列表的示例。这段代码的核心是请求收件箱所在的实际 URL然后将返回的 HTML 通过正则或简单的字符串处理提取邮件主题和发件人。import urllib.request import re # 手动从浏览器开发者工具中复制的 Cookie cookie_str your_cookie_here url https://mail.163.com/js6/s?funcmbox:listMessages headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Cookie: cookie_str, Referer: https://mail.163.com/ } req urllib.request.Request(url, headersheaders) resp urllib.request.urlopen(req, timeout10) html resp.read().decode(utf-8, errorsignore) # 假设邮件列表中的主题和发件人通过特定 class 或者属性输出 # 不同时期页面结构差异很大需要按实际 DOM 调整 subjects re.findall(rsubject:(.*?), html) senders re.findall(rsender:(.*?), html) for idx, (subject, sender) in enumerate(zip(subjects, senders), 1): print(f{idx}. 发件人: {sender} | 主题: {subject})实际运行时会发现一个问题163 邮箱网页版的邮件列表数据非常喜欢用 JSON 格式内嵌在script标签里或者通过单独的接口返回。用正则虽然能快速提取但只要你没逃过字符转义问题比如主题里出现引号解析就会出错。所以我建议 urllib 方案只作为研究 HTTP 流向的教学工具真正用来做业务还是得靠 requests 更稳定的解析手段。2.3 urllib 方案的真实局限性可能有人会觉得urllib 什么都能做为什么大家还是更愿意用 requests差别在于开发效率和代码可读性。urllib 处理 Cookie 要引入专门的 CookieJar重定向行为需要额外配置请求头一个没写全就可能被服务器拒绝参数编码也得手动调用 urllib.parse.urlencode。这些在 requests 里都是非常自然的操作。另外urllib 并不天然支持连接池和 Session 这种抽象每次请求都像第一次见面一样重建连接性能和稳定性都不理想。如果你的任务是循环翻页抓取多个文件夹的邮件列表urllib 的代码会写得越来越长而 requests 只需要在同一 Session 上换 URL 就行。所以我对 urllib 的定位是用它写一两次脚本搞清楚 HTTP 请求构成和 Cookie 机制就够了真正干活不用它。3. 方案二requests——日常自动化任务的主力方案3.1 requests.Session 与 urllib 的差异requests 的设计思路和 urllib 最大的不同就是 Session 机制。Session 对象相当于一个持久化客户端自动保存 Cookie自动处理请求头如 Referer连接复用也有底层 urllib3 连接池顶着。对于需要登录态的接口调用你只需要登录一次后续请求全部走同一个 Session代码干净思维负担小。在 163 邮箱这个场景里requests 的优势尤其明显邮件列表数据如果是异步接口返回的你可以直接对接口发请求拿 JSON不用再浪费时间写正则如果是服务端渲染的 HTML也可以配合 BeautifulSoup 做结构化解析。相比 urllib解析准确度和维护性上升一个台阶。3.2 登录难题网易的统一登录和密码加密虽然 requests 写请求很爽但登录 163 邮箱依然是绕不开的坎。网易统一登录地址在 reg.163.com 域名下页面会加载一段加密脚本。正常情况下提交登录表单时密码字段已经变成 RSA 加密后的密文同时页面还会校验验证码常见的是滑块验证。直接拿明文密码 POST 是过不了服务器的。有两条路可以走第一种完整复刻登录流程。先去页面源码里找到 RSA 公钥然后使用 rsa 库对密码进行加密再模拟提交。这一步还要处理验证码问题。滑块验证码的自动化识别复杂且不稳定我建议不要硬碰硬可以在检测到验证码时手动完成一次之后 Cookie 就驻留在 Session 里了。第二种更务实仍然采用“浏览器手动登录一次导出 Cookie 给 requests 用”的方式。这种方式适合抓取频率不高、运行环境不固定的个人脚本省去所有加密和验证码的麻烦。把 Cookie 导入 requests 的姿势很简单我直接贴代码。这种做法的核心就是构造一个 requests.cookies.RequestsCookieJar 对象把键值对塞进去然后挂在 Session 上。import requests session requests.Session() session.headers.update({ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 }) # 手动从浏览器复制 Cookie 字符串格式类似 name1value1; name2value2 cookie_str name1value1; name2value2 for item in cookie_str.split(;): key, value item.strip().split(, 1) session.cookies.set(key, value) resp session.get(https://mail.163.com/, timeout10) print(resp.status_code)这里有个细节163 邮箱顶部可能还有一个主域名跳转第一次请求 163.com 后服务器会下发新的 Cookie所以如果你发现某些接口提示未登录可能是跳转过程中漏掉了中间域的 Cookie。最简单的办法是把所有域名下的 Cookie 都复制进 session包括 .163.com、.mail.163.com 等。3.3 用 requests 获取收件箱列表的代码和解析容错登录问题解决后抓取收件箱列表就简单了。下面是我用 requests 加 BeautifulSoup 解析邮件列表的示例。注意页面结构会随版本变化所以我在代码里做了多级容错先尝试从 JSON 接口拿数据失败再去解析 HTML。import requests from bs4 import BeautifulSoup import json def fetch_inbox(session, folder_url): resp session.get(folder_url, timeout10) resp.encoding utf-8 # 方式一如果能直接从接口拿到 JSON try: data resp.json() messages data.get(var, {}).get(list, []) for msg in messages: print(msg.get(subject), msg.get(sender)) return except ValueError: pass # 方式二解析 HTML soup BeautifulSoup(resp.text, html.parser) mail_items soup.select(.mailListItem) # 选择器根据实际页面调整 for item in mail_items: subject_node item.select_one(.subject) sender_node item.select_one(.sender) if subject_node: print(subject_node.get_text(stripTrue), |, sender_node.get_text(stripTrue))如果你是直接对内部的异步接口发起请求那么拿到的基本都是 JSON 格式。163 邮箱的接口返回值通常经过一层 JSONP 封装可能在变量赋值里也可能在 callback 函数里。遇到这种情况可以用正则先抽取 JSON 对象再交给 json.loads 解析。import re match re.search(rvar listData (.*?);, resp.text, re.S) if match: data json.loads(match.group(1)) for msg in data.get(list, []): print(msg.get(subject), msg.get(from))这个方案跑起来很稳缺点是接口地址和返回字段名可能改版。我建议在代码里加上“字段不存在时的兜底逻辑”比如用 msg.get(subject) 而不是 msg[subject]避免单个字段异常导致整个脚本中断。4. 方案三selenium——浏览器兜底动态渲染也不怕4.1 为什么还需要 selenium有些场景下requests 方案会走到死胡同页面里某个关键数据怎么都找不到接口或者必须点击某个按钮后才出现文件夹列表又或者登录验证码太复杂连人工介入都不方便。这时候 selenium 就是最后一层兜底。selenium 的价值在于它是真实浏览器环境用户能看到操作过程调试直观对反爬虫的扰动更小。163 邮箱网页版虽然绝大多数数据接口都能直接拿到 JSON但如果你对接口不熟悉最快验证页面行为的方式就是用 selenium 跑一遍。另外如果需要模拟用户操作比如自动打开某封邮件、点击加载更多、切换文件夹selenium 都是最直接的工具。代价也很明显启动浏览器大约消耗上百 M 内存每次操作多一步等待跑批量任务时的速度远比不上 requests。4.2 selenium 操作 163 收件箱的完整流程selenium 的关键是先解决浏览器驱动问题。我用 Chrome 举例确保本机 Chrome 版本和 chromedriver 匹配否则启动就会报 SessionNotCreatedException。驱动装好以后核心步骤就是打开登录页、输入账号密码、等待登录成功、跳转到收件箱、提取邮件列表元素。登录 163 邮箱时有个比较烦人的点登录框可能在 iframe 里。你在主页面找不到输入框需要先切换进 iframe 才能操作。这一步卡住过很多人我贴一段兼容 iframe 的登录代码。from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC driver webdriver.Chrome() wait WebDriverWait(driver, 10) driver.get(https://mail.163.com/) # 邮箱登录页一般有 iframe需要切换 driver.switch_to.frame(login-frame) # frame id 或 name 按实际调整 # 等账号输入框出现 user_input wait.until(EC.presence_of_element_located((By.NAME, email))) user_input.send_keys(your_username163.com) password_input driver.find_element(By.NAME, password) password_input.send_keys(your_password) # 登录按钮可能有多个选择可见的那个 login_button driver.find_element(By.CSS_SELECTOR, a#dologin) login_button.click() # 等待登录完成回到默认内容 driver.switch_to.default_content() wait.until(EC.url_contains(mail.163.com)) print(登录成功) # 进入收件箱 driver.get(https://mail.163.com/js6/main.jsp)登录成功后提取邮件列表的核心操作是等待列表元素的出现。目标元素通常是包含主题、发件人、时间的行容器用 XPath 或 CSS 选择器遍历。注意邮箱页面为了性能列表行可能部分复用元素数量和邮件数量不是严格的对应关系需要配合滚动来加载更多内容。4.3 WebDriverWait 显式等待与 iframe/弹窗处理selenium 最大的坑就是“元素还没渲染出来你去点它”。163 邮箱的网络请求多尤其是第一次登录后列表数据加载需要时间。如果代码里全部用 time.sleep(5) 这种固定等待要么等太久要么网络慢时依然超时。正确姿势是显式等待也就是 WebDriverWait 配合 expected_conditions。例如等待某个主题文本出现wait.until(EC.presence_of_element_located((By.XPATH, //div[classd]//span[classsubject])))还有 iframe 的嵌套问题。163 邮箱的邮件详情页也可能使用 iframe处理思路和登录 iframe 一样先 switch_to.frame 进入解析完再 switch_to.default_content 退出。如果你在页面里怎么都找不到元素第一反应应该是检查当前上下文是否还在正确 frame。弹窗方面163 邮箱偶尔会有引导浮层。如果你的脚本被浮层挡住点击可以用 EC.element_to_be_clickable先等待元素可点击再执行 click。或者手动关闭浮层try: close_btn wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, .close-btn))) close_btn.click() except Exception: pass这种“能关就关关不掉忽略”的逻辑在自动化脚本里非常实用。4.4 divulli 组合定位与上传文件等细节热搜词里有一个很典型的场景页面元素不是原生下拉框而是由 div、ul、li 组合出来的自定义下拉框。这在 163 邮箱的文件夹切换里很常见。遇到这种控件selenium 的 Select 类是失效的你需要先点击触发下拉展开的 div再定位 ul 下的 li 项。# 假设点击一个自定义下拉框然后选择“收件箱” driver.find_element(By.CSS_SELECTOR, div.select-wrapper).click() time.sleep(1) driver.find_element(By.XPATH, //ul[classselect-options]/li[text()收件箱]).click()另外selenium 上传本地文件也是个常见需求。很多人以为要先打开文件选择对话框再用 pywin32 或 AutoIT 操作窗口但实际上 selenium 提供了最简方式只要 input 标签存在直接用 send_keys 传入本地文件绝对路径即可。file_input driver.find_element(By.CSS_SELECTOR, input[typefile]) file_input.send_keys(C:/path/to/attachment.txt)这些细节看似皮毛但在自动化测试或采集脚本里经常是卡住进度的关键点。5. 绕开网页爬取直接通过 IMAP 协议读邮件5.1 IMAP 是什么为什么推荐如果你可以接受不使用“网页爬虫”的形式那么 IMAP 协议是最省心的路子。IMAP 是邮件客户端与邮件服务器之间的标准协议你用的网易邮箱客户端、手机自带邮件 App 底层就是走 IMAP或 POP3。Python 标准库 imaplib 已经实现了客户端逻辑你只需要处理字符串解析不用关心网页结构。IMAP 的这种“绕过浏览器操作”优势非常明显第一不依赖页面 DOM网易怎么改版都不影响你的流程第二请求量小通常一次 select 加一次 search 就能拿到整个收件箱的邮件 ID 列表再按需 fetch 内容对服务器的压力远小于 Web 自动化第三协议稳定接口几乎不变代码可以长期使用。说白了听到“爬邮件”这个词第一反应不应该是 selenium而是 IMAP。正如我在第 1 部分提到的那样Web 爬虫通常是在没有邮件服务器权限或者需要操作特定网页功能时才必须使用。5.2 163 邮箱开启 IMAP 服务并获取授权码用 IMAP 连 163 邮箱有一个关键前提需要在网页端设置里开启 IMAP/SMTP 服务并且用“授权码”而不是邮箱密码登录。这是 163 的安全策略目的是避免你的邮箱密码直接暴露给第三方客户端。具体操作路径登录 163 邮箱网页版进入设置 - POP3/SMTP/IMAP开启 IMAP 服务。开启过程中会要求发送一条短信验证验证通过后会生成一个 16 位授权码。这个授权码只显示一次保存好。后面 imaplib 登录时“密码”这个位置填的就是授权码。这个点我当初踩过坑直接用邮箱密码去连 imap.163.com一直报认证失败后来才意识到需要开启服务和授权码。如果你发现 login 一直失败第一反应就检查这个。5.3 imaplib 获取收件箱列表和邮件正文的完整示例下面的代码用 imaplib 连接 163 邮箱的 IMAP 服务器选择 INBOX搜索所有邮件然后拉取最近几封邮件的发件人和主题。import imaplib import email from email.header import decode_header def decode_mime_header(raw): if raw is None: return decoded decode_header(raw) result [] for text, charset in decoded: if isinstance(text, bytes): charset charset or utf-8 result.append(text.decode(charset, errorsignore)) else: result.append(text) return .join(result) HOST imap.163.com APP_PASSWORD your_authorization_code # 不是邮箱密码 conn imaplib.IMAP4_SSL(HOST, 993) conn.login(your_username163.com, APP_PASSWORD) conn.select(INBOX) # 搜索所有邮件返回的是邮件 ID 列表 status, data conn.search(None, ALL) mail_ids data[0].split() # 拉取最近 5 封 for mail_id in mail_ids[-5:]: status, msg_data conn.fetch(mail_id, (RFC822)) msg email.message_from_bytes(msg_data[0][1]) subject decode_mime_header(msg.get(Subject)) sender decode_mime_header(msg.get(From)) print(f主题: {subject} | 发件人: {sender}) conn.logout()这段代码注意几点邮件主题和发件人可能是 MIME 编码过的比如 ?UTF-8?B?...? 这种所以要用 email.header.decode_header 解码fetch 返回的报文是 bytes用 email.message_from_bytes 转换搜索条件可以更精确比如用 UNSEEN 拿未读邮件或用 SINCE 限定日期这样每次拉取的就只是增量邮件效率更高。5.4 三种 Web 方案 vs IMAP 的选型对照表我根据自己的经验做了一张选型对照表方便你按实际需求挑方案方案登录难度解析稳定性请求速度是否推荐长期使用适用场景urllib难需手动加密/带Cookie差页面改版就崩中不推荐学习HTTP原理、救急requests中建议手动Cookie中依赖接口和结构快视情况接口明确、结构稳定的抓取selenium中需处理iframe/滑块高只要元素能找到就行慢不推荐长期批量页面交互复杂、临时兜底IMAP低开服务授权码高协议稳定非常快强烈推荐各类邮件读取、监控、归档可以看到IMAP 在绝大多数需要“读邮件”的场景下都是最合适的。requests 适合调试接口和做轻量验证selenium 则适合作为最后手段千万别一上来就把项目压在 selenium 上那会浪费大量时间在等待和元素抖动上。6. 常见问题与排查技巧实录6.1 429 too many requests请求太频繁被限流怎么处理如果你用 requests 或 urllib 频繁请求 163 邮箱相关接口大概率会遇到 429 状态码错误信息通常类似exceeded retry limit, last status: 429 too many requests。这是服务器在做限流说明你在短时间内请求量太大被识别为风险行为。解决办法也很朴素给请求之间加随机延时比如time.sleep(random.uniform(1, 3))。控制整体并发别用多线程或者多进程同时开太多 Session。实际项目中如果并发量超过 5我就建议改用 IMAP 协议因为 IMAP 一次连接可以连续处理大批邮件对服务端更友好。请求到达一定次数后强制休息 30 秒到 1 分钟让限流窗口过去。一定要设置重试机制遇到 429 时等待一段时间后重试不要无限重试。import requests import time def get_with_retry(session, url, max_retries3): for i in range(max_retries): resp session.get(url, timeout10) if resp.status_code 429: wait 2 ** i print(f收到 429等待 {wait} 秒后重试) time.sleep(wait) continue return resp raise RuntimeError(重试多次依然被限流)这种指数退避的策略非常管用既简单又有效。实际跑的时候建议在日志里记录每次请求的状态码和耗时方便事后分析。6.2 登录失败、验证码弹窗真实场景下的处理姿势登录失败是 163 邮箱脚本最常见的痛点。如果你用 requests 模拟登录提示密码错误先检查是不是加密环节出了问题。最简单验证方式抓取网页版登录成功后产生的 Cookie直接复用绕开加密逻辑而不是死磕 JS 逆向。如果登录时弹出了滑块验证码千万不要想着完全自动化识别。滑块识别成本高、容易被风控而且对普通脚本来说根本没有必要。我建议的方案是程序负责把浏览器窗口弹出来人手动拖一下滑块然后脚本继续跑。这种方式既稳定又不会被封号。如果是 selenium 场景登录成功后注意等待页面跳转完成不要立刻去点其他元素。163 邮箱登录成功后会有一个短暂的过渡页可能还会弹出“设置密保/绑定手机”之类的引导。如果你的脚本执行太快很容易点到不该点的东西。6.3 元素定位不到、Cookie 失效、邮件变 base64 的排查清单元素定位不到第一先看页面是否加载完用显式等待代替 sleep第二看元素是否在 iframe 里需要先 switch_to.frame第三看是否为隐藏元素可能需要先点击某个父元素触发显示。Cookie 失效Cookie 通常有几个小时到几天的有效期取决于你抓取的接口。如果脚本突然报未登录重新手动登录一次并更新 Cookie 即可。我习惯把 Cookie 保存到本地 JSON 文件每天开始运行前检查是否过期。邮件正文显示成 base64邮件正文可能使用了 base64 编码传输。用 email 库解析时需要判断 payload 是否为 base64然后进行解码。判断方法是在头部查看 Content-Transfer-Encoding 字段。IMAP 场景下处理这个比较简单因为 email 库自带 decode 逻辑只要你用 email.message_from_bytes 解析就能自动处理大部分情况。还有一个我在实战中发现的规律爬 163 邮箱网页版时尽量选择内部接口而不是解析整张 HTML 页面。内部接口返回的数据结构虽然初期需要摸索但一旦找到稳定性远超脆弱的 DOM 解析。最后再说点实在的我这个项目实际落地时最终选型是 IMAP 少量 requests。IMAP 负责邮件列表、正文、附件的拉取requests 只用来处理网页端特有的操作比如某些设置页的修改。selenium 只是前期确认页面结构时用过一次后来就再也没有出现在正式脚本里。如果你在多个方案之间纠结我的建议很简单先考虑邮件协议再考虑网页接口最后才考虑浏览器自动化。这样不仅能省力还能让你的脚本活得更久。另外一个小技巧无论你用哪种方案请务必加日志和异常收集。邮件项目最容易出问题的地方是单个邮件解析失败导致整个任务中断。我在写 imaplib 脚本时会对每一封邮件的解析做 try-except失败时把邮件 ID 记录下来继续下一封最后统一查看失败列表。这个习惯让我少熬了很多夜推荐给你。