Финальный код статьи доступен на Github! В статье используется Python 3.12.7.
¶ Предварительные требования
В первую очередь, вам понадобится пользовательская сессия в Telethon через свое приложение Telegram. Как создать свое приложение Telegram, я писал в другой статье, не буду заострять внимание. После получения параметров вы сможете открыть произвольную сессию и через этот скрипт.
Далее, вам понадобится ID канала, откуда вы хотите получить посты. Несколько вариантов описаны ниже.
Самое простое - скопируйте ссылку на пост. Получите ссылку вида https://t.me/c/<ID канала>/<номер поста>. ID-канала получен!
Альтернативный способ - переслать из канала сообщение боту @ShowJsonBot. Далее, найти поле forward_origin и взять оттуда значение id. В примере ниже - это значение -1001112223333. Далее, удалите -100 в начале, то есть оставьте значение 1112223333
...
"forward_origin":
...
¶ Установка зависимостей
В руководстве я буду использовать библиотеку telethon версии 1.38.0. Обратите внимание на совместимость версий, если используете отличную.
¶ Скрипт
Данный скрипт обрабатывает только текстовые сообщения и посты с фото. Из-за особенностей telethon посты с фото “разбиваются” на несколько.
Полученные посты сохраняются в файл messages.json, в нем содержится:
- ID поста
- Дата публикации в UNIX-timestamp
- Текст поста
- Изображение поста (если есть)
Фото к сообщениям сохраняются в папку images. Предварительно создайте ее.
Код также доступен на Github!
=
=
= 0 # YOUR CHANNEL
: =
= 0
= 100
: | None | = await
assert
break
:
: | None = None
: | None = None
=
=
+=
=
await # type: ignore
=
pass
+= 100
+= 100
¶ Объяснение работы скрипта
¶ Запуск функции
Создаем event loop для обработки нашей асинхронной функции и устанавливаем его.
=
Выставляем уровень логгирования чтобы видеть прогресс выполнения и создаем объект клиента, через который будем работать. Вставьте свои параметры приложения Telegram, имя сессии менять опционально.
=
Создаем переменную, где хранится ID канала, который мы “читаем” и переменную, куда будут записываться все сообщения
= 0 # YOUR CHANNEL
: =
В конце скрипта добавляем открытие подключения клиентом при помощи with и запускаем нашу функцию с переданным клиентом в ранее созданном event loop’e.
¶ Функция обработки
Для соблюдения rate-лимитов и большей гибкости скрипт получает сообщения по 100 сообщений максимум (если посты не были удалены ранее, в таком случае меньше). Стандартная редакция скрипта начинает получения от постов с ID от 0 до 100 (т.е первые 100 сообщений в канале).
ID поста можно получить, скопировав ссылку на него.
24
25 = 0
26 = 100
27
28
29
30 : | None | = await 31 32 33 34 35
36 assert
37
Если список сообщений пуст, скрипт завершает свою работу. Если 100 постов были удалены подряд, это также может сказаться на их количестве и вызвать ложное завершение скрипта, обратите внимание и отредактируйте поведение скрипта по необходимости.
38
39 break
Посты идут в обратном хронолическом порядке по умолчанию. Если у объекта сообщения есть текст и дата, они записываются в переменные для дальнейшей записи в payload.
42 :
43
44 : | None = None
45 : | None = None
46 =
47
48 =
49
50
51 +=
Далее идет обработка медиавложений, с которой все сложнее. Поле media объекта Message может быть None, а также иметь следующий тип:
=
Поэтому, если вы хотите обработать отличные от изображений вложения, требуется проверка на то, чем является поле и дальнейшая обработка класса.
Обработка изображений также усложняется из-за системы типов, поскольку тип MessageMediaPhoto имеет опциональное поле photo, содержащее в себе тип TypePhoto выглядящий следующим образом:
=
Таким образом, проверка ожидает что у сообщения есть медиавложение в виде фото, в котором информация о фото присутствует. В таком случае клиент скачивает медиафайл в папку images с именем в виде ID сообщения. После, вся полученная информация добавляется в массив payload.
53 54 55 56 57
58 =
59 await # type: ignore
60 =
61
62 pass
63
64 65 66
В конце, мы сдвигаем порог ID постов на 100 и записываем имеющиеся данные в файл, чтобы они не “потерялись” в случае ошибки.
67
68
69 += 100
70 += 100
¶ Заключение
Данный скрипт может развиваться под различные применения, поэтому я надеюсь что он полслужит отправной точкой для вашей задачи и поможет совладать с тяжелой структурой Telethon'а. Удачи!