Ermitteln Sie die Größe einer Datei vor dem Herunterladen in Python
Frage
Ich lade ein ganzes Verzeichnis von einem Webserver herunter.Es funktioniert einwandfrei, aber ich weiß nicht, wie ich die Dateigröße vor dem Download ermitteln kann, um zu vergleichen, ob sie auf dem Server aktualisiert wurde oder nicht.Kann dies so erfolgen, als würde ich die Datei von einem FTP-Server herunterladen?
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:danke für deine schnelle Antwort.Es funktioniert, aber die Dateigröße auf dem Webserver ist etwas kleiner als die Dateigröße der heruntergeladenen Datei.
Beispiele:
Local Size Server Size
2.223.533 2.115.516
664.603 662.121
Hat es etwas mit der CR/LF-Umwandlung zu tun?
Lösung
Ich habe reproduziert, was Sie sehen:
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
Gibt Folgendes aus:
opening url: http://python.org
Content-Length: 16535
File on disk: 16535
File on disk after download: 16535
os.stat().st_size returns: 16861
Was mache ich hier falsch?Gibt os.stat().st_size nicht die richtige Größe zurück?
Bearbeiten:OK, ich habe herausgefunden, was das Problem war:
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
Dies gibt aus:
$ 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
Stellen Sie sicher, dass Sie beide Dateien zum binären Lesen/Schreiben öffnen.
// open for binary write
open(filename, "wb")
// open for binary read
open(filename, "rb")
Andere Tipps
Verwendung der Methode „returned-urllib-object“. info()
, können Sie verschiedene Informationen zum abgerufenen Dokument abrufen.Beispiel für das Ergreifen des aktuellen Google-Logos:
>>> 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 ist ein Diktat. Um die Größe der Datei zu ermitteln, müssen Sie dies tun urllibobject.info()['Content-Length']
print f.info()['Content-Length']
Und um die Größe der lokalen Datei (zum Vergleich) zu ermitteln, können Sie den Befehl os.stat() verwenden:
os.stat("/the/local/file.zip").st_size
Die Größe der Datei wird als Content-Length-Header gesendet.So erhalten Sie es mit urllib:
>>> site = urllib.urlopen("http://python.org")
>>> meta = site.info()
>>> print meta.getheaders("Content-Length")
['16535']
>>>
Sehen Sie sich auch an, ob der Server, zu dem Sie eine Verbindung herstellen, dies unterstützt Etags und das Wenn-geändert-seit Und Wenn-Keine-Übereinstimmung Kopfzeilen.
Wenn Sie diese verwenden, werden die Caching-Regeln des Webservers ausgenutzt und ein zurückgegeben 304 Nicht geändert Statuscode, wenn sich der Inhalt nicht geändert hat.
In Python3:
>>> import urllib.request
>>> site = urllib.request.urlopen("http://python.org")
>>> print("FileSize: ", site.length)
Für einen Python3-Ansatz (getestet auf 3.5) würde ich Folgendes empfehlen:
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 Anfragen-basierte Lösung mit HEAD statt GET (druckt auch HTTP-Header):
#!/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))
Verwendung
$ python filesize-remote-url.py https://httpbin.org/image/jpeg ... Content-Length : 35588 FILE SIZE (MB) : 0.03 MB