Si tengo una URL que, cuando se envía en un navegador web, aparece un cuadro de diálogo para guardar un archivo zip, ¿cómo puedo capturar y descargar este archivo zip en Python?
Si tengo una URL que, cuando se envía en un navegador web, aparece un cuadro de diálogo para guardar un archivo zip, ¿cómo puedo capturar y descargar este archivo zip en Python?
Respuestas:
La mayoría de las personas recomiendan usarlo requests
si está disponible, y la requests
documentación lo recomienda para descargar y guardar datos sin procesar desde una URL:
import requests
def download_url(url, save_path, chunk_size=128):
r = requests.get(url, stream=True)
with open(save_path, 'wb') as fd:
for chunk in r.iter_content(chunk_size=chunk_size):
fd.write(chunk)
Dado que la respuesta pregunta sobre cómo descargar y guardar el archivo zip, no he entrado en detalles sobre la lectura del archivo zip. Vea una de las muchas respuestas a continuación para conocer las posibilidades.
Si por alguna razón no tiene acceso requests
, puede usar urllib.request
. Puede que no sea tan robusto como el anterior.
import urllib.request
def download_url(url, save_path):
with urllib.request.urlopen(url) as dl_file:
with open(save_path, 'wb') as out_file:
out_file.write(dl_file.read())
Finalmente, si todavía usa Python 2, puede usar urllib2.urlopen
.
from contextlib import closing
def download_url(url, save_path):
with closing(urllib2.urlopen(url)) as dl_file:
with open(save_path, 'wb') as out_file:
out_file.write(dl_file.read())
Por lo que puedo decir, la forma correcta de hacer esto es:
import requests, zipfile, StringIO
r = requests.get(zip_file_url, stream=True)
z = zipfile.ZipFile(StringIO.StringIO(r.content))
z.extractall()
por supuesto, querrá comprobar que el GET fue exitoso r.ok
.
Para python 3+, sustituya el módulo StringIO con el módulo io y use BytesIO en lugar de StringIO: aquí hay notas de la versión que mencionan este cambio.
import requests, zipfile, io
r = requests.get(zip_file_url)
z = zipfile.ZipFile(io.BytesIO(r.content))
z.extractall("/path/to/destination_directory")
z.extractall()
conz.extractall("/path/to/destination_directory")
urllib.request.urlretrieve(url, filename)
.
pd.read_table(z.open('filename'))
con lo anterior. Útil si tiene un enlace de URL zip que contiene varios archivos y solo está interesado en cargar uno.
Con la ayuda de esta publicación de blog , lo tengo funcionando con solo requests
. El punto de lo extraño stream
es que no necesitamos llamar content
a solicitudes grandes, lo que requeriría que se procesen todas a la vez, obstruyendo la memoria. El stream
evita esto iterando a través de los datos un fragmento a la vez.
url = 'https://www2.census.gov/geo/tiger/GENZ2017/shp/cb_2017_02_tract_500k.zip'
target_path = 'alaska.zip'
response = requests.get(url, stream=True)
handle = open(target_path, "wb")
for chunk in response.iter_content(chunk_size=512):
if chunk: # filter out keep-alive new chunks
handle.write(chunk)
handle.close()
Esto es lo que tengo para trabajar en Python 3:
import zipfile, urllib.request, shutil
url = 'http://www....myzipfile.zip'
file_name = 'myzip.zip'
with urllib.request.urlopen(url) as response, open(file_name, 'wb') as out_file:
shutil.copyfileobj(response, out_file)
with zipfile.ZipFile(file_name) as zf:
zf.extractall()
urllib.error.HTTPError: HTTP Error 302: The HTTP server returned a redirect error that would lead to an infinite loop.
?
Utilice urllib2.urlopen, o podría intentar usar el Requests
módulo excelente y evitar los dolores de cabeza de urllib2:
import requests
results = requests.get('url')
#pass results.content onto secondary processing...
zipfile
módulo: zip = zipfile.ZipFile(results.content)
. A continuación, sólo analizar a través de los archivos a través de ZipFile.namelist()
, ZipFile.open()
oZipFile.extractall()
Vine aquí buscando cómo guardar un archivo .bzip2. Permítanme pegar el código para otros que puedan venir a buscarlo.
url = "http://api.mywebsite.com"
filename = "swateek.tar.gz"
response = requests.get(url, headers=headers, auth=('myusername', 'mypassword'), timeout=50)
if response.status_code == 200:
with open(filename, 'wb') as f:
f.write(response.content)
Solo quería guardar el archivo como está.
Gracias a @yoavram por la solución anterior, mi ruta de URL se vinculó a una carpeta comprimida y encontré un error de BADZipfile (el archivo no es un archivo zip), y fue extraño si intenté varias veces recuperar la URL y descomprimirlo todo de repente, modifico un poco la solución. usando el método is_zipfile según aquí
r = requests.get(url, stream =True)
check = zipfile.is_zipfile(io.BytesIO(r.content))
while not check:
r = requests.get(url, stream =True)
check = zipfile.is_zipfile(io.BytesIO(r.content))
else:
z = zipfile.ZipFile(io.BytesIO(r.content))
z.extractall()