🏴‍☠️
Сашка ☕
Blog  Tags  💀 🔵 🔴

Получаем размер загружаемого файла на Python

Опубликовано: 16 сентября 2022 г.

Введение

Многие пишут грабберы сайтов на Python.
Я вот например скачиваю сиськи с blog.stanis.ru.

Но иногда, требуется проверить, не загружен ли файл уже, до того как его скачать.

Способов сравнения файлов существует достаточное количество, но в рамках этого руководства я рассмотрю способ сравнения файлов по их размеру.

Получение размера локального файла

В стандартной библиотеке Python, есть функция getsize() в модуле os.path.

import os.path

if __name__ == '__main__':
    file_size = os.path.getsize("./avatar.png")

    print("Size: {0} ({1})".format(file_size, type(file_size)))

Программа вернёт следующий результат:

Size: 14390 (<class 'int'>)

Однако не стоит забывать, что файла может и не быть.
По этому лучше проверять такие ситуации.

os.path.exists("./avatar/png")

Получение размера удалённого файла

Для работы с HTTP, я использую модуль requests.

Каждый web-сервер, возвращает заголовки, в которых может быть полезная информация.
Для примера, получим заголовки файла аватара на моём сайте.

import requests

response = requests.get("https://iiiypuk.me/avatar.png")
print(response.headers)

Вывод будет следующий:

{
    'Server': 'nginx/1.20.2',
    'Date': 'Thu, 15 Sep 2022 22:14:41 GMT',
    'Content-Type': 'image/png',
    'Content-Length': '14390',
    'Last-Modified': 'Fri, 08 Jul 2022 11:23:06 GMT',
    'Connection': 'keep-alive',
    'Accept-Ranges': 'bytes'
}

Нас интересует заголовок Content-Length.

print(response.headers['Content-Length'])
# Выхлоп: 14390

Сравнение до боли простое:

import os.path
import requests

if __name__ == '__main__':
    local_size = os.path.getsize("./avatar.png")

    response = requests.get("https://iiiypuk.me/avatar.png")
    remote_size = int(response.headers['Content-Length'])

    if local_size != remote_size:
        print("Файлы разные")
        print("Локальный размер: {0}\nУдалённый размер: {1}".format(
            local_size, remote_size))
    else:
        print("Файлы одинаковые")

Обрати внимание, что response.headers['Content-Length'] возвращает значение строкой, а не целым числом.

ВСЁ!

Можно скачивать файл.

import shutil
import requests

response = requests.get("https://iiiypuk.me/avatar.png", stream=True)

with open("./file.png", "wb") as out_image:
    shutil.copyfileobj(response.raw, out_image)