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?
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")
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
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']
>>>
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.
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)
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
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())
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