发布于 

Python 加 PowerShell 删除指定 QQ 群的图片

前言

不知道你们是不是和我一样,QQ 加了不少的群,基本是加了就不看的。

有一些水群又水得厉害,收进群助手了,但没有屏蔽信息,不知道不觉间,就堆了一堆的图片。

而 QQ 的删除聊天记录,就真的只是删除聊天记录,群里面图片还是会留在聊天记录的文件夹里面。

这就很麻烦了,你又分不清哪个群的图片,把图片全删除了,又有那么几个群是想保留图片的。

刚好,腾讯最近出了个新的 NT 架构的 QQ,我本来期待他能像微信一样按群来删除图片,结果还是不行。

搜索一番,找到两个项目,分别用来解密和解码 QQ 的数据库,然后发现能从数据库的群聊天信息拿到图片路径。

那就好办了,写了几个脚本来实现按群来删除图片。

GitHub 项目地址:

tjxwork/qq_db_export_group_image_path_and_move_or_delete: QQ 数据库导出群图片路径并移动或者删除 (github.com)

视频教程地址:

其实是先有的视频教程(演示),这篇文章算是图文教程,会比视频教程详细一点。

删除指定 QQ 群的图片【tjxwork】_哔哩哔哩_bilibili

删除指定 QQ 群的图片【tjxwork】 - YouTube

建议

如果你是出于:“想要清理不看的 QQ 群的群图片,并且希望能一直保持聊天记录比较 “干净”。” 的目的。

那么,新版的 NTQQ 暂时不建议使用,因为目前只有旧版的 QQ 才能屏蔽接受群图片(看的时候可以手动点击加载)

image-20230722003128049

QQ 的相关信息

QQ 的聊天记录路径

聊天记录的配置文件存放在:C:\Users\Public\Documents\Tencent\QQ\UserDataInfo.ini

同一台电脑下,所有用户使用同一个配置文件。

例如,当聊天记录存放在 D:\Chats\Tencent Files 时,UserDataInfo.ini 的内容为:

1
2
3
[UserDataSet]
UserDataSavePathType=2
UserDataSavePath=D:\Chats\Tencent Files

QQ 配置文件的相关信息可以看之前这篇:免登录,用脚本提前修改微信、企业微信、QQ 的聊天路径 - tjxblog

NT 版本 QQ 暂时无法修改记录路径,它直接沿用了旧版 QQ 的路径设定。

QQ 的图片文件结构

例如,当聊天记录存放在 D:\Chats\Tencent Files,QQ 账号是 303xxx445

1
2
3
4
5
6
7
8
9
10
11
存放所有图片的文件夹
D:\Chats\Tencent Files\303xxx445\Image

存放个人对个人聊天图片的文件夹
D:\Chats\Tencent Files\303xxx445\Image\C2C

存放群聊天图片的文件夹
D:\Chats\Tencent Files\303xxx445\Image\Group
D:\Chats\Tencent Files\303xxx445\Image\Group2

有两个,是不同时期的,里面的结构也不太一样,不知道腾讯怎么搞的屎山代码。

移动脚本要处理的是,聊天记录文件夹的 Image 下面的 Group Group2 两个文件夹

新版 NT 架构 QQ 的相关信息

当你使用首次使用 NTQQ 的时候,会提示导入数据库。

其实就是把旧的 聊天记录文件夹\QQ账号\Msg3.0.db

导入了到了新的 聊天记录文件夹\QQ账号\nt_qq\nt_db\nt_msg.db

这期间会提示优化过程,新的数据库应该是和旧数据库不一样的。

使用新的 NTQQ 的时候,会在原来的聊天记录路径下建立聊天记录路径\QQ账号\nt_qq\ 文件夹

接收到的图片及各类文件都是存放在新的路径下面。

各种数据库:聊天记录路径\QQ账号\nt_qq\nt_db

图片之类的:聊天记录路径\QQ账号\nt_qq\nt_data

图片的存放结构和 Windows 版微信类似,会按年-月份的方式来区分。

但是 NTQQ 目前仍然做不到像微信那样,按群来删除图片之类的文件。

聊天记录路径\QQ账号\nt_qq\nt_data\Pic 的结构:

image-20230722003155704

前置项目及所需工具

解密 QQ 数据库 qq-win-db-key

Young-Lord/qq-win-db-key: Windows QQ 聊天数据库解密 (github.com)

解码 QQ 数据库 qq_msg_decode

saucer-man/qq_msg_decode: 解码 qq 聊天数据库 (github.com)

修复 QQ 数据库 SQLite-Tools

SQLite Download Page

这里用的是 sqlite-tools-win32-x86-3420000

操作流程

为了方便描述,假设下载完上面 2 个项目及 SQLite-Tools 后,都带文件夹解压到和我的脚本文件在同一级,为当前目录,文件结构如下:

image-20230721222244008

我的项目地址:

tjxwork/qq_db_export_group_image_path_and_move_or_delete: QQ 数据库导出群图片路径并移动或者删除 (github.com)

以及:

你已经安装好 Python,并且添加到系统环境变量。(安装时,勾选 PATH 选项)

Python 脚本运行时,提示缺少什么模块的时候,你要学会 pip install xxxxxx

PowerShell 已允许脚本运行 (请管理员权限打开 PowerShell 运行: Set-ExecutionPolicy -ExecutionPolicy RemoteSigned

在资源管理器的目录空白处,按着Shift + 鼠标右键,点击 在此处打开 PowerShell 窗口 就可以在当前目录直接打开 PowerShell

如果有不是很清楚的地方,请搭配视频版演示食用。

解密 QQ 数据库

先去你的聊天记录文件夹下面备份 Msg3.0.db

先打开 QQ,出现登陆窗口,先不要点击登陆。

在当前目录打开 PowerShell,运行解密脚本 \qq-win-db-key-master\main.py

1
2
3
4
PS > python .\qq-win-db-key-master\main.py

# 实际的提示路径是 "PS D:\qq_db_export_group_image_path_and_move_or_delete-main> "
# 为简短显示,全文省略为 "PS >" 下文不再提示

然后点击 QQ 的登陆按钮。

耐心等待登陆,登陆成功后,脚本也随之运行结束。

此时当前目录下出现一个解密完成的 Msg3.0.db_0_xxxxxxxxxx.db 数据库文件。

QQ 可以退出了,后面用不到它了。

修复 QQ 数据库

在当前目录打开 PowerShell,运行 SQLite-Tools

1
PS > .\sqlite-tools-win32-x86-3420000\sqlite3.exe 

使用 SQLite-Tools 打开 Msg3.0.db_0_xxxxxxxxxx.db

1
sqlite> .open Msg3.0.db_0_xxxxxxxxxx.db

检查是否出错

1
sqlite> .selftest

不出错就输入 .quit 退出 。

如提示出错的话,就继续处理,导出为 temp.sql 临时的 SQL 文件。

1
2
3
sqlite> .output temp.sql
sqlite> .dump
sqlite> .quit

运行完成后,当前目录下出现一个 temp.sql 文件。

modify_temp_sql_last_line.py 脚本功能及默认参数:修改 temp.sql 文件的最后一行为 COMMIT;

运行 modify_temp_sql_last_line.py 脚本

1
PS > python .\modify_temp_sql_last_line.py

运行完成,可以看到 temp.sql 文件的修改时间发现变化。

在当前目录打开 PowerShell,运行 SQLite-Tools

创建新数据库 Msg.db 并导入 temp.sql

1
2
3
4
PS > .\sqlite-tools-win32-x86-3420000\sqlite3.exe 
sqlite> .open Msg.db
sqlite> .read temp.sql
sqlite> .quit

等待运行完成后,当前目录下出现一个修复完成的 Msg.db 文件。

解码 QQ 数据库

使用文本编辑器打开 \qq_msg_decode-main\index.py 文件,

在大约 534 行处,修改为你的数据库路径,建议使用绝对路径。

例如:

1
2
3
...
conn = sqlite3.connect(r'D:\qq_db_export_group_image_path_and_move_or_delete-main\Msg.db')
...

在当前目录打开 PowerShell,运行解码脚本 \qq_msg_decode-main\index.py

1
PS > python .\qq_msg_decode-main\index.py

此过程最为漫长,我 10G 左右的 QQ 数据库,跑了 4 小时 20 分钟。

脚本跑完后,Msg.db 的体积会变大,因为会在表里面多加一个字段,用于存放解码完成后的信息。

解码完成后的数据库结构如图:

image-20230721232138527

导出群聊天记录的图片路径为 CSV

regex_processing_img_path_to_csv.py 脚本功能及默认参数:

读取当前目录下的 Msg.db,导出各个群聊天记录中的图片路径为 csv 格式,存放到当前目录下的 QQ_Group_CSV 文件夹下

1
2
3
4
5
6
7
...
# QQ聊天记录数据库的路径
qq_msg3_db_path = "Msg.db"

# QQ聊天记录相关csv的存放路径
csv_folder_path = "QQ_Group_CSV"
...

运行 regex_processing_img_path_to_csv.py 脚本。

会将数据库内的群消息中的图片路径,以群分类,以数据库中的表名为命名,导出为 csv 文件。

1
PS > python .\regex_processing_img_path_to_csv.py

运行完成后,当前目录下出现一个 QQ_Group_CSV 文件夹

其中包含若干数量的,格式类似 group_123456789.csv 的 CSV 文件。

注意:CSV 文件名,其数字部分并不 100% 和 QQ 群的群号对应!

以聊天记录查询对应的群的数据库表名

由于在 QQ 数据库里面存储的群消息的表的名称,并不是绝对和 QQ 群的群号是一致对应的。

image-20230721234721478

再加之,有部分还能在 QQ 消息管理器中查看聊天记录的 QQ 群,已经被封禁,无法查看其群号。

所以需要通过查询来确定,QQ 群与数据库中的表的关系。

query_chat_come_from_qq_group.py 脚本功能及默认参数:

连接到当前目录下的 Msg.db 数据库,使用聊天记录来查询确定其在数据库中对应的表名。

1
2
3
4
...
# QQ聊天记录数据库的路径
qq_msg3_db_path = "Msg.db"
...

运行 query_chat_come_from_qq_group.py 脚本

1
2
3
4
PS > python .\query_chat_come_from_qq_group.py
获取到: 94 个 QQ 群

输入 quit 退出,请输入聊天文本:

复制消息管理器中的文本内容,粘贴到 PowerShell 窗口中查询,复制内容请尽量具有独特性,防止返回内容过多。

查询效果如图:

image-20230721234507753

定义移动文件脚本参数来移动图片

move_csv_img_path.ps1 的脚本功能:

按脚本中定义黑白名单的群列表、运行模式、时间线,来移动对应群 csv 文件中记录的图片,按群来分类,移动到指定的目录下。

move_csv_img_path.ps1 的脚本参数部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
...
# QQ聊天记录路径
$qq_chats_path = "D:\Chats\Tencent Files\303xxx445"

# 存放移动后的QQ群的图片的指定目录,例如:$qq_chats_path\Image_Group_Move_Img
$qq_group_move_img_folder_path = "$qq_chats_path\Image_Group_Move_Img"

# 数据库导出的QQ群的图片路径csv文件夹
$qq_group_csv_folder_path = "C:\Users\xin\Desktop\QQ\QQ_Group_CSV"

# 避免操作此时间线后的图片
$time_line = Get-Date "2023-07-08 12:00:00"

# 黑名单运行模式? $ture:黑名单,$False:白名单
$blacklist_operation_mode = $False

# 注意! QQ群的名字,和数据库里面的群表名,两者的名字不一定是一样的。
# 请配合 query_chat_come_from_qq_group.py 查询聊天记录来确定在数据库的表名,复制到以下对应列表

# qq群 移动图片 黑名单
$qq_group_blacklist = @("group_552xxx835")

# qq群 移动图片 白名单
$qq_group_whitelist = @("group_206xxx7139", "group_777xxx650", "group_609xxx153", "group_806xxx657")
...

请自行修改脚本中的参数为自己的实际路径。

建议移动后的存放目录,设置为聊天记录同分一区下面,能极大地节省移动时间,同分区移动文件只是修改文件系统中的路径指向而已。

move_csv_img_path.ps1 的脚本运行逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 只处理修改时间在时间线之前、聊天记录文件夹的 Image 下面的 Group Group2 这两个文件夹的图片

# 白名单模式效果:
# 保留白名单内的群聊天图片;
# 其他已知的群图片,按群归类,保留文件夹结构移动到别的地方;
# 没有对应csv记录的群图片,移动到 group_unknown 文件夹

# 黑名单模式效果:
# 黑名单内的群,按群归类,保留文件夹结构移动到别的地方;
# 其余所有图片文件保持在原地不动。

# 由于不同QQ群是有可能使用同一张图片,特别是表情包。
# 所以实际的处理流程是:

# 先把 聊天记录文件夹的 Image 下面的 Group Group2 两个文件夹,移动到聊天记录文件夹内的 Image_Group_Temp 临时文件夹内
# 将修改时间在时间线之后的图片文件,移动回原来的位置

# 黑名单分支流程:
# 把 非黑名单 的csv对应的图片 从 Image_Group_Temp 移动回原来的位置
# 把 黑名单 csv对应的图片,从 Image_Group_Temp 移动到指定目录下(例如:Image_Group_Move_Img)对应的群文件夹(group_xxxxxx)
# 然后把剩下的图片再全部移动回原来的位置

# 白名单流程:
# 然后把 白名单 csv对应的图片,从 Image_Group_Temp 移动回原来的位置
# 然后把 非白名单 有csv对应的图片,从 Image_Group_Temp 移动到指定目录下(例如:Image_Group_Move_Img)对应的群文件夹(group_xxxxxx)
# 再剩下的图片,移动到指定目录下的 group_unknown 文件夹

# 每次在移动文件的时候,都会在聊天记录文件夹内的 Image_Group_Temp 下生成每次移动文件的操作日志。
# 日志记录了时间,旧的完整路径,新的完整路径,理由上可以通过读取日志记录来逆转移动操作。

运行 move_csv_img_path.ps1 脚本

1
PS > move_csv_img_path.ps1

返回内容如图:

image-20230722000837947

image-20230722000910891

移动日志中出现大量错误的原因

由于存在表情包之类的复用图片,同一个图片路径,可能会在多个群 CSV 里面反复出现。
从而导致移动脚本读取第 1 个群 CSV 正常移走图片后,移动脚本再读取到后续的群 CSV 文件中再出这条图片路径,
脚本再次移动该图片路径时找不到图片,就会在日志中记录为失败。此部分内容可以看看视频版演示。

image-20230722002046584

效果

我最后清掉了 183G 的图片,最多那个群 35G……

留下的 4 个群只有 3.32G。

Snipaste_2023-07-11_09-55-44

image-20230722002112383

image-20230722002207156


原文作者:tjxwork
原文链接:https://www.tjxblog.com/blog/2023-0009
发布时间:2023-07-22