у меня есть бот-автопостер и модуль парсера. мне нужно сохранять последний пост из искомого канала на комп и постить в список каналов channels.json (только от имени бота, вариант отправки сообщения пользователем через сессию не подойдет). сейчас парсер может сохранить не более одного медиа + текст, когда он пытается спарсить сообщение в котором более 1 медиа, то скачивается только какое-то одно фото или видео, и текст не сохраняется
код парсера:
import os
import json
from telethon.sync import TelegramClient
from telethon.errors import SessionPasswordNeededError
from telethon.tl.types import MessageMediaPhoto, MessageMediaDocument # Убираем все устаревшие импорты
from config import API_ID, API_HASH, PHONE_NUMBER, ADMIN_ID
from handlers.logging import log_error, log_action # Импортируем логирование
# Загружаем данные из last_post.json
def load_last_post():
"""Загружает данные о последнем посте из файла"""
try:
with open('data/last_post.json', 'r', encoding='utf-8') as file:
data = json.load(file)
print("Загружены данные о последнем посте:", data) # Для отладки
return data
except Exception as e:
print(f"Ошибка при загрузке данных о последнем посте: {e}")
return {"channels": {}}
# Сохраняем данные в last_post.json
def save_last_post(data):
"""Сохраняет данные в last_post.json"""
with open('data/last_post.json', 'w', encoding='utf-8') as file:
json.dump(data, file, ensure_ascii=False, indent=4)
async def process_message(message, client, channel_folder):
"""Обработка сообщения, извлечение текста и медиа."""
message_data = {
'message_id': message.id,
'text': "Без текста", # Начальная установка, если текст не найден
'media': [],
'date': message.date.isoformat()
}
# Попробуем извлечь текст из разных источников
if message.text:
message_data['text'] = message.text
elif hasattr(message, 'raw_text') and message.raw_text:
message_data['text'] = message.raw_text
elif hasattr(message, 'caption') and message.caption:
message_data['text'] = message.caption
# Логируем текст
log_action(ADMIN_ID, "Текст сообщения", f"Текст: {message_data['text']}")
if not message_data['text']:
log_action(ADMIN_ID, "Текст не найден", f"Сообщение {message.id} не содержит текста")
else:
log_action(ADMIN_ID, "Текст найден", f"Текст: {message_data['text']}")
# Проверка наличия медиа
media_folder = f"{channel_folder}/media"
os.makedirs(media_folder, exist_ok=True)
# Обработка нескольких медиа в одном сообщении
if isinstance(message.media, list): # Если медиа несколько объектов
log_action(ADMIN_ID, "Медиа в сообщении", f"Найдено несколько медиа объектов")
for i, media in enumerate(message.media):
if isinstance(media, (MessageMediaPhoto, MessageMediaDocument)):
file_path = f"{media_folder}/{message.id}_media_{i + 1}.mp4" # Пример для видео
result = await client.download_media(media, file_path)
if result:
message_data['media'].append({'type': 'media', 'file_path': result})
log_action(ADMIN_ID, "Медиа сохранено", f"Файл: {result}")
elif isinstance(message.media, (MessageMediaPhoto, MessageMediaDocument)): # Обработка одного медиа
log_action(ADMIN_ID, "Обработка одного медиа", "Обрабатываем одно медиа.")
file_path = f"{media_folder}/{message.id}_media"
result = await client.download_media(message.media, file_path)
if result:
message_data['media'].append({'type': 'media', 'file_path': result})
log_action(ADMIN_ID, "Медиа сохранено", f"Файл: {result}")
# Логируем количество медиа
log_action(ADMIN_ID, "Количество медиа", f"Медиа в сообщении: {len(message_data['media'])}")
# Сохраняем данные о сообщении в JSON файл
message_json_path = f"{channel_folder}/{message.id}.json"
with open(message_json_path, "w", encoding="utf-8") as f:
json.dump(message_data, f, ensure_ascii=False, indent=4)
log_action(ADMIN_ID, "Сообщение сохранено", f"Сообщение {message.id} в канале {message.peer_id}")
return message_data
async def get_channel_messages(api_id, api_hash, phone_number, channel_links):
"""Функция для получения сообщений с канала"""
log_action(ADMIN_ID, "Запуск парсинга каналов", f"Каналы: {channel_links}")
client = TelegramClient('session_name', api_id, api_hash)
await client.start(phone_number)
# Загружаем данные о последнем сообщении
last_post_data = load_last_post()
for channel_link in channel_links:
try:
log_action(ADMIN_ID, "Получаем сообщения", f"Из канала: {channel_link}")
channel = await client.get_entity(channel_link)
messages = await client.get_messages(channel, limit=10) # Получаем последние 10 сообщений
# Получаем имя канала (используем username канала)
channel_name = channel.username if channel.username else str(channel.id)
channel_folder = f"parsed_content/{channel_name}"
# Создаём папку для канала, если она не существует
os.makedirs(channel_folder, exist_ok=True)
# Проверка, если это первый запуск для этого канала
if channel_link not in last_post_data['channels']:
# Если канал новый, добавляем его в last_post_data
last_post_data['channels'][channel_link] = {
'message_id': None,
'date': None,
'text': "Без текста",
'media': []
}
# Получаем последнее сообщение
last_message = messages[0]
# Проверяем, если последнее сообщение не совпадает с тем, что было сохранено
if last_post_data['channels'][channel_link]['message_id'] != last_message.id:
# Если новое сообщение, сохраняем его данные
await process_message(last_message, client, channel_folder)
# Обновляем данные о последнем сообщении для канала
last_post_data['channels'][channel_link] = {
'message_id': last_message.id,
'date': last_message.date.isoformat(),
'text': last_message.text if last_message.text else "Без текста",
'media': [] # Здесь можно добавлять информацию о медиа
}
log_action(ADMIN_ID, "Новое сообщение", f"Сохранено новое сообщение с id: {last_message.id}")
else:
log_action(ADMIN_ID, "Нет новых сообщений", "Последнее сообщение не изменилось.")
except Exception as e:
log_error(f"Ошибка при парсинге канала {channel_link}: {e}")
# Сохраняем обновлённые данные о каналах и их сообщениях
save_last_post(last_post_data)
await client.disconnect()
async def monitor_channels():
"""Функция для мониторинга каналов и парсинга новых сообщений"""
log_action(ADMIN_ID, "Запуск мониторинга каналов", "Начало парсинга")
# Загружаем данные из last_post.json
last_post_data = load_last_post()
log_action(ADMIN_ID, "Данные последнего поста", f"{last_post_data}") # Для отладки
if 'channels' in last_post_data:
# Получаем ссылки каналов
channel_links = list(last_post_data['channels'].keys())
# Используем API ID, API HASH и номер телефона из config.py
api_id = API_ID
api_hash = API_HASH
phone_number = PHONE_NUMBER
# Запускаем парсинг сообщений
await get_channel_messages(api_id, api_hash, phone_number, channel_links)
log_action(ADMIN_ID, "Парсинг завершён", "Парсинг каналов завершён успешно.")
else:
log_action(ADMIN_ID, "Нет каналов для парсинга", "Нет каналов, указанных в last_post.json.")