无用小程序之——论如何将导出为txt格式的QQ聊天记录进行合并

news2025/2/25 7:40:27

众所周知,QQ的PC端向我们提供了导出聊天记录的功能,并且允许我们导出为可读的文本文档(txt)格式,就像这样:

 然后导出之后就是这样的(不要怪我啥都看不见,这已经是我能提供的最多的信息了doge):

 结合上图以及生活常识我们可以发现,导出的聊天记录存在如下问题:

  1. 昵称、备注存在变动,而系统是不会自动更正这个变动的,如上图所示;
  2. 由于PC端聊天记录与移动端聊天记录是有限交换的,即只互相同步最近的聊天记录,这就导致PC端导出的记录存在大量的缺失;

对于上面所述问题2,想解决那是不可能的,但我们可以想办法缓解,比如将另一方关于此聊天的记录也导出来,合并为一个,于是这里又出现了新的问题:

  1. 两方昵称、备注不一样,得更新为统一的吧;
  2. 两边的聊天记录不能直接复制粘贴,得去重;

为了解决对应的问题,直接上代码(文中涉及的消息块样式在代码后面的图片):

import datetime
import re


with open('chat_history_1.txt', encoding='utf-8') as file_base:
    lines_base = file_base.readlines()
with open('chat_history_2.txt', encoding='utf-8') as file_add:
    lines_add = file_add.readlines()

pattern_ts = "%Y-%m-%d %H:%M:%S"
pattern_re = r"[0-9]{4}(-)[0-9]{2}(-)[0-9]{2}( )[0-9]{1,2}(:)[0-9]{2}(:)[0-9]{2}"
pattern_re_2 = \
    r"[0-9]{4}(-)[0-9]{2}(-)[0-9]{2}( )[0-9]{1,2}(:)[0-9]{2}(:)[0-9]{2}( )(备注1|备注2|备注3)"  # 这个地方备注或昵称就是聊天记录里面显示的其中一方的昵称(包括两个聊天记录里面所有涉及到的其中一方的昵称或备注)
pattern_re_3 = r"[0-9]{4}(-)[0-9]{2}(-)[0-9]{2}( )[0-9]{1,2}(:)[0-9]{2}(:)[0-9]{2}( )(备注1|备注2|备注3)"  # 这个地方备注或昵称就是聊天记录里面显示的另一方的昵称(包括两个聊天记录里面所有涉及到的另一方的昵称或备注)


list_stamp = []
for line_base in lines_base:
    result = re.match(pattern_re, line_base)  # 这里是读取chat_history_1的消息发送的时间轴(为了下一步合并去重做准备)
    if result:
        result = result.group()
        timestamp = datetime.datetime.strptime(result, pattern_ts).timestamp()  # 转换为时间戳
        list_stamp.append(timestamp)  # 添加入时间轴列表
    else:
        list_stamp.append(0.0)  # 这个我也不知道是啥了,反正有用,不知道有啥用,估计就是占位?我也不确定,自己看着办吧

for index_add in range(len(lines_add)):  #外层逐行循环chat_history_2里面的信息(索引)
    print(index_add)  # 看看循环到哪一个了
    result = re.match(pattern_re, lines_add[index_add])  # 还是格式化时间
    sign = 0  # 标签,用于标记这个是否是一个重复的信息(从而确定是否要转移该条消息)
    if result:  # 如果该行有格式化时间,就肯定是(极大概率是,毕竟应该不会有人给别人发消息的时候发格式化时间吧)一个消息的开头
        sign = 1
        result = result.group()
        timestamp = datetime.datetime.strptime(result, pattern_ts).timestamp()  # 转时间戳
        for index_base in range(len(list_stamp)):  # 开始对比时间轴进行插值
            if timestamp < list_stamp[index_base]:
                sign = 2
                counter = 0
                index_current = index_add
                while True:  # 检查这部分消息块(信息块结构见下图)总共占用了几行
                    index_current += 1
                    try:
                        if not re.match(pattern_re, lines_add[index_current]):
                            counter += 1
                        else:
                            break
                    except IndexError:
                        break
                list_stamp.insert(index_base, timestamp)
                lines_base.insert(index_base, lines_add[index_add])  # 插入首行信息,即包含格式化时间等的那一行,同步更新时间戳和内容
                index_base += 1
                index_add += 1
                for i in range(counter):  # 插入本信息块(信息块结构见下图)中的其余信息
                    list_stamp.insert(index_base, 0)
                    lines_base.insert(index_base, lines_add[index_add])
                    index_base += 1
                    index_add += 1
                break
            elif timestamp == list_stamp[index_base]:  # 如果出现时间戳对上了,那就说明消息重复了,不需要合并过来
                sign = 2
                break
            else:
                continue
    if sign == 1:  # 为1代表时间戳直接干到底了,也就是时间戳超出了时间轴的范围,到达了最末端,说明chat_history_2里有比chat_history_1里最后一条记录还要晚的记录,这时候就不用插值了,一个个往里写就行了,下面的追加操作就和之前的插值理论上没啥区别,只不过变成了append
        counter = 0
        index_current = index_add
        while True:
            index_current += 1
            print(index_current)
            try:
                if not re.match(pattern_re, lines_add[index_current]):
                    counter += 1
                else:
                    break
            except IndexError:
                break
        lines_base.append(lines_add[index_add])
        index_add += 1
        for i in range(counter):
            lines_base.append(lines_add[index_add])
            index_add += 1

for index in range(len(lines_base)):  # 这个是在所有信息都合并完之后,重新统一所有乱七八糟的昵称和内容
    result1 = re.match(pattern_re_2, lines_base[index])
    result2 = re.match(pattern_re_3, lines_base[index])
    if result1:
        result1 = result1.group()
        result1 = re.match(pattern_re, result1).group()
        result1 += " 统一后一方的昵称1\n"  # 和前面的正则表达式对起来哈,对错了就悲剧了
        lines_base[index] = result1
    elif result2:
        result2 = result2.group()
        result2 = re.match(pattern_re, result2).group()
        result2 += " 统一后另一方的昵称\n"
        lines_base[index] = result2
    else:
        continue

 
with open('chat_history_merged', 'w+', encoding='utf-8') as final:  # 写入最终文件
    final.writelines(lines_base)

(上图为消息块格式,注意,最后的那个换行是不能删掉的)

除此之外,对于文件格式的要求:

文件开头类似:

文件结尾类似:

 

就总之,整个文件就只剩下消息块,全都是消息块,从头到尾全部是完整的消息块(务必都得是完整的,导出来的结果一般都是完整的,把头部去掉就行,头部类似下图)

 哦等等,最后,关于我为什么要整这么个程序……

 就是方便查看,然后又有点强迫症,然后正好考完试了……

四舍五入就是闲的。

不知给这个程序取个什么名字好呢?

 

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

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

相关文章

MFC 硬件序列号

获取cpu序列号函数 uint64_t CpuId() { //获取CPU序列号int cpuInfo[4] { 0 };__cpuid(cpuInfo, 1);uint64_t serialNumber 0;if ((cpuInfo[3] & (1 << 3)) ! 0) {serialNumber static_cast<std::uint64_t>(_getwch()) << 32;}return serialNumber; …

2023年你需要知道的最佳预算Wi-Fi路由器清单

买新路由器?让我们帮助你挑选一些既有很多功能和性能,又经济实惠的产品。 购买Wi-Fi路由器并不一定要倾家荡产,尤其是如果你不需要一个提供数百Mbps速度的路由器。廉价路由器是一个很好的选择,它包含了许多功能,不会对钱包造成影响。 一、2023年在廉价Wi-Fi路由器中寻找…

754. 到达终点数字

754. 到达终点数字 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;参考代码&#xff1a; 原题链接&#xff1a; 754. 到达终点数字 https://leetcode.cn/problems/reach-a-number/description/ 完成情况&#xff1a; 解题思路&#xff1a; 参考代码&#xf…

5个流程图模板网站,帮你轻松绘制专业流程图

在复杂的项目管理和团队协作中&#xff0c;流程图成为了一个必不可少的工具。从零开始创建流程图可能会很耗时&#xff0c;同时也需要一定的技能。使用模板可以让流程图方便制作又保持高颜值&#xff0c;降低制作的成本&#xff0c;一款模板众多、功能强大、具有丰富编辑工具的…

AP6315 DC单节锂电池充电IC 同步2A锂电芯片

概述 是一款面向5V交流适配器的2A锂离子电池充电器。它是采用1.5MHz固定频率的同步降压型转换器&#xff0c;因此具有高达90%以上的充电效率&#xff0c;自身发热量极小。包括完整的充电终止电路、自动再充电和一个达1%的4.2V预设充电电压&#xff0c;内部集成了防反灌保护、输…

2022年30m全国逐年土地覆被数据

1.研究背景 2023年8月,武汉大学杨杰和黄昕教授团队向公众更新发布了CLCD 2022年全国土地覆数据(V1.0.2)。而CLCD 2021年全国土地覆数据(V1.0.1)也是在去年8月向公众更新发布。 中国在过去几十年中经济和人口迅速发展,土地覆盖随之发生巨大变化,因此迫切需要对其进行连续…

第9天----【位运算进阶之----按位取反(~)】(附补码,原码讲解)

今天我们来谈谈按位取反这件事。 简单来说&#xff0c;按位取反就是先将一个数写成其二进制表达形式&#xff0c;然后1变0&#xff0c;0变1。下面就让我们展开深入地讨论吧&#xff01; 文章目录 一、预备知识&#xff1a;1. 原码&#xff1a;定义&#xff1a;优缺点&#xff…

PyCharm下安装配置PySide6开发环境(Qt Designer(打开,编辑)、PyUIC和PyRCC)

一.准备工作 1.安装python和pycharm并配置好环境变量 python安装路径 pycharm安装路径&#xff1a; python系统变量&#xff1a; pycharm环境变量&#xff1a; 注意&#xff1a;正常安装&#xff0c;并勾选ADD PATH一般会自动配好 2.在pycharm创建一个新的python的虚拟环境 …

lEC 61068-2-14_2023环境试验.第2-14部分:试验.试验N:温度变化, 最新版发布

https://download.csdn.net/download/m0_67373485/88251313 lEC 61068-2-14_2023环境试验.第2-14部分:试验.试验N:温度变化 A change of temperature test is intended to determine the effect on the specimen of a changeof temperature or a succession of changes of tem…

postgre 基本操作

给已经创建好的table 添加主键,在postgrep中添加主键&#xff0c;才可以在pgAdmin中修改表中内容 ALTER TABLE user ADD PRIMARY KEY (id); 这个编辑的按钮才会显示&#xff0c;不然就是小锁 给表添加json数据 INSERT INTO POWER (tool,METRICS) VALUES (powerpro,[{"n…

stm32之11.USART串口通信

可以添加上拉电阻&#xff0c;但会增加功耗&#xff0c;传输距离变长 要添加库函数USART 官方参考文档说明书位置 ALT&#xff0b;左键可实现整体删除&#xff08;如下图&#xff09; 输出模式第三种模式AF ---------------------- 源码 远程控制pc端 #include <stm32f4x…

[ACL2023] Exploring Lottery Prompts for Pre-trained Language Models

Exploring Lottery Prompts for Pre-trained Language Models 文章链接 清深的工作&#xff0c;比较有意思的一篇。作者先给出假设&#xff0c;对于分类问题&#xff0c;在有限的语料空间内总能找到一个prompt让这个问题分类正确&#xff0c;作者称之为lottery prompt。为此&…

windows窗口背景色修改方法

windows也不知道什么时候将notepad, word, vs的背景色由白色变成了浅绿色&#xff0c;用了一段时间没去改觉得麻烦&#xff0c;就一直用下去了&#xff0c;今天有时间找了下方法改回了白色。 1. 被动默认浅绿色效果 2. 修改注册表. 保存&#xff0c;重启电脑. 3. 恢复如初.

[LeetCode周赛复盘] 第 111 场双周赛20230819

[LeetCode周赛复盘] 第 111 场双周赛20230819 一、本周周赛总结2824. 统计和小于目标的下标对数目1. 题目描述2. 思路分析3. 代码实现 2825. 循环增长使字符串子序列等于另一个字符串1. 题目描述2. 思路分析3. 代码实现 2826. 将三个组排序1. 题目描述2. 思路分析3. 代码实现 …

element纯前端table分页

<template><div class"boxs"><div class"close" click"closeShow()"><img src"./image/close.png"></div><div class"title">一舟储能峰谷收益统计数据</div><div class"…

计算机安全学习笔记(II):自主访问控制 - DAC

书接上篇博客&#xff0c;自主访问方案是指一个实体可以被授权按其自己的意志使另一个实体能够访问某些资源。DAC的一种通常访问方式是在操作系统或数据库管理系统中运用的访问矩阵(access matrix)。 矩阵中的一维由试图访问资源的被标识的主体组成。这个列表一般由用户或用户…

【核磁共振成像】方格化重建

目录 一、缩放比例二、方格化变换的基础三、重建时间四、方格化核 一、缩放比例 对于笛卡尔K空间直线轨迹数据可直接用FFT重建&#xff0c;而如果K空间轨迹的任何部分都是非均匀取样的 可用DFT直接重建&#xff0c;有时称为共轭相位重建&#xff0c;但此法太慢不实用。把数据再…

js、PHP连接外卖小票机打印机方案(调用佳博、芯烨等)

前言&#xff1a; 目前开发需要用到电脑直接连接外卖小票机打印小票&#xff0c;查阅各种资料&#xff0c;使用 6612345浏览器 终于解决了这个问题。 效果&#xff1a; PHP、js直接连接小票机并且自动出票。 支持的小票机&#xff1a; 目前测试可以的有&#xff1a;电脑A4打印…

【TI毫米波雷达笔记】SOC外设初始化配置及驱动(以IWR6843AOP为例)

【TI毫米波雷达笔记】SOC外设初始化配置及驱动&#xff08;以IWR6843AOP为例&#xff09; 最基本的工程建立好以后 需要给SOC进行初始化配置 SOC_Cfg socCfg; //SOC配置结构体Task_Params taskParams; //任务参数SOC_Handle socHandle;ESM_init(0U); …

网络安全工程师岗位分类-徐庆臣(黑客洗白者)

研发系&#xff1a; 安全研发、安全攻防研究、逆向分析、云计算研究、机器安全 工程系&#xff1a; 安全工程师、安全运维工程师、安全服务工程师、安全技术支持、安全售后、Web渗透测试工程师、Web安全工程师、应用安全审计、移动安全工程师 销售系&#xff1a; 安全销售…