微信图片防撤回

了解需求

实际生活中,由于猎奇朋友撤回的微信图片信息,但直接去要又怎会是我的性格呢。由此萌生出做一个微信防撤回程序(已向朋友说明)。

当时网络上其实存在一些微信防撤回程序,不过担心不正规软件存在漏洞,泄漏个人信息,这里也就不考虑此种办法。

解决方案

思路

由于当时微信不支持微信网页版登陆,因而运用itchat的办法不再适用。

后来了解到电脑端微信图片会先存储在本地,撤回后图片再从本地删去,因而只要在撤回前将微信本地图片转移到新文件夹即可。

在此运用Python的watchdog包来监视文件体系事情,例如文件被创立、修改、删去、移动,我们只需监听创立文件事情即可。

装置watchdog包:    pip install watchdog
我的python环境为python3.9版别

完成

1.首先进行文件创立事情监听,在监听事情发生后的事情处理目标为仿制微信图片到新文件夹。详细代码如下。

需要注意的是微信在2022.05前,图片存储在images目录下;在2022.05后,图片存储在MsgAttach目录下,并按微信目标分别进行存储。

# 第一步:加载途径,并实时读取JPG信息
import os
import shutil
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
def mycopyfile(srcfile,dst_dir):
    if not os.path.isfile(srcfile):
        print ("%s not exist!"%(srcfile))
    else:
        fpath,fname=os.path.split(srcfile)             # 分离文件名和途径
        if fname.endswith('.jpg') or fname.endswith('.png') or fname.endswith('.dat'):
            dst_path = os.path.join(dst_dir, fname)
            shutil.copy(srcfile, dst_path)          # 仿制文件
class MyEventHandler(FileSystemEventHandler):
    # 文件移动
    # def on_moved(self, event):
    #     print("文件移动触发")
    #     print(event)
    def on_created(self, event):
        # print("文件创立触发")
        print(event)
        mycopyfile(event.src_path, dst_dir)
    # def on_deleted(self, event):
    #     print("文件删去触发")
    #     print(event)
    #
    # def on_modified(self, event):
    #     print("文件修改触发")
    #     print(event)
if __name__ == '__main__':
    dst_dir = r"E:\03微信防撤回\weixin"  #TODO:修改为自己的保存文件目录
    if not os.path.exists(dst_dir):
        os.makedirs(dst_dir)  
    observer = Observer()  # 创立观察者目标
    file_handler = MyEventHandler()  # 创立事情处理目标
    listen_dir = r"C:\Users\hc\Documents\WeChat"  #TODO:修改为自己的监听目录
    observer.schedule(file_handler, listen_dir, True)  # 向观察者目标绑定事情和目录
    observer.start() # 发动
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()

2.由于微信保存文件以.dat格局保存,因而需要对微信文件格局进行解码,详细解码代码如下。

# weixin_Image.dat 破解
# JPG 16进制 FF D8 FF
# PNG 16进制 89 50 4e 47
# GIF 16进制 47 49 46 38
# 微信.bat 16进制 a1 86----->jpg  ab 8c----jpg     dd 04 --->png
# 自动核算异或 值
import os
into_path = r'E:\03微信防撤回\weixin'  # 微信image文件途径
out_path = r'E:\03微信防撤回\image'
def main(into_path, out_path):
    dat_list = Dat_files(into_path)  # 把途径文件夹下的dat文件以列表呈现
    lens = len(dat_list)
    if lens == 0:
        print('没有dat文件')
        exit()
    num = 0
    for dat_file in dat_list:  # 逐步读取文件
        num += 1
        temp_path = into_path + '/' + dat_file  # 拼接途径:微信图片途径+图片名
        dat_file_name = dat_file[:-4]  # 截取字符串 去掉.dat
        imageDecode(temp_path, dat_file_name, out_path)  # 转码函数
        value = int((num / lens) * 100)             # 显示进度
        print('正在处理--->{}%'.format(value))
def Dat_files(file_dir):
    """
    :param file_dir: 寻觅文件夹下的dat文件
    :return: 回来文件夹下dat文件的列表
    """
    dat = []
    for files in os.listdir(file_dir):
        if os.path.splitext(files)[1] == '.dat':
            dat.append(files)
    return dat
def imageDecode(temp_path, dat_file_name, out_path):
    dat_read = open(temp_path, "rb")  # 读取.bat 文件
    xo, j = Format(temp_path)  # 判别图片格局 并核算回来异或值 函数
    if j == 1:
        mat = '.png'
    elif j == 2:
        mat = '.gif'
    else:
        mat = '.jpg'
    out = out_path + '/' + dat_file_name + mat  # 图片输出途径
    png_write = open(out, "wb")  # 图片写入
    dat_read.seek(0)  # 重置文件指针位置
    for now in dat_read:  # 循环字节
        for nowByte in now:
            newByte = nowByte ^ xo  # 转码核算
            png_write.write(bytes([newByte]))  # 转码后从头写入
def Format(f):
    """
    核算异或值
    各图片头部信息
    png:89 50 4e 47
    gif: 47 49 46 38
    jpeg:ff d8 ff
    """
    dat_r = open(f, "rb")
    try:
        a = [(0x89, 0x50, 0x4e), (0x47, 0x49, 0x46), (0xff, 0xd8, 0xff)]
        for now in dat_r:
            j = 0
            for xor in a:
                j = j + 1  # 记载是第几个格局 1:png 2:gif 3:jpeg
                i = 0
                res = []
                now2 = now[:3]      # 取前三组判别
                for nowByte in now2:
                    res.append(nowByte ^ xor[i])
                    i += 1
                if res[0] == res[1] == res[2]:
                    return res[0], j
    except:
        pass
    finally:
        dat_r.close()
# 运转
if __name__ == '__main__':
    main(into_path, out_path)