10.20 发现一个问题:
当压缩包过大,文件条目超过1048576时,rarfile库中的代码已经不能解决这个压缩包了,需要加装unrar库(from unrar import rarfile)和unrar.dll.exe(安装后还需要修改文件名,对于x64里面的俩以64结尾文件,去掉64,改成小写),还不行的话,需要修改unrarlib.py,在代码里指定unrar.dll的路径。
代码可以直接用,它会读取并记录指定文件夹下的所有文件名,记录结果存于该文件夹下的result.xlsx,不记录子文件夹,遇到压缩包会自动解压(注意:会删除原有压缩包,使用前建议备份),需要用的可以点击目录链接去找代码,无注释的代码中我认为有一些需要额外加上的东西。
哦对,运行之前需要做两件事儿,用过python的应该已经知道了
首先,将unrar.exe复制一份放在你要用的Python的\venv\Scripts中
然后,在系统环境变量,路径(path)中添加它的位置C:\j\venv\Scripts\unrar.exe(我的)
还有第三件不算事儿的事儿,安装你要用的包
下面是一些废话:
所以python的优缺点都很明显了,想用啥用啥,想用啥就得现场设置啥。好吧,看来要学学exe怎么编。
显然以我的水平,它做不到像人一样根据指定的规则检查所有文件的质量评个三六九等,它只能给出一个文件清单,供我概览一下我的文件,当需要总结数量或者看看都有些什么之类的事情时会有一些便利,随后也许会加入一些有的没的,扩充一下功能,因为我写的东西大多来说都是小儿科了,码农甚至都不愿意看。
那么对黑客来讲,快速完成一些事情,是现场写一些代码呢,还是利用cmd网络传输调用个人电脑或者文件去完成一些事情呢?
或许也许之后可以看看高级的深度学习之类的东西,算法写起来应该会非常困难……
目录
1 效果展示
我的文件,名称不便展示:
已有名单,读取结果,名称不便展示:
没有名单的读取结果:
2 代码
2.1 详细注释版
# -*-coding:utf-8-*-
""" **************************************************************************
读取并记录指定文件夹下的所有文件名
记录结果存于该文件夹下的result.xlsx
不记录子文件夹,遇到压缩包自动解压
代码核心为OS和Pandas包的使用,及文件名的获取与写入操作
rarfile和zipfile用于压缩包的处理
参数handle_path为文件夹,如(E:/文件夹)
check_list_path为校对文件,如(E:/校对.xlsx)
没有校对列表时,可以将check_list_path设置为None
取excel表格第一列数据作为输出结果的行索引名
**************************************************************************"""
import os
import pandas as pd
import rarfile
from zipfile import ZipFile
class File_record:
# 构造函数
def __init__(self, handle_path, check_list_path):
self.handle_path = handle_path
self.check_list_path = check_list_path
# os.walk辅助函数
def Walk(path):
file_list = []
# files为各文件名,root为该文件路径,dirs为子文件夹路径
for root, dirs, files in os.walk(path):
for name in files:
file_path = os.path.join(root, name)
file_list.append(file_path)
# 返回文件所在位置的储存列表
return file_list
# 解压函数
def Decompression(self):
path = self.handle_path
# 获取目录文件
handle_list = File_record.Walk(path)
# 解压所有zip和rar文件
for each_file in handle_list:
suffix = each_file.split('.')[-1]
if suffix == 'zip':
file = File_record.support_gbk(ZipFile(each_file))
file.extractall(each_file.split('.')[0])
file.close()
os.remove(each_file)
elif suffix == 'rar':
file = rarfile.RarFile(each_file)
file.extractall(each_file.split('.')[0])
file.close()
os.remove(each_file)
# 若压缩包中仍存在压缩包,重新调用函数
handle_list = File_record.Walk(path)
n = 0
for each_file in handle_list:
suffix = each_file.split('.')[-1]
if suffix == 'zip' or suffix == 'rar':
n = 1
break
if n == 1:
self.Decompression()
# 解压函数辅助函数,处理编码不同导致乱码的情况
def support_gbk(zip_file: ZipFile):
""" 别人的代码,链接在文末,
进行了修改,忽略了编码器异常的错误
该错误并未对解压的文件造成任何影响
但是却会影响代码的执行,原因未知
"""
name_to_info = zip_file.NameToInfo
# copy map first
for name, info in name_to_info.copy().items():
try:
real_name = name.encode('cp437').decode('gbk')
except:
if name.split('.')[-1] == 'zip' or name.split('.')[-1] == 'rar':
print(name + '解压后文件可能存在问题!!!!')
continue
if real_name != name:
info.filename = real_name
del name_to_info[name]
name_to_info[real_name] = info
return zip_file
def file_record(self):
"""
2022.10.11修正了主函数的错误
"""
if self.check_list_path != None:
# 将检查文件转换为列表
check_list1 = pd.read_excel(self.check_list_path, header=None, usecols=[0]).values.tolist()
# 将二维列表转换为1维列表
check_list = []
for i in check_list1:
for j in i:
check_list.append(j)
# 创建二位空数据框,以检查文件数据作为索引
df = pd.DataFrame(index=list(check_list))
# 获取所有待处理文件
else:
# 将文件列表作为行索引
check_list = os.listdir(self.handle_path)
df = pd.DataFrame(index=list(check_list))
# 建立文件路径列表,跳过文件夹和压缩包
for each_dir in check_list:
file_list = []
file_path = os.path.join(self.handle_path, each_dir)
for root, dirs, files in os.walk(file_path):
for name in files:
if name.split('.') == 'rar' or name.split('.') == 'zip':
continue
file_list.append(name)
# 核心记录函数,遍历文件列表,记录文件类型与数量
count = 0
while count < len(file_list)-1:
i = len(file_list) - count
while file_list[count+1].split('.')[-1] != file_list[count].split('.')[-1] and i != 1:
record_str = file_list[count+1]
file_list.remove(record_str)
file_list.append(record_str)
i = i - 1
count += 1
record_str = '';count = 0;suffix = ''
for each_file in file_list:
if suffix == each_file.split('.')[-1]:
record_str = record_str + ' ' + each_file.split('.')[0]
count = count + 1
else:
if suffix != '':
df.at[each_dir, suffix] = record_str
df.at[each_dir, str(suffix + 'count')] = count
record_str = each_file.split('\\')[-1].split('.')[0]
count = 1
suffix = each_file.split('\\')[-1].split('.')[-1]
df.at[each_dir, suffix] = record_str
df.at[each_dir, str(suffix + 'count')] = count
df.to_excel(os.path.join(self.handle_path, 'result.xlsx'))
if __name__ == "__main__":
handle_path = r'C:\Users\TW\Desktop\test\图片类'
check_list_path = None
Terminal = File_record(handle_path, check_list_path)
Terminal.Decompression()
Terminal.file_record()
3 问题与讨论
3.1 压缩包处理
首先,从我找到的各种资料中,没有可以直接用的很全面的解压代码,于是unrar和unzip需要分别设置,unzip很友好,调用现成的包,unrar需要调用已有的unrar.exe,还需要设置环境变量。显然我没有找到绕过它的方法,我懒得去找7z格式的解压方法了,至少我没有7z的压缩包。
然后,遇到了cp437的问题,不同系统,不同的默认设置,有时候同样格式的文件内部编码模式不同,于是就会儿出现乱码。CSDN的i止于至善提供了一个解决方法,链接在下面,然而仍然存在问题,我不太懂这些代码的内部逻辑,所以无法解决异常。于是用了try方法来忽略异常,从运行结果来看,该异常并未给结果造成影响。
再者,就是压缩包套压缩包套压缩包的问题,我以为简单递归就可以解决,于是循环终止条件横在了我面前,给函数增加参数、额外设置全局变量……最终我选择了删除被解压过的压缩包,于是在运行前就多了需要复制一下原数据的步骤。
最后,合并文件夹,解压文件时常出现重复文件夹的问题,再说吧。
3.2 记录格式
这是代码构建的核心问题,但比上个问题容易解决,因为这是我自己的问题。
文件夹,文件路径,文件类型,文件名,文件大小,文件内部信息……可以记得太多,怎么记是个问题,我考虑过在Excel中一个文件记录为一行,列索引为文件类型、文件名这些信息,然后发现,上百条记录的表大的不堪入目。忽然想到我可以制作统计图和记录表,这样我的记录表就只是一个用于检索文件的,额……表。
如果你在阅读,你会发现,我是边想边写的,也就意味着,是的,代码并没有实现上述功能,我将每个压缩包的文件写在一行内,文件名用分隔符合成了一个字符串写入了一个单元格内,后边写上了该类型的数量,不是很明智,等等优化吧。