Question

J'ai un petit utilitaire que j'utilise pour télécharger un MP3 à partir d'un site web sur un calendrier, puis construit les mises à jour/un podcast fichier XML que je n'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 Windows .bat fichier à télécharger le réel MP3 cependant.Je préfère avoir l'intégralité de l'utilitaire écrit en Python si.

J'ai eu du mal mais pour trouver un moyen de télécharger le fichier en Python, donc pourquoi j'ai eu recours à wget.

Alors, comment puis-je télécharger le fichier à l'aide de Python?

Était-ce utile?

La solution

En Python 2, utilisez urllib2 qui vient avec la bibliothèque standard.

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

C'est la façon la plus simple d'utiliser la bibliothèque, moins toute erreur de manipulation.Vous pouvez également faire des trucs plus complexe comme la modification des en-têtes.La documentation peut être trouvée ici.

Autres conseils

Un de plus, à l'aide de urlretrieve:

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

(pour Python 3+ utilisation import urllib.request et urllib.request.urlretrieve)

Encore une 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()

En 2012, l'utilisation de la python demandes de la bibliothèque

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

Vous pouvez l'exécuter pip install requests pour l'obtenir.

Demandes a de nombreux avantages sur les solutions de rechange parce que l'API est beaucoup plus simple.Cela est particulièrement vrai si vous avez à faire de l'authentification.urllib et urllib2 sont assez peu intuitive et douloureux dans ce cas.


2015-12-30

Les gens ont exprimé leur admiration pour la barre de progression.C'est cool, c'est sûr.Il y a plusieurs solutions prêtes à l'emploi, 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 sur 30 mois.

import urllib2
mp3file = urllib2.urlopen("http://www.example.com/songs/mp3.mp3")
with open('test.mp3','wb') as output:
  output.write(mp3file.read())

L' wb dans open('test.mp3','wb') ouvre un fichier (et efface tous les fichiers existants) en mode binaire, de sorte que vous pouvez enregistrer des données au lieu de juste le texte.

Python 3

  • urllib.request.urlopen

    import urllib.request
    response = urllib.request.urlopen('http://www.example.com/')
    html = response.read()
    
  • urllib.request.urlretrieve

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

Python 2

  • urllib2.urlopen (merci Corey)

    import urllib2
    response = urllib2.urlopen('http://www.example.com/')
    html = response.read()
    
  • urllib.urlretrieve (merci PabloG)

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

utiliser wget module:

import wget
wget.download('url')

Une version améliorée de la PabloG code 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)

Écrit wget bibliothèque en pur Python juste pour ce but.Il est pompé vers le haut urlretrieve avec ces caractéristiques à partir de la version 2.0.

Simple mais Python 2 & Python 3 compatible est livré avec six bibliothèque:

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

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

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

Fonctionnera très bien.Ou, si vous ne voulez pas avoir affaire avec la "réponse" de l'objet, vous pouvez appeler lire() directement:

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

Suivants sont les plus couramment utilisées appels pour le téléchargement de 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 trouvé à effectuer relativement mal avec le téléchargement de gros fichiers (taille > 500 MO). requests.get stocke le fichier en mémoire jusqu'à ce que le téléchargement est terminé.

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")

Vous pouvez obtenir de l'avancement de la rétroaction avec urlretrieve ainsi:

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)

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, une nouvelle tentative en cas d'échec , et il peut même télécharger des fichiers sur une machine distante.

En python3 vous pouvez utiliser urllib3 et shutil libraires.Télécharger en utilisant pip ou pip3 (Selon que python3 est par défaut ou non)

pip3 install urllib3 shutil

Puis exécutez 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 l'utilisation de urllib dans le code

Si la vitesse de questions à 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érentes 500 mo de fichiers de test avec (fichiers différents - pour éliminer la possibilité qu'il y a de la mise en cache se cache sous le capot).Testé sur une machine debian, avec python2.

Tout d'abord, ce sont les résultats (ils sont semblables dans les différentes pistes):

$ 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 à l'aide de "profil" décorateur.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 le plus rapide

Juste par souci d'exhaustivité, il est également possible d'appeler n'importe quel programme pour récupérer des fichiers à l'aide de la subprocess package.Des programmes dédiés à la récupération de fichiers sont plus puissants que les fonctions Python comme urlretrieve.Par exemple, wget pouvez télécharger des répertoires de manière récursive (-R), peuvent traiter avec les FTP, les redirections, les serveurs proxy HTTP, peut éviter de re-télécharger les fichiers existants-nc), et aria2 pouvez faire de multi-connexion téléchargements qui peuvent potentiellement accélérer vos téléchargements.

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

Dans Jupyter ordinateur Portable, l'on peut aussi appeler des programmes directement avec les ! syntaxe:

!wget -O example_output_file.html https://example.com

Le code Source peut être:

import urllib
sock = urllib.urlopen("http://diveintopython.org/")
htmlSource = sock.read()                            
sock.close()                                        
print htmlSource  

J'ai écrit ce qui suit, qui travaille à la vanille Python 2 et 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:

  • Prend en charge une "barre de progression" de rappel.
  • Le téléchargement est un 4 MO de test .zip à partir de mon site web.

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()

Cela peut être un peu tard, Mais j'ai vu pabloG du code et ne pouvait pas aider l'ajout d'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 en cours d'exécution dans un environnement autre que Windows, vous devrez utiliser autre chose que 'cls'.Dans MAC OS X et Linux, il doit être "claire".

urlretrieve et des demandes.obtenir sont simples, mais la réalité n'.J'ai récupéré les données pour le couple de sites, y compris le texte et les images, les deux probablement résoudre la plupart des tâches.mais pour plus de solution universelle, je suggère l'utilisation de urlopen.Comme il est inclus dans Python 3 de la bibliothèque standard, votre code peut s'exécuter sur n'importe quel ordinateur d'exécuter Python 3, sans pré-installation de site-package

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

#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 pour HTTP 403 Forbidden lors du téléchargement de fichiers via http à l'aide de 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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top