Téléchargement de fichiers http de base et enregistrement sur disque en python?

159

Je suis nouveau sur Python et j'ai parcouru les questions / réponses sur ce site, pour une réponse à ma question. Cependant, je suis un débutant et j'ai du mal à comprendre certaines des solutions. J'ai besoin d'une solution très basique.

Quelqu'un pourrait-il m'expliquer une solution simple pour «Télécharger un fichier via http» et «Enregistrer sur le disque, sous Windows»?

Je ne sais pas non plus comment utiliser les modules shutil et os.

Le fichier que je veux télécharger fait moins de 500 Mo et est un fichier d'archive .gz. Si quelqu'un peut expliquer comment extraire l'archive et utiliser les fichiers qu'il contient également, ce serait génial!

Voici une solution partielle, que j'ai écrite à partir de diverses réponses combinées:

import requests
import os
import shutil

global dump

def download_file():
    global dump
    url = "http://randomsite.com/file.gz"
    file = requests.get(url, stream=True)
    dump = file.raw

def save_file():
    global dump
    location = os.path.abspath("D:\folder\file.gz")
    with open("file.gz", 'wb') as location:
        shutil.copyfileobj(dump, location)
    del dump

Quelqu'un pourrait-il signaler des erreurs (niveau débutant) et expliquer des méthodes plus simples pour le faire?

Merci!

Arvindch
la source

Réponses:

207

Une manière propre de télécharger un fichier est:

import urllib

testfile = urllib.URLopener()
testfile.retrieve("http://randomsite.com/file.gz", "file.gz")

Cela télécharge un fichier à partir d'un site Web et le nomme file.gz. C'est l'une de mes solutions préférées, depuis le téléchargement d'une image via urllib et python .

Cet exemple utilise la urllibbibliothèque, et il récupérera directement le fichier d'une source.

Glace bleue
la source
3
OK merci! Mais y a-t-il un moyen de le faire fonctionner grâce aux demandes?
arvindch
5
Une possibilité de sauvegarder dans /myfolder/file.gz?
John Snow
17
Pas de meilleure possibilité que de l'essayer vous-même, peut-être? :) Je pourrais réussir testfile.retrieve("http://example.com/example.rpm", "/tmp/test.rpm").
Dharmit le
18
Ceci est obsolète depuis Python 3.3, et la solution urllib.request.urlretrieve (voir la réponse ci-dessous) est la méthode `` moderne ''
MichielB
1
Quelle est la meilleure façon d'ajouter un nom d'utilisateur et un mot de passe à ce code? tks
Estefy
110

Comme mentionné ici :

import urllib
urllib.urlretrieve ("http://randomsite.com/file.gz", "file.gz")

EDIT:Si vous souhaitez toujours utiliser des requêtes, jetez un œil à cette question ou à celle-ci .

dparpyani
la source
1
urllib fonctionnera, cependant, de nombreuses personnes semblent recommander l'utilisation de requêtes sur urllib. Pourquoi ça?
arvindch
2
requestsest extrêmement utile par rapport à l'utilisation urllibd'une API REST. À moins que vous ne cherchiez à faire beaucoup plus, cela devrait être une bonne chose.
dparpyani
Ok, maintenant j'ai lu les liens que vous avez fournis pour l'utilisation des demandes. Je ne sais pas comment déclarer le chemin du fichier, pour enregistrer le téléchargement. Comment utiliser os et shutil pour cela?
arvindch
62
Pour Python3:import urllib.request urllib.request.urlretrieve(url, filename)
Flash
1
Je ne suis pas en mesure d'extraire le code d'état http avec cela si le téléchargement échoue
Aashish Thite
34

J'utilise wget .

Bibliothèque simple et bonne si vous voulez donner des exemples?

import wget

file_url = 'http://johndoe.com/download.zip'

file_name = wget.download(file_url)

le module wget prend en charge les versions python 2 et python 3

Ali
la source
33

Quatre méthodes utilisant wget, urllib et request.

#!/usr/bin/python
import requests
from StringIO import StringIO
from PIL import Image
import profile as profile
import urllib
import wget


url = 'https://tinypng.com/images/social/website.jpg'

def testRequest():
    image_name = 'test1.jpg'
    r = requests.get(url, stream=True)
    with open(image_name, 'wb') as f:
        for chunk in r.iter_content():
            f.write(chunk)

def testRequest2():
    image_name = 'test2.jpg'
    r = requests.get(url)
    i = Image.open(StringIO(r.content))
    i.save(image_name)

def testUrllib():
    image_name = 'test3.jpg'
    testfile = urllib.URLopener()
    testfile.retrieve(url, image_name)

def testwget():
    image_name = 'test4.jpg'
    wget.download(url, image_name)

if __name__ == '__main__':
    profile.run('testRequest()')
    profile.run('testRequest2()')
    profile.run('testUrllib()')
    profile.run('testwget()')

testRequest - 4469882 appels de fonction (4469842 appels primitifs) en 20,236 secondes

testRequest2 - 8580 appels de fonction (8574 appels primitifs) en 0,072 seconde

testUrllib - 3810 appels de fonction (3775 appels primitifs) en 0,036 seconde

testwget - 3489 appels de fonction en 0,020 seconde

Saurabh yadav
la source
1
Comment avez-vous obtenu le nombre d'appels de fonction?
Abdelhak
30

Pour Python3 + URLopener est obsolète. Et lorsqu'il est utilisé, vous obtiendrez une erreur comme ci-dessous:

url_opener = urllib.URLopener () AttributeError: le module 'urllib' n'a pas d'attribut 'URLopener'

Alors, essayez:

import urllib.request 
urllib.request.urlretrieve(url, filename)
Om Sao
la source
1
Bizarre ... Pourquoi personne ne vote pour cette réponse lorsque Python 2 est devenu obsolète et que seule cette solution devrait fonctionner correctement ...
wowkin2
1
D'accord! Je tirais mes cheveux sur les solutions précédentes. J'aimerais pouvoir voter 200 fois!
Yechiel K le
5

Solution Windows exotique

import subprocess

subprocess.run("powershell Invoke-WebRequest {} -OutFile {}".format(your_url, filename), shell=True)
Max
la source
1

J'ai commencé dans cette voie car le wget d'ESXi n'est pas compilé avec SSL et je voulais télécharger un OVA à partir du site Web d'un fournisseur directement sur l'hôte ESXi qui se trouve à l'autre bout du monde.

J'ai dû désactiver le pare-feu (paresseux) / activer https en modifiant les règles (correct)

a créé le script python:

import ssl
import shutil
import tempfile
import urllib.request
context = ssl._create_unverified_context()

dlurl='https://somesite/path/whatever'
with urllib.request.urlopen(durl, context=context) as response:
    with open("file.ova", 'wb') as tmp_file:
        shutil.copyfileobj(response, tmp_file)

Les bibliothèques ESXi sont en quelque sorte jumelées, mais l'installateur open source de belette semblait utiliser urllib pour https ... donc cela m'a inspiré à suivre cette voie

Jayme Snyder
la source
-5

Une autre façon propre d'enregistrer le fichier est la suivante:

import csv
import urllib

urllib.retrieve("your url goes here" , "output.csv")
Ala
la source
Cela devrait probablement être urllib.urlretrieveou urllib.URLopener().retrievenon ce que vous vouliez dire ici.
mateor
9
Pourquoi importez-vous csv si vous ne faites que nommer un fichier?
Azeezah M