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实现的简单抽奖系统实例
May 22 Python
基于随机梯度下降的矩阵分解推荐算法(python)
Aug 31 Python
在pycharm上mongodb配置及可视化设置方法
Nov 30 Python
Python简单获取二维数组行列数的方法示例
Dec 21 Python
对python3中, print横向输出的方法详解
Jan 28 Python
对Python中DataFrame选择某列值为XX的行实例详解
Jan 29 Python
Django模型修改及数据迁移实现解析
Aug 01 Python
Python 支持向量机分类器的实现
Jan 15 Python
tensorflow 环境变量设置方式
Feb 06 Python
详解python metaclass(元类)
Aug 13 Python
Python通过字典映射函数实现switch
Nov 06 Python
Python实现疫情地图可视化
Feb 05 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
php模板函数 正则实现代码
2012/10/15 PHP
C# WinForm中实现快捷键自定义设置实例
2015/01/23 PHP
php+ajax注册实时验证功能
2016/07/20 PHP
JavaScript 数组详解
2013/10/10 Javascript
web css实现整站样式互相切换
2013/10/29 Javascript
jquery插件之定时查询待处理任务数量
2014/05/01 Javascript
NodeJS制作爬虫全过程(续)
2014/12/22 NodeJs
js实现人才网站职位选择功能的方法
2015/08/14 Javascript
js数字计算 误差问题的快速解决方法
2017/02/28 Javascript
详解AngularJs HTTP响应拦截器实现登陆、权限校验
2017/04/11 Javascript
各种选择框jQuery的选中方法(实例讲解)
2017/06/27 jQuery
Node.JS段点续传:Nginx配置文件分段下载功能的实现方法
2018/03/12 Javascript
JS隐藏号码中间4位代码实例
2019/04/09 Javascript
微信小程序 SOTER 生物认证DEMO 指纹识别功能
2019/12/13 Javascript
js实现简单贪吃蛇游戏
2020/05/15 Javascript
[01:55]2014DOTA2国际邀请赛快报:国土生病 紧急去医院治疗
2014/07/10 DOTA
[02:42]岂曰无衣,与子同袍!DOTA2致敬每一位守护人
2020/02/17 DOTA
[46:14]完美世界DOTA2联赛PWL S3 Magma vs INK ICE 第一场 12.11
2020/12/16 DOTA
基于scrapy实现的简单蜘蛛采集程序
2015/04/17 Python
Python中的多行注释文档编写风格汇总
2016/06/16 Python
Python3安装Scrapy的方法步骤
2017/11/23 Python
Django Docker容器化部署之Django-Docker本地部署
2019/10/09 Python
python属于解释型语言么
2020/06/15 Python
Python+OpenCV检测灯光亮点的实现方法
2020/11/02 Python
css3和jquery实现的可折叠导航菜单适合放在手机网页的导航菜单
2014/09/02 HTML / CSS
阿根廷票务网站:StubHub阿根廷
2018/04/13 全球购物
美国在线面料商店:Online Fabric Store
2018/07/26 全球购物
茱莉蔻美国官网:Jurlique美国
2020/11/24 全球购物
安全教育心得体会
2013/12/29 职场文书
大学生旷课检讨书
2014/01/22 职场文书
感恩母亲节演讲稿
2014/05/07 职场文书
商业街策划方案
2014/05/31 职场文书
湖南省党的群众路线教育实践活动总结会议新闻稿
2014/10/21 职场文书
关于教师节的广播稿
2015/08/19 职场文书
2016年度基层党建工作公开承诺书
2016/03/25 职场文书
Nginx服务器添加Systemd自定义服务过程解析
2021/03/31 Servers