Pregunta

Estoy descargando un directorio completo desde un servidor web.Funciona bien, pero no sé cómo obtener el tamaño del archivo antes de descargarlo para comparar si se actualizó en el servidor o no.¿Se puede hacer esto como si estuviera descargando el archivo desde un servidor FTP?

import urllib
import re

url = "http://www.someurl.com"

# Download the page locally
f = urllib.urlopen(url)
html = f.read()
f.close()

f = open ("temp.htm", "w")
f.write (html)
f.close()

# List only the .TXT / .ZIP files
fnames = re.findall('^.*<a href="(\w+(?:\.txt|.zip)?)".*$', html, re.MULTILINE)

for fname in fnames:
    print fname, "..."

    f = urllib.urlopen(url + "/" + fname)

    #### Here I want to check the filesize to download or not #### 
    file = f.read()
    f.close()

    f = open (fname, "w")
    f.write (file)
    f.close()

@Jon:gracias por tu rápida respuesta.Funciona, pero el tamaño del archivo en el servidor web es ligeramente menor que el tamaño del archivo descargado.

Ejemplos:

Local Size  Server Size
 2.223.533  2.115.516
   664.603    662.121

¿Tiene algo que ver con la conversión CR/LF?

¿Fue útil?

Solución

He reproducido lo que estás viendo:

import urllib, os
link = "http://python.org"
print "opening url:", link
site = urllib.urlopen(link)
meta = site.info()
print "Content-Length:", meta.getheaders("Content-Length")[0]

f = open("out.txt", "r")
print "File on disk:",len(f.read())
f.close()


f = open("out.txt", "w")
f.write(site.read())
site.close()
f.close()

f = open("out.txt", "r")
print "File on disk after download:",len(f.read())
f.close()

print "os.stat().st_size returns:", os.stat("out.txt").st_size

Produce esto:

opening url: http://python.org
Content-Length: 16535
File on disk: 16535
File on disk after download: 16535
os.stat().st_size returns: 16861

¿Qué estoy haciendo mal aquí?¿os.stat().st_size no devuelve el tamaño correcto?


Editar:Bien, descubrí cuál era el problema:

import urllib, os
link = "http://python.org"
print "opening url:", link
site = urllib.urlopen(link)
meta = site.info()
print "Content-Length:", meta.getheaders("Content-Length")[0]

f = open("out.txt", "rb")
print "File on disk:",len(f.read())
f.close()


f = open("out.txt", "wb")
f.write(site.read())
site.close()
f.close()

f = open("out.txt", "rb")
print "File on disk after download:",len(f.read())
f.close()

print "os.stat().st_size returns:", os.stat("out.txt").st_size

esto genera:

$ python test.py
opening url: http://python.org
Content-Length: 16535
File on disk: 16535
File on disk after download: 16535
os.stat().st_size returns: 16535

Asegúrese de abrir ambos archivos para lectura/escritura binaria.

// open for binary write
open(filename, "wb")
// open for binary read
open(filename, "rb")

Otros consejos

Usando el método de objeto-urllib-devuelto info(), puede obtener diversa información sobre el documento recuperado.Ejemplo de cómo tomar el logotipo actual de Google:

>>> import urllib
>>> d = urllib.urlopen("http://www.google.co.uk/logos/olympics08_opening.gif")
>>> print d.info()

Content-Type: image/gif
Last-Modified: Thu, 07 Aug 2008 16:20:19 GMT  
Expires: Sun, 17 Jan 2038 19:14:07 GMT 
Cache-Control: public 
Date: Fri, 08 Aug 2008 13:40:41 GMT 
Server: gws 
Content-Length: 20172 
Connection: Close

Es un dict, así que para obtener el tamaño del archivo, debes urllibobject.info()['Content-Length']

print f.info()['Content-Length']

Y para obtener el tamaño del archivo local (para comparar), puedes usar el comando os.stat():

os.stat("/the/local/file.zip").st_size

El tamaño del archivo se envía como encabezado de longitud del contenido.Aquí se explica cómo obtenerlo con urllib:

>>> site = urllib.urlopen("http://python.org")
>>> meta = site.info()
>>> print meta.getheaders("Content-Length")
['16535']
>>>

Además, si el servidor al que te estás conectando lo admite, mira Etiquetas electrónicas y el Si-modificado-desde y Si ninguno coincide encabezados.

Su uso aprovechará las reglas de almacenamiento en caché del servidor web y devolverá un 304 No modificado código de estado si el contenido no ha cambiado.

En Python3:

>>> import urllib.request
>>> site = urllib.request.urlopen("http://python.org")
>>> print("FileSize: ", site.length)

Para un enfoque de python3 (probado en 3.5), recomendaría:

with urlopen(file_url) as in_file, open(local_file_address, 'wb') as out_file:
    print(in_file.getheader('Content-Length'))
    out_file.write(response.read())

A peticiones-solución basada en HEAD en lugar de GET (también imprime encabezados HTTP):

#!/usr/bin/python
# display size of a remote file without downloading

from __future__ import print_function
import sys
import requests

# number of bytes in a megabyte
MBFACTOR = float(1 << 20)

response = requests.head(sys.argv[1], allow_redirects=True)

print("\n".join([('{:<40}: {}'.format(k, v)) for k, v in response.headers.items()]))
size = response.headers.get('content-length', 0)
print('{:<40}: {:.2f} MB'.format('FILE SIZE', int(size) / MBFACTOR))

Uso

$ python filesize-remote-url.py https://httpbin.org/image/jpeg
...
Content-Length                          : 35588
FILE SIZE (MB)                          : 0.03 MB
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top