Python哈希炼丹术连夜“去重“破咒,老板“雷影“附体凌晨甩来1000张销售表:明早我要看汇总!财务喵总监惊呆!(附源码|截图|可白嫖)

🔥兄弟姐妹们,老板这套
雷影
“闪电五连鞭”是压根不想停啊!本蜀黎就算野生药材药性再猛,也顶不住这种连续暴击!

💥一、 这次直接放大招——要把办公文档「常用格式」一网打尽!(附源码 | 截图 | 可白嫖)

涵盖格式:
📕 PDF文档
📘 Word文档(.doc / .docx / .rtf / .odt)
📗 Excel文档(.xls / .xlsx / .csv / .ods)
📙 PowerPoint文档(.ppt / .pptx / .odp)
📄 文本文件(.txt)
🗂️ Project文件(.mpp)
🌐 OpenOffice系列(.odt / .ods / .odp)

🚨 重点升级:
和上次图片哈希验证不同,这次咱们玩点硬的——
✅ 不仅比文件名、文件大小
✅ 还要深入文件内容,精准比对!

让你再也别想用“最终版2”、“真的最终版”
多重影分身之术
这种骚操作糊弄本蜀黎!

—————————————-

🧙 二、故事开始

🚀“兄弟姐妹们,顶不住了啊!老板这‘闪电五连鞭’是他喵的
‘雷影’
亲传的吧?一鞭比一鞭狠啊!”
“本蜀黎这株‘野生药材’都快被榨成药渣了!”🍒

第一鞭:人参发票验真,FileNotFound咒!(我忍)”😂“第二鞭:100G老板旅游自拍照,中文乱码咒!(我再忍)”😂😂“第三鞭:业务部狂甩上千份销售表,财务喵头发已薅秃!(我……)”😂😂😂“第四鞭:老板:‘今晚整合好,明天晨会我要看全国汇总!’(我****)”😂😂😂😂

💨“我打开文件夹一看:销售表(最终版).xlsx、销售表(最终版2).xlsx、销售表(真的最终版).xlsx…📈”

“好家伙!这哪是销售数据,这TM是
‘多重影分身之术’
!全是替身!”💥💥

“业务员搁这儿玩‘替身文学’呢?改个名就敢交差?老板的钱是大风刮来的吗?!”🎨🎨

“🧙本蜀黎CTO今天就要开‘写轮眼’,给你来个‘哈希照妖镜’,让这些妖魔鬼怪统统现出原形!”

—————————————-

⚙️ 三、核心内容设计(中医+编程比喻)

「用哈希算法(MD5/SHA1)精准比对文件内容,避免误删」🚀
技术步骤 中医比喻 编程实现(你的代码)
1. 多线程扫描文件 “望闻问切”四诊合参
ThreadPoolExecutor
多线程快速扫描目录
2. 计算文件哈希 “药材性状鉴别”
get_file_hash()
函数,兼容元数据和内容哈希两种模式
3. 分组重复文件 “君臣佐使”分组配伍
defaultdict
分组,相同哈希值为一组
4. 智能删除/保留 “扶正祛邪”
keep_oldest
/
keep_newest
策略,自动祛除冗余
5. 生成HTML报告 “开出药方”
generate_html_report()
生成可视化报告,一目了然

🏆设计说明:

中医理论映射:⏬

望闻问切 → 多线程扫描(全面检测文件状态)✅药材性状鉴别 → 哈希计算(精准识别文件本质)⭕君臣佐使 → 分组逻辑(科学分类重复项)🍀扶正祛邪 → 清理策略(平衡保留与删除)🍗🍗开出药方 → 报告生成(清晰呈现处理方案)🌿🌿

编程实现亮点:⏬

使用
ThreadPoolExecutor
实现高效并行扫描✅双模式哈希计算(兼顾性能与准确性)🌼
defaultdict
自动归类重复文件🔮🔮智能策略选择(时间戳判断保留最优版本)🚀🚀可视化报告(HTML格式直观展示结果)📊📊

—————————————-

🔔安全警告(醒目强调版):

⚠️ 操作前必读(防翻车指南):
1️⃣ 备份原文件:

📦 运行脚本前,务必先备份原始文件!💥 防止误删珍贵素材和文件,数据无价,删错本蜀黎不赔!

2️⃣ 路径输入格式:

🗂️ 支持绝对路径(如C:Users雷影老板的销售明细表)或相对路径(如./雷影老板的销售明细表)🔍 示例:直接粘贴文件夹路径,不用加引号!

3️⃣ 模式选择提示:

🔄 脚本启动后会问删除策略:输入 keep_oldest → 保留最旧文件(默认)输入 keep_newest → 保留最新文件输入 manual → 手动选择保留(逐个确认)

4️⃣ 确认环节:

👀 生成HTML报告后会自动弹出预览!✅ 仔细核对重复组,确认无误再删!💯重要数据一定要人工干预检查!

🚀示例运行流程:


请输入要扫描的目录路径: D:雷影老板的绝对不能丢的销售明细表终极版最终版 
请选择删除策略(keep_oldest/keep_newest/manual): manual  

⚡ 开始扫描 D:D:雷影老板的绝对不能丢的销售明细表终极版最终版...  
🔍 找到 1588 个图片文件  
🎯 发现 42 组重复文件  
📊 可视化报告已生成:D:雷影老板的绝对不能丢的销售明细表终极版最终版重复文件报告.html  

是否查看报告后再删除?(y/n) y  
(报告自动打开,请核对缩略图!)  
确认执行删除操作?(y/n) y  
🗑️ 已删除:D:雷影老板的绝对不能丢的销售明细表终极版最终版最终版(1).xlsx (4.2 MB)  
🗑️ 已删除:D:雷影老板的绝对不能丢的销售明细表终极版最终版最终版(2).xlsx (3.8 MB)  
✅ 清理完成!共删除 86 个文件,释放 1.2 GB 空间  
🚀 四、过程和源码演示⏬

接下来先拿老板上上回买人参PDF发票验证,好家伙搞那么多版本,我瞅瞅:🧿🧿人参(普通版),人参(老年参泡酒版),人参(生晒版),各种炮制版大规格版💞结果都是同一个重复文件老板搞晕头了😂😂
图片[1] - Python哈希炼丹术连夜“去重“破咒,老板“雷影“附体凌晨甩来1000张销售表:明早我要看汇总!财务喵总监惊呆!(附源码|截图|可白嫖) - 宋马
—————————————-

老板甩来销售表,为了执行结果直观,这里选100个excel文件演示📈📈

图片[2] - Python哈希炼丹术连夜“去重“破咒,老板“雷影“附体凌晨甩来1000张销售表:明早我要看汇总!财务喵总监惊呆!(附源码|截图|可白嫖) - 宋马
图片[3] - Python哈希炼丹术连夜“去重“破咒,老板“雷影“附体凌晨甩来1000张销售表:明早我要看汇总!财务喵总监惊呆!(附源码|截图|可白嫖) - 宋马
————————–

“🎯疗效展示:

咒前: 😹财务喵熬夜手动对比,眼花缭乱,哭诉发际线不保。

咒后: 👼Python一键运行,3分钟生成带可视化报告的HTML,自动去重合并。财务喵惊呼:『你这华佗转世来做CTO了吧?!这效率,我财务总监的位置让给你算了!』🚀”

以下是源码✅✅⏬

import os
import hashlib
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor
from collections import defaultdict
import time
import zipfile
import olefile

# 配置区
OFFICE_EXTENSIONS = {
    '.pdf',  # PDF文档
    '.doc', '.docx',  # Word文档
    '.xls', '.xlsx', '.csv',  # Excel文档
    '.ppt', '.pptx',  # PowerPoint文档
    '.odt', '.ods', '.odp',  # OpenOffice文档
    '.rtf', '.txt',  # 文本文件
    '.mpp'  # Project文件
}

THREADS = os.cpu_count() * 2
DELETE_STRATEGY = "keep_oldest"  # 可选: keep_oldest / keep_newest / manual
CONTENT_HASH = True  # 是否比较文件内容(True)或只比较元数据(False)


def get_office_metadata(file_path):
    """提取办公文件的元数据"""
    metadata = {
        'size': os.path.getsize(file_path),
        'mtime': os.path.getmtime(file_path),
        'ext': Path(file_path).suffix.lower()
    }

    try:
        if metadata['ext'] in ('.doc', '.xls', '.ppt'):
            with olefile.OleFileIO(file_path) as ole:
                metadata['ole_created'] = ole.root.getctime()
                metadata['ole_modified'] = ole.root.getmtime()

        elif metadata['ext'] in ('.docx', '.xlsx', '.pptx'):
            with zipfile.ZipFile(file_path) as z:
                core_props = [name for name in z.namelist() if 'core.xml' in name]
                if core_props:
                    with z.open(core_props[0]) as f:
                        content = f.read().decode('utf-8', errors='ignore')
                        if 'dcterms:created' in content:
                            metadata['created'] = content.split('dcterms:created>')[1].split('<')[0]
                        if 'dcterms:modified' in content:
                            metadata['modified'] = content.split('dcterms:modified>')[1].split('<')[0]
    except Exception as e:
        pass

    return metadata


def get_file_hash(file_path, chunk_size=8192):
    """计算文件的哈希值"""
    if not CONTENT_HASH:
        # 快速模式:只比较元数据
        metadata = get_office_metadata(file_path)
        hasher = hashlib.md5()
        hasher.update(str(metadata['size']).encode('utf-8'))
        hasher.update(str(metadata['mtime']).encode('utf-8'))
        if 'ole_modified' in metadata:
            hasher.update(str(metadata['ole_modified']).encode('utf-8'))
        return hasher.hexdigest()

    # 完整内容哈希模式
    hasher = hashlib.md5()
    file_size = os.path.getsize(file_path)
    hasher.update(str(file_size).encode('utf-8'))

    # 特殊处理压缩格式的办公文档
    ext = Path(file_path).suffix.lower()
    if ext in ('.docx', '.xlsx', '.pptx'):
        try:
            with zipfile.ZipFile(file_path) as z:
                # 按名称排序文件以确保一致性
                for name in sorted(z.namelist()):
                    with z.open(name) as f:
                        while chunk := f.read(chunk_size):
                            hasher.update(chunk)
            return hasher.hexdigest()
        except:
            pass  # 失败则回退到普通哈希

    # 普通文件哈希
    with open(file_path, 'rb') as f:
        while chunk := f.read(chunk_size):
            hasher.update(chunk)
    return hasher.hexdigest()


def scan_files(root_dir):
    """递归扫描所有办公文件"""
    for dirpath, _, filenames in os.walk(root_dir):
        for f in filenames:
            if Path(f).suffix.lower() in OFFICE_EXTENSIONS:
                yield Path(dirpath) / f


def find_duplicates(files):
    """多线程比对文件"""
    size_groups = defaultdict(list)
    for file in files:
        size_groups[os.path.getsize(file)].append(file)

    duplicates = defaultdict(list)
    with ThreadPoolExecutor(max_workers=THREADS) as executor:
        for size, group in size_groups.items():
            if len(group) > 1:
                hash_map = {}
                for file, file_hash in zip(group, executor.map(get_file_hash, group)):
                    hash_map.setdefault(file_hash, []).append(file)

                for files in hash_map.values():
                    if len(files) > 1:
                        # 按修改时间排序
                        files.sort(key=lambda x: os.path.getmtime(x))
                        duplicates[files[0]] = files[1:]

    return duplicates


def delete_duplicates(duplicates):
    """根据策略删除重复文件"""
    deleted_count = 0
    total_size = 0

    for orig, copies in duplicates.items():
        if DELETE_STRATEGY == "manual":
            print(f"
🔍 原始文件: {orig}")
            for i, copy in enumerate(copies, 1):
                print(f"  {i}. {copy}")

            while True:
                choice = input("输入要保留的文件编号(0=全删,回车=跳过): ").strip()
                if choice == "":
                    break
                try:
                    choice = int(choice)
                    if 0 <= choice <= len(copies):
                        to_keep = [] if choice == 0 else [copies[choice - 1]]
                        break
                except ValueError:
                    print("请输入有效数字!")
        else:
            # 自动选择保留最早或最新的文件
            to_keep = [orig] if DELETE_STRATEGY == "keep_oldest" else [copies[-1]]

        # 执行删除
        for copy in copies:
            if copy not in to_keep:
                try:
                    file_size = os.path.getsize(copy)
                    os.remove(copy)
                    print(f"🗑️ 已删除: {copy} ({file_size / 1024:.1f} KB)")
                    deleted_count += 1
                    total_size += file_size
                except Exception as e:
                    print(f"❌ 删除失败 {copy}: {e}")

    return deleted_count, total_size


def generate_html_report(duplicates, report_file):
    """生成HTML报告"""
    html = f"""<html><head><style>
        <meta charset="UTF-8">  
        body {{ font-family: Arial; margin: 20px; }}
        .group {{ border: 1px solid #ddd; margin: 15px 0; padding: 15px; border-radius: 5px; }}
        .file-info {{ color: #666; font-size: 0.9em; margin-left: 10px; }}
        h1 {{ color: #333; border-bottom: 2px solid #eee; padding-bottom: 10px; }}
        .icon {{ font-size: 1.2em; margin-right: 5px; }}
        .pdf {{ color: #e74c3c; }}
        .word {{ color: #2b579a; }}
        .excel {{ color: #217346; }}
        .ppt {{ color: #d24726; }}
        .other {{ color: #7f8c8d; }}
    </style></head><body>
    <h1>📝 办公文档重复文件报告</h1>
    <p>生成时间:{time.strftime("%Y-%m-%d %H:%M:%S")}</p>
    <p>比较模式:{'内容哈希' if CONTENT_HASH else '元数据哈希'}</p>
    """

    def get_file_icon(ext):
        ext = ext.lower()
        if ext == '.pdf': return '<span class="icon pdf">📕</span>'
        if ext in ('.doc', '.docx', '.rtf', '.odt'): return '<span class="icon word">📘</span>'
        if ext in ('.xls', '.xlsx', '.csv', '.ods'): return '<span class="icon excel">📗</span>'
        if ext in ('.ppt', '.pptx', '.odp'): return '<span class="icon ppt">📙</span>'
        return '<span class="icon other">📄</span>'

    for orig, copies in duplicates.items():
        orig_size = os.path.getsize(orig) / 1024
        ext = orig.suffix.lower()
        html += f"""
        <div class="group">
            <h3>{get_file_icon(ext)} 原始文件: {orig.name}</h3>
            <p>路径: {orig} <span class="file-info">({orig_size:.1f} KB | 修改时间: {time.ctime(os.path.getmtime(orig))})</span></p>
            <h4>🚨 重复文件 ({len(copies)}个):</h4>"""

        for copy in copies:
            copy_size = os.path.getsize(copy) / 1024
            copy_ext = copy.suffix.lower()
            html += f"""
            <div>
                {get_file_icon(copy_ext)}
                <span class="file-info">{copy} ({copy_size:.1f} KB | {time.ctime(os.path.getmtime(copy))})</span>
            </div>"""

        html += "</div>"

    with open(report_file, 'w', encoding='utf-8') as f:
        f.write(html + "</body></html>")
    print(f"📊 可视化报告已生成: {report_file}")


def main():
    global DELETE_STRATEGY, CONTENT_HASH

    print("=== 办公文档重复文件清理工具 ===")
    root_dir = input("请输入要扫描的目录路径: ").strip()

    # 策略选择
    print("
请选择删除策略:")
    print("1. 保留最旧的文件 (默认)")
    print("2. 保留最新的文件")
    print("3. 手动选择保留")
    choice = input("请输入选项 (1-3): ").strip()
    if choice == '2':
        DELETE_STRATEGY = "keep_newest"
    elif choice == '3':
        DELETE_STRATEGY = "manual"
    else:
        DELETE_STRATEGY = "keep_oldest"

    # 哈希模式选择
    hash_choice = input(
        "
比较模式:
1. 完整内容比较 (精确但慢)
2. 元数据比较 (快速但可能有误判)
选择 (1/2): ").strip()
    CONTENT_HASH = (hash_choice != '2')

    print(f"
⚡ 开始扫描 {root_dir}...")
    start_time = time.time()
    all_files = list(scan_files(root_dir))
    print(f"🔍 找到 {len(all_files)} 个办公文档")

    duplicates = find_duplicates(all_files)
    elapsed = time.time() - start_time

    print(f"
🎯 发现 {len(duplicates)} 组重复文件")
    print("⏱️ 扫描耗时: %.2f秒 | 平均 %.1f 文件/秒" % (elapsed, len(all_files) / elapsed))

    if duplicates:
        report_file = Path(root_dir) / "办公文档重复报告.html"
        generate_html_report(duplicates, report_file)

        confirm = input("
是否查看报告后再删除?(y/n) ").lower()
        if confirm == 'y':
            os.startfile(report_file)
            if input("确认执行删除操作?(y/n) ").lower() != 'y':
                print("❌ 已取消删除操作")
                return

        deleted_count, total_size = delete_duplicates(duplicates)
        print(f"
✅ 清理完成!共删除 {deleted_count} 个文件,释放 {total_size / 1024 / 1024:.2f} MB 空间")

        # 删除后再次生成报告
        generate_html_report(duplicates, Path(root_dir) / "办公文档最终删除报告.html")
    else:
        print("
🎉 未发现重复文件,无需清理")


if __name__ == "__main__":
    main()

“🤵老板内心OS: 这员工咋财务、IT、数据分析(老板驾驶舱)全能?!下次干脆让他来当野生副总裁算了!顺便把食堂阿姨的菜谱也优化一下!📊📊”

图片[4] - Python哈希炼丹术连夜“去重“破咒,老板“雷影“附体凌晨甩来1000张销售表:明早我要看汇总!财务喵总监惊呆!(附源码|截图|可白嫖) - 宋马
—————————————-

💡 虎山CTOの职场心法:

真正的高手,不是抱怨需求变态,而是用技术把变态需求做成常规操作💎💎。让老板觉得你无所不能,但又要云淡风轻:『小意思,也就写了几行Python🏅🏅。』”

🌟本蜀黎功德量化报告(走心加料版):

✅ 拯救发际线:100+条
(每避免手动删除1个重复文件=挽救0.01根头发💇‍♀️,按此推算已守护一片黑森林🌳)

✅老肝能量释放:200+小时
(财务圈集体提前下班⏰,陪对象/娃/猫时间++,家庭和谐度直接拉满🏡)

✅拯救职场爱情:N对
(程序猿借代码秀操作撩动财务喵❤️,成就“技术姻缘”佳话——
“那年报销季,TA用Python帮我验票帮我去重…”)

✅欢乐普渡:功德无量
-(各位打工人看完本座故事,欢乐指数++++📈,摸鱼时间笑声溢出屏幕😂,
建议HR纳入员工心理健康福利方案)

🎯暴击式总结:

「本怪蜀黎不一定要三连,只要众生解脱——
愿天下再无加班发票,每个打工人都能准时拥抱夕阳与爱人🌇
(当然,如果顺带救了几个程序猿的单身劫,也算功德+999🧧)」

⚠️ 免责声明(附因果律警告)

本代码已注入中医玄学能量,请谨慎使用:

✅ 允许白嫖,但白嫖不点赞可能导致:
下次面试官恰好问到这个算法键盘自动打出
//这里感谢冷溪虎山老中医
奶茶精准洒在刚写好的代码上 ✅ 允许商用,但商用不注明出处可能触发:
产品上线前夜突然出现递归栈溢出数据库莫名存储君臣佐使字段 ✅ 允许吐槽,但吐槽不带改进建议可能引发:
终生与边界条件相爱相杀,并永远在深夜收到老板的“在吗?”

🚀 现在立即行动:

点赞 → 吸收本篇算法精华+怪蜀黎脑洞思维收藏 → 避免日后求医无门关注 → 接收更多「中医+代码」脑洞评论区留言 → 领取你的专属「算法药方」

📚 往期爆文推荐:

Python工具箱系列上线,VIP轮换解锁,复制粘贴就能用✅✅:

设计狮别用PS切图了!Python像素炼丹术炸平UI流水线——老板的旅游照被我哈希去重后自动生成视频素材(附源码|可白嫖)

财务小姐姐秃力觉醒!别再用Excel手抠发票了!Python暴力解析PDF,文件名金额自动追杀差额(附源码|白嫖救发)

Python抓虫笔记:零宽空格(zwsp)隐形乱码?3分钟学会 揪出所有“文字幽灵”!(附清洗工具实战)

路径“如人体经络?Python/JS/Java/Go四语言“针灸术”——通不了算我输!附源码白嫖|职场生存指南|专治老板“文件找不到”咒术
—————————————————-

💡✨本文采用【开源共享】协议!欢迎转载、洗稿、甚至做成视频!只需保留原作者署名(ERP老兵-冷溪虎山),让我们一起把跨界技术的快乐传递出去!。
让我们一起把快乐和效率带给更多人!,缺爆款素材的兄弟姐妹可以关注私我,保证你用不完的爆款素材🚀🚀

✨碰到 其他卡顿问题| 其他数据抓取”正则”匹配问题? JetBrains 全家桶性能优化 ,点击以下链接👇👇直达其他爆款指南:

1.IDEA 调参高手都在偷学的配置!9GB 堆内存+OpenGL 渲染优化全公开(附注释版 vmoptions)

2.全网 10 万 Python 开发者在找的 vmoptions 配置!PyCharm 性能炸裂的秘密在这

3.WebStorm 调参高手都在用的配置!续集:IDEA/PyCharm 飞升后,前端 IDE 性能炸裂的秘密

4.GoLand 调参高手都在用的配置!续集:WebStorm 飞升后,Go 开发 IDE 性能炸裂的秘密

5.CLion 调参高手都在用的配置!续集:GoLand 飞升后,C/C++ 开发 IDE 性能炸裂的秘密

6.DataGrip 性能狂暴调优!2025 最新 JVM 参数+数据库索引加速配置,实测查询效率飙升

7.正则“|“表达式“?别再死记硬背了:17年非科班老炮 用正则速通秘籍,把你喂到饱!面试必备!(附记忆口诀->映射表)

8.程序员用国际正则征服全球文本!从ASCII到Unicode的玄学调试指南 面试高频!(附四大语言Python/JS/Java/Go支持对比+中医(HIS)映射表)

9.Java反射如中医“望闻问切”?HIS系统开发必备魔法逆向术!(附源码/面试高频/最小原型实战)

10.一群程序员跑去学中医,竟然是为了治好“祖传屎山”版的HIS系统?(附编程术语映射列表)

PS:按顺序看效果更佳!从 Java 到 Python,从 Web 到 C/C++,再到数据库——一套逻辑通吃 JetBrains 全家桶!

转发给团队里还在用默认配置的同事,救救他们的电脑和头发!”

“💡 不用东找西找——你要的「性能调优×数据抓取」爆款攻略,这里全都有!点击↑↑↑快速查漏补缺!”

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容