Python 如何实现文件自动去重


Posted in Python onJune 02, 2021

Python 文件自动去重

平日里一来无聊,二来手巧,果然下载了好多无(luan)比(qi)珍(ba)贵(zao)的资料,搞得我小小的硬盘(已经扩到6T了)捉襟见肘,

有次无意间,发现有两个居然长得一毛一样,在房子这么小的情况下,我怎能忍两个一毛一样的东西不要脸皮的躺在我的硬盘里,果断搞掉一个,整理一下,本来想文件名一样的就保留一份,但问题出现了,居然有名字一样,内容却完全不一样的文件,想我背朝黄土面朝天吹着空调吃着西瓜下载下来的东西,删除是不可能的,这辈子都是不可能删除的。可是我也又不能把这数以亿计的文件挨个打开看看里面一样不一样吧,这个工程我大概够我做了好久好久了,有没有办法搞个软件帮帮我呢,答案是肯定的,要不然我也不用在这里写这个博客了(应该是苦逼的一个一个打开比较吧),说正题,Python提供了一个比较文件内容的东西,那就是。。。。。。。。。。哈希算法

MD5消息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。MD5由美国密码学家罗纳德·李维斯特(Ronald Linn Rivest)设计,于1992年公开,用以取代MD4算法。

说了这么长,总结出来就一句,这玩意就是文件的指纹,几乎每个文件是唯一的(碰到重复的,恭喜你,可以去买彩票了),那我们就把这个指纹拿出来,一个一个比对,肯定不能会有漏网的文件,既不会错杀三千,也不使一文件漏网,原理上通了,那么我们就要去搞个代码来帮我完成这个工作,作为最好用的语言,Python就这样被我翻了牌子

# -*- coding:utf-8 -*-
import os
import hashlib
import time
import sys
#搞到文件的MD5
def get_ms5(filename):
    m = hashlib.md5()
    mfile = open(filename , "rb")
    m.update(mfile.read())
    mfile.close()
    md5_value = m.hexdigest()
    return md5_value
#搞到文件的列表
def get_urllist():
    base = ("D:\\lwj\\spider\\pic\\")#这里就是你要清缴的文件们了
    list = os.listdir(base)
    urllist = []
    for i in list:
        url = base + i
        urllist.append(url)
 
    return urllist
#主函数
if __name__ == '__main__':
    md5list = []
    urllist = get_urllist()
    print("test1")
    for a in urllist:
        md5 = get_ms5(a)
        if(md5 in md5list):
            os.remove(a)
            print("重复:%s" % a)
        else:
            md5list.append(md5)
            print("一共%s张照片" % len(md5list))

效果

Python 如何实现文件自动去重Python 如何实现文件自动去重

python3 大文件去重

一、生成待去重数据

每行是固定位数的数字串

import os
from random import randint
#-- from u_工具 import *
print("———— 开始 ————")
#-- 打点()
 
# 用来配置的变量
位数 = 13
行数 = 500 * 10000
 
输出目录 = "./a_输入"
输出文件 = f"{输出目录}/随机数.txt"
 
# 预处理
_00 = "".join(["0" for i in range(位数 - 1)])
_100 = "1" + _00
最小值 = int(_100)
_1000 = _100 + "0"
最大值 = int(_1000)
 
if not os.path.exists(输出目录):
    os.makedirs(输出目录)
#-- 输出文件 = 文件名防重_追加数字(输出文件)
 
# 实际处理
with open(输出文件,"a") as f:
    for i in range(行数):
 
        f.write(f"{randint(最小值, 最大值)}\n")
 
        百分比 = (i+1) / 行数 * 100
        if 百分比 == int(百分比):
            print(f"已完成{int(百分比)}%")
#-- 打点()
#-- print(f"\n总耗时:{计时(0)}")
print("———— 结束 ————")

Python 如何实现文件自动去重Python 如何实现文件自动去重

二、通过set按行去重

1. 按原值比较

(1)读取全部数据

(2)用split来分行

(3)通过set数据结构来去除重复数据

(4)将set的数据写入文件

import os
#-- from u_工具 import *
print("———— 开始 ————")
#-- 打点()
 
# 用来配置的变量
输入目录 = "./a_输入"
输出目录 = "./b_输出"
输出文件 = f"{输出目录}/去重结果.txt"
# 预处理
# 目录不存在就手动建立
if not os.path.exists(输出目录):
    os.makedirs(输出目录)
if not os.path.exists(输入目录):
    os.makedirs(输入目录)
#-- 输出文件 = 文件名防重_追加数字(输出文件)
 
# 获取待去重文件
待去重文件列表 = []
待去重文件列表 = [f"{输入目录}/{i}" for i in os.listdir(输入目录)]
#-- getDeepFilePaths(待去重文件列表,输入目录,"txt")
print(f"\n总共{len(待去重文件列表)}个文件")
 
换行符 = b"\n"
if platform.system().lower() == 'windows':
    换行符 = b"\r\n"
 
# 实际处理
all_lines = []
文件个数 = 0
for 文件 in 待去重文件列表:
    文件个数 += 1
    print(f"\n处理第{文件个数}个文件")
 
    #-- 打点()
    # (1)读全部
    with open(文件, "rb") as f:
        data = f.read()
 
    # (2)split分行
    lines = data.split(换行符)
    all_lines.extend(lines)
    #-- 打点()
    #-- print(f"分行完毕,耗时:{计时()}")
 
# (3)集合去重
all_lines_set = set(all_lines)
all_lines_set.remove(b"")
#-- 打点()
#-- print(f"\n\n去重完毕,耗时:{计时()}")
 
# (4)循环写入
with open(输出文件,"ab") as f_rst:
    for line in all_lines_set:
        f_rst.write(line + 换行符)
#-- 打点()
#-- print(f"\n写入完毕,耗时:{计时()}")
print(f"\n输出文件:{输出文件}")
 
#-- 打点()
#-- print(f"\n\n总耗时:{计时(0)}")
print("———— 结束 ————")

Python 如何实现文件自动去重Python 如何实现文件自动去重

附:

(2)用正则表达式来分行

import re
 
# (2)正则分行 二进制的话要加b, b''' '''
regx = '''[\w\~`\!\@\#\$\%\^\&\*\(\)\_\-\+\=\[\]\{\}\:\;\,\.\/\<\>\?]+'''
lines = re.findall(regx, data)

2. 按md5比较

import hashlib
import os
#-- from u_工具 import *
print("———— 开始 ————")
#-- 打点()
 
# 用来配置的变量
输入目录 = "./a_输入"
输出目录 = "./b_输出"
输出文件 = f"{输出目录}/去重结果.txt"
 
# 预处理
# 目录不存在就手动建立
if not os.path.exists(输出目录):
    os.makedirs(输出目录)
if not os.path.exists(输入目录):
    os.makedirs(输入目录)
#-- 输出文件 = 文件名防重_追加数字(输出文件)
 
# 获取待去重文件
待去重文件列表 = [f"{输入目录}/{i}" for i in os.listdir(输入目录)]
#-- 待去重文件列表 = []
#-- getDeepFilePaths(待去重文件列表,输入目录,"txt")
print(f"\n总共{len(待去重文件列表)}个文件")
 
def gen_md5(data):
    md5 = hashlib.md5()
    if repr(type(data)) == "<class 'str'>":
        data = data.encode('utf-8')
    md5.update(data)
    return md5.hexdigest()
 
# 实际处理
md5集 = set()
with open(输出文件, "a") as f_rst:
    文件个数 = 0
    for 文件 in 待去重文件列表:
        文件个数 += 1
        print(f"\n处理第{文件个数}个文件")
 
        # 计算总行数
        with open(文件, 'rb') as f:
            行数 = 0
            buf_size = 1024 * 1024
            buf = f.read(buf_size)
            while buf:
                行数 += buf.count(b'\n')
                buf = f.read(buf_size)
 
        # 读取、分行、去重、写入
        #-- 打点()
        i = 0
        for line_带换行 in open(文件):
            i += 1
            line = line_带换行.strip()
            md5值 = gen_md5(line)
            if md5值 not in md5集:
                md5集.add(md5值)
                f_rst.write(line_带换行)
 
            百分比 = i / 行数 * 10
            if 百分比 == int(百分比):
                print(f"已完成{int(百分比)*10}%")
                #-- 打点()
                #-- print(f"耗时:{计时()}")
 
print(f"\n输出文件:{输出文件}")
 
#-- 打点()
#-- print(f"\n\n总耗时:{计时(0)}")
print("———— 结束 ————")

Python 如何实现文件自动去重

三、二路归并

import hashlib
import os
import platform
import queue
import shutil
from uuid import uuid1
from u_工具 import *
 
print("———— 开始 ————")
打点()
 
# 1.用来配置的变量
输入目录 = "./a_输入"
输出目录 = "./b_输出"
输出文件 = f"{输出目录}/去重结果.txt"
临时目录 = "./c_临时"
小文件大小 = 50 * 1024 * 1024  # 50M
 
# 2.预处理
# 目录不存在就手动建立
if not os.path.exists(输出目录):
    os.makedirs(输出目录)
if not os.path.exists(输入目录):
    os.makedirs(输入目录)
if not os.path.exists(临时目录):
    os.makedirs(临时目录)
shutil.rmtree(临时目录)
os.makedirs(临时目录)
输出文件 = 文件名防重_追加数字(输出文件)
 
# 获取待去重文件
# 待去重文件列表 = [f"{输入目录}/{i}" for i in os.listdir(输入目录)]
待去重文件列表 = []
getDeepFilePaths(待去重文件列表,输入目录,"txt")
print(f"总共{len(待去重文件列表)}个文件")
 
换行符 = b"\n"
if platform.system().lower() == 'windows':
    换行符 = b"\r\n"
 
# 3.实际处理
 
# (1)分割大文件
打点()
待排序文件列表 = []
待补全数据 = b""
for 文件 in 待去重文件列表:
    with open(文件, 'rb') as f:
        buf = f.read(小文件大小)
        while buf:
            data = buf.split(换行符,1)
            新路径 = f"{临时目录}/无序_{序号(1)}_{uuid1()}.txt"
            with open(新路径, 'ab') as ff:
                ff.write(待补全数据 + data[0])
            待排序文件列表.append(新路径)
            try:
                待补全数据 = data[1]
            except:
                待补全数据 = b""
            buf = f.read(小文件大小)
    新路径 = f"{临时目录}/无序_{序号(1)}_{uuid1()}.txt"
    with open(新路径, 'ab') as ff:
            ff.write(待补全数据 + 换行符)
            待排序文件列表.append(新路径)
    待补全数据 = b""
del buf,data,待补全数据
打点()
print(f"\n分割大文件完成,共耗时:{计时()}")
 
# (2)排序小文件
打点()
序号_重置(1)
待归并文件队列 = queue.Queue()
for 文件 in 待排序文件列表:
    with open(文件, "rb") as f:
        data = f.read()
    data = set(data.split(换行符))
    if b"" in data:
        data.remove(b"")
    if 换行符 in data:
        data.remove(换行符)
    data = sorted(data)
 
    新路径 = f"{临时目录}/有序_{序号(1)}_{uuid1()}.txt"
    with open(新路径, 'ab') as ff:
        for line in data:
            ff.write(line + 换行符)
    待归并文件队列.put(新路径)
    os.remove(文件)
del data
打点()
print(f"\n排序小文件完成,共耗时:{计时()}")
 
# (3)归并小文件
打点("归并前")
序号_重置(1)
个数 = 待归并文件队列.qsize()
归并次数 = 个数 - 1
print(f"\n\n归并共{归并次数}次")
当前次数 = 0
while 个数 > 1:
    当前次数 += 1
    print(f"\n执行第{当前次数}次归并")
    文件路径a = 待归并文件队列.get()
    文件路径b = 待归并文件队列.get()
    新文件路径 = f"{临时目录}/{序号(1)}_{uuid1()}.txt"
    if 当前次数 == 归并次数:
        新文件路径 = 输出文件
    with open(文件路径a,"rb") as 文件a, open(文件路径b,"rb") as 文件b, open(新文件路径,"wb") as ff:
        # region 归并操作
        is_a_over = False
        is_b_over = False
 
        a = 文件a.readline().strip()
        b = 文件b.readline().strip()
        last = None
 
        while not (is_a_over and is_b_over):
 
            if is_a_over:
                b = 文件b.readline()
                if not b:
                    is_b_over = True
                else:
                    ff.write(b)
 
            elif is_b_over:
                a = 文件a.readline()
                if not a:
                    is_a_over = True
                else:
                    ff.write(a)
 
            else:
                # region 处理初始赋值
                if not a:
                    is_a_over = True
                    if not b:
                        is_b_over = True
                        continue
                    else:
                        ff.write(b + 换行符)
                        continue
 
                if not b:
                    is_b_over = True
                    ff.write(a + 换行符)
                    continue
                # endregion
 
                if a <= b:
                    if a == b or a == last:
                        a = 文件a.readline().strip()
                        if not a:
                            is_a_over = True
                            ff.write(b + 换行符)
                        continue
                    else:
                        last = a
                        ff.write(last + 换行符)
                        a = 文件a.readline().strip()
                        if not a:
                            is_a_over = True
                            ff.write(b + 换行符)
                        continue
                else:
                    if b == last:
                        b = 文件b.readline().strip()
                        if not b:
                            is_b_over = True
                            ff.write(a + 换行符)
                        continue
                    else:
                        last = b
                        ff.write(last + 换行符)
                        b = 文件b.readline().strip()
                        if not b:
                            is_b_over = True
                            ff.write(a + 换行符)
                        continue
        # endregion
 
    待归并文件队列.put(新文件路径)
    os.remove(文件路径a)
    os.remove(文件路径b)
    个数 = 待归并文件队列.qsize()
    打点()
    print(f"耗时:{计时()}")
 
打点("归并后")
print(f"\n\n归并小文件完成,共耗时:{计时('归并前','归并后')}")
print(f"\n输出文件:{输出文件}")
 
打点()
print(f"\n\n总耗时:{计时(0)}")
print("———— 结束 ————")

Python 如何实现文件自动去重

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python读取html中指定元素生成excle文件示例
Apr 03 Python
对于Python装饰器使用的一些建议
Jun 03 Python
详解在Python程序中自定义异常的方法
Oct 16 Python
举例讲解Python设计模式编程中对抽象工厂模式的运用
Mar 02 Python
Python获取文件所在目录和文件名的方法
Jan 12 Python
python爬取m3u8连接的视频
Feb 28 Python
python2与python3中关于对NaN类型数据的判断和转换方法
Oct 30 Python
Python简单获取二维数组行列数的方法示例
Dec 21 Python
Python编程深度学习绘图库之matplotlib
Dec 28 Python
Python线程障碍对象Barrier原理详解
Dec 02 Python
Python 实现 T00ls 自动签到脚本代码(邮件+钉钉通知)
Jul 06 Python
Python调用飞书发送消息的示例
Nov 10 Python
python状态机transitions库详解
Jun 02 #Python
python爬取某网站原图作为壁纸
Python爬虫之自动爬取某车之家各车销售数据
从np.random.normal()到正态分布的拟合操作
golang特有程序结构入门教程
Jun 02 #Python
Python中的np.argmin()和np.argmax()函数用法
Jun 02 #Python
python之np.argmax()及对axis=0或者1的理解
You might like
phpmyadmin的#1251问题
2006/11/25 PHP
菜鸟学PHP之Smarty入门
2007/01/04 PHP
PHP的cURL库功能简介 抓取网页、POST数据及其他
2011/04/07 PHP
thinkPHP通用控制器实现方法示例
2017/11/23 PHP
JavaScript 实现类的多种方法实例
2013/05/01 Javascript
深入理解javascript动态插入技术
2013/11/12 Javascript
javascript 兼容各个浏览器的事件
2015/02/04 Javascript
JavaScript数据结构和算法之二叉树详解
2015/02/11 Javascript
JS+CSS实现实用的单击输入框弹出选择框的方法
2015/02/28 Javascript
Javascript中的getUTCDay()方法使用详解
2015/06/10 Javascript
基于代数方程库Algebra.js解二元一次方程功能示例
2017/06/09 Javascript
vue-cli开发时,关于ajax跨域的解决方法(推荐)
2018/02/03 Javascript
如何实现小程序tab栏下划线动画效果
2019/05/18 Javascript
jQuery实现checkbox全选、反选及删除等操作的方法详解
2019/08/02 jQuery
小程序选项卡以及swiper套用(跨页面)
2020/06/19 Javascript
OpenLayers3实现图层控件功能
2020/09/25 Javascript
[01:02:10]DOTA2上海特级锦标赛B组小组赛#2 VG VS Fnatic第一局
2016/02/26 DOTA
Zabbix实现微信报警功能
2016/10/09 Python
独特的python循环语句
2016/11/20 Python
在python中,使用scatter绘制散点图的实例
2019/07/03 Python
Python编写打字训练小程序
2019/09/26 Python
基于python的docx模块处理word和WPS的docx格式文件方式
2020/02/13 Python
Django-xadmin后台导入json数据及后台显示信息图标和主题更改方式
2020/03/11 Python
利用Python优雅的登录校园网
2020/10/21 Python
Python 实现劳拉游戏的实例代码(四连环、重力四子棋)
2021/03/03 Python
html5文本内容_动力节点Java学院整理
2017/07/11 HTML / CSS
简单整理HTML5的基本特性和语法
2016/02/18 HTML / CSS
理工科学生的自我评价
2013/12/15 职场文书
教师绩效工资方案
2014/02/01 职场文书
工作分析计划书
2014/04/30 职场文书
2014年工作总结及2015工作计划
2014/12/12 职场文书
劳模事迹材料范文
2014/12/24 职场文书
导游欢迎词范文
2015/01/23 职场文书
销售经理工作检讨书
2015/02/19 职场文书
《敬重卑微》读后感3篇
2019/11/26 职场文书
JavaScript的Set数据结构详解
2022/02/18 Javascript