python解压缩rar,zip文件的正确姿势

时间:2024-03-07 12:53:59

上级给了一个文件夹,文件夹里有rar,zip类型的压缩包,有的压缩包还有密码,有的压缩包还有中文。要求把包里的文件全部解压缩出来。以为简单得很,码的时候才发现,坑一堆呢。

一、对于rar文件,仅pip install rarfile是不够的,还需要pip install unrar。如果不想安装unrar,把机器里安装的winrar文件夹中的unrar.exe文件复制到python安装路径下的scripts文件夹中吧。

二、对于中文名的zip文件,得认真得处理一下,不能直接调用extractall,你会发现出来的全是乱码,需要获取zip文件的信息,将文件名重新进行编码。需要注意的是,有的中文名,zip文件竟然是可以直接识别出来的。因此,在判断的时候,多考虑一步。如下:

with zipfile.ZipFile(filename, \'r\') as zf:
    for info in zf.infolist():
        try:
            newname=info.filename.encode(\'cp437\').decode(\'gbk\');
        except:
            try:#此处多进行了一次判断
                newname=info.filename.encode(\'cp437\').decode(\'utf-8\');
            except:
                newname=info.filename
        outname=newname.split(\'/\')
        l=len(outname)
        if outname[l-1]!=\'\':#判断解压出来的是否文件夹

三、没有了,直接上代码吧。

import rarfile,zipfile,os,shutil
from pathlib import Path

basePath=\'d:/basePath\'
outPath=\'d:/outPath\'
passlist=[]
with open(\'pass.txt\',\'r\') as f:
    for line in f.readlines():
        passlist.append(line.rstrip())

for root,dirs,fs in os.walk(basePath):
    for f in fs:
        filename=os.path.join(root,f)
        type=os.path.splitext(filename)[-1][1:]
        if type==\'rar\':
            fileget=rarfile.RarFile(filename)
            with fileget as rf:
                if rf.needs_password():#判断是否需要密码
                    for pwds in passlist:
                        try:
                            fileget.extractall(outPath,pwd=pwds.encode())#不要直接用pwds,要编码一下
                            print(filename+":"+pwds)
                        except:
                            pass
                else:
                    fileget.extractall(outPath)
        elif type==\'zip\':
            with zipfile.ZipFile(filename, \'r\') as zf:
                for info in zf.infolist():
                    try:
                        newname=info.filename.encode(\'cp437\').decode(\'gbk\');
                    except:
                        try:
                            newname=info.filename.encode(\'cp437\').decode(\'utf-8\');
                        except:
                            newname=info.filename
                    outname=newname.split(\'/\')
                    l=len(outname)
                    if outname[l-1]!=\'\':#如果是文件
                        if info.flag_bits & 0x01:#如果文件有密码
                            for pwd in passlist:
                                try:
                                    body=zf.read(info,pwd=pwd.encode())
                                    print("pass:"+pwd)
                                    with open(outPath+\'/\'+outname[l-1],\'wb\') as outfile:
                                        outfile.write(body)
                                except:
                                    pass
                        else:
                            with open(outPath+\'/\'+outname[l-1],\'wb\') as outfile:#要把中文的zip解压出中文,就不要用extract了,在新位置创建中文名文件,然后把读取出来的数据写进去就可以。
                                outfile.write(zf.read(info))
        else:#如果是文件,直接复制到新位置
            shutil.copy(filename,outPath+\'\\\'+f)