web-dev-qa-db-fra.com

Téléchargez le fichier à partir du Web dans Python 3

Je crée un programme qui téléchargera un fichier .jar (Java) à partir d'un serveur Web en lisant l'URL spécifiée dans le fichier .jad du même jeu/de la même application. J'utilise Python 3.2.1

J'ai réussi à extraire l'URL du fichier JAR du fichier JAD (chaque fichier JAD contient l'URL du fichier JAR), mais comme vous pouvez l'imaginer, la valeur extraite est la chaîne type ().

Voici la fonction pertinente:

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

downloadFile(URL_from_file)

Cependant, j'obtiens toujours une erreur disant que le type dans la fonction ci-dessus doit être en octets et non en chaîne. J'ai essayé d'utiliser l'URL.encode ('utf-8'), ainsi que des octets (URL, encoding = 'utf-8'), mais j'obtiendrais toujours la même erreur ou une erreur similaire.

Donc, fondamentalement, ma question est de savoir comment télécharger un fichier à partir d’un serveur lorsque l’URL est stockée dans un type de chaîne.

275
Bo Milanovich

Si vous souhaitez obtenir le contenu d’une page Web dans une variable, il vous suffit de read la réponse 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
_

Le moyen le plus simple de télécharger et d’enregistrer un fichier est d’utiliser la fonction 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 (e.g. '/tmp/tmpb48zma.txt') in the `file_name` variable:
file_name, headers = urllib.request.urlretrieve(url)
_

Mais gardez à l'esprit que urlretrieve est considéré hérité et peut devenir obsolète (vous ne savez pas pourquoi, cependant).

Donc, le moyen le plus correct consiste à utiliser le urllib.request.urlopen fonction pour renvoyer un objet de type fichier représentant une réponse HTTP et le copier dans un fichier réel à l'aide de 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 cela semble trop compliqué, vous voudrez peut-être aller plus simple et stocker le téléchargement complet dans un objet bytes, puis l'écrire dans un fichier. Mais cela ne fonctionne que pour les petits fichiers.

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

Il est possible d'extraire des données compressées _.gz_ (et peut-être d'autres formats) à la volée, mais une telle opération nécessite probablement que le serveur HTTP prenne en charge un accès aléatoire au fichier.

_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`.
_
547
Oleh Prypin

J'utilise le paquet requests chaque fois que je veux quelque chose lié aux requêtes HTTP car son API est très facile à utiliser:

d'abord, installez requests

$ pip install requests

alors le code:

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)
115
Ali Faki

J'espère avoir bien compris la question: comment télécharger un fichier à partir d'un serveur lorsque l'URL est stockée dans un type de chaîne?

Je télécharge des fichiers et les enregistre localement en utilisant le code ci-dessous:

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()
13
Ranvijay Kumar

Ici, nous pouvons utiliser l'interface Legacy d'urllib en Python3:

Les fonctions et les classes suivantes sont portées à partir de l'urllib du module Python 2 (par opposition à urllib2). Ils pourraient devenir obsolètes à un moment donné dans le futur.

Exemple (code de 2 lignes):

import urllib.request

url = 'https://www.python.org/static/img/python-logo.png'
urllib.request.urlretrieve(url, "logo.png")
7
Yang Yu

Vous pouvez utiliser wget qui est un outil de téléchargement populaire pour Shell. https://pypi.python.org/pypi/wget Ce sera la méthode la plus simple car il n’est pas nécessaire d’ouvrir le fichier de destination. Voici un exemple.

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') 
6
Lasith Niroshan

Oui, definietly request est un excellent package à utiliser dans un domaine lié aux requêtes HTTP. mais nous devons être prudents avec le type de codage des données entrantes. En voici un exemple qui explique la différence


from requests import get

# case when the response is byte array
url = 'some_image_url'

response = get(url)
with open('output', 'wb') as file:
    file.write(response.content)


# case when the response is text
# Here unlikely if the reponse content is of type **iso-8859-1** we will have to override the response encoding
url = 'some_page_url'

response = get(url)
# override encoding by real educated guess as provided by chardet
r.encoding = r.apparent_encoding

with open('output', 'w', encoding='utf-8') as file:
    file.write(response.content)

1
Kaushal