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?
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.
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()
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.
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.
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.
Python 3
-
import urllib.request response = urllib.request.urlopen('http://www.example.com/') html = response.read()
-
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')
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)
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.
utiliser le module wget:
import wget
wget.download('url')
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()
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")
ci-dessous sont les appels les plus couramment utilisés pour télécharger des fichiers en python:
-
urllib.urlretrieve ('url_to_file', file_name)
-
urllib2.urlopen('url_to_file')
-
requests.get(url)
-
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é.
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)
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.
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
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
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 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.
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.
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".
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
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()