Как скачать файл по HTTP?
У меня есть небольшая утилита, которую я использую для планового загрузки MP3 файла с веб-сайта. Затем эта утилита создает/обновляет XML файл подкаста, который я добавил в iTunes.
Обработка текста, создающая или обновляющая XML файл, написана на Python. Однако для загрузки самого MP3 файла я использую wget внутри Windows .bat файла. Я бы предпочел, чтобы вся утилита была написана на Python.
Я долго искал способ загрузить файл с помощью Python, именно поэтому вынужден был прибегнуть к использованию wget.
Как мне загрузить файл с помощью Python?
5 ответ(ов)
В вашем коде вы используете wb
в функции open('test.mp3', 'wb')
. Этот параметр открывает файл в бинарном режиме, что означает, что вы можете записывать в файл двоичные данные, такие как аудиофайлы, вместо текстовых данных. Важно использовать бинарный режим, когда вы работаете с файлами, которые не являются текстовыми, например, с MP3-файлами, чтобы избежать искажения данных. Если бы вы открыли файл в текстовом режиме, это могло бы привести к ошибкам или повреждению файла при записи.
В вашем случае, код успешно загружает MP3-файл по указанному URL и сохраняет его локально с именем test.mp3
.
Ваша функция для скачивания файла по URL выглядит неплохо, и её вполне можно использовать. Вот ваш код с небольшими улучшениями и переводом:
import os
import requests
def download(url):
get_response = requests.get(url, stream=True)
# Извлекаем имя файла из URL
file_name = url.split("/")[-1]
# Сохраняем файл с использованием 'wb' - режим записи в бинарном формате
with open(file_name, 'wb') as f:
# Итерируем по содержимому ответа
for chunk in get_response.iter_content(chunk_size=1024):
if chunk: # отфильтровываем пустые фрагменты
f.write(chunk)
# Пример вызова функции
download("https://example.com/example.jpg")
Объяснение:
- Функция
download(url)
делает запрос к указанному URL. - Мы извлекаем имя файла из URL, используя
split("/")[-1]
. - При помощи
with open(file_name, 'wb') as f:
открываем файл для записи в бинарном формате, что необходимо для изображения. - Цикл
for chunk in get_response.iter_content(chunk_size=1024):
позволяет загружать файл порциями по 1024 байта, что также помогает избежать больших затрат памяти при загрузке больших файлов. - Условие
if chunk:
предотвращает запись пустых фрагментов данных.
Этот подход позволяет более эффективно загружать файлы и обрабатывать их по частям. Убедитесь, что библиотека requests
установлена в вашей среде. Вы можете установить её с помощью pip install requests
.
Вот улучшенная версия кода PabloG для Python 2 и 3:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import (division, absolute_import, print_function, unicode_literals)
import sys
import os
import urllib.request as urllib2 if sys.version_info >= (3,) else __import__('urllib2')
import urllib.parse as urlparse if sys.version_info >= (3,) else __import__('urlparse')
def download_file(url, dest=None):
"""
Скачивает и сохраняет файл по указанному URL в указанную директорию dest.
"""
u = urllib2.urlopen(url)
scheme, netloc, path, query, fragment = urlparse.urlsplit(url)
filename = os.path.basename(path) or 'downloaded.file'
if dest:
filename = os.path.join(dest, filename)
with open(filename, 'wb') as f:
meta = u.info()
meta_func = meta.getheaders if hasattr(meta, 'getheaders') else meta.get_all
meta_length = meta_func("Content-Length")
file_size = int(meta_length[0]) if meta_length else None
print("Скачивание: {0} Размер: {1}".format(url, file_size))
file_size_dl = 0
block_sz = 8192
while True:
buffer = u.read(block_sz)
if not buffer:
break
file_size_dl += len(buffer)
f.write(buffer)
status = "{0:16}".format(file_size_dl)
if file_size:
status += " [{0:6.2f}%]".format(file_size_dl * 100 / file_size)
status += chr(13)
print(status, end="")
print()
return filename
if __name__ == "__main__": # Запускаем только если файл был вызван напрямую
print("Тестирование с загрузкой 10МБ")
url = "http://download.thinkbroadband.com/10MB.zip"
filename = download_file(url)
print(filename)
В этом коде исправлены некоторые моменты для повышения читаемости и совместимости между версиями Python 2 и 3. Он также обрабатывает ситуацию, когда имя файла отсутствует, и выводит прогресс загрузки в понятном формате.
Ответ на ваш вопрос о совместимости между Python 2 и Python 3 с использованием библиотеки six
выглядит следующим образом:
Существует простой, но эффективный способ, который обеспечивает совместимость с обеими версиями Python с помощью библиотеки six
. Вы можете использовать следующий код:
from six.moves import urllib
urllib.request.urlretrieve("http://www.example.com/songs/mp3.mp3", "mp3.mp3")
Этот код загружает файл mp3.mp3
с указанного URL и сохраняет его в текущей директории. Использование six.moves
позволяет вам писать универсальный код без необходимости беспокоиться о различиях в модулях между Python 2 и Python 3.
Следующие методы являются самым распространённым образом для загрузки файлов в Python:
urllib.urlretrieve('url_to_file', file_name)
urllib2.urlopen('url_to_file')
requests.get(url)
wget.download('url', file_name)
Обратите внимание, что urlopen
и urlretrieve
могут показывать плохую производительность при загрузке больших файлов (размером более 500 МБ). Метод requests.get
хранит файл в памяти до завершения загрузки.
Какой самый быстрый способ выполнить HTTP GET в Python?
Как выполнить URL-кодирование строки запроса в Python?
Почему используется string.join(list), а не list.join(string)?
Создание словаря с помощью генератора словарей
Найти все файлы с расширением .txt в директории на Python