Получите размер файла перед загрузкой в ​​Python

Я загружаю весь каталог с веб-сервера. Он работает нормально, но я не могу понять, как получить размер файла перед загрузкой, чтобы сравнить, был ли он обновлен на сервере или нет. Можно ли это сделать, как если бы я загружал файл с 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: спасибо за быстрый ответ. Это работает, но размер файла на веб-сервере немного меньше, чем размер загруженного файла.

Примеры:

Local Size  Server Size
 2.223.533  2.115.516
   664.603    662.121

Это как-то связано с преобразованием CR / LF?

Возможно. Можете ли вы запустить на нем diff и увидеть разницу? Также вы видите разницу в размере файлов в двоичных (.zip) файлах? Обновлено: здесь пригодятся такие вещи, как Etags. Сервер сообщит вам, когда что-то изменится, поэтому вам не нужно загружать полный файл, чтобы понять это.

Jonathan Works 08.08.2008 18:07

ты прав, я не использовал "wb" при открытии локального файла на запись. Работает как шарм! Спасибо

PabloG 29.01.2011 18:23
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
46
2
46 511
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Размер файла отправляется как заголовок Content-Length. Вот как получить его с помощью urllib:

>>> site = urllib.urlopen("http://python.org")
>>> meta = site.info()
>>> print meta.getheaders("Content-Length")
['16535']
>>>

Используя метод info() возвращенного urllib-объекта, вы можете получить различную информацию о полученном документе. Пример получения текущего логотипа 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

Это диктат, поэтому, чтобы получить размер файла, вы делаете urllibobject.info()['Content-Length']

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

А чтобы получить размер локального файла (для сравнения), вы можете использовать команду os.stat ():

os.stat("/the/local/file.zip").st_size

Я использовал это решение, однако я столкнулся с крайним случаем, когда иногда заголовок длины содержимого не определен. Может ли кто-нибудь объяснить, почему его не возвращают постоянно?

user12121234 10.06.2016 21:18
stackoverflow.com/questions/22087370/… maybe explains it?
dbr 08.07.2016 16:50

Также, если сервер, к которому вы подключаетесь, поддерживает это, посмотрите на заголовки Etags и If-Modified-Since и Если-нет-совпадение.

Их использование позволит воспользоваться преимуществами правил кэширования веб-сервера и вернет код состояния 304 Не изменено, если содержимое не изменилось.

Ответ принят как подходящий

Я воспроизвел то, что вы видите:

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

Выводит это:

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

Что я здесь делаю не так? Os.stat (). St_size не возвращает правильный размер?


Редактировать: Хорошо, я понял, в чем проблема:

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

это выводит:

$ 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

Убедитесь, что вы открываете оба файла для двоичного чтения / записи.

// open for binary write
open(filename, "wb")
// open for binary read
open(filename, "rb")

когда вы выполняете site = urllib.urlopen(link), вы выполнили загрузку файла, поэтому он не имеет размера перед загрузкой, его информация загружается в буфер, откуда вы извлекаете длину содержимого

Ciasto piekarz 05.07.2014 13:50

@Ciastopiekarz Я думаю, что когда вы пытаетесь read (), файл фактически загружается в буфер проверьте этот ответ

CaptainDaVinci 31.07.2017 22:54

urllib.urlopen больше не действует в версии не ниже 3.6.

ch4rl1e97 21.06.2019 00:10

В Python3:

>>> import urllib.request
>>> site = urllib.request.urlopen("http://python.org")
>>> print("FileSize: ", site.length)

Это скачивает файл!

Joseph Victor Zammit 04.02.2016 16:39

Решение на основе Запросы, использующее HEAD вместо GET (также печатает заголовки 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))

использование

$ python filesize-remote-url.py https://httpbin.org/image/jpeg
...
Content-Length                          : 35588
FILE SIZE (MB)                          : 0.03 MB

Для подхода python3 (проверенного на 3.5) я бы рекомендовал:

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

@PabloG Относительно разницы в размерах файлов на локальном / серверном уровне

Ниже приводится иллюстративное объяснение высокого уровня того, почему это может произойти:

Размер на диске иногда отличается от фактического размера данных. Это зависит от базовой файловой системы и того, как она работает с данными. Как вы, возможно, видели в Windows, при форматировании флеш-накопителя вас просят указать «размер блока / кластера», и он варьируется [512b - 8kb]. Когда файл записывается на диск, он сохраняется в «сортированном связном списке» дисковых блоков. Когда определенный блок используется для хранения части файла, никакое другое содержимое файла не будет храниться в том же блоке, поэтому, даже если кусок не занимает все пространство блока, блок становится непригодным для использования другими файлами.

Пример: Когда файловая система разделена на блоки по 512 байт, и нам нужно сохранить файл размером 600 байт, два блока будут заняты. Первый блок будет использован полностью, тогда как второй блок будет использовать только 88b, а оставшиеся (512-88) b будут непригодны для использования, в результате чего «размер файла на диске» будет равен 1024b. Вот почему в Windows разные обозначения «размера файла» и «размера на диске».

ПРИМЕЧАНИЕ: Есть разные плюсы и минусы, которые связаны с меньшим / большим блоком FS, поэтому лучше изучите, прежде чем играть с вашей файловой системой.

Другие вопросы по теме