使用Python创建排序SQLite数据库:邮箱发件次数统计实现问询
完成SQLite邮箱发送次数统计的完整解决方案
嘿,你的代码框架已经搭得差不多了,我来帮你把剩下的逻辑补全,顺便讲清楚关键细节,确保这个邮箱统计功能能正常跑起来~
完整可运行代码
import sqlite3 # 连接到目标SQLite数据库(不存在会自动创建) conn = sqlite3.connect('Counts.sqlite') cur = conn.cursor() # 重建Counts表:先删旧表再新建,给email设主键避免重复记录 cur.execute('DROP TABLE IF EXISTS Counts') cur.execute('''CREATE TABLE Counts (email TEXT PRIMARY KEY, count INTEGER)''') # 获取用户输入的文件名,支持默认值 fname = input('Enter file name: ') if len(fname) < 1: fname = 'mbox.txt' # 可以换成你常用的测试文件名 # 处理文件打开异常,避免程序直接崩溃 try: fh = open(fname) except FileNotFoundError: print(f"哎呀,找不到文件 {fname} 哦,请检查路径是否正确!") quit() # 核心:解析文本并更新数据库计数 for line in fh: # 假设你的文件里,发件邮箱在以"From: "开头的行里(比如标准mbox格式) if not line.startswith('From: '): continue # 拆分行内容提取邮箱地址 email = line.split()[1] # 方案1:先查询再判断是插入还是更新(逻辑直观,适合新手) cur.execute('SELECT count FROM Counts WHERE email = ?', (email,)) existing_count = cur.fetchone() if existing_count is None: cur.execute('INSERT INTO Counts (email, count) VALUES (?, 1)', (email,)) else: cur.execute('UPDATE Counts SET count = count + 1 WHERE email = ?', (email,)) # 方案2:用SQLite的INSERT OR REPLACE简化代码(二选一即可) # cur.execute('''INSERT OR REPLACE INTO Counts (email, count) # VALUES (?, COALESCE((SELECT count FROM Counts WHERE email = ?), 0) + 1)''', # (email, email)) # 一定要提交事务!否则数据不会写入数据库文件 conn.commit() # 可选:查询并打印统计结果,方便验证 print("\n📊 邮箱发送次数统计结果(Top 10):") cur.execute('SELECT email, count FROM Counts ORDER BY count DESC LIMIT 10') for email, count in cur.fetchall(): print(f"{email}: {count} 次") # 关闭资源 cur.close() conn.close()
关键细节说明
- 表结构优化:给
email字段加上PRIMARY KEY,这样每个邮箱只会存一条记录,既避免重复数据,也让后续的更新操作更高效。 - 文本解析适配:代码里默认是处理
From: someone@example.com格式的行,如果你的文本文件是每行直接放一个邮箱,只需要把解析部分改成:for line in fh: email = line.strip() if not email: # 跳过空行 continue # 后面的数据库操作不变 - 数据库操作逻辑:
- 方案1是“先查后改”,逻辑直观,适合新手理解;
- 方案2用
INSERT OR REPLACE合并了查询和更新,代码更简洁,适合追求效率的场景。
- 事务提交:
conn.commit()非常重要!SQLite默认是手动提交事务,如果你不调用这个方法,所有的插入/更新操作都只是在内存里,不会真正写入数据库文件。 - 异常处理:增加了文件不存在的捕获,避免用户输入错误文件名时程序直接崩溃。
额外小提示
- 如果想统计所有邮箱的结果,把查询语句里的
LIMIT 10去掉就行; - 可以给
count字段加个默认值0,不过代码里已经通过逻辑处理了初始计数,所以不是必须的; - 测试的时候可以先用小文件试跑,确认逻辑没问题再用大文件。
内容的提问来源于stack exchange,提问作者mucce
相关产品推荐
相关产品推荐

