本篇文章记录学习:
一、实现功能
1.image文件去重
1)将image文件里有上千张图片,其中大部分图片是内容相同,但是名称不同的文件。
2)去重原则是通过计算每张图片md5,md5值相同,则表示内容相同,则可以删除。
- 以字典方式保存第一张图片得md5值(value)和图片名称(key)
- 以字典方式保存删除图片名称(key)和已存MD5 对应的图片名称(value)
备注:保存删除图片名称得意义:将SVG文件调用删除图片的连接名称修改为第一张图片的名称。。
2.查找其他文件里包含“删除图片”的字符串
- 通过正则表达式,逐一打开所在目录的svg文件,逐行查找,根据正则表达式规则查中找是否有匹配的图片名称的字符串,
- 如果有匹配的图片名称字符串,判断字符串是否在all_svg_jpg字典中
- 如果在,则进行替换,如果不在,则进行源文件内容打印
# coding=UTF-8
import re
import hashlib
import os
import time
import logging
import logging.handlers
LOG_FILE = 'svg_parser.log'
handler = logging.handlers.RotatingFileHandler(LOG_FILE, maxBytes=1024 * 1024, backupCount=5) # 实例化handler
fmt = '%(asctime)s - %(filename)s:%(lineno)s - %(name)s - %(message)s'
formatter = logging.Formatter(fmt) # 实例化formatter
handler.setFormatter(formatter) # 为handler添加formatter
logger = logging.getLogger('svg_parser') # 获取名为tst的logger
logger.addHandler(handler) # 为logger添加handler
logger.setLevel(logging.DEBUG)
def getmd5(filename):
"""
获取文件 md5 码
:param filename: 文件路径
:return: 文件 md5 码
"""
file_txt = open(filename, 'rb').read()
# 调用一个md5对象
m = hashlib.md5(file_txt)
# hexdigest()方法来获取摘要(加密结果)
return m.hexdigest()
def getallkey(path):
"""
1.将image文件夹里数据通过md5 码判断是否是相同内容不同名字的文件,如果是则保留第一次遇到的文件名及md5.
2.将1对多图片(重复的图片名称和需要替换的图片名称)保存在all_svg_jpg字典:
all_svg_jpg的key为将在SVG文件里查找到的图片名称
all_svg_jpg的value将SVG文件里查找到的图片名称替换的新名称
:param path: 程序所在路径,也就是svg所在路径,与image文件夹级别相同
:return: 空
"""
# 文件夹路径
# path = input("path: ")
image_path = path + "\image"
# 存放文件的 md5 码
all_svg = {} # 改为字典
global all_svg_jpg
all_svg_jpg = {} # 存储所有svg里面的链接的jpg、gif 与image下的jpg、gif对应值。
total_save = 0
total_file = 0
total_delete = 0
# 开始时间
# start = time.time()
# 遍历文件夹下的所有文件
for file in os.listdir(image_path):
# 文件数量加 1
total_file += 1
# 文件的路径
# real_path = os.path.join(path, file)
real_path = image_path + "\\" + file
filename = os.path.split(real_path)[1]
# 获取image文件的md5码
filemd5 = getmd5(real_path)
# 如果文件 md5 已存在,则删除此文件
if filemd5 in all_svg.values(): # 字典的值为已存在的文件 md5 码
total_delete += 1
for svgnamekey, svgmd5value in all_svg.items():
if svgmd5value == filemd5:
# print(f"svgnamekey= {svgnamekey} svgmd5value = {svgmd5value} filename :{filename}")
all_svg_jpg[filename] = svgnamekey
os.remove(real_path)
# print('删除', real_path)
else:
# 如果文件 md5 不存在,则将此文件的 md5 码添加到 all_svg 字典中,文件名为key,文件value为md5
all_svg[filename] = filemd5
# 结束时间
# end = time.time()
# time_last = end - start
# for key, value in all_svg_jpg.items():
# # print(f"key= {key} value = {value}")
# total_save += 1
print('image文件总数:', total_file)
print('删除image个数:', total_delete)
logger.info(f'image文件总数:{total_file}')
logger.info(f'删除image个数:{total_delete}')
# print('耗时:', time_last, '秒')
# print('存储键值对个数:', total_save)
def alter(file):
"""
1.逐一打开所在目录的svg文件,逐行查找,根据正则表达式规则查中找是否有匹配的图片名称的字符串,
2.如果有匹配的图片名称字符串,判断字符串是否在all_svg_jpg字典中
3.如果在,则进行替换,如果不在,则进行源文件内容打印
:param file: svg所在路径
:return: bFind False:没修改文件 True:成功修改文件
"""
bFind = False
with open(file, "r", encoding="utf-8") as f1, open("%s.bak" % file, "w", encoding="utf-8") as f2:
for line in f1:
search_obj = re.search(
"image/([0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}.(jpg|gif|png))",
line)
if search_obj:
# 在svg文件中找到匹配的图片,判断该图片是否在all_svg_jpg字典中,如果在,则进行替换,修改SVG文件并保存
for key, value in all_svg_jpg.items():
if key == search_obj.group(1):
print(f"file :{file} 旧字符串= {search_obj.group(1)} 新字符串 = {value}")
logger.info(f"file :{file} 旧字符串= {search_obj.group(1)} 新字符串 = {value}")
# 修改SVG
f2.write(re.sub(search_obj.group(1), value, line))
bFind = True
else:
f2.write(line)
os.remove(file)
os.rename("%s.bak" % file, file)
return bFind
def filepath():
global path
path = os.getcwd() # 获取指定路径下的文件
dirs = os.listdir(path)
# 准备要替换的数据
# print(path)
getallkey(path)
total_file = 0
total_right = 0
total_wrong = 0
for svgname in dirs: # 循环读取路径下的文件并筛选输出
if os.path.splitext(svgname)[1] == ".svg": # 筛选svg文件
# print(svgname)
num = alter(svgname)
total_file += 1
if num > 0:
total_right += 1
else:
total_wrong += 1
print('SVG文件总数:', total_file)
print('修改SVG个数:', total_right)
print('未修SVG改个数:', total_wrong)
logger.info(f'SVG文件总数:{total_file}')
logger.info(f'修改SVG个数:{total_right}')
logger.info(f'未修SVG改个数:{total_wrong}')
if __name__ == '__main__':
filepath()
time.sleep(60)