Как мне загрузить файл через HTTP, используя Python? - PullRequest
775 голосов
/ 22 августа 2008

У меня есть небольшая утилита, которую я использую для загрузки MP3 с веб-сайта по расписанию, а затем для создания / обновления XML-файла подкаста, который я, очевидно, добавил в iTunes.

Обработка текста, который создает / обновляет файл XML, написана на Python. Однако я использую wget внутри файла Windows .bat, чтобы загрузить настоящий MP3. Я бы предпочел, чтобы вся утилита была написана на Python.

Я изо всех сил пытался найти способ фактически загрузить файл в Python, поэтому я прибег к wget.

Итак, как мне загрузить файл с помощью Python?

Ответы [ 22 ]

13 голосов
/ 05 ноября 2018
import os,requests
def download(url):
    get_response = requests.get(url,stream=True)
    file_name  = url.split("/")[-1]
    with open(file_name, 'wb') as f:
        for chunk in get_response.iter_content(chunk_size=1024):
            if chunk: # filter out keep-alive new chunks
                f.write(chunk)


download("https://example.com/example.jpg")
13 голосов
/ 19 сентября 2016

Ниже приведены наиболее часто используемые вызовы для загрузки файлов в Python:

  1. urllib.urlretrieve ('url_to_file', file_name)

  2. urllib2.urlopen('url_to_file')

  3. requests.get(url)

  4. wget.download('url', file_name)

Примечание: urlopen и urlretrieve работают относительно плохо при загрузке больших файлов (размер> 500 МБ). requests.get сохраняет файл в памяти до завершения загрузки.

7 голосов
/ 26 января 2014

Вы также можете получить отзыв о прогрессе с помощью urlretrieve:

def report(blocknr, blocksize, size):
    current = blocknr*blocksize
    sys.stdout.write("\r{0:.2f}%".format(100.0*current/size))

def downloadFile(url):
    print "\n",url
    fname = url.split('/')[-1]
    print fname
    urllib.urlretrieve(url, fname, report)
6 голосов
/ 20 ноября 2015

Если у вас установлен wget, вы можете использовать parallel_sync.

pip install parallel_sync

from parallel_sync import wget
urls = ['http://something.png', 'http://somthing.tar.gz', 'http://somthing.zip']
wget.download('/tmp', urls)
# or a single file:
wget.download('/tmp', urls[0], filenames='x.zip', extract=True)

Doc: https://pythonhosted.org/parallel_sync/pages/examples.html

Это довольно мощно. Он может загружать файлы параллельно, повторять попытки при сбое и даже загружать файлы на удаленном компьютере.

5 голосов
/ 08 февраля 2018

В python3 вы можете использовать библиотеки библиотек urllib3 и shutil. Загрузите их, используя pip или pip3 (в зависимости от того, используется ли python3 по умолчанию)

pip3 install urllib3 shutil

Затем запустите этот код

import urllib.request
import shutil

url = "http://www.somewebsite.com/something.pdf"
output_file = "save_this_name.pdf"
with urllib.request.urlopen(url) as response, open(output_file, 'wb') as out_file:
    shutil.copyfileobj(response, out_file)

Обратите внимание, что вы загружаете urllib3, но используете urllib в коде

4 голосов
/ 29 августа 2018

Для полноты картины можно также вызвать любую программу для получения файлов, используя пакет subprocess. Программы, предназначенные для извлечения файлов, более мощные, чем функции Python, такие как urlretrieve. Например, wget может рекурсивно загружать каталоги (-R), может работать с FTP, перенаправлениями, HTTP-прокси, может избежать повторной загрузки существующих файлов (-nc) и aria2 может выполнять загрузку с несколькими подключениями, что потенциально может ускорить загрузку.

import subprocess
subprocess.check_output(['wget', '-O', 'example_output_file.html', 'https://example.com'])

В Jupyter Notebook можно также вызывать программы напрямую с синтаксисом !:

!wget -O example_output_file.html https://example.com
4 голосов
/ 03 ноября 2017

Если скорость имеет значение для вас, я провел небольшой тест производительности для модулей urllib и wget, а в отношении wget я пробовал один раз со строкой состояния и один раз без. Я взял три разных файла размером 500 МБ для тестирования (разные файлы - чтобы исключить вероятность того, что под капотом происходит какое-то кэширование). Протестировано на машине Debian с python2.

Во-первых, это результаты (они похожи в разных прогонах):

$ python wget_test.py 
urlretrive_test : starting
urlretrive_test : 6.56
==============
wget_no_bar_test : starting
wget_no_bar_test : 7.20
==============
wget_with_bar_test : starting
100% [......................................................................] 541335552 / 541335552
wget_with_bar_test : 50.49
==============

Я выполнил тест с использованием декоратора профиля. Это полный код:

import wget
import urllib
import time
from functools import wraps

def profile(func):
    @wraps(func)
    def inner(*args):
        print func.__name__, ": starting"
        start = time.time()
        ret = func(*args)
        end = time.time()
        print func.__name__, ": {:.2f}".format(end - start)
        return ret
    return inner

url1 = 'http://host.com/500a.iso'
url2 = 'http://host.com/500b.iso'
url3 = 'http://host.com/500c.iso'

def do_nothing(*args):
    pass

@profile
def urlretrive_test(url):
    return urllib.urlretrieve(url)

@profile
def wget_no_bar_test(url):
    return wget.download(url, out='/tmp/', bar=do_nothing)

@profile
def wget_with_bar_test(url):
    return wget.download(url, out='/tmp/')

urlretrive_test(url1)
print '=============='
time.sleep(1)

wget_no_bar_test(url2)
print '=============='
time.sleep(1)

wget_with_bar_test(url3)
print '=============='
time.sleep(1)

urllib кажется самым быстрым

3 голосов
/ 26 ноября 2013

Исходный код может быть:

import urllib
sock = urllib.urlopen("http://diveintopython.org/")
htmlSource = sock.read()                            
sock.close()                                        
print htmlSource  
2 голосов
/ 08 августа 2018

Вы можете использовать PycURL на Python 2 и 3.

import pycurl

FILE_DEST = 'pycurl.html'
FILE_SRC = 'http://pycurl.io/'

with open(FILE_DEST, 'wb') as f:
    c = pycurl.Curl()
    c.setopt(c.URL, FILE_SRC)
    c.setopt(c.WRITEDATA, f)
    c.perform()
    c.close()
2 голосов
/ 14 мая 2017

Я написал следующее, которое работает в vanilla Python 2 или Python 3.


import sys
try:
    import urllib.request
    python3 = True
except ImportError:
    import urllib2
    python3 = False


def progress_callback_simple(downloaded,total):
    sys.stdout.write(
        "\r" +
        (len(str(total))-len(str(downloaded)))*" " + str(downloaded) + "/%d"%total +
        " [%3.2f%%]"%(100.0*float(downloaded)/float(total))
    )
    sys.stdout.flush()

def download(srcurl, dstfilepath, progress_callback=None, block_size=8192):
    def _download_helper(response, out_file, file_size):
        if progress_callback!=None: progress_callback(0,file_size)
        if block_size == None:
            buffer = response.read()
            out_file.write(buffer)

            if progress_callback!=None: progress_callback(file_size,file_size)
        else:
            file_size_dl = 0
            while True:
                buffer = response.read(block_size)
                if not buffer: break

                file_size_dl += len(buffer)
                out_file.write(buffer)

                if progress_callback!=None: progress_callback(file_size_dl,file_size)
    with open(dstfilepath,"wb") as out_file:
        if python3:
            with urllib.request.urlopen(srcurl) as response:
                file_size = int(response.getheader("Content-Length"))
                _download_helper(response,out_file,file_size)
        else:
            response = urllib2.urlopen(srcurl)
            meta = response.info()
            file_size = int(meta.getheaders("Content-Length")[0])
            _download_helper(response,out_file,file_size)

import traceback
try:
    download(
        "https://geometrian.com/data/programming/projects/glLib/glLib%20Reloaded%200.5.9/0.5.9.zip",
        "output.zip",
        progress_callback_simple
    )
except:
    traceback.print_exc()
    input()

Примечания:

  • Поддерживает обратный вызов «индикатор выполнения».
  • Загрузите 4-МБ тестовый ZIP-файл с моего веб-сайта.
...