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 12:35
fonte usuário
Em outras línguas...                            


8 respostas

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 12:41
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 12:47
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 12:51
fonte usuário

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 13:21
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 08:31
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 08:21
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 04:33
fonte usuário

votos
0

@PabloG Em relação à diferença filesize local / servidor

A seguir é de alto nível explicação ilustrativa de por que podem ocorrer:

O tamanho em disco, por vezes, é diferente do tamanho real dos dados. Depende do sistema de arquivos subjacente e como ela opera em dados. Como você deve ter visto no Windows quando formatar uma unidade flash você está convidado a provice 'tamanho do bloco / cluster' e varia [512b - 8kb]. Quando um arquivo é gravado no disco, é storled em uma 'lista espécie de ligado' de blocos de disco. Quando um determinado bloco é usado para armazenar parte de um arquivo, nenhum outro conteúdo de arquivos serão armazenados na mesma blok, por isso mesmo se o bloco não é occupuing todo o espaço do bloco, o bloco é inutilizado por outros arquivos.

Exemplo: Quando o sistema de arquivos é dividido em 512B blocos, e precisamos armazenar arquivo 600b, dois blocos será ocupada. O primeiro bloco será totalmente utilizado, enquanto que o segundo bloco terá apenas utilizado 88b e o restante (512-88) b será resultante inutilizável na 1024B '-de tamanho do ficheiro no disco' sendo. É por isso que o Windows tem diferentes notações para 'tamanho' e 'tamanho em disco'.

NOTA: Existem diferentes prós e contras que vêm com menor maior bloco / FS, então, fazer uma pesquisa melhor antes de jogar com o seu sistema de arquivos.

Respondeu 28/01/2020 em 21:45
fonte usuário

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