Descarga básica de archivos http y guardar en disco en python?

159

Soy nuevo en Python y he estado revisando las preguntas y respuestas de este sitio para obtener una respuesta a mi pregunta. Sin embargo, soy un principiante y me resulta difícil entender algunas de las soluciones. Necesito una solución muy básica.

¿Podría alguien explicarme una solución simple para 'Descargar un archivo a través de http' y 'Guardarlo en el disco, en Windows'?

Tampoco estoy seguro de cómo usar los módulos shutil y os.

El archivo que quiero descargar tiene menos de 500 MB y es un archivo .gz. Si alguien puede explicar cómo extraer el archivo y utilizar los archivos también, ¡sería genial!

Aquí hay una solución parcial, que escribí a partir de varias respuestas combinadas:

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

¿Podría alguien señalar errores (nivel principiante) y explicar métodos más fáciles para hacer esto?

¡Gracias!

Arvindch
fuente

Respuestas:

207

Una forma limpia de descargar un archivo es:

import urllib

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

Esto descarga un archivo de un sitio web y lo nombra file.gz. Esta es una de mis soluciones favoritas, desde Descargar una imagen a través de urllib y python .

Este ejemplo utiliza la urllibbiblioteca y recuperará directamente el archivo de una fuente.

Hielo azul
fuente
3
¡OK gracias! Pero, ¿hay alguna manera de hacerlo funcionar a través de solicitudes?
arvindch
55
¿Alguna posibilidad de guardar en /myfolder/file.gz?
John Snow
17
¿No hay mejor posibilidad que intentarlo tú mismo? :) Podría hacerlo con éxito testfile.retrieve("http://example.com/example.rpm", "/tmp/test.rpm").
Dharmit
18
Esto está en desuso desde Python 3.3, y la solución urllib.request.urlretrieve (ver la respuesta a continuación) es la forma 'moderna'
MichielB
1
¿Cuál es la mejor manera de agregar un nombre de usuario y contraseña a este código? TKS
Estefy
110

Como se menciona aquí :

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

EDIT:Si aún desea utilizar solicitudes, eche un vistazo a esta pregunta o esta .

dparpyani
fuente
1
urllib funcionará, sin embargo, muchas personas parecen recomendar el uso de solicitudes sobre urllib. ¿Porque eso?
arvindch
2
requestses extremadamente útil en comparación con urllibcuando se trabaja con una API REST. A menos que quiera hacer mucho más, esto debería ser bueno.
dparpyani
Ok, ahora he leído los enlaces que ha proporcionado para el uso de solicitudes. Estoy confundido acerca de cómo declarar la ruta del archivo, para guardar la descarga. ¿Cómo uso os y shutil para esto?
arvindch
62
Para Python3:import urllib.request urllib.request.urlretrieve(url, filename)
Flash
1
No puedo extraer el código de estado http con esto si la descarga falla
Aashish Thite
34

Yo uso wget .

¿Biblioteca simple y buena si quieres un ejemplo?

import wget

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

file_name = wget.download(file_url)

El módulo wget admite las versiones python 2 y python 3

Ali
fuente
33

Cuatro métodos que utilizan wget, urllib y 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 llamadas a funciones (4469842 llamadas primitivas) en 20.236 segundos

testRequest2 - 8580 llamadas a funciones (8574 llamadas primitivas) en 0.072 segundos

testUrllib - 3810 llamadas a funciones (3775 llamadas primitivas) en 0.036 segundos

testwget - 3489 llamadas a funciones en 0.020 segundos

Saurabh yadav
fuente
1
¿Cómo obtuvo el número de llamadas a funciones?
Abdelhak
30

Para Python3 + URLopener está en desuso. Y cuando lo use, obtendrá el error de la siguiente manera:

url_opener = urllib.URLopener () AttributeError: el módulo 'urllib' no tiene el atributo 'URLopener'

Entonces, intente:

import urllib.request 
urllib.request.urlretrieve(url, filename)
Om Sao
fuente
1
Extraño ... ¿Por qué nadie vota por esta respuesta cuando Python 2 quedó en desuso y solo esta solución debería funcionar correctamente ...
wowkin2
1
¡Convenido! Estaba tirando de mi cabello sobre las soluciones anteriores. ¡Ojalá pudiera votar 200 veces!
Yechiel K
5

Solución exótica de Windows

import subprocess

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

Comencé por este camino porque el wget de ESXi no está compilado con SSL y quería descargar un OVA del sitio web de un proveedor directamente en el host de ESXi que está al otro lado del mundo.

Tuve que desactivar el firewall (perezoso) / activar https editando las reglas (correcto)

creó el script de 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)

Las bibliotecas ESXi están un poco emparejadas, pero el instalador de comadrejas de código abierto parecía usar urllib para https ... así que me inspiró a seguir este camino

Jayme Snyder
fuente
-5

Otra forma limpia de guardar el archivo es esta:

import csv
import urllib

urllib.retrieve("your url goes here" , "output.csv")
Ala
fuente
Esto probablemente debería ser urllib.urlretrieveo urllib.URLopener().retrieveno está claro a qué te referías aquí.
Mateor
9
¿Por qué importa csv si solo nombra un archivo?
Azeezah M