遞歸調用解壓zip包或rar包


不知道有沒有小伙伴跟我一樣犯這樣的懶,一些簡單重復的工作,總是嫌麻煩,懶得一步步去做,還每次都重復一樣的操作。比如解壓zip或rar的包,也許你會說,不就解壓嘛,有啥的。問題來了,如果只是一個簡單的壓縮包也是算了,關鍵是壓縮包里還有壓縮包,也不知道多少層,要一層層去解壓,這就比較惡心了吧?如下圖:

學習了Python的遞歸調用后,心想,為什么我不寫一個腳本自動解壓所有的壓縮包呢?emmm....心動不如行動,說寫就寫,誰讓我是這么懶的一個人呢,連解壓都得自動化,哈哈哈。

那就來吧,先從最簡單的開始,搞個zip包用命令行解壓看看:

# -*- coding: utf-8 -*-
import zipfile
import os

path = r'C:\Users\ES-IT-PC-193\Desktop\aa\A.zip'
z = zipfile.ZipFile(path, 'r')
unzip_path = os.path.split(path)[0] #解壓路徑
z.extractall(path=unzip_path)

嗯,試了試,沒問題,能正常解壓。那接下來就是解決如果把壓縮包里包含壓縮包的也一塊解壓了,那我得把解壓的命令封裝成函數,然后循環解壓就好了。這里正好用上了剛學不久的遞歸調用。

# -*- coding: utf-8 -*-
# 2019/8/13 14:57
import zipfile
import os

def unzip_file(path):
    '''解壓zip包'''
    if os.path.exists(path):
        if path.endswith('.zip'):
            z = zipfile.ZipFile(path, 'r')
            unzip_path = os.path.split(path)[0]
            z.extractall(path=unzip_path)
            zip_list = z.namelist() # 返回解壓后的所有文件夾和文件
            for zip_file in zip_list:
                new_path = os.path.join(unzip_path,zip_file)
                unzip_file(new_path)
            z.close()
        elif os.path.isdir(path):
            for file_name in os.listdir(path):
                unzip_file(os.path.join(path, file_name))
    else:
        print('the path is not exist!!!')


if __name__ == '__main__':
    zip_path = r'C:\Users\ES-IT-PC-193\Desktop\aa\A.zip'
    unzip_file(zip_path)

嗯,效果還不錯,能把所有的壓縮包都遞歸解壓開了,然而,問題來了,解壓開的文件名稱怎么都成亂碼了?!!

於是開始尋找解決亂碼問題的方法,然后是各種百度。哎,編碼問題一直困擾了我很久,總也搞不明白,這里推薦Alex寫的一篇博客,寫的很詳細,反正我看完后就只知道,不管什么編碼格式,都統統給它轉成Unicode,然后再轉成utf-8或者gbk的格式。哈哈哈。

Alex的博客鏈接:https://www.cnblogs.com/alex3714/articles/7550940.html

然后我就接着搞搞,各種嘗試,還是不行,就是轉換不過來,奇怪了。搞了好久還是沒找到什么原因。徹底蒙圈了,郁悶~~,晚上睡覺我都能夢見我在解決編碼問題,哈哈哈。今天早上腦袋還算比較清醒,再繼續找bug。一行行代碼調試。果然啊,功夫不負有心人。還是被我找到是什么原因了。

C:\Users\ES-IT-PC-193\Desktop\aa\A\│┬┤·└╓\
C:\Users\ES-IT-PC-193\Desktop\aa\A\╤Θ╓ñ┬δ.py

像這樣的一個路徑,打印出來的類型就是一個普通的<type 'str'>,整行路徑去轉換格式是不行的!!只有把亂碼的部分切割出來,再單獨轉換就可以了。哦,天。就這樣,一個小小的問題,卡了我好久。淚奔~ 

再加上編碼轉換:

# -*- coding: utf-8 -*-
# 2019/8/13 14:57
import zipfile
import os

def unzip_file(path):
    '''解壓zip包'''
    if os.path.exists(path):
        if path.endswith('.zip'):
            z = zipfile.ZipFile(path, 'r')
            unzip_path = os.path.split(path)[0]
            z.extractall(path=unzip_path)
            zip_list = z.namelist() # 返回解壓后的所有文件夾和文件
for zip_file in zip_list:
try: zip_file2 = zip_file.encode('cp437').decode('gbk') except: zip_file2 = zip_file.encode('utf-8').decode('utf-8') old_path = os.path.join(unzip_path,zip_file) new_path = os.path.join(unzip_path,zip_file2) if os.path.exists(old_path): os.renames(old_path, new_path) unzip_file(new_path) z.close() elif os.path.isdir(path): for file_name in os.listdir(path): unzip_file(os.path.join(path, file_name)) else: print('the path is not exist!!!') if __name__ == '__main__': zip_path = r'C:\Users\ES-IT-PC-193\Desktop\aa\A.zip' unzip_file(zip_path)

作為有強迫症患者的我,看着這個代碼真是亂啊,不爽,需要優化一下。
於是做了一下幾點優化:

1、加上rar壓縮包的解壓,這里需要注意的是,需要下載一個UnRAR.exe文件放在腳本的同級目錄。

2、把編碼轉換再單獨寫一個函數,傳入一個帶有亂碼的路徑,返回轉換好的路徑就行了。

3、把解壓單獨寫一個函數,這樣解壓zip和rar的包就不用寫段重復的代碼了。

4、解壓后,目錄里有一堆壓縮包,我只想要解壓后的文件,於是再寫了一個刪除解壓后不用的壓縮包的函數。

最終版的代碼如下,歡迎各位小伙伴指導。

 

# -*- coding: utf-8 -*-
# 2019/8/13 14:57
import zipfile
import rarfile
import os
import sys


def chengeChar(path):
    '''處理亂碼'''
    if not os.path.exists(path): return path
    path = path.rstrip('/').rstrip('\\')  # 去除路徑最右邊的/
    file_name = os.path.split(path)[-1]  # 獲取最后一段字符,准備轉換
    file_path = os.path.split(path)[0]  # 獲取前面的路徑,為rename做准備
    try:  # 將最后一段有亂碼的字符串轉換,嘗試過整個路徑轉換,不生效,估計是無法獲取整個路徑的編碼格式吧。
        new_name = file_name.encode('cp437').decode('gbk')
    except:  # 先轉換成Unicode再轉換回gbk或utf-8
        new_name = file_name.encode('utf-8').decode('utf-8')
    path2 = os.path.join(file_path, new_name)  # 將轉換完成的字符串組合成新的路徑
    try:
        os.renames(path, path2)  # 重命名文件
    except:
        print('renames error!!')
    return path2


def del_zip(path):
    '''刪除解壓出來的zip包'''
    path = chengeChar(path)
    if path.endswith('.zip') or path.endswith('.rar'):
        os.remove(path)
    elif os.path.isdir(path):
        for i in os.listdir(path):
            file_path = os.path.join(path, i)
            del_zip(file_path)  # 遞歸調用,先把所有的文件刪除


def unzip_file(z, unzip_path):
    '''解壓zip包'''
    z.extractall(path=unzip_path)
    zip_list = z.namelist()  # 返回解壓后的所有文件夾和文件list
    z.close()
    for zip_file in zip_list:
        path = os.path.join(unzip_path, zip_file)
        if os.path.exists(path): main(path)


def main(path):
    '''主邏輯函數'''
    path = chengeChar(path)
    if os.path.exists(path):
        unzip_path = os.path.splitext(path)[0]  # 解壓至當前目錄
        if path.endswith('.zip') and zipfile.is_zipfile(path):
            z = zipfile.ZipFile(path, 'r')
            unzip_file(z, unzip_path)
        elif path.endswith('.rar'):
            r = rarfile.RarFile(path)
            unzip_file(r, unzip_path)
        elif os.path.isdir(path):
            for file_name in os.listdir(path):
                path = os.path.join(path, file_name)
                if os.path.exists(path): main(path)
        else:
            print(path)
    else:
        print('the path is not exist!!!')
        print(path)


if __name__ == '__main__':
    #zip_path = r'C:\Users\ES-IT-PC-193\Desktop\aa\HighLevel\HighLevel'
    zip_path = r'C:\Users\ES-IT-PC-193\Desktop\aa\HighLevel.zip'
    # zip_path = sys.argv[1]  # 接收傳入的路徑參數
    if os.path.isdir(zip_path):
        for file_name in os.listdir(zip_path):
            path = os.path.join(zip_path, file_name)
            main(path)
    else:
        main(zip_path)
    if zipfile.is_zipfile(zip_path):  # 刪除解壓出來的壓縮包
        del_zip(os.path.splitext(zip_path)[0]) # 以后綴名切割

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM