Pobierz Rozmiar pliku przed pobraniem w Pythonie

Ściągam cały katalog z serwera www. Działa OK, ale nie mogę dowiedzieć się, jak uzyskać Rozmiar pliku przed pobraniem, aby porównać, czy został zaktualizowany na serwerze, czy nie. Czy można to zrobić tak, jakbym pobierał Plik z serwera 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: dzięki za szybką odpowiedź. To działa, ale Rozmiar Pliku na serwerze WWW jest nieco mniejszy niż rozmiar pobranego pliku.

Przykłady:

Local Size  Server Size
 2.223.533  2.115.516
   664.603    662.121

Ma to coś wspólnego z CR / LF nawrócenie?

Author: Prashant Kumar, 2008-08-08

7 answers

Odtworzyłem to, co widzisz:

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

Wypisuje to:

opening url: http://python.org
Content-Length: 16535
File on disk: 16535
File on disk after download: 16535
os.stat().st_size returns: 16861
Co ja tu robię źle? Czy os. stat (). st_size nie zwraca poprawnego rozmiaru?

Edytuj: OK, rozgryzłem na czym polega problem:

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

To wyjście:

$ 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

Upewnij się, że otwierasz oba pliki do odczytu/zapisu binarnego.

// open for binary write
open(filename, "wb")
// open for binary read
open(filename, "rb")
 23
Author: Jonathan Works,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-08 14:26:40

Używając metody Return-urllib-object info(), można uzyskać różne informacje o pobranym dokumencie. Przykład przechwytywania obecnego logo 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

Jest to dict, więc aby uzyskać Rozmiar pliku, robisz urllibobject.info()['Content-Length']

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

I aby uzyskać Rozmiar pliku lokalnego (dla porównania), możesz użyć systemu operacyjnego.polecenie stat ():

os.stat("/the/local/file.zip").st_size
 20
Author: dbr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-08 13:47:26

Rozmiar pliku jest wysyłany jako nagłówek Content-Length. Oto jak go zdobyć z urllib:

>>> site = urllib.urlopen("http://python.org")
>>> meta = site.info()
>>> print meta.getheaders("Content-Length")
['16535']
>>>
 7
Author: Jonathan Works,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-08 13:44:47

Jeśli serwer, z którym się łączysz, obsługuje tę funkcję, spójrz na nagłówki Etags oraz If-Modified-Since i If-None-Match.

Ich użycie wykorzysta reguły buforowania serwera WWW i zwróci kod statusu 304 Not Modified, jeśli zawartość się nie zmieniła.

 5
Author: Jonathan Works,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-08 13:51:23

W Python3:

>>> import urllib.request
>>> site = urllib.request.urlopen("http://python.org")
>>> print("FileSize: ", site.length)
 2
Author: Madhusudhan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-26 09:31:46

A requests - based solution using HEAD zamiast GET (również drukuje nagłówki 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))

Użycie

$ python filesize-remote-url.py https://httpbin.org/image/jpeg
...
Content-Length                          : 35588
FILE SIZE (MB)                          : 0.03 MB
 1
Author: ccpizza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-02 13:24:18

Dla podejścia python3 (testowanego na 3.5) polecam:

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())
 1
Author: yukashima huksay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-08 18:38:08