2011-08-30 16 views
167

Sto creando un programma che scaricherà un file .jar (java) da un server Web, leggendo l'URL specificato nel file .jad dello stesso gioco/applicazione. Sto usando Python 3.2.1Download del file dal web in Python 3

Sono riuscito a estrarre l'URL del file JAR dal file JAD (ogni file JAD contiene l'URL del file JAR), ma come puoi immaginare, il valore estratto è tipo() stringa.

Ecco la relativa funzione:

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

downloadFile(URL_from_file) 

Tuttavia ottengo sempre un errore che dice che il tipo nella funzione deve essere al di sopra di byte, e non stringa. Ho provato a utilizzare URL.encode ('utf-8') e anche byte (URL, encoding = 'utf-8'), ma ottengo sempre lo stesso errore o errore simile.

Quindi in sostanza la mia domanda è come scaricare un file da un server quando l'URL è memorizzato in un tipo di stringa?

+3

@alvas, A taglie per questo? Il rispondente è ancora (e abbastanza) attivo su SO. Perché non aggiungere un commento e chiedere? –

+2

Cos una buona risposta che dura la prova del tempo vale la pena premiare. Inoltre, dovremmo iniziare a farlo per molte altre domande per verificare se le risposte sono rilevanti oggi. Soprattutto quando lo smistamento delle risposte SO è piuttosto folle, a volte la risposta obsoleta o addirittura peggiore va in alto. – alvas

risposta

353

Se si desidera ottenere il contenuto di una pagina web in una variabile, basta read la risposta del 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 

Il modo più semplice per scaricare e salvare un file è quello di utilizzare il urllib.request.urlretrieve funzione:

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 (e.g. '/tmp/tmpb48zma.txt') in the `file_name` variable: 
file_name, headers = urllib.request.urlretrieve(url) 

Ma tieni presente che urlretrieve è considerato legacy e potrebbe diventare deprecato (non sono sicuro del perché, però).

Quindi la più corretta modo per farlo sarebbe quello di utilizzare la funzione urllib.request.urlopen per restituire un oggetto simile a file che rappresenta una risposta HTTP e copiarlo su un vero e proprio file 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) 

Se questo vi sembra troppo complicato, si consiglia di andare più semplice e memorizzare l'intero scaricare in un oggetto bytes e poi scrivere in un file. Ma questo funziona bene solo per i file di piccole dimensioni.

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) 

E 'possibile estrarre .gz (e forse altri formati) i dati compressi al volo, ma una simile operazione richiede probabilmente il server HTTP per supportare l'accesso casuale ai file.

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`. 
+7

potresti usare 'response.info(). Get_param ('charset', 'utf-8')' invece di hardcoding 'utf-8', per ottenere la codifica dei caratteri dall'intestazione' Content-Type' – jfs

+2

@OlehPrypin Perché 'outfile.write (data)' funziona bene solo per file di piccole dimensioni? – Startec

+0

"urlretrieve è considerato legacy e potrebbe diventare deprecato" dove hai preso quell'idea? –

11

Spero ho capito la domanda giusta, che è: come scaricare un file da un server quando l'URL viene memorizzato in un tipo stringa?

mi scaricare file e salvarlo localmente usando il codice seguente:

import requests 

url = 'https://www.python.org/static/img/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() 
+0

ciao, sto anche usando lo stesso tipo di codice per scaricare il file ma qualche volta ho affrontato un'eccezione come - il codec 'charmap' non può codificare il carattere '\ u010c' ... puoi aiutami con quello – Joyson

51

Io uso requests pacchetto ogni volta che voglio qualcosa legato alle richieste HTTP perché la sua API è molto facile per iniziare con:

primo , installare requests

$ pip install requests 

quindi il codice:

012.
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) 
+29

+1 per menzionare le "prime richieste di installazione". Questo tipo di cultura dovrebbe essere realizzato nello stackoverflow e nei siti vicini, supponendo che il pubblico sappia che tutti i bit di informazione sono errati. – TechJS

-2
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)) 
0

È possibile utilizzare wget che è popolare strumento di shell scaricano per questo. https://pypi.python.org/pypi/wget Questo sarà il metodo più semplice in quanto non è necessario aprire il file di destinazione. Ecco un esempio.

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') 
Problemi correlati