QQ邮箱“已发送”邮件竟然无法一键清空?看我操作,怎么删除12万+已发送邮件

最近遇到了一个问题,QQ邮箱提示我空间已满,所以我就专门去看看有哪些邮件可以删除,释放点空间。

我直接暴力删除了很多文件夹的邮件,在文件夹管理界面 有“清空”按钮,点一个即可清空。

但是。。。不出意外的话要出意外了

“已发送”中有12w+邮件,但是它居然没有清空选项!!!

产品经理怎么想的?请出来狡辩狡辩。

如果我不知道邮件列表每页展示数量可以修改,使用默认的25条每页,那我将需要删除 120000/25 约等于4800次;

如果我改成每页显示的最大条数100,那么我将删除1200次才能删除完。。。即使不停的点全选、删除也要花费我20分钟以上。

作为程序员的我怎么能被这个打败呢?重复点击的事情交给程序去做吧。

原理

利用python的selenium库可以很方便地实现 查找控件、条件判断、自动点击等操作,所以这里推荐使用python来完成。

基本流程如下:

  1. 利用webdriver打开chrome界面
  2. 在界面中手动进行qq邮箱登录
  3. 切换到已发送界面
  4. 自动化程序开始工作
  5. 等待程序结束即可。

最终效果如下(全自动删除了一千多页邮件):

大概一秒钟不到就删除了一页,至于总共花了多久?我不记得了,hhh, 我也不需要记得。

代码

今天不想太啰嗦,直接上代码,感兴趣地看注释吧

由于该代码主要是用来解放双手,所以看起来可能没那么优雅,望大家见谅,轻喷。

import datetime
import json
import os.path
import time
from selenium.webdriver.support import expected_conditions as EC

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait

chrome_options = Options()
# chrome_options.add_argument("--headless")  # 启用无头模式
chrome_options.add_argument("--disable-gpu")  # 禁用 GPU 硬件加速
chrome_options.add_argument("--no-sandbox")  # 解决沙盒问题
service = Service('/usr/bin/chromedriver')
browser = webdriver.Chrome(options=chrome_options, service=service)
# browser.get('http://baidu.com')

print("start")
try:
    print(datetime.datetime.now())
    # https://mail.qq.com/cgi-bin/frame_html?sid=vIKUzEIdIy73Aztd&r=15a14fa632ba665b73d40ab865d5d901&lang=zh
    browser.get('https://mail.qq.com/cgi-bin/frame_html?sid=vIKUzEIdIy73Aztd&r=15a14fa632ba665b73d40ab865d5d901&lang=zh')
    if os.path.exists('cookies_180.json'):
        # browser.delete_all_cookies()  # 删除所有cookie信息
        with open('cookies_180.json', 'r', encoding='utf-8') as f:
            cookie_list = json.loads(f.read())
            for cookie in cookie_list:
                browser.add_cookie(cookie)
            browser.get('https://mail.qq.com/cgi-bin/frame_html?sid=vIKUzEIdIy73Aztd&r=15a14fa632ba665b73d40ab865d5d901&lang=zh')
            browser.refresh()

    time.sleep(1)

    hasStoreCookie = False
    while True:
        try:
            # 第一步 手动进行qq邮箱登录
            # 第二步 等待并找到类名为 '升级为邮箱会员' 的元素.目的:判断是否已经登录
            element = WebDriverWait(browser, 10).until(
                EC.presence_of_element_located((By.LINK_TEXT, '升级为邮箱会员'))
            )
            print("Element 升级为邮箱会员 found!")
            # 第三步 查找所有 iframe 元素
            iframes = browser.find_elements(By.TAG_NAME, 'iframe')

            # 打印每个 iframe 的信息
            for index, iframe in enumerate(iframes):
                print(f"Iframe {index + 1}:")
                print(f"src: {iframe.get_attribute('src')}")
                print(f"id: {iframe.get_attribute('id')}")
                print(f"name: {iframe.get_attribute('name')}")
                # 切换到当前 iframe,很关键!!!
                browser.switch_to.frame(iframe)

                # 查找元素(例如,查找 class 为 'txt_title' 的元素)
                try:
                    element = browser.find_element(By.CLASS_NAME, 'txt_title')
                    print(f"Element found in Iframe {index + 1}: {element.text}")
                except Exception as e:
                    print(f"Element not found in Iframe {index + 1}. Error: {e}")

                try:
                    # 处于已发送界面
                    selectAll = browser.find_element(By.ID, 'ckb_selectAll')
                    print("click select all")
                    if selectAll.is_selected() is not True:
                        selectAll.click()
                except Exception as e:
                    print(f"Element ckb_selectAll not found in Iframe {index + 1}. Error: {e}")

                try:
                    # 处于已发送界面
                    delete = browser.find_element(By.ID, 'quick_del')
                    print("click delete")
                    delete.click()
                    time.sleep(0.5)
                    # 切换回主文档
                    browser.switch_to.default_content()
                    break
                except Exception as e:
                    print(f"Element quick_del not found in Iframe {index + 1}. Error: {e}")

                try:
                    # 请求太快触发了限制界面,需要返回并睡眠几秒中
                    delete = browser.find_element(By.LINK_TEXT, '您请求的频率太快,请稍后再试')
                    print("click too quickly")
                    deleteBtn = browser.find_element(By.LINK_TEXT, ' 返回上一步 ')
                    print("click too quickly")
                    deleteBtn.click()
                    time.sleep(5)
                    break
                except Exception as e:
                    print(f"Element quick_del not found in Iframe {index + 1}. Error: {e}")
                # 切换回主文档
                browser.switch_to.default_content()

            time.sleep(0.3)
            if hasStoreCookie is False:
                hasStoreCookie = True
                cookies = browser.get_cookies()
                with open('cookies_180.json', 'w') as f:
                    print('save cookies')
                    f.write(json.dumps(cookies))
        except Exception as e:
            print('str Error:', repr(e))
            # 可能是正在登录,找不到元素,稍微等等
            time.sleep(2)
except Exception as e:
    print('str Error:', e)
    print(str(e))
    error_msg = repr(e)
    print('repr Error:')

    if 'NoSuchElementException' in error_msg:
        print('没找到元素')
    else:
        print(repr(e))
finally:
    time.sleep(2)
    print('---------关闭浏览器---------')
    # 关闭窗口
    browser.close()
    # 退出浏览器
    browser.quit()
    print(datetime.datetime.now())

踩过的坑

整个过程并不是一帆风顺的,说说遇到的坑吧

为了减少登录流程,需要保存cookie并恢复cookie

设置cookie之前,必须先加载指定的url。

比如 要设置mail.qq.com对应的cookie,要先加载mail.qq.com相关的域名,是不是有点反直觉?我加载域名之后,你才设置cookie那不晚了吗?

我的做法是:先加载再设置再刷新,这样就能保证后面加载的域名一定是用到了我设置的cookie。

但实际测试发现:在刷新之前以登录的界面就已经显示出来了,可能是我想多了,设置cookie的速度很快,不会影响页面加载。

明明页面存在那个元素,但却一直报 NoSuchElementException

这个坑可厉害了,在网上搜索查看了很多资料都说的是 要等待页面加载完成。。。我都能看到页面并且有些元素已经能查到,当然已经加载完成,排除这个原因。

最后问chatgpt才知道可能是frame/iframe的问题:一个页面加载了其他网页,查找元素时需要切换到对应的frame才可以。详见代码。

chrome界面怎么没看到?

刚开始从网上抄来的模板,稍加修改后运行,发现chrome界面没有出现。原因:

添加了 --headless 参数,注释掉即可。

总结

身为程序员,必须学会利用代码解决一些重复的操作来解放双手,你说对吗?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值