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?
Probé la sección Descargar un archivo binario y escribirlo en el disco de esta página que funcionó como chram.
Zeinab Abbasimazar
Respuestas:
32
La mayoría de las personas recomiendan usarlo requestssi está disponible, y la requestsdocumentación lo recomienda para descargar y guardar datos sin procesar desde una URL:
import requests
defdownload_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
defdownload_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
defdownload_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())
¿Puede agregar el fragmento de muestra también? Sería muy amable de su parte hacerlo
Sarvagya Dubey
203
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")
yoavram, en su código, ¿dónde ingreso la url de la página web?
newGIS
25
Si desea guardar el archivo descargado en una ubicación diferente, reemplácelo z.extractall()conz.extractall("/path/to/destination_directory")
user799188
1
Si lo que desea guardar el archivo de la URL que puede hacer: urllib.request.urlretrieve(url, filename).
yoavram
3
Para ayudar a otros a conectar los puntos que me tomó 60 minutos de más, puedes usarlo 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.
Viernes
12
Con la ayuda de esta publicación de blog , lo tengo funcionando con solo requests. El punto de lo extraño streames que no necesitamos llamar contenta solicitudes grandes, lo que requeriría que se procesen todas a la vez, obstruyendo la memoria. El streamevita 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()
Las respuestas no deben depender de enlaces para la mayor parte de su contenido. Los enlaces pueden dejar de funcionar o el contenido del otro lado se puede cambiar para que ya no responda la pregunta. Edite su respuesta para incluir un resumen o una explicación de la información a la que apunta el enlace.
mypetlion
7
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()
Hola. ¿Cómo puedo evitar este error urllib.error.HTTPError: HTTP Error 302: The HTTP server returned a redirect error that would lead to an infinite loop.?
Victor M Herasme Perez
@VictorHerasmePerez, un código de estado de respuesta HTTP 302 significa que la página se ha movido. Creo que el problema que enfrenta se aborda aquí: stackoverflow.com/questions/32569934/…
Webucator
5
Utilice urllib2.urlopen, o podría intentar usar el Requestsmódulo excelente y evitar los dolores de cabeza de urllib2:
Utilice el zipfilemó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()
aravenel
5
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)
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))
whilenot 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()
Respuestas:
La mayoría de las personas recomiendan usarlo
requests
si está disponible, y larequests
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 usarurllib.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())
fuente
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")
fuente
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ñostream
es que no necesitamos llamarcontent
a solicitudes grandes, lo que requeriría que se procesen todas a la vez, obstruyendo la memoria. Elstream
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()
fuente
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()
fuente
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...
fuente
zipfile
módulo:zip = zipfile.ZipFile(results.content)
. A continuación, sólo analizar a través de los archivos a través deZipFile.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á.
fuente
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()
fuente