Obter tamanho de um arquivo antes de baixar em Python

votos
34

Eu estou baixando um diretório inteiro de um servidor web. Ele funciona bem, mas eu não consigo descobrir como obter o tamanho do arquivo antes de baixar para comparar se ele foi atualizado no servidor ou não. isso pode ser feito como se eu fosse o download do arquivo a partir de um 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: obrigado pela sua resposta rápida. Ele funciona, mas o tamanho do arquivo no servidor web é ligeiramente menor do que o tamanho do arquivo do arquivo baixado.

Exemplos:

Local Size  Server Size
 2.223.533  2.115.516
   664.603    662.121

Tem alguma coisa a ver com a conversão CR / LF?

Publicado 08/08/2008 em 14:35
fonte usuário
Em outras línguas...                            


7 respostas

votos
22

Eu ter reproduzido o que você está vendo:

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

Ficará assim:

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

O que estou fazendo de errado aqui? os.stat é (). st_size não retornando o tamanho correto?


Edit: OK, eu descobri que o problema era:

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

Isso gera:

$ 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

Certifique-se de que você está abrindo ambos os ficheiros para binário de leitura / gravação.

// open for binary write
open(filename, "wb")
// open for binary read
open(filename, "rb")
Respondeu 08/08/2008 em 15:21
fonte usuário

votos
19

Usando o método voltou-urllib-objeto info(), você pode obter diversas informações sobre o documento retrived. Exemplo de agarrar o logotipo do Google atual:

>>> 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

É um dicionário, por isso, para obter o tamanho do arquivo, você faz urllibobject.info()['Content-Length']

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

E para obter o tamanho do arquivo local (para comparação), você pode usar o comando os.stat ():

os.stat("/the/local/file.zip").st_size
Respondeu 08/08/2008 em 14:47
fonte usuário

votos
7

O tamanho do arquivo é enviado como o cabeçalho Content-Length. Aqui está como obtê-lo com urllib:

>>> site = urllib.urlopen("http://python.org")
>>> meta = site.info()
>>> print meta.getheaders("Content-Length")
['16535']
>>>
Respondeu 08/08/2008 em 14:41
fonte usuário

votos
5

Além disso, se o servidor estiver a ligar a suportá-lo, olhar para Etags e os If-Modified-Since e If-None-Match cabeçalhos.

Usando estes irão tirar proveito de regras de cache do servidor web e irá retornar um não modificado 304 código de status se o conteúdo não mudou.

Respondeu 08/08/2008 em 14:51
fonte usuário

votos
2

Em Python3:

>>> import urllib.request
>>> site = urllib.request.urlopen("http://python.org")
>>> print("FileSize: ", site.length)
Respondeu 26/08/2014 em 10:31
fonte usuário

votos
1

Para uma abordagem python3 (testado em 3.5) eu recomendo:

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())
Respondeu 27/09/2017 em 05:33
fonte usuário

votos
1

A pedidos solução baseada usando cabeça em vez de GET (também imprime cabeçalhos 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
Respondeu 04/12/2016 em 10:21
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more