Telegram机器人实现聊天内搜索功能的代码与数据库设计实战

本文详细介绍如何通过Telegram机器人记录聊天消息并实现关键词搜索,包括数据库设计、Python代码实现、FTS5中文搜索优化等,帮助开发者快速搭建聊天内搜索功能。

阅读提示涉及账号和安全设置时,请边阅读边核对当前设备界面。

在Telegram群组或频道中,随着消息数量增长,快速找到特定内容成为刚需。然而,Telegram Bot API并不提供直接搜索聊天历史的接口。本文将带你通过消息记录与数据库索引,开发一个能够实现聊天内搜索的机器人,并提供完整的Python代码与进阶优化方案。

为什么Telegram机器人需要聊天搜索功能?

无论是管理一个活跃的社群,还是维护知识型频道,用户经常需要回溯历史消息。机器人作为自动化助手,若能提供关键词搜索,将大幅提升效率。但受限于Bot API,无法读取历史消息,只能通过实时记录积累数据,再基于数据库实现自定义搜索。

核心思路:消息记录与数据库索引

机器人在加入群组后,通过监听所有消息(需关闭隐私模式)将消息内容、发送者、时间等信息写入数据库。当用户执行/search命令时,机器人从数据库检索关键词,并以分页形式返回结果。整个过程不依赖官方未开放的接口,完全合规。

环境准备与数据库设计

我们使用Python的python-telegram-bot(v20+)作为机器人框架,SQLite作为存储引擎。首先安装依赖:

pip install python-telegram-bot

数据库表设计如下:

CREATE TABLE messages (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    chat_id INTEGER,
    message_id INTEGER,
    user_id INTEGER,
    username TEXT,
    text TEXT,
    date INTEGER
);

字段包括聊天ID、消息ID、发送者ID、用户名、消息文本、时间戳。使用AUTOINCREMENT保证消息顺序。

实现消息监听与存储

创建一个异步处理器,对Message类型进行监听。注意在BotFather中通过/setprivacy将机器人设置为Disable,才能接收群组内所有消息。

import sqlite3
from telegram import Update
from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes

conn = sqlite3.connect('messages.db', check_same_thread=False)
cursor = conn.cursor()
cursor.execute('''CREATE TABLE IF NOT EXISTS messages (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    chat_id INTEGER,
    message_id INTEGER,
    user_id INTEGER,
    username TEXT,
    text TEXT,
    date INTEGER
)''')
conn.commit()

async def record_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
    msg = update.message
    if not msg.text:
        return
    cursor.execute(
        'INSERT INTO messages (chat_id, message_id, user_id, username, text, date) VALUES (?,?,?,?,?,?)',
        (msg.chat.id, msg.message_id, msg.from_user.id, msg.from_user.username, msg.text, msg.date.timestamp())
    )
    conn.commit()

def main():
    app = Application.builder().token('YOUR_BOT_TOKEN').build()
    app.add_handler(MessageHandler(filters.TEXT & (~filters.COMMAND), record_message))
    app.run_polling()

以上代码会将所有文本消息存入SQLite表。注意线程安全,使用check_same_thread=False

实现关键词搜索命令

添加/search命令,用户输入关键词后,从数据库查询,并展示结果。为控制输出长度,我们分页显示,每次5条。

from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import CommandHandler, ContextTypes

async def search(update: Update, context: ContextTypes.DEFAULT_TYPE):
    if not context.args:
        await update.message.reply_text('用法:/search 关键词')
        return
    keyword = ' '.join(context.args)
    cursor.execute(
        'SELECT * FROM messages WHERE text LIKE ? ORDER BY id DESC LIMIT 50',
        (f'%%',)
    )
    rows = cursor.fetchall()
    if not rows:
        await update.message.reply_text('未找到匹配消息。')
        return
    # 显示前5条
    text = '\n\n'.join(
        f"{r[4] or '未知用户'} ({r[3]}): {r[5]}" for r in rows[:5]
    )
    await update.message.reply_text(f'找到 {len(rows)} 条结果,显示前5条:\n\n')

def main():
    app.add_handler(CommandHandler('search', search))

对于大量结果,可增加回调分页。以下是一个简单分页按钮示例:

async def page_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()
    # 解析页码,继续查询并渲染
    # 实现略...

进阶优化:使用SQLite FTS5全文搜索

LIKE查询对中文支持较差,且全表扫描性能低下。SQLite的FTS5扩展支持全文搜索,如果数据源是纯文本,可以配合分词实现高效检索。创建FTS5虚拟表:

CREATE VIRTUAL TABLE messages_fts USING fts5(text, content='messages', content_rowid='id');
INSERT INTO messages_fts(rowid, text) SELECT id, text FROM messages;

查询时使用MATCH:

SELECT * FROM messages_fts WHERE messages_fts MATCH ?

中文搜索还需引入分词,例如使用simple分词器或提前用jieba切分后存储到独立字段。需要更全面的方案,可以参考相关分词库文档。

总结与部署建议

通过本文的代码,你可以快速实现一个具备聊天内搜索能力的Telegram机器人。关键点在于消息的实时记录与数据库的有效索引。建议在部署时考虑以下几点:

  1. 使用环境变量存储BOT_TOKEN,避免硬编码。
  2. 定期备份数据库文件,防止数据丢失。
  3. 若消息量极大,可迁移到PostgreSQL或MySQL,并使用Redis缓存搜索结果。
  4. 注意用户隐私,不要在搜索结果中暴露敏感信息,遵守平台规范。

希望本教程能帮助你打造更智能的Telegram机器人。如果你有更多优化思路,欢迎在实践中探索。

FAQ

下载与安装

常见问题

Telegram机器人能直接调用API搜索聊天历史吗?

不能。Telegram Bot API没有提供直接搜索聊天记录的方法。机器人只能通过开始运行后接收新消息,因此需要将消息存储到数据库,再自行实现搜索功能。

如何让机器人接收群组中的所有消息?

需要将机器人的隐私模式设置为关闭。通过BotFather发送/setprivacy,选择Disable,这样机器人就可以看到群组中所有的消息,从而记录并搜索。

中文搜索效果不佳怎么办?

SQLite的LIKE查询对中文支持有限,建议使用FTS5全文搜索,并配合jieba分词等工具对中文文本进行预处理,以提高搜索准确度。