Скачивание медиа из группы в Telegram может быть необходимо в различных сценариях, в зависимости от ваших потребностей или целей.
Принцип работы download_media
Определение медиа в сообщении. Сначала функция download_media определяет, какой тип медиа содержится в сообщении. Это может быть фотография, видео, аудио, документ и т.д.
Получение идентификатора файла. Каждое медиа в Telegram хранится с уникальным идентификатором файла. Функция download_media извлекает этот идентификатор, который необходим для запроса файла с серверов Telegram.
"photo": { "_": "ChatPhoto", "small_file_id": "AQADAgADqacxG7aAEAIAA7aEMDQABB3IcE6wwwvEAAQeBA", "small_photo_unique_id": "AgADqaG7aEMDQ", "big_file_id": "AQADAgADqacxGMDQAEAMAA7aEMDQABB3IcE6wwwvEAAQeBA", "big_photo_unique_id": "AgADqG7aEMDQ" }
Скачивание файла. Затем функция инициирует запрос к серверам Telegram для скачивания файла. При этом она использует различные параметры, такие как идентификатор файла и сессионные данные пользователя (ключи авторизации).
Прогресс загрузки. Во время скачивания файла download_media может отслеживать прогресс загрузки. Это особенно полезно для больших файлов, так как пользователь может видеть, сколько данных уже скачано и сколько еще предстоит загрузить(ниже подробнее об этом).
Сохранение файла на устройстве пользователя. После завершения скачивания файла функция сохраняет его на локальное устройство пользователя. Путь к сохранению файла можно указать в параметрах функции.
Обработка ошибок. Если в процессе скачивания возникают ошибки (например, проблемы с соединением или неверный идентификатор файла), download_media обрабатывает эти ошибки соответствующим образом, предоставляя информацию для отладки или повторных попыток загрузки.
app.download_media(message, file_name, in_memory, block, progress, progress_args)
message — это объект сообщения Message, из которого вы хотите скачать медиа. Сообщение может содержать различные типы медиа, такие как фотографии, видео, аудиофайлы и т.д.
available_media = ("audio", "document", "photo", "sticker", "animation", "video", "voice", "video_note", "new_chat_photo")
file_name (str, необязательный) — пользовательское имя файла, которое будет использовано вместо имени, предоставленного Telegram. По умолчанию все файлы загружаются в папку downloads в рабочем каталоге.
Также можно указать путь для загрузки файлов в определённое место: пути, оканчивающиеся на /, считаются директориями. Все несуществующие папки будут созданы автоматически.
file_name=f"media/{message.message_id}.mp4"
in_memory (bool, необязательный) — укажите True, чтобы загрузить медиа в оперативную память. В таком случае будет возвращён бинарный объект, подобный файлу, с установленным атрибутом .name. По умолчанию: False. Это полезно, если вам нужно обработать медиа на лету, не сохраняя его физически.
block (bool, необязательный) — этот аргумент определяет, будет ли функция блокирующей. Если установить True, код будет заблокирован до завершения загрузки файла. По умолчанию: True. Если False, код продолжит выполняться параллельно скачиванию (для асинхронного выполнения кода).
progress (Callable, необязательный) — функция обратного вызова, которая вызывается для отслеживания прогресса скачивания. Эта функция может использоваться для отображения прогресс-бара или для логирования прогресса скачивания.
# Функция для обновления прогресс-бара def progress(current, total): # 'current' - текущее количество скачанных байт, # 'total' - общий размер файла progress_bar.update(current - progress_bar.n) # Обновляем прогресс-бар #... #Любое количество кода #... app.download_media(message..., file_name=..., progress=progress)
progress_args (tuple, необязательный) — дополнительные аргументы для функции обратного вызова progress. Вы можете передать всё, что нужно для использования в области видимости функции, например, объект Message или экземпляр Client, чтобы обновить статус прогресса.
Другие параметры:
current (int) — количество переданных байтов на текущий момент.
total (int) — общий размер файла.
*args (tuple, необязательный) — дополнительные аргументы, указанные в параметре progress_args. Вы можете оставить *args или добавить все дополнительные аргументы в сигнатуру функции.
Возвращаемое значение: (str | None | BinaryIO):
- В случае успеха возвращается абсолютный путь к загруженному файлу.
- Если загрузка не удалась или была намеренно остановлена с помощью stop_transmission(), возвращается None.
- Если указано in_memory=True, возвращается бинарный объект, подобный файлу, с установленным атрибутом .name.
Исключения: ValueError
- Выбрасывается, если сообщение не содержит медиафайлов, доступных для загрузки.
audio. Аудиофайлы или музыкальные треки.
# Проверка наличия аудио в сообщении if message.audio: # Скачиваем аудио app.download_media(message.audio, file_name=f"audio/{message.message_id}.mp3")
document. Документы, такие как PDF, Word или любые другие файлы, которые не подпадают под другие медиа-категории.
# Проверка наличия документа в сообщении if message.document: # Скачиваем документ app.download_media(message.document, file_name=f"documents/{message.message_id}_{message.document.file_name}")
photo. Фотографии или изображения.
# Проверка наличия фотографии в сообщении if message.photo: # Скачиваем фотографию app.download_media(message.photo, file_name=f"photos/{message.message_id}.jpg")
sticker. Стикеры, используемые в Telegram для выражения эмоций или реакций.
# Проверка наличия стикера в сообщении if message.sticker: # Скачиваем стикер app.download_media(message.sticker, file_name=f"stickers/{message.message_id}.webp")
animation. Гифки или анимированные изображения.
# Проверка наличия анимации (гифки) в сообщении if message.animation: # Скачиваем анимацию app.download_media(message.animation, file_name=f"animations/{message.message_id}.mp4")
video. Видеофайлы.
# Проверка наличия видео в сообщении if message.video: # Скачиваем видео app.download_media(message.video, file_name=f"videos/{message.message_id}.mp4")
voice. Голосовые сообщения.
# Проверка наличия голосового сообщения if message.voice: # Скачиваем голосовое сообщение app.download_media(message.voice, file_name=f"voice/{message.message_id}.ogg")
video_note. Круглые видео сообщения, которые обычно короткие и записываются через камеру фронтального вида.
# Проверка наличия видеосообщения if message.video_note: # Скачиваем app.download_media(message.video_note, file_name=f"video_notes/{message.message_id}.mp4")
new_chat_photo. Фотографии, которые установлены как новые изображения профиля чата.
# Проверка наличия новой фотографии чата в сообщении if message.new_chat_photo: # Скачиваем новую фотографию чата app.download_media(message.new_chat_photo, file_name=f"chat_photos/{message.message_id}.jpg")
Вот код, который реализует эту функциональность:
from pyrogram import Client api_id = 1111 api_hash = "" app = Client("my_session", api_id=api_id, api_hash=api_hash) group_url = "test" # URL группы def main(): with app: for message in app.get_chat_history(group_url): # Проверяем, содержит ли сообщение изображение if message.photo: # Скачиваем изображение app.download_media(message.photo, file_name=f"images/{message.from_user.id}_{message.id}.jpg") main()
В этом коде мы итерируемся по всем сообщениям в истории чата app.get_chat_history(group_url), и если сообщение содержит фото (if message.photo), то мы скачиваем его. Изображения сохраняются в папке images с именем файла, основанным на {message.from_user.id}_{message.id}.jpg. Убедитесь, что папка images существует в вашей рабочей директории или измените путь сохранения в соответствии с вашей структурой.
Код ниже автоматически обрабатывает историю чата и скачивает различные типы медиа файлов (фото, видео, аудио и др.), отображая прогресс загрузки каждого файла.
Вы можете спокойно запустить этот код, указав свои api_hash и api_id, он скачает все медиа находящиеся в группе.
from pyrogram import Client from tqdm import tqdm api_id = 1111 api_hash = "" app = Client("my_session", api_id=api_id, api_hash=api_hash) group_url = "test" # URL группы def progress(current, total, progress_bar): # Обновляем прогресс-бар progress_bar.update(current - progress_bar.n) def main(): with app: for message in app.get_chat_history(group_url): if message.media: file_name = f"media/{message.id}" file_size = None # Определение расширения файла и размера в зависимости от типа медиа if message.photo: file_name += ".jpg" file_size = message.photo.file_size elif message.video: file_name += ".mp4" file_size = message.video.file_size elif message.audio: file_name += ".mp3" file_size = message.audio.file_size elif message.document: file_name += f".{message.document.mime_type.split('/')[-1]}" file_size = message.document.file_size elif message.voice: file_name += ".ogg" file_size = message.voice.file_size elif message.video_note: file_name += ".mp4" file_size = message.video_note.file_size elif message.sticker: file_name += ".webp" file_size = message.sticker.file_size elif message.animation: file_name += ".mp4" file_size = message.animation.file_size # Создание прогресс-бара для каждого файла # Если размер файла определен, создаем прогресс-бар и начинаем загрузку if file_size: with tqdm(total=file_size, unit='B', unit_scale=True, desc="Скачивание") as progress_bar: app.download_media(message, file_name=file_name, progress=progress, progress_args=(progress_bar,)) main()
Этот код теперь обрабатывает различные типы медиа, которые могут быть в сообщении, и создает индивидуальный прогресс-бар для каждого скачиваемого файла. Убедитесь, что у вас создана папка media в директории, где выполняется ваш скрипт, чтобы избежать ошибок при сохранении файлов.
Вывод:
Скачивание: 100%|██████████| 23.2k/23.2k [00:00<00:00, 29.1kB/s] Скачивание: 100%|██████████| 23.0k/23.0k [00:00<00:00, 30.9kB/s] Скачивание: 100%|██████████| 177k/177k [00:01<00:00, 175kB/s] Скачивание: 100%|██████████| 10.4k/10.4k [00:00<00:00, 14.3kB/s] Скачивание: 100%|██████████| 23.1k/23.1k [00:00<00:00, 25.2kB/s] Скачивание: 100%|██████████| 43.6k/43.6k [00:00<00:00, 50.3kB/s] ... ... ... Скачивание: 100%|██████████| 97.5k/97.5k [00:00<00:00, 107kB/s] Скачивание: 100%|██████████| 79.3k/79.3k [00:00<00:00, 88.1kB/s] Скачивание: 100%|██████████| 55.1k/55.1k [00:00<00:00, 60.9kB/s] Скачивание: 100%|██████████| 4.14k/4.14k [00:00<00:00, 6.47kB/s] Скачивание: 100%|██████████| 19.8k/19.8k [00:00<00:00, 26.2kB/s] Скачивание: 100%|██████████| 79.0k/79.0k [00:00<00:00, 84.0kB/s] Скачивание: 100%|██████████| 71.0k/71.0k [00:00<00:00, 80.5kB/s]
Пояснения по работе кода с progress_bar
В этом фрагменте кода используется библиотека tqdm, которая представляет собой инструмент для создания текстовых индикаторов выполнения (прогресс-баров) в командной строке при выполнении итераций в циклах или при обработке данных.
from tqdm import tqdm def progress(current, total, progress_bar): # Обновляем прогресс-бар progress_bar.update(current - progress_bar.n)
В данном контексте функция progress предназначена для обновления прогресс-бара tqdm во время загрузки файла с помощью pyrogram. Вот что означают аргументы этой функции:
current. Текущее количество байт, которое было загружено на данный момент. Это значение передаётся Pyrogram во время загрузки медиафайла.
total. Общий размер файла в байтах, который предстоит загрузить. Это значение также предоставляется Pyrogram и используется для определения общего прогресса загрузки.
progress_bar. Экземпляр tqdm, который представляет собой индикатор прогресса. Он используется для визуализации текущего состояния загрузки в виде прогресс-бара.
Функция progress вызывается Pyrogram при каждом обновлении загрузки.
В этой функции метод progress_bar.update(current — progress_bar.n) используется для обновления прогресс-бара на значение, насколько изменился прогресс с последнего вызова.
progress_bar.n хранит текущее значение прогресс-бара до вызова update, и вычитая его из current, вы передаёте в update то количество байт, которое было загружено с момента последнего обновления прогресс-бара.