You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 15:04:54