Скачать возвращенный Zip-файл с URL

88

Если у меня есть URL-адрес, который при отправке в веб-браузере открывает диалоговое окно для сохранения zip-файла, как я могу поймать и загрузить этот zip-файл в Python?

user1229108
источник
1
Я попробовал раздел Загрузка двоичного файла и записи его на диск с этой страницы , которая работала как chrám.
Зейнаб Аббасимазар

Ответы:

36

Большинство людей рекомендуют использовать, requestsесли он доступен, и requests документация рекомендует это для загрузки и сохранения необработанных данных с URL-адреса:

import requests 

def download_url(url, save_path, chunk_size=128):
    r = requests.get(url, stream=True)
    with open(save_path, 'wb') as fd:
        for chunk in r.iter_content(chunk_size=chunk_size):
            fd.write(chunk)

Поскольку в ответе спрашивается о загрузке и сохранении zip-файла, я не вдавался в подробности относительно чтения zip-файла. Возможности см. В одном из многих ответов ниже.

Если по какой-то причине у вас нет доступа requests, вы можете использовать urllib.requestвместо него. Это может быть не так надежно, как указано выше.

import urllib.request

def download_url(url, save_path):
    with urllib.request.urlopen(url) as dl_file:
        with open(save_path, 'wb') as out_file:
            out_file.write(dl_file.read())

Наконец, если вы все еще используете Python 2, вы можете использовать urllib2.urlopen.

from contextlib import closing

def download_url(url, save_path):
    with closing(urllib2.urlopen(url)) as dl_file:
        with open(save_path, 'wb') as out_file:
            out_file.write(dl_file.read())
отправитель
источник
Не могли бы вы также добавить образец фрагмента. Было бы так любезно с вашей стороны сделать это
Сарвагья Дубей
207

Насколько я могу судить, правильный способ сделать это:

import requests, zipfile, StringIO
r = requests.get(zip_file_url, stream=True)
z = zipfile.ZipFile(StringIO.StringIO(r.content))
z.extractall()

конечно, вы хотите проверить, успешно ли GET r.ok.

Для python 3+ вложите модуль StringIO с io и используйте BytesIO вместо StringIO: вот примечания к выпуску, в которых упоминается это изменение.

import requests, zipfile, io
r = requests.get(zip_file_url)
z = zipfile.ZipFile(io.BytesIO(r.content))
z.extractall("/path/to/destination_directory")
Йоаврам
источник
Спасибо за этот ответ. Я использовал его, чтобы решить свою проблему с получением zip-файла с запросами .
gr1zzly be4r 02
yoavram, в вашем коде - где я ввожу адрес веб-страницы?
newGIS 01
25
Если вы хотите сохранить загруженный файл в другом месте, замените его z.extractall()наz.extractall("/path/to/destination_directory")
user799188,
1
Если вы просто хотите сохранить файл с URL вы можете сделать: urllib.request.urlretrieve(url, filename).
yoavram 02
3
Чтобы помочь другим соединить точки, мне потребовалось слишком много времени на 60 минут, вы можете использовать их pd.read_table(z.open('filename'))с указанным выше. Полезно, если у вас есть ссылка на zip-адрес, содержащая несколько файлов, и вас интересует только загрузка одного.
Frikster
13

С помощью этого сообщения в блоге я получил возможность работать с просто requests. Суть странной streamвещи в том, что нам не нужно вызывать contentбольшие запросы, которые потребовали бы обработки всех сразу, забивая память. Это streamпозволяет избежать этого, перебирая данные по одному фрагменту за раз.

url = 'https://www2.census.gov/geo/tiger/GENZ2017/shp/cb_2017_02_tract_500k.zip'
target_path = 'alaska.zip'

response = requests.get(url, stream=True)
handle = open(target_path, "wb")
for chunk in response.iter_content(chunk_size=512):
    if chunk:  # filter out keep-alive new chunks
        handle.write(chunk)
handle.close()
Иеремия Англия
источник
2
Ответы не должны полагаться на ссылки для большей части своего содержания. Ссылки могут исчезнуть, или содержимое на другой стороне может быть изменено, чтобы больше не отвечать на вопрос. Измените свой ответ, включив в него краткое изложение или объяснение информации, на которую указывает ссылка.
mypetlion
8

Вот что мне нужно для работы в Python 3:

import zipfile, urllib.request, shutil

url = 'http://www....myzipfile.zip'
file_name = 'myzip.zip'

with urllib.request.urlopen(url) as response, open(file_name, 'wb') as out_file:
    shutil.copyfileobj(response, out_file)
    with zipfile.ZipFile(file_name) as zf:
        zf.extractall()
Webucator
источник
Здравствуйте. Как избежать этой ошибки urllib.error.HTTPError: HTTP Error 302: The HTTP server returned a redirect error that would lead to an infinite loop.:?
Victor M Herasme Perez
@VictorHerasmePerez, код состояния ответа HTTP 302 означает, что страница была перемещена. Я думаю, что проблема, с которой вы столкнулись, решается здесь: stackoverflow.com/questions/32569934/…
Webucator
5

Либо используйте urllib2.urlopen, либо вы можете попробовать использовать отличный Requestsмодуль и избежать головной боли urllib2:

import requests
results = requests.get('url')
#pass results.content onto secondary processing...
аравенель
источник
1
Но как разобрать results.content в zip-архиве?
0atman 09
Используйте zipfileмодуль: zip = zipfile.ZipFile(results.content). Затем просто разобрать через файлы , используя ZipFile.namelist(), ZipFile.open()илиZipFile.extractall()
aravenel
5

Я пришел сюда искать, как сохранить файл .bzip2. Позвольте мне вставить код для тех, кто может это найти.

url = "http://api.mywebsite.com"
filename = "swateek.tar.gz"

response = requests.get(url, headers=headers, auth=('myusername', 'mypassword'), timeout=50)
if response.status_code == 200:
with open(filename, 'wb') as f:
   f.write(response.content)

Я просто хотел сохранить файл как есть.

Swateek
источник
3

Благодаря @yoavram за указанное выше решение, мой URL-адрес связан с заархивированной папкой и обнаружил ошибку BADZipfile (файл не является zip-файлом), и было странно, если я несколько раз пытался получить URL-адрес и разархивировал его все внезапно, поэтому я немного поправлю решение. используя метод is_zipfile, как здесь

r = requests.get(url, stream =True)
check = zipfile.is_zipfile(io.BytesIO(r.content))
while not check:
    r = requests.get(url, stream =True)
    check = zipfile.is_zipfile(io.BytesIO(r.content))
else:
    z = zipfile.ZipFile(io.BytesIO(r.content))
    z.extractall()
хиндамош
источник