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

Telethon中替换消息指定词汇时如何调整文本实体的offset和length?

Telegram机器人关键词替换保留原有格式解决方案

核心问题原因

你之前修改event.message.entities后格式错位的核心原因是:Telegram消息实体的offset、length参数均按照UTF-16码位计算,并非普通UTF-8字符计数,替换词汇后长度变化如果没有按UTF-16标准重新计算偏移,就会出现格式错位。

具体实现步骤

  • 第一步:深拷贝原始消息的纯文本内容与实体列表,不要直接修改event对象的原始属性
  • 第二步:先对纯文本做关键词替换,同时记录每个替换操作产生的偏移差:例如将长度为A的原词替换为长度为B的新词,需要将该替换位置之后所有实体的offset统一加上 (B的UTF-16码位长度 - A的UTF-16码位长度)
  • 第三步:如果替换的词汇本身被某个实体覆盖,需要同步调整该实体的length参数:例如原词thisUTF-16长度为4,替换为testing后UTF-16长度为7,对应实体的length直接修改为7即可,不需要调整起始offset
  • 第四步:发送消息时同时传入替换后的纯文本、调整完成的实体列表,不需要指定parse_mode参数,即可完全复现原始消息的格式

代码示例(Python python-telegram-bot v13.x 版本)

import copy
def get_utf16_len(s: str) -> int:
    return len(s.encode('utf-16-le')) // 2

# 原始消息数据
raw_text = event.message.text
raw_entities = copy.deepcopy(event.message.entities)
replace_map = {"this": "testing", "keyboard": "mouse"}

new_text = raw_text
offset_adjust = 0

for old_word, new_word in replace_map.items():
    start = new_text.find(old_word)
    while start != -1:
        # 计算偏移差
        old_len = get_utf16_len(old_word)
        new_len = get_utf16_len(new_word)
        diff = new_len - old_len
        # 调整该位置之后的所有实体offset
        for ent in raw_entities:
            if ent.offset > start + offset_adjust:
                ent.offset += diff
            # 如果实体覆盖当前替换的词,调整实体长度
            elif ent.offset <= start + offset_adjust and ent.offset + ent.length >= start + offset_adjust + old_len:
                ent.length += diff
        # 替换文本
        new_text = new_text[:start] + new_word + new_text[start+len(old_word):]
        offset_adjust += diff
        # 查找下一个匹配词
        start = new_text.find(old_word, start + len(new_word))

# 发送新消息
await event.respond(new_text, entities=raw_entities)

内容的提问来源于stack exchange,提问作者SAL

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 01:42:01