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

news2024/9/20 0:28:21

最近遇到了一个问题,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 参数,注释掉即可。

总结

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2118795.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

南卡、韶音、墨觉:精选三款旗舰骨传导耳机全面对比评测!

在科技日新月异的今天,耳机作为我们日常生活中不可或缺的音频伴侣,正经历着前所未有的变革。特别是骨传导耳机,凭借其独特的声音传导方式和出色的佩戴体验,逐渐成为了运动爱好者和户外探索者的首选。在众多品牌中,南卡…

Pycharm的安装与Conda环境的配置

目录 第一步:下载并安装 PyCharm 社区版 第二步:创建新项目并配置 Python 解释器 第三步:配置 Conda 环境 第四步:验证环境 第五步:测试 PyTorch 第六步:测试基本 PyTorch 代码 第一步:下…

替代区块链

随着比特币的成功,人们逐渐意识到区块链技术的潜力,并随之出现了迅速的发展,各种区块链协议、应用程序和平台相应产生。 需要指出的是,在这种多元的局面下,很多项目迅速失去了它们的吸引力。事实上,有不少项…

深圳MES系统在制造业的应用与发展

深圳MES在制造业的应用与发展呈现以下几个特点: 应用范围广泛:深圳制造业涵盖了电子、通信、汽车、机械等多个领域,MES系统在这些领域的应用非常广泛。不同行业的企业可以根据自身的需求和特点,定制化地应用MES系统来实现生产管理…

测试即服务(TaaS):概念、优势及应用场景!

引言 随着数字化转型的深入发展,软件质量和用户体验变得愈发重要。传统的软件测试方法已经难以满足现代企业对于快速迭代和高质量交付的需求。在此背景下,“测试即服务”(Testing as a Service, TaaS) 模式应运而生,为软件测试带来了新的解决…

基于SpringBoot+Vue+MySQL的足球俱乐部管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 如今社会上各行各业,都喜欢用自己行业的专属软件工作,互联网发展到这个时候,人们已经发现离不开了互联网。新技术的产生,往往能解决一些老技术的弊端问题。因为传统足球俱乐部管理…

Gtest(Google Test)使用

下面Gtest是在arm-linux下运行的 https://download.csdn.net/download/qq_31868891/89729426 一、下载编译 1.下载gtest代码 https://github.com/google/googletest 2.配置编译 vscode安装CMake Tools 将上面下载的gtest代码文件夹拖到vscode里,然后选择对应的…

SAP 凭证的替代传输GGB1

SAP 凭证的替代传输GGB1 之前没有留意过,前人一直是直接改的,搜索了一下是可以这样弄得 1.一般通过OBBH,配置的凭证替代,产生的请求号,从开发机传输不到生产机。只能通过GGB1来传输。在GGB1里面选择要传输的替代 选中…

BookStack在线文档管理系统本地Docker部署与远程访问详细教程

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

LEAN类型系统属性之规范性(Regularity)注解

在 《小结》 中,列出LEAN类型系统所定义的全部规律,下面 关于 LEAN 属性 的一些推论(Lemma)进行注解。主要是其规范性(Regularity),以说明LEAN类型系统是完备构建的(well founded&am…

Java+selenium+chrome+linux/windows实现数据获取

背景:在进行业务数据获取或者自动化测试时,通常会使用模拟chrome方式启动页面,然后获取页面的数据。在本地可以使用windows的chromedriver.exe进行打开chrome页面、点击等操作。在linux 下通常使用无界面无弹窗的方式进行操作。接下来是实现方…

【AI绘画】Midjourney之Lighting详解

博客主页: [小ᶻZ࿆] 本文专栏: AI绘画 | Midjourney 文章目录 💯前言💯为什么要学习光影控制光影控制的作用 💯强化主题hard lighting(硬光 )soft lighting(软光/柔光)测试 &…

宠物浮毛怎么办,用专业工具——希喂、小米、美的宠物空气净化器

前段时间被医生科普,原来猫咪的毛发也分好几种的,我不是最后一个知道的吧...事情的起因是这样的,上次我去朋友家和她的猫咪玩,实在太可爱了所以自己也养了一只猫。一人一猫的幸福生活没过多久,我就发现自己的鼻炎好像复…

如何用AI先行者2.0轻松画出美图?我的亲身体验分享给你看!

越来越多的AI绘画工具开始出现在市场上。AI先行者2.0是一款备受关注的AI绘画软件。本文将为大家详细介绍这款软件的功能特点,并分享一些使用心得。 AI先行者2.0拥有强大的图像处理能力。 它支持多种AI模型,包括Midjourney、Niji、DallE3和Stable Diffu…

【C++】——string类的使用

目录 一.为什么学习string类&#xff1f; 1.1 C语言的字符串 二. 标准库中的string类 2.1 string类(了解) 2.2 string类成员函数 ● string类对象的常见构造 ● string类析构函数 ● 赋值重载 2.3 string的迭代器 <1>正向迭代器 Iterator <2> 反向迭代器…

接口测试工具:Postman详解

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、前言 在前后端分离开发时&#xff0c;后端工作人员完成系统接口开发后&#xff0c;需要与前端人员对接&#xff0c;测试调试接口&#xff0c;验证接口的正确性…

面试笔试 场景题(部分总结)

文章目录 题目--找出一堆随机数中的前 k 大数字PriorityQueue 类PriorityQueue 常用方法 题目--数组中的第 K 个最大元素 题目–找出一堆随机数中的前 k 大数字 找出一堆随机数中的前 k 大数字&#xff0c;找出一堆随机数中的前 k 小数字。都一样 方法&#xff1a;快速排序。…

【springsecurity】使用PasswordEncoder加密用户密码

目录 1. 导入依赖2. 配置 PasswordEncoder3. 使用 PasswordEncoder 加密用户密码4. 使用 PasswordEncoder 验证用户密码 1. 导入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifac…

docker部署NginxProxyManager

1.效果展示 有啥用&#xff1f;&#xff0c; 能把域名代理到 117.xx.xx.xx:3000 服务器上 而不用写一堆的location / { proxy… } 2.步骤 2.1往期docker安装 docker和docker-compose安装脚本-CSDN博客 2.2创建目录 mkdir ~/npm #创建一个目录用来安装此服务 cd ~/npm #…

兴业周报|“一套房子不留”的马斯克 在北京买房了?

稀有房源&#xff1a;标的物位于北京五环内&#xff0c;真正的城市别墅。中间建筑三区“全网无二手”&#xff0c;二手房市场无在售房源。 高性价比&#xff1a;标的物市场价2800万&#xff0c;起拍价1124万&#xff0c;四折上拍&#xff0c;四室两厅南北通透&#xff0c;建面…