当前位置 博文首页 > 用python批量解压带密码的压缩包

    用python批量解压带密码的压缩包

    作者:Mario-Hero 时间:2021-08-12 17:48

    目录
    • 项目地址:
    • 环境需求
    • 用法 Usage
    • 参数 Parameters
    • 完整代码

    项目地址:

    https://github.com/Mario-Hero/toolUnRar

    环境需求

    • Windows系统
    • Python 3
    • 对于解压RAR文件,需要安装WinRAR
    • 对于解压7z/zip等其他7-Zip支持解压的文件,需要安装7-Zip

    用法 Usage

    直接拖入文件夹或压缩文件即可批量解压缩包含密码的压缩文件。如果拖入的是文件夹,则会把该文件夹下的压缩文件解压缩,但不进入下一级目录。通过设置PASSWD来设置字典,通过设置DELETEIT来设置解压后是否删除被成功解压的压缩文件。本脚本会通过文件的后缀识别该文件是否为压缩文件。

    你可以把WinRAR目录下的Unrar.exe和7-Zip目录下的7z.exe直接复制到这个toolUnRar.py文件的相同目录下,这样就可以携带使用了。

    参数 Parameters

    • PASSWD = ["hello","123456"] :你的密码本,该脚本会从这个数组中不断试验密码来解压缩,直到成功为止。
    • DELETEIT :一个危险的参数。为真时,该脚本会直接删除成功解压的压缩文件。为假则不会删除。
    • LOC_WINRAR = "C:\Program Files\WinRAR\" 你的WinRAR安装位置。就算这个变量的设置的不对,该程序也会在可能的位置来寻找对应的程序。
    • LOC_7Z:7-Zip的安装位置。
    • SAVE_MODE = True:如果该脚本无法通过后缀判断这是不是压缩文件,则不对该文件进行操作。

    完整代码

    #!/usr/bin/python3
    # -*- coding: UTF-8 -*-
    
    # Created by Mario Chen, 04.04.2021, Shenzhen
    # My Github site: https://github.com/Mario-Hero
    
    import sys
    import os
    import subprocess
    
    # you can change it >>>>>
    
    PASSWD     = ["123456","hello"]  # the possible passwords
    DELETEIT   = False                                     # DANGER!! If it is True,will delete rar file after extraction
    LOC_WINRAR = "C:\\Program Files\\WinRAR\\"              # location of WinRAR
    LOC_7Z     = "C:\\Program Files\\7-Zip\\"               # location of 7-Zip
    SAVE_MODE  = True                                       # if the suffix of file doesn't look like a compressed file, then do nothing with it.
    
    # <<<<< you can change it
    
    
    PROGRAM_RAR  = "UnRAR.exe" # the program we use
    PROGRAM_7Z   = "7z.exe"    # the program we use
    LOC_S_WINRAR = ["C:\\Program Files\\WinRAR\\","C:\\Program Files (x86)\\WinRAR\\","./",""] # some possible locations of WinRAR
    LOC_S_7Z     = ["C:\\Program Files\\7-Zip\\","C:\\Program Files (x86)\\7-Zip\\","./",""]   # some possible locations of 7-Zip
    RAR_FILE     = ["rar","zip","7z","tar","gz","xz","bzip2","gzip","wim","arj","cab","chm","cpio","cramfs","deb","dmg","fat","hfs","iso","lzh","lzma","mbr","msi","nsis","ntfs","rpm","squashfs","udf","vhd","xar","z"]
    NOT_RAR_FILE = ["jpg","exe","png","mkv","mp4","mp3","avi","mov","jpeg","wav","gif","mpeg","webp","txt","doc","docx","ppt","pptx","xls","xlsx","html","wps","torrent","swf","bmp","crdownload","xltd","downloading"]
    ENABLE_RAR = False         # initial state only
    ENABLE_7Z = False          # initial state only
    
    # for guessing >>>
    GUESS_FLAG_INIT     = ["密码", "码", "password", "Password"]    #0
    GUESS_FLAG_START_1  = [":", ":"]                            #1
    GUESS_FLAG_START_2  = ["是", "为", "is", "are"," "]          #1
    GUESS_FLAG_END      = ["\n","   "]                           #2
    GUESS_FLAG_DIVIDE   = ["或是", "或", " or "]                 #3
    # <<< for guessing
    
    
    def guessWDComment(comment):
        guess_flag = 0
        guess_wd: list[str] = []
        guess_ps = 0
        cutIn = 0
        cutOut = 0
        while True:
            if guess_flag == 0:
                guess_newPs = len(comment)
                guess_len = 0
                for initStr in GUESS_FLAG_INIT:
                    ps_temp = comment.find(initStr, guess_ps)
                    if ps_temp == -1:
                        continue
                    else:
                        if ps_temp<guess_newPs:
                            guess_newPs = ps_temp
                            guess_len = len(initStr)
                if guess_newPs == len(comment):
                    if not guess_wd:
                        cutIn = 0
                        cutOut = len(comment)
                        guess_flag = 3
                    else:
                        break
                else:
                    guess_ps = guess_newPs + guess_len
                    guess_flag = 1
            elif guess_flag == 1:
                found_temp = False
                found_temp_2 = False
                guess_newPs = len(comment)
                for startStr in GUESS_FLAG_START_1:
                    ps_temp = comment.find(startStr, guess_ps, guess_ps + 20)
                    if ps_temp == -1:
                        continue
                    else:
                        if ps_temp < guess_newPs:
                            found_temp = True
                            guess_newPs = ps_temp + len(startStr)
                            guess_flag = 2
                if found_temp:
                    guess_ps = guess_newPs
                    cutIn = guess_ps
                    continue
                else:
                    guess_newPs = len(comment)
                    for startStr in GUESS_FLAG_START_2:
                        ps_temp = comment.find(startStr, guess_ps, guess_ps + 20)
                        if ps_temp == -1:
                            continue
                        else:
                            if ps_temp < guess_newPs:
                                found_temp_2 = True
                                guess_newPs = ps_temp + len(startStr)
                                guess_flag = 2
                if found_temp_2:
                    guess_ps = guess_newPs
                cutIn = guess_ps
                guess_flag = 2
            elif guess_flag == 2:
                guess_newPs = len(comment)
                for endStr in GUESS_FLAG_END:
                    ps_temp = comment.find(endStr, guess_ps)
                    if ps_temp == -1:
                        continue
                    else:
                        if ps_temp < guess_newPs:
                            guess_newPs = ps_temp
                guess_ps = guess_newPs
                guess_flag = 3
                cutOut = guess_ps
            elif guess_flag == 3:
                found_cut_temp = False
                for divideStr in GUESS_FLAG_DIVIDE:
                    if comment.find(divideStr, cutIn, cutOut) != -1:
                        found_cut_temp = True
                        for wd in comment[cutIn:cutOut].split(divideStr):
                            guess_wd.append(wd.strip())
                        break
                if not found_cut_temp:
                    guess_wd.append(comment[cutIn:cutOut].strip())
                guess_flag = 0
            else:
                guess_flag = 0
        return guess_wd
    
    
    def isCompressedFile(file):
        file = file.lower()
        for rar in RAR_FILE:
            if file.endswith("." + rar):
                return True
        for media in NOT_RAR_FILE:
            if file.endswith("." + media):
                return False
        return not SAVE_MODE
    
    
    def utfIsNumber(uchar):
        return uchar >= u'\u0030' and uchar<=u'\u0039'
    
    
    def winRarDo(folder, file, wd):
        extractStr = " x -y -p" + wd + " \"" + folder + "\\" + file + "\" \"" + folder + "\\\""
        extM = subprocess.call("@\""+LOC_WINRAR+PROGRAM_RAR+"\""+extractStr,shell=True)     
        if extM == 1:    # not rar file
            return 2
        elif extM == 11: # wrong password
            return 1
        elif extM != 0:  # error
            return 1
        else:
            return 0
    
    
    def z7Do(folder, file, wd):
        extractStr = " x -y -p" + wd + " \"" + folder + "\\" + file + "\" -o\"" + folder + "\\\"" 
        extM = subprocess.call("@\""+LOC_7Z+PROGRAM_7Z+"\""+extractStr,shell=True)
        if extM !=0: # error
            return 1
        else:
            return 0
    
    
    def unrarFile(folder, file):
        successThisFile = False
        fileNameEncrypted = True
        if not folder:
            cutPos = file.rindex("\\")
            folder = file[:cutPos]
            file = file[cutPos+1:]
            #print(folder)
            #print(file)
        if ENABLE_RAR and file.endswith(".rar"):
            winRarReturn = winRarDo(folder, file, PASSWD[0])
            #print(winRarReturn)
            if winRarReturn == 0:
                #successThisFile = True
                return True
            elif winRarReturn == 2:
                pass
            else:
                getCommentStr = " l -p0 -z" + " \"" + folder + "\\" + file + "\""
                commentNumber = subprocess.call("@\""+LOC_WINRAR+PROGRAM_RAR+"\""+getCommentStr,shell=True)
                #commentNumber = 1
                if commentNumber == 0:
                    commentM = subprocess.getstatusoutput("@\""+LOC_WINRAR+PROGRAM_RAR+"\""+getCommentStr)
                    if commentM[0] == 0:
                        fileNameEncrypted = False
                        comment = commentM[1][(commentM[1].index("\n\n")+2):commentM[1].index(folder)]
                        comment = comment[0:comment.rindex("\n\n")]
                        #print(comment)
                        if comment:
                            wdArray = guessWDComment(comment)
                            print("Possible passwords:", wdArray)
                            for wd in wdArray:
                                winRarReturn = winRarDo(folder, file, wd)
                                if winRarReturn == 1:
                                    continue
                                elif winRarReturn == 0:
                                    successThisFile = True
                                    break
                                elif winRarReturn == 2:
                                    break
                                else:
                                    break
                if successThisFile:
                    return True
                for index in range(1,len(PASSWD)):
                    winRarReturn = winRarDo(folder, file, PASSWD[index])
                    if winRarReturn == 1:
                        continue
                    elif winRarReturn == 0:
                        successThisFile = True
                        PASSWD[0],PASSWD[index]=PASSWD[index],PASSWD[0]
                        break
                    elif winRarReturn == 2:
                        break
                    else:
                        break
                
        if not successThisFile:
            if ENABLE_7Z:
                for index in range(len(PASSWD)):
                    z7Return = z7Do(folder, file, PASSWD[index])
                    if z7Return == 1:
                        continue
                    else:
                        successThisFile = True
                        PASSWD[0],PASSWD[index]=PASSWD[index],PASSWD[0]
                        break
                         
        if not successThisFile: 
            print("Failed:"+file)
        return successThisFile
    
    
    def unrar(folder):
        if os.path.isdir(folder):
            print(folder)
            file_list = os.listdir(folder)
            for file in file_list:
                if os.path.isdir(folder + "/" + file):
                    #print(folder +"/"+ file)
                    #unrar(folder +"/"+file)
                    pass
                else:
                    if isCompressedFile(file):
                        if unrarFile(folder, file):
                            if DELETEIT:
                                os.remove(folder + "/" + file)
        else:
            if isCompressedFile(folder):
                if unrarFile("", folder):
                    if DELETEIT:
                        os.remove(folder)
                      
    
    if __name__ == '__main__':
        if len(sys.argv) <= 1:
            sys.exit(1)
        testRar = os.popen("\""+LOC_WINRAR+PROGRAM_RAR+"\"").read()    
        if not testRar:
           for loc in LOC_S_WINRAR:
               testRar = os.popen("\""+loc+PROGRAM_RAR+"\"").read()
               if testRar:
                   LOC_WINRAR = loc
                   ENABLE_RAR = True
                   break
        else:
            ENABLE_RAR = True
    
        test7z = os.popen("\""+LOC_7Z+PROGRAM_7Z+"\"").read()    
        if not test7z:
           for loc in LOC_S_7Z:
               test7z = os.popen("\""+loc+PROGRAM_7Z+"\"").read()
               if test7z:
                   LOC_7Z = loc
                   ENABLE_7Z = True
                   break
        else:
            ENABLE_7Z = True
    
        if (not ENABLE_RAR) and (not ENABLE_7Z):
            print("Cannot find winRAR and 7-zip")
            sys.exit(1)
        while len(PASSWD) < 2:
            PASSWD.append("0")   
        for folder in sys.argv[1:]:
            #print(folder)
            unrar(folder)
        print("Finish.")
        #subprocess.call("pause",shell=True)
        sys.exit(0)
    jsjbwy