Descargar archivo desde la web en Python 3

Estoy creando un progtwig que descargará un archivo .jar (java) desde un servidor web, leyendo la URL que se especifica en el archivo .jad del mismo juego / aplicación. Estoy usando Python 3.2.1

Me las arreglé para extraer la URL del archivo JAR del archivo JAD (cada archivo JAD contiene la URL del archivo JAR), pero como puede imaginar, el valor extraído es una cadena de tipo ().

Aquí está la función relevante:

def downloadFile(URL=None): import httplib2 h = httplib2.Http(".cache") resp, content = h.request(URL, "GET") return content downloadFile(URL_from_file) 

Sin embargo, siempre recibo un error que dice que el tipo en la función anterior tiene que ser bytes y no una cadena. He intentado usar el URL.encode (‘utf-8’) y también los bytes (URL, encoding = ‘utf-8’), pero siempre obtengo el mismo error o uno similar.

¿Así que básicamente mi pregunta es cómo descargar un archivo de un servidor cuando la URL se almacena en un tipo de cadena?

Si desea obtener el contenido de una página web en una variable, simplemente read la respuesta de urllib.request.urlopen :

 import urllib.request ... url = 'http://example.com/' response = urllib.request.urlopen(url) data = response.read() # a `bytes` object text = data.decode('utf-8') # a `str`; this step can't be used if data is binary 

La forma más fácil de descargar y guardar un archivo es usar la función urllib.request.urlretrieve :

 import urllib.request ... # Download the file from `url` and save it locally under `file_name`: urllib.request.urlretrieve(url, file_name) 
 import urllib.request ... # Download the file from `url`, save it in a temporary directory and get the # path to it (eg '/tmp/tmpb48zma.txt') in the `file_name` variable: file_name, headers = urllib.request.urlretrieve(url) 

Pero tenga en cuenta que urlretrieve se considera legado y puede quedar en desuso (aunque no estoy seguro de por qué).

Entonces, la forma más correcta de hacer esto sería usar la función urllib.request.urlopen para devolver un objeto similar a un archivo que representa una respuesta HTTP y copiarlo en un archivo real usando shutil.copyfileobj .

 import urllib.request import shutil ... # Download the file from `url` and save it locally under `file_name`: with urllib.request.urlopen(url) as response, open(file_name, 'wb') as out_file: shutil.copyfileobj(response, out_file) 

Si esto parece demasiado complicado, es posible que desee ir más simple y almacenar toda la descarga en un objeto de bytes y luego escribirlo en un archivo. Pero esto funciona bien solo para archivos pequeños.

 import urllib.request ... # Download the file from `url` and save it locally under `file_name`: with urllib.request.urlopen(url) as response, open(file_name, 'wb') as out_file: data = response.read() # a `bytes` object out_file.write(data) 

Es posible extraer datos comprimidos .gz (y quizás otros formatos) sobre la marcha, pero tal operación probablemente requiera que el servidor HTTP admita el acceso aleatorio al archivo.

 import urllib.request import gzip ... # Read the first 64 bytes of the file inside the .gz archive located at `url` url = 'http://example.com/something.gz' with urllib.request.urlopen(url) as response: with gzip.GzipFile(fileobj=response) as uncompressed: file_header = uncompressed.read(64) # a `bytes` object # Or do anything shown above using `uncompressed` instead of `response`. 

Utilizo el paquete de requests cuando quiero algo relacionado con las solicitudes HTTP porque su API es muy fácil para comenzar:

primero, instale las requests

 $ pip install requests 

entonces el código:

 from requests import get # to make GET request def download(url, file_name): # open in binary mode with open(file_name, "wb") as file: # get request response = get(url) # write to file file.write(response.content) 

Espero haber entendido bien la pregunta, que es: ¿cómo descargar un archivo desde un servidor cuando la URL se almacena en un tipo de cadena?

Descargo archivos y los guardo localmente usando el siguiente código:

 import requests url = 'http://sofes.miximages.com/python/python-logo.png' fileName = 'D:\Python\dwnldPythonLogo.png' req = requests.get(url) file = open(fileName, 'wb') for chunk in req.iter_content(100000): file.write(chunk) file.close() 

Aquí podemos usar la interfaz Legacy de urllib en Python3:

Las siguientes funciones y clases se portan desde el módulo urllib de Python 2 (a diferencia de urllib2). Podrían quedar en desuso en algún momento en el futuro.

Ejemplo (código de 2 líneas) :

 import urllib.request url = 'http://sofes.miximages.com/python/python-logo.png' urllib.request.urlretrieve(url, "logo.png") 

Puedes usar wget, que es la herramienta de descarga de shell más popular para eso. https://pypi.python.org/pypi/wget Este será el método más sencillo, ya que no necesita abrir el archivo de destino. Aquí hay un ejemplo.

 import wget url = 'https://i1.wp.com/python3.codes/wp-content/uploads/2015/06/Python3-powered.png?fit=650%2C350' wget.download(url, '/Users/scott/Downloads/cat4.jpg') 
 from urllib import request def get(url): with request.urlopen(url) as r: return r.read() def download(url, file=None): if not file: file = url.split('/')[-1] with open(file, 'wb') as f: f.write(get(url))