Скачать и распаковать zip-архив
Подскажите, как с помощью библиотеки requests считать данные по имеющемуся url в папку — без .zip? Делаю:
r = requests.get('https:URL') with open('. ', 'wb') as code: code.write(r.content)
Если я на месте . указываю файл, то он просто превращается папку с файлами(полученную из URL) непонятно во что. Работает только с Name.zip, но потом нужно разорхивировать, что очень неудобно.
Отслеживать
52.3k 11 11 золотых знаков 108 108 серебряных знаков 312 312 бронзовых знаков
задан 6 фев 2018 в 21:26
1 1 1 серебряный знак 3 3 бронзовых знака
Например можно было заголовок такой написать: Скачать и распаковать zip-архив , подобное уже делал
7 фев 2018 в 6:21
3 ответа 3
Сортировка: Сброс на вариант по умолчанию
import tempfile, os, zipfile import requests response = requests.get('https://URL') file = tempfile.TemporaryFile() file.write(response.content) fzip = zipfile.ZipFile(file) fzip.extractall('') file.close() fzip.close()
Отслеживать
ответ дан 6 фев 2018 в 22:25
1,138 5 5 серебряных знаков 15 15 бронзовых знаков
Чтобы скачать и распаковать zip-архив в output папку в Питоне:
#!/usr/bin/env python import io import zipfile import requests # $ pip install requests r = requests.get("http://www.pythonchallenge.com/pc/def/channel.zip") with r, zipfile.ZipFile(io.BytesIO(r.content)) as archive: archive.extractall('output')
Если вы сразу хотите информацию из распакованных файлов в вашем коде использовать, то можно налету распаковывать и читать файлы:
with r, zipfile.ZipFile(io.BytesIO(r.content)) as archive: print()
Статья Работа с запароленными архивами с помощью Python
Распаковка zip-архивов с помощью Python и встроенной библиотеки zipfile довольно простое занятие. И, может быть я и не столкнулся с некоторыми трудностями, если бы не стал распаковывать с помощью этой библиотеки запароленный архив. Вот тут-то архиватор и не захотел с ним работать. Хотя, распаковка архивов с паролем в нем предусмотрена уже по умолчанию. Тогда я решил немного разобраться, почему же так происходит и как с этим быть. Таким образом, получилась небольшая заметка по поводу того, как распаковать запароленные архивы разными типами архиваторов с помощью Python.
Дисклеймер: данная статья служит для ознакомления и не призывает к действию.
На оригинальность вовсе не претендую. Я просто хочу поделиться с другими тем, на что было потрачено пару часов моего времени. Чтобы человек, который решил распаковать архив питоном, не столкнулся с теми же трудностями, что и я. Если, конечно же, он прочтет эту заметку.
Пара слов про архивы с паролем
Для начала нужно понять, что же такое архив с паролем. Это не что иное, как зашифрованный с помощью алгоритмов шифрования файл. А пароль, это ключ для дешифровки. Таким образом, архиватор, при упаковке и распаковке файлов в архив с паролем, шифрует или дешифрует их встроенными средствами.
Библиотека zipfile для шифрования и расшифровки файлов использует алгоритм ZIP-шифрования. Однако, файлы с паролем, созданные с помощью стандартного архиватора Linux используют уже другой алгоритм шифрования AES. И соответственно, распаковать архив созданный таким способом с помощью библиотеки zipfile не получается. Это же касается и формата архивов 7zip.
Про формат RAR вообще отдельный разговор. Так как он является проприетарным, а значит закрытым форматом, то инструменты для распаковки доступны для данного формата только те, что поставляются разработчиками данного архиватора. И хоть они и предоставляются бесплатно, все равно, без помощи данных инструментов распаковка зашифрованных архивов будет недоступной. Да и вообще распаковка, как таковая. Для python, в данный момент, доступны лишь оболочки, которые являются лишь интерфейсами для инструментов rar.
А теперь хочу поделиться с вами теми способами, что я нашел для распаковки зашифрованных архивов, то есть архивов с паролем.
Что потребуется?
Для распаковки зашифрованного zip-архива нужно установить библиотеку pyzipper. В терминале выполняем команду:
pip install pyzipper
После чего импортируем загруженную библиотеку в скрипт:
Ну и можно распаковывать архивы. Я не стал писать какие-то специальные скрипты для распаковки. Вместо этого будут просто обозначены функции, с помощью которых можно это сделать.
Расшифровка и распаковка zip-архива
Ну и раз мы начали с zip-архивов, то ниже приведен код для расшифровки и распаковки:
# pip install pyzipper import pyzipper def decrypt(file_path, word): with pyzipper.AESZipFile(file_path, 'r', compression=pyzipper.ZIP_LZMA, encryption=pyzipper.WZ_AES) \ as extracted_zip: try: extracted_zip.extractall(pwd=word) except RuntimeError as ex: print(ex) decrypt('test.txt.zip', b'123')
pyzipper является контекстным, потому открываем его с помощью with. Используем класс AESZipFile, в который передаем необходимые аргументы. Здесь file_path – путь к запароленному архиву. compression – метод сжатия. encryption – алгоритм шифрования, который будет использован для расшифровки. А далее в extracted_zip.extractall(pwd=word) вызывается функция extractall для распаковки всего содержимого архива. Здесь также можно указать путь для распаковки в параметре path, а в параметре pwd указывается пароль или ключ к зашифрованному архиву. Если путь для распаковки не указан, архив распаковывается в ту же папку, где он и располагается. Ключ должен быть в байтовом формате. Поэтому, нужно его перед тем, как передавать его в функцию, в него перевести. Либо как в примере, либо, использовав функцию encode().
Распаковка и расшифровка 7zip-архива
У данного типа архива при шифровании может использоваться алгоритм на выбор. А потому библиотека, которая распаковывает такие архивы, в теории, должна уметь автоматически подбирать нужный алгоритм для распаковки.
Для распаковки 7zip я использовал библиотеку py7zr, которая устанавливается в терминале с помощью команды:
pip install py7zr
Далее она импортируется в скрипт. Вот небольшой код для расшифровки и распаковки:
# pip install py7zr import py7zr try: with py7zr.SevenZipFile('test.txt.7z', mode='r', password='123') as z: z.extractall() except py7zr.exceptions.Bad7zFile as ex: if str(ex) == 'not a 7z file': print('Файл не является 7zip')
Параметры для распаковки, это путь к файлу архива, метод, который используется для открытия зашифрованного файла. Так как файл расшифровывается и распаковывается, то здесь нужно использовать read. И пароль к зашифрованному файлу. Я пробовал указать для распаковки с помощью данной библиотеки zip-архив. И если оригинальный архиватор 7zip справляется с этим на ура, то в данном случае возникает исключение, текст которого так и гласит, что файл не является 7zip.
Расшифровка и распаковка RAR
С данным типом архивов возникли довольно большие трудности. Не в том плане, что его невозможно распаковать без установленного архиватора, а в том плане, что он является проприетарным, следовательно, компоненты для его работы нужно качать с
Ссылка скрыта от гостей
. В данном случае скачивается исполняемый файл unrar.exe, который нужно положить либо в папку с расшифровываемым архивом, либо в папку WinRAR, которую нужно создать в Program Files. Для того чтобы библиотека, то есть интерфейс к данному экзешнику, корректно находил к ней путь. Ну и так как exe используется в ОС Windows, то, как вы поняли, речь пока идет о ней. Или, если у вас уже установлен архиватор WinRAR, качать ничего не надо. Библиотека использует для распаковки Rar.exe находящийся в папке с программой. Его, при отсутствии архиватора и большом желании можно найти в интернете и положить в папку с архивом для распаковки. Данная конструкция тоже будет работать.
А теперь о том, что понадобиться. А понадобиться установить библиотеку patoolib с помощью команды в терминале:
pip install patoolib.
Используется в коде она очень просто. Для начала импортируется в скрипт, а затем указывается в качестве опций путь для распаковки. И на этом все. Библиотека сама ищет Rar или Unrar.exe по заданным в ней путям и использует их в работе.
# pip install patoolib import patoolib patoolib.extract_archive("test.rar")
Здесь пароль для распаковки в коде не указывается, а вводиться в терминале. А значит, в автоматическом режиме данную конструкцию использовать не получиться. Есть еще библиотеки, которые выполняют похожие функции. Но, все они, в той или иной степени, используют инструменты Rar.
Если вы решите распаковать данный вид архива с помощью python в Linux, то вам нужно будет установить библиотеку unrar. Ну и rar, в придачу, чтобы была возможность эти архивы создавать. Мало ли, вдруг для чего-то может, потребуется.
sudo apt-get install -y rar unrar
Вот такая вот небольшая заметка. Надеюсь, что она кому-то поможет при работе с запароленными архивами. Хотя это и не секретная информация, но искать ее в куче статей о работе с архивами с помощью zipfile довольно нудно ))
Ну и небольшой код, который пытается работать с запароленными zip-архивами. А началось все с того, что у меня в архиве лежала нужная информация, а вот пароль на него я подзабыл. Потому и попробовал написать код для работы с запароленными архивами с помощью стандартной библиотеки и столкнулся с трудностями по расшифровке. Ну и соответственно, начал искать информацию:
Код для работы с запароленными zip-архивами
# pip install pyzipper # pip install tqdm import pyzipper from tqdm import tqdm def decrypt(extracted_zip, word): try: extracted_zip.extractall(pwd=word) except RuntimeError: pass except pyzipper.zipfile.BadZipFile: pass else: print(f'\n[+] Пароль найден: ') exit(0) def open_pass_list(wordlist, file_path): len_zip = len(list(open(wordlist, 'rb'))) with open(wordlist, 'r', errors='ignore') as wordlist: with pyzipper.AESZipFile(file_path, 'r', compression=pyzipper.ZIP_LZMA, encryption=pyzipper.WZ_AES) as extracted_zip: for word in tqdm(wordlist, total=len_zip, unit=' word'): decrypt(extracted_zip, word.strip().encode()) def main(): wordlist = input('[+] Введите путь к словарю: ') file_path = input('[+] Введите путь к архиву: ') print(" ") open_pass_list(wordlist, file_path) if __name__ == "__main__": main()
Работа с архивом идет по словарю. А потому, его надо где-то скачать. Впрочем, в интернете словарей великое множество. Но я использовал rockyou.txt. Это, наверно, один из самых больших словарей с паролями, которые я видел. Попадались мне и на 10 миллионов. Но тут, больше 14-ти. К слову, пароль я так и не нашел. Пришлось вспоминать самостоятельно ))
Спасибо за внимание. Надеюсь, что данная информация будет вам полезна
Извлечение Файлов из архива tar.gz (Python)
Извлечение всего tar-файла, осуществляется с помощью функции extractall(). Данная функция извлечет файл в текущей рабочей директории. Также можно определить путь для разархивирования файлов в другом месте.
Извлечение полного содержимого tar-файла:
>>> import tarfile
>>> tar = tarfile.open(«archive.tar.gz», «r»)
>>> tar.extractall()
>>> tar.extractall(r»c:\temp»)
Когда необходимо извлечь определенные файлы, используйте функцию extract()
>>> import tarfile
>>> tar = tarfile.open(«archive.tar.gz», «r:gz»)
>>> tar.extract(«text.txt»)
>>> tar.extract(«text.txt», r»c:\temp»)
Как распаковать архив python
Zip представляет наиболее популярный формат архивации и сжатия файлов. И язык Python имеет встроенный модуль для работы с ними — zipfile . С помощью этого модуля можно создавать, считывать, записывать zip-файлы, получать их содержимое и добавлять в них файлы. Также поддерживается шифрование, но не поддерживается дешифрование.
Для представления zip-файла в этом модуле определен класс ZipFile . Он имеет следующий конструктор:
ZipFile(file, mode='r', compression=ZIP_STORED, allowZip64=True, compresslevel=None, *, strict_timestamps=True, metadata_encoding=None)
- file : путь к zip-файлу
- mode : режим открытия файла. Может принимать следующие значения:
- r : применяется для чтения существующего файла
- w : применяется для записи нового файла
- a : применяется для добавления в файл
- ZIP_STORED : архивация без сжатия (значение по умолчанию)
- ZIP_DEFLATED : стандартный тип сжатия при архивации в zip
- ZIP_BZIP2 : сжатие с помощью способа BZIP2
- ZIP_LZMA : сжатие с помощью способа LZMA
Для работы с файлами этот класс предоставляет ряд методов:
- close() : закрывает zip-файл
- getinfo() : возвращает информацию об одном файле из архива в виде объекта ZipInfo
- namelist() : возвращает список файлов архива
- infolist() : возвращает информацию обо всех файлах из архива в виде списока объектов ZipInfo
- open() : предоставляет доступ к одному из файлов в архиве
- read() : считывает файл из архива в набор байтов
- extract() : извлекает из архива один файл
- extractall() : извлекает все элементы из архива
- setpassword() : устанавливает пароль для zip-файла
- printdir() : выводит на консоль содержимое архива
Создание и закрытие файла
Для создания архивного файла в конструктор ZipFile передается режим «w» или «a»:
from zipfile import ZipFile myzip = ZipFile("metanit.zip", "w")После выполнения кода в текущей папке будет создаваться пустой архивный файл «metanit.zip».
После окончания работы с архивом для его закрытия применяется метод close() :
from zipfile import ZipFile myzip = ZipFile("metanit.zip", "w") myzip.close()Но так как ZipFile также представляет менеджер контекста, то он поддерживает выражение with , которое определяет контекст и автоматически закрывает файл по завершению контекста:
from zipfile import ZipFile with ZipFile("metanit.zip", "w") as myzip: passЗапись файлов в архив
Для записи файлов в архив применяется файл write() :
write(filename, arcname=None, compress_type=None, compresslevel=None)
Первый параметр представляет файл, который записиывается в архив. Второй параметр — arcname устанавливает произвольное имя для файла внутри архива (по умолчанию это само имя файла). Третий параметр — compress_type представляет тип сжатия, а параметр compresslevel — уровень сжатия.
Например, запишем в архив «metanit.zip» файл «hello.txt» (который, как предполагается, находится в той же папке, где и текущий скрипт python):
from zipfile import ZipFile with ZipFile("metanit.zip", "w") as myzip: myzip.write("hello.txt")Стоит учитывать, что при открытии файла в режиме «w» при всех последующих записях текущее содержимое будет затираться, то есть фактически архивный файл будет создаваться заново. Если нам необходимо добавить, то необходимо определять zip-файл в режиме «a»:
from zipfile import ZipFile with ZipFile("metanit.zip", "a") as myzip: myzip.write("hello2.txt") myzip.write("forest.jpg")Стоит отметить, что по умолчанию сжатие не применяется. Но при необходимости можно применить какой-нибудь способ сжатия и уровень сжатия»
from zipfile import ZipFile, ZIP_DEFLATED with ZipFile("metanit.zip", "w", compression=ZIP_DEFLATED, compresslevel=3) as myzip: myzip.write("hello.txt")Необходимо учитывать, что если мы попробуем добавить в архив файлы с уже имеющимися именами, то консоль выведет предупреждение. Чтобы избежать наличия файлов с дублирующимися именами можно через второй папаметр метода write явным образом определить для них уникальное имя внутри архива:
from zipfile import ZipFile with ZipFile("metanit.zip", "a") as myzip: myzip.write("hello.txt", "hello1.txt") myzip.write("hello.txt", "hello2.txt") myzip.write("hello.txt", "hello3.txt")Получение информации о файлах в архиве
Метод infolist() возвращает информацию о файлах в архиве с виде списка, где каждый отдельный файл представлен объектом ZipInfo:
from zipfile import ZipFile with ZipFile("metanit.zip", "a") as myzip: print(myzip.infolist())Класс ZipInfo предоставляет ряд атрибутов для хранения информации о файле. Основные из них:
- filename : название файла
- date_time : дата и время последнего изменения файла в виде кортежа в формате (год, месяц, день, час, минута, секунда)
- compress_type : тип сжатия
- compress_size : размер после сжатия
- file_size : оригинальный размер файла до сжатия
Получим эти данные по каждому отдельному файлу в архиве:
from zipfile import ZipFile with ZipFile("metanit.zip", "r") as myzip: for item in myzip.infolist(): print(f"File Name: Date: Size: ")Примерный консольный вывод:
File Name: hello.txt Date: (2022, 11, 23, 20, 21, 34) Size: 18 File Name: forest.jpg Date: (2022, 11, 19, 20, 46, 52) Size: 103956 File Name: hello1.txt Date: (2022, 11, 23, 20, 21, 34) Size: 18 File Name: hello2.txt Date: (2022, 11, 23, 20, 21, 34) Size: 18 File Name: hello3.txt Date: (2022, 11, 23, 20, 21, 34) Size: 18
С помощью метода is_dir() можно проверить, является ли элемент в архиве папкой:
from zipfile import ZipFile with ZipFile("metanit.zip", "r") as myzip: for item in myzip.infolist(): if(item.is_dir()): print(f"Папка: ") else: print(f"Файл: ")Если надо получить только список имен входящих в архив файлов, то применяется метод namelist() :
from zipfile import ZipFile with ZipFile("metanit.zip", "r") as myzip: for item in myzip.namelist(): print(item)Консольный вывод в моем случае:
hello.txt forest.jpg hello1.txt hello2.txt hello3.txt
С помощью метода getinfo() можно получить данные по одному из архивированных файлов, передав в метод его имя в архиве. Результат метода — объект ZipInfo:
from zipfile import ZipFile with ZipFile("metanit.zip", "r") as myzip: try: hello_file = myzip.getinfo("hello.txt") print(hello_file.file_size) except KeyError: print("Указанный файл отсутствует")Если в архиве не окажется элемента с указанным именем, то метод сгенерирует ошибку KeyError.
Извлечение файлов из архива
Для извлечения всех файлов из архива применяется метод extractall() :
extractall(path=None, members=None, pwd=None)
Первый параметр метода устанавливает каталог для извлечения архива (по умолчанию извлечение идет в текущий каталог). Параметр members представляет список строк — список названий файлов, которые надо извлечт из архива. И третий параметр — pwd представляет пароль, в случае если архив закрыт паролем.
Например, извлечем все файлы из архива:
from zipfile import ZipFile with ZipFile("metanit.zip", "r") as myzip: myzip.extractall()Извлечение в определенную папку:
myzip.extractall(path="metanit")
Извлечение части файлов:
# извлекаем файлы "hello.txt", "forest.jpg" в папку "metanit2" myzip.extractall(path="metanit2", members=["hello.txt", "forest.jpg"])
Для извлечения одного файла применяется метод extract() , в который в качестве обязательного параметра передается имя извлекаемого файла:
myzip.extract("hello.txt")Считывание файла
Метод read() позволяет считать содержимое файла из архива в набор байтов:
from zipfile import ZipFile with ZipFile("metanit.zip", "r") as myzip: content = myzip.read("hello5.txt") print(content)Открытие файла
Метод open() позволяет открывать отдельные файлы из архива без непосредственного их извлечения:
open(name, mode='r', pwd=None, *, force_zip64=False)
В качестве первого обязательного параметра передается имя файла внутри архива. Второй параметр — mode устанавливает режим открытия. Параметр pwd задает пароль, если файл защищен паролем. И параметр force_zip64 при значении True позволяет открывать файлы больше 4 Гб.
Этот файл может быть полезен для манипулирования файлом, например, для считывания его содержимого или, наоборот, для записи в него. Например, откроем файл и считаем его содержимое:
from zipfile import ZipFile with ZipFile("metanit.zip", "a") as myzip: # записываем в архив новый файл "hello5.txt" with myzip.open("hello5.txt", "w") as hello_file: encoded_str = bytes("Python. ", "UTF-8") hello_file.write(encoded_str)