from - urllib.urlencode python 3
¿Cómo descargo un archivo a través de HTTP usando Python? (22)
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
(gracias Corey )import urllib2 response = urllib2.urlopen(''http://www.example.com/'') html = response.read()
urllib.urlretrieve
(gracias PabloG )import urllib urllib.urlretrieve(''http://www.example.com/songs/mp3.mp3'', ''mp3.mp3'')
Tengo una pequeña utilidad que uso para descargar un MP3 de un sitio web en un horario y luego compilo / actualizo un archivo XML de podcast que obviamente he agregado a iTunes.
El procesamiento de texto que crea / actualiza el archivo XML está escrito en Python. Sin embargo, uso wget dentro de un archivo .bat
Windows para descargar el MP3 real. Sin embargo, preferiría tener toda la utilidad escrita en Python.
Sin embargo, luché por encontrar una manera de descargar el archivo en Python, y por eso recurrí a wget
.
Entonces, ¿cómo descargo el archivo usando Python?
El código fuente puede ser:
import urllib
sock = urllib.urlopen("http://diveintopython.org/")
htmlSource = sock.read()
sock.close()
print htmlSource
En 2012, usa la biblioteca de peticiones python.
>>> import requests
>>>
>>> url = "http://download.thinkbroadband.com/10MB.zip"
>>> r = requests.get(url)
>>> print len(r.content)
10485760
Puede ejecutar pip install requests
para obtenerlo.
Las solicitudes tienen muchas ventajas sobre las alternativas porque la API es mucho más simple. Esto es especialmente cierto si tiene que hacer autenticación. urllib y urllib2 son bastante poco intuitivos y dolorosos en este caso.
2015-12-30
La gente ha expresado admiración por la barra de progreso. Está bien, claro. Ahora hay varias soluciones disponibles, incluyendo 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)
Esta es esencialmente la implementación @kvance descrita hace 30 meses.
En Python 2, use urllib2 que viene con la biblioteca estándar.
import urllib2
response = urllib2.urlopen(''http://www.example.com/'')
html = response.read()
Esta es la forma más básica de usar la biblioteca, menos cualquier manejo de errores. También puedes hacer cosas más complejas como cambiar los encabezados. La documentación se puede encontrar here.
En python3 puedes usar urllib3 y shutil libraires. Descárguelos utilizando pip o pip3 (dependiendo de si Python3 es predeterminado o no)
pip3 install urllib3 shutil
Entonces ejecuta este codigo
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)
Tenga en cuenta que descarga urllib3
pero usa urllib
en el código
Escribí lo siguiente, que funciona en vainilla Python 2 o 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()
Notas:
- Es compatible con una devolución de llamada "barra de progreso".
- Descargar es un archivo .zip de prueba de 4 MB de mi sitio web.
Escribió wget library en Python puro solo para este propósito. Se bombea urlretrieve
con estas características a partir de la versión 2.0.
Esto puede ser un poco tarde, pero vi el código de pabloG y no pude evitar agregar un os.system (''cls'') para que se viera INCREÍBLE! Echale un vistazo :
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 se ejecuta en un entorno que no sea Windows, tendrá que usar algo que no sea ''cls''. En MAC OS X y Linux debería estar ''claro''.
Estoy de acuerdo con Corey, urllib2 es más completo que urllib y probablemente debería ser el módulo utilizado si quiere hacer cosas más complejas, pero para que las respuestas sean más completas, urllib es un módulo más simple si solo desea lo básico:
import urllib
response = urllib.urlopen(''http://www.example.com/sound.mp3'')
mp3 = response.read()
Funcionará bien. O, si no desea tratar el objeto de "respuesta", puede llamar a read () directamente:
import urllib
mp3 = urllib.urlopen(''http://www.example.com/sound.mp3'').read()
Las siguientes son las llamadas más utilizadas para descargar archivos en python:
urllib.urlretrieve (''url_to_file'', file_name)
urllib2.urlopen(''url_to_file'')
requests.get(url)
wget.download(''url'', file_name)
Nota: se encuentra que urlopen
y urlretrieve
tienen un rendimiento relativamente malo con la descarga de archivos grandes (tamaño> 500 MB). requests.get
almacena el archivo en memoria hasta que se completa la descarga.
Puedes usar PycURL en Python 2 y 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()
Si la velocidad es importante para usted, hice una pequeña prueba de rendimiento para los módulos urllib
y wget
, y con respecto a wget
probé una vez con la barra de estado y una vez sin. Tomé tres archivos diferentes de 500 MB para probarlos (diferentes archivos, para eliminar la posibilidad de que haya un poco de almacenamiento en caché bajo el capó). Probado en la máquina debian, con python2.
Primero, estos son los resultados (son similares en diferentes ejecuciones):
$ 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 forma en que realicé la prueba es usando el decorador "perfil". Este es el código completo:
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
parece ser el más rápido
Si tiene instalado wget, puede usar parallel_sync.
pip instalar 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
Esto es bastante poderoso. Puede descargar archivos en paralelo, reintentar en caso de falla, e incluso puede descargar archivos en una máquina remota.
Sin embargo, la forma simple Python 2 & Python 3
compatible con Python 2 & Python 3
incluye six
bibliotecas:
from six.moves import urllib
urllib.request.urlretrieve("http://www.example.com/songs/mp3.mp3", "mp3.mp3")
Solo por estar completo, también es posible llamar a cualquier programa para recuperar archivos utilizando el paquete de subprocess
. Los programas dedicados a recuperar archivos son más poderosos que las funciones de Python como urlretrieve
, por ejemplo, wget
puede descargar directorios de forma recursiva ( -R
), puede manejar FTP, redireccionamientos, proxies HTTP, puede evitar volver a descargar archivos existentes ( -nc
), y aria2
puede paralelizar las descargas.
import subprocess
subprocess.check_output([''wget'', ''-O'', ''example_output_file.html'', ''https://example.com''])
En Jupyter Notebook, también se puede llamar a programas directamente con el !
sintaxis:
!wget -O example_output_file.html https://example.com
También puede obtener la retroalimentación de progreso con 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)
Una más, usando urlretrieve
:
import urllib
urllib.urlretrieve ("http://www.example.com/songs/mp3.mp3", "mp3.mp3")
(para Python 3+, use ''import urllib.request'' y urllib.request.urlretrieve)
Otra más, con una "barra de progreso".
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()
Una versión mejorada del código PabloG para 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)
urlretrieve y requests.get es simple, sin embargo la realidad no. He recuperado datos para sitios de parejas, incluidos texto e imágenes, los dos anteriores probablemente resuelven la mayoría de las tareas. pero para una solución más universal sugiero el uso de urlopen. Como se incluye en la biblioteca estándar de Python 3, su código podría ejecutarse en cualquier máquina que ejecute Python 3 sin preinstalar el sitio
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()
Esta respuesta proporciona una solución a HTTP 403 Prohibido cuando se descarga un archivo a través de http usando Python. He intentado solo solicitudes y módulos urllib, el otro módulo puede proporcionar algo mejor, pero este es el que utilicé para resolver la mayoría de los problemas.
utilizar el módulo wget:
import wget
wget.download(''url'')
import urllib2
mp3file = urllib2.urlopen("http://www.example.com/songs/mp3.mp3")
with open(''test.mp3'',''wb'') as output:
output.write(mp3file.read())
El wb
en open(''test.mp3'',''wb'')
abre un archivo (y borra cualquier archivo existente) en modo binario para que pueda guardar datos en lugar de solo texto.
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")