Comment puis-je télécharger un fichier sur HTTP en utilisant Python?

j'ai un petit utilitaire que j'utilise pour télécharger un MP3 à partir d'un site web sur un horaire et puis construit/met à jour un fichier de podcast XML que j'ai évidemment ajouté à iTunes.

le traitement de texte qui crée/met à jour le fichier XML est écrit en Python. J'utilise wget à l'intérieur d'un fichier .bat de Windows pour télécharger le MP3 réel cependant. Je préférerais que L'utilitaire entier soit écrit en Python.

j'ai lutté pour trouver un moyen de en fait, charge le fichier en Python, c'est pourquoi j'ai utilisé wget .

alors, comment puis-je télécharger le fichier en utilisant Python?

707
demandé sur kilojoules 2008-08-22 19:34:13

21 réponses

en Python 2, Utilisez urllib2 qui est fourni avec la bibliothèque standard.

import urllib2
response = urllib2.urlopen('http://www.example.com/')
html = response.read()

c'est la façon la plus basique d'utiliser la bibliothèque, sans aucune manipulation d'erreur. Vous pouvez également faire des choses plus complexes comme changer les en-têtes. La documentation peut être trouvée ici.

391
répondu Corey 2014-06-05 11:06:21

un de plus, en utilisant urlretrieve :

import urllib
urllib.urlretrieve ("http://www.example.com/songs/mp3.mp3", "mp3.mp3")

(pour Python 3+ Utilisez 'importer urllib.demande' et urllib.demande.urlretrieve)

encore un autre, avec un "progressbar "

import urllib2

url = "http://download.thinkbroadband.com/10MB.zip"

file_name = url.split('/')[-1]
u = urllib2.urlopen(url)
f = open(file_name, 'wb')
meta = u.info()
file_size = int(meta.getheaders("Content-Length")[0])
print "Downloading: %s Bytes: %s" % (file_name, 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 = r"%10d  [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
    status = status + chr(8)*(len(status)+1)
    print status,

f.close()
963
répondu PabloG 2016-08-19 12:34:18

en 2012, utilisez la Python requests library

>>> import requests
>>> 
>>> url = "http://download.thinkbroadband.com/10MB.zip"
>>> r = requests.get(url)
>>> print len(r.content)
10485760

vous pouvez lancer pip install requests pour l'obtenir.

Les requêtes

présentent de nombreux avantages par rapport aux alternatives car L'API est beaucoup plus simple. Ceci est particulièrement vrai si vous devez faire l'authentification. urllib et urllib2 sont assez peu intuitive et douloureux dans ce cas.


2015-12-30

personnes ont exprimé leur admiration pour la barre de progrès. C'est cool, c'est sûr. Il existe maintenant plusieurs solutions disponibles sur le marché, y compris tqdm :

from tqdm import tqdm
import requests

url = "http://download.thinkbroadband.com/10MB.zip"
response = requests.get(url, stream=True)

with open("10MB", "wb") as handle:
    for data in tqdm(response.iter_content()):
        handle.write(data)

il s'agit essentiellement de la mise en œuvre @kvance décrite il y a 30 mois.

302
répondu hughdbrown 2015-12-31 16:45:47
import urllib2
mp3file = urllib2.urlopen("http://www.example.com/songs/mp3.mp3")
with open('test.mp3','wb') as output:
  output.write(mp3file.read())

le wb dans open('test.mp3','wb') ouvre un fichier (et efface tout fichier existant) en mode binaire de sorte que vous pouvez enregistrer des données avec elle au lieu de juste le texte.

148
répondu Grant 2016-03-10 17:14:43

Python 3

Python 2

69
répondu bmaupin 2018-01-03 14:00:12

une version améliorée du code PabloG pour Python 2/3:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import ( division, absolute_import, print_function, unicode_literals )

import sys, os, tempfile, logging

if sys.version_info >= (3,):
    import urllib.request as urllib2
    import urllib.parse as urlparse
else:
    import urllib2
    import urlparse

def download_file(url, dest=None):
    """ 
    Download and save a file specified by url to dest directory,
    """
    u = urllib2.urlopen(url)

    scheme, netloc, path, query, fragment = urlparse.urlsplit(url)
    filename = os.path.basename(path)
    if not filename:
        filename = '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 = None
        if meta_length:
            file_size = int(meta_length[0])
        print("Downloading: {0} Bytes: {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__":  # Only run if this file is called directly
    print("Testing with 10MB download")
    url = "http://download.thinkbroadband.com/10MB.zip"
    filename = download_file(url)
    print(filename)
18
répondu Stan 2017-08-06 06:32:19

a écrit wget bibliothèque en Python pur juste pour ce but. Il est gonflé urlretrieve avec ces caractéristiques à partir de la version 2.0.

16
répondu anatoly techtonik 2013-09-25 17:55:16

utiliser le module wget:

import wget
wget.download('url')
16
répondu Sara Santana 2015-03-25 12:59:25

je suis d'accord avec Corey, urllib2 est plus complet que urllib et devrait probablement être le module utilisé si vous voulez faire des choses plus complexes, mais pour rendre les réponses plus complètes, urllib est un module plus simple si vous voulez juste les bases:

import urllib
response = urllib.urlopen('http://www.example.com/sound.mp3')
mp3 = response.read()

marchera très bien. Ou, si vous ne voulez pas traiter avec l'objet "response" vous pouvez appeler read () directement:

import urllib
mp3 = urllib.urlopen('http://www.example.com/sound.mp3').read()
12
répondu akdom 2008-08-22 15:58:52

Simple encore Python 2 & Python 3 compatible manière revient avec six de la bibliothèque:

from six.moves import urllib
urllib.request.urlretrieve("http://www.example.com/songs/mp3.mp3", "mp3.mp3")
12
répondu Akif 2018-01-16 12:05:10

ci-dessous sont les appels les plus couramment utilisés pour télécharger des fichiers en 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)

Note: urlopen et urlretrieve sont disponibles pour effectuer relativement mal avec téléchargement de gros fichiers (Taille > 500 Mo). requests.get stocke le fichier en mémoire jusqu'à ce que le téléchargement soit terminé.

11
répondu Jaydev 2016-09-19 12:45:10

vous pouvez obtenir la rétroaction de progrès avec urlretrieve aussi bien:

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
répondu Marcin Cuprjak 2014-01-26 13:12:54

Si vous avez wget installé, vous pouvez utiliser 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

C'est assez puissant. Il peut télécharger des fichiers en parallèle , réessayer en cas de panne, et il peut même télécharger des fichiers sur une machine distante.

5
répondu max 2015-11-19 23:48:06

si la vitesse compte pour vous, j'ai fait un petit test de performance pour les modules urllib et wget , et en ce qui concerne wget j'ai essayé une fois avec barre d'état et une fois sans. J'ai pris trois différents fichiers de 500 Mo à tester (différents fichiers - pour éliminer la possibilité qu'il y ait une mise en cache sous le capot). Testé sur debian machine, avec python2.

tout D'abord, ce sont les résultats (ils sont similaires dans des passages différents):

$ 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
==============

la façon dont j'ai effectué le test est d'utiliser" profile " decorator. C'est le code complet:

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 semble être la manière la plus rapide

3
répondu Omer Dagan 2017-11-03 14:25:38

en python3 vous pouvez utiliser urllib3 et shutil libraires. Téléchargez - les en utilisant pip ou pip3 (selon que python3 est par défaut ou non)

pip3 install urllib3 shutil

puis lancez ce code

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)

notez que vous téléchargez urllib3 mais utilisez urllib dans le code

3
répondu Apoorv Agarwal 2018-02-08 17:37:15

le code Source peut être:

import urllib
sock = urllib.urlopen("http://diveintopython.org/")
htmlSource = sock.read()                            
sock.close()                                        
print htmlSource  
2
répondu Sherlock Smith 2013-11-26 14:25:14

j'ai écrit ce qui suit, qui fonctionne en vanilla Python 2 ou 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()

Notes:

  • supporte une fonction de rappel "progress bar".
  • Download est un test de 4 Mo .zip à partir de mon site web.
1
répondu imallett 2017-05-13 21:52:30

urlretrieve et des demandes.obtenir est simple, mais la réalité n'. J'ai récupéré des données pour deux sites, y compris du texte et des images, les deux ci-dessus résolvent probablement la plupart des tâches. mais pour une solution plus universelle, je suggère l'utilisation d'urlopen. Comme il est inclus dans la bibliothèque standard de Python 3, votre code pourrait fonctionner sur n'importe quelle machine qui exécute Python 3 sans pré-installer site-par

import urllib.request
url_request = urllib.request.Request(url, headers=headers)
url_connect = urllib.request.urlopen(url_request)
len_content = url_content.length

#remember to open file in bytes mode
with open(filename, 'wb') as f:
    while True:
        buffer = url_connect.read(buffer_size)
        if not buffer: break

        #an integer value of size of written data
        data_wrote = f.write(buffer)

#you could probably use with-open-as manner
url_connect.close()

cette réponse fournit une solution à HTTP 403 Interdit lorsque télécharger un fichier sur http en utilisant Python. J'ai essayé une seule demande et urllib modules, l'autre module peut fournir quelque chose de mieux, mais c'est celui que j'ai utilisé pour résoudre la plupart des problèmes.

0
répondu Sphynx-HenryAY 2017-03-13 13:12:19

c'est peut-être un peu tard, mais j'ai vu le code de pabloG et je n'ai pas pu m'empêcher d'ajouter un os.system('cls') pour en faire un super look! Check it out :

    import urllib2,os

    url = "http://download.thinkbroadband.com/10MB.zip"

    file_name = url.split('/')[-1]
    u = urllib2.urlopen(url)
    f = open(file_name, 'wb')
    meta = u.info()
    file_size = int(meta.getheaders("Content-Length")[0])
    print "Downloading: %s Bytes: %s" % (file_name, file_size)
    os.system('cls')
    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 = r"%10d  [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
        status = status + chr(8)*(len(status)+1)
        print status,

    f.close()

si vous exécutez dans un environnement autre que Windows, vous devrez utiliser quelque chose d'autre que 'cls'. Dans MAC OS X et Linux, cela devrait être "clair".

0
répondu JD3 2017-05-16 16:46:21

par souci d'exhaustivité, il est également possible d'appeler n'importe quel programme pour récupérer des fichiers en utilisant le paquet subprocess . Les programmes dédiés à la récupération de fichiers sont plus puissants que les fonctions Python comme urlretrieve , par exemple wget peut télécharger des répertoires de façon récursive ( -R ), peut traiter avec FTP, redirections, mandataires HTTP, peut éviter de télécharger à nouveau des fichiers existants ( -nc ), et aria2 peut paralléliser les téléchargements.

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

dans Jupyter Notebook, on peut aussi appeler des programmes directement avec la syntaxe ! :

!wget -O example_output_file.html https://example.com
0
répondu Robin Dinse 2018-08-29 12:24:49

vous pouvez utiliser PycURL sur Python 2 et 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()
0
répondu gzerone 2018-09-10 06:01:38