如何在Telethon的Message对象中获取非回复消息的主题ID?
问题
我尝试使用Telethon将Telegram超级群中所有消息的发送者名称、主题名称导出到文本文件,但无法从非回复的Message对象中获取主题ID。目前仅当消息为回复消息时,才能通过msg.reply_to.reply_to_top_id获取主题ID;而GetForumTopicsByIDRequest或GetForumTopicsRequest仅返回主题的最后一条消息及其ID。我使用的是Telethon 1.40版本,相关代码如下:
from telethon.sync import TelegramClient api_id = ... api_hash = "..." group_id = ... client = TelegramClient('anon_session', api_id, api_hash) client.start() with client: with open("all_messages.txt", "w", encoding="utf-8") as f: for msg in client.iter_messages(group_id, reverse=True): if msg.message: sender = msg.sender name = f"{sender.first_name or ''} {sender.last_name or ''}".strip() if sender else "Unknown" topic_name = '' if msg.reply_to and msg.reply_to.forum_topic: #returns topic name only if msg is a reply to another message topic_id = msg.reply_to.reply_to_top_id topic_name = client(functions.channels.GetForumTopicsByIDRequest(channel=channel_id, topics=[topic_id])).topics[0].title text = msg.message.replace('\n', ' ') if msg.message else '' f.write(f"[{topic_name}] {name}: {text}\n")
请问是否有办法从非回复的Message对象中获取主题ID?
解决方法
- 直接读取Message对象的
forum_topic_id属性:Telethon 1.40版本中,论坛超级群内的所有消息(无论是否为回复)都自带forum_topic_id字段,无需依赖reply_to对象即可直接获取对应主题ID。 - 缓存主题信息优化效率:先批量获取群内所有主题并构建ID-名称映射表,避免每次处理消息都调用API查询主题名称,大幅提升导出速度。
修改后的代码示例:
from telethon.sync import TelegramClient from telethon import functions api_id = ... api_hash = "..." group_id = ... client = TelegramClient('anon_session', api_id, api_hash) client.start() with client: # 批量获取所有论坛主题并缓存ID与名称的映射 topic_map = {} offset_topic = 0 while True: topics = client(functions.channels.GetForumTopicsRequest( channel=group_id, offset_date=None, offset_id=0, offset_topic=offset_topic, limit=1000 )).topics if not topics: break topic_map.update({t.id: t.title for t in topics}) offset_topic += len(topics) with open("all_messages.txt", "w", encoding="utf-8") as f: for msg in client.iter_messages(group_id, reverse=True): if msg.message: sender = msg.sender name = f"{sender.first_name or ''} {sender.last_name or ''}".strip() if sender else "Unknown" topic_name = '' # 直接从消息获取主题ID并匹配名称 if msg.forum_topic_id: topic_name = topic_map.get(msg.forum_topic_id, f"未命名主题_{msg.forum_topic_id}") # 若forum_topic_id为0,代表是群默认顶栏的消息(非话题内消息),可自行补充逻辑 text = msg.message.replace('\n', ' ') if msg.message else '' f.write(f"[{topic_name}] {name}: {text}\n")
补充说明:如果群内主题数量超过1000,代码会自动分页获取所有主题;forum_topic_id为0时,对应群默认顶栏的消息(不属于任何话题),可根据需求添加自定义处理逻辑。
内容的提问来源于stack exchange,提问作者MihMas
相关产品推荐
相关产品推荐

