☰
Telegram搜索资源与搜索引擎搭建实战:Telethon+SQLite+Flask全流程
2026/10/23 3:12:17 网站建设 项目流程

这次我们来看一个和 Telegram 搜索资源、搜索引擎搭建有关的实战教程。

核心不是把 Telegram 改成一个花哨的网页,而是解决一个很实际的问题:当你面对大量频道、群组和历史消息时,怎么快速找到想要的内容,怎么把自己有权访问的消息整理成本地索引,怎么做成可以重复调用的搜索接口。Telegram 本身有消息搜索能力,平时在某个聊天内搜关键词够用;但频道一多、消息一多、需要反复过滤的时候,直接搜就明显不够了。

更稳妥的做法是把它拆成三层。第一层用客户端和 Bot 的搜索能力做临时检索;第二层用 Telethon 把消息批量采集到本地 SQLite 数据库;第三层把数据库封装成 HTTP 搜索接口,供脚本、网站或者其他工具调用。这套方案不需要 GPU,对显存完全没有需求,普通服务器就能跑,适合做内容留档、信息聚合、群聊资料库和个人知识库。

本文会带读者完成完整链路:环境准备、账号凭证获取、Telethon 客户端搭建、消息关键词搜索测试、自定义 Bot 搜索指令、消息采集入库、批量任务调度、搜索接口封装,以及常见问题排查。使用边界先说明:本文不讨论任何网络访问配置,所有操作必须在当地法律法规、Telegram 服务条款以及内容授权允许的范围内进行。

1. 核心能力速览

这个教程不是下载某个现成软件,而是通过组合 Telegram 已有搜索能力和 Telethon 客户端库,搭建一套轻量级“Telegram 搜索资源 + 搜索引擎”方案。关键能力先用一张表快速过一遍:

能力项说明
项目类型Telegram 搜索技巧 + 基于 Telethon 的轻量搜索引擎搭建教程
主要功能关键词消息检索、频道/群组内容采集、自定义 Bot 搜索指令、HTTP 搜索接口、批量轮询
运行环境Python 3.9+,普通 CPU 即可,无需 GPU,无显存占用
依赖工具Telethon、SQLite 标准库,可选 Flask/FastAPI 做接口
启动方式命令行启动 Python 脚本,可常驻运行
接口能力可封装为本地 HTTP 搜索接口,支持 curl / Python 调用
批量任务支持按频道列表逐个采集,配合定时任务做增量轮询
数据存储SQLite 本地数据库,适合十万级消息以内检索
适合场景内容留档、群聊资料库、内部信息聚合、自定义搜索工具
合规要求必须遵守当地法律法规、Telegram 服务条款与内容授权规则

从表里可以快速得到几个判断点:

  • 不需要 GPU,不消耗显存,低成本服务器就能跑。
  • 支持 API 封装,用 Flask 可以快速暴露搜索接口。
  • 支持批量任务,把频道列表写进配置,循环采集即可。
  • 启动方式不是 WebUI,而是命令行 Python 脚本,适合放在服务器后台运行。
  • 使用前需要准备 Telegram 账号凭证和 Bot Token。

2. 适用场景与使用边界

先回答一个最关键的问题:这个方案到底适合谁,不适合谁。

适合的场景很明确。如果你需要定期把某个公开频道里的文字消息汇总留档,或者要给多个人维护一个内部检索入口,或者想把一段时间内某个群聊里的讨论内容保存下来做二次分析,这套“Telethon 采集 + SQLite 存储 + HTTP 接口”的思路都适用。它的核心价值是两点:第一,把分散在多个聊天的内容集中到一个本地库;第二,用本地 SQL 查询替代每次实时请求 Telegram 服务器,检索更快、更稳定。

不适合的场景也很清楚。这个方案不适合采集私密聊天内容,不适合把未授权媒体文件批量转发保存,也不适合把搜索结果公开到没有访问控制的站点上。Telethon 虽然能够以客户端身份读取账号有权访问的聊天,但这只是技术能力,不等于可以无视授权。本节说的“资源”,严格限定为已授权、可公开访问或你有权读取的频道/群组内的文本消息和文字内容。

合规边界必须划清楚:

  • 不要采集和保存任何你没有权限访问的私密聊天记录。
  • 不要将抓取到的消息公开传播,尤其是涉及个人信息、内部讨论和未授权内容。
  • 不要批量下载和二次分发受版权保护的图片、视频、音频等媒体文件。
  • 账号凭证和个人 session 文件不要提交到公开代码仓库,不要泄露给第三方。
  • 使用个人主账号批量采集前要慎重,高频请求可能触发账号风控限制,后果由使用者自行承担。

3. 环境准备与前置条件

在开始写代码之前,先把环境确认好。

硬件方面,这个方案对性能要求很低。单个 Telethon 客户端进程主要消耗网络带宽和少量内存,普通 1 核 2G 的 Linux 服务器就能跑。磁盘空间需要根据采集量设计,如果只保存文字消息,几万条通常只占几 MB 到几十 MB;如果后续要扩展媒体文件,磁盘占用会快速上升,所以第一章建议先把范围控制在文本消息。

软件方面需要准备:

  • Python 3.9 或更高版本。
  • pip 包管理工具。
  • 建议使用虚拟环境隔离依赖。
  • 需要一个可以正常访问 Telegram API 的网络环境,访问配置不在本教程范围内。

凭证准备是很多人容易卡住的地方,需要准备两套东西。

第一套是 Telegram 账号的api_id和api_hash。在 Telegram 官方应用管理平台创建一个应用,创建完成后就能拿到这两个值。这个凭证本质上是你的客户端身份标识,Telethon 登录时需要用到。使用个人客户端模式搜索消息,就是通过这组凭证以你的账号身份去访问有权查看的聊天记录。

第二套是 Bot Token,用于 Bot 模式的搜索指令。在 Telegram 中向 @BotFather 发送命令创建机器人,会得到一个123456:ABC...格式的 Token。Bot 模式适合部署成群聊内的搜索机器人,但它的消息读取范围受权限限制,通常只能处理 Bot 所在聊天中它能访问到的消息,后面会具体讲。

创建虚拟环境并安装依赖:

python -m venv venv source venv/bin/activate # Windows # venv\Scripts\activate pip install telethon pip install flask

telethon是核心依赖,负责以 MTProto 协议连接 Telegram API;flask用于最后封装 HTTP 搜索接口,可以按需要选装。

4. 安装部署与启动方式

先用一个最小脚本验证账号凭证和 Telethon 客户端能否正常工作。新建search_client.py:

from telethon import TelegramClient api_id = 123456 # 替换为你在官方应用管理平台获取的 api_id api_hash = "0123456789abcdef0123456789abcdef" # 替换为 api_hash client = TelegramClient("search_session", api_id, api_hash) async def main(): await client.start() me = await client.get_me() print("登录账号:", me.username or me.first_name) if __name__ == "__main__": import asyncio asyncio.run(main())

运行:

python search_client.py

第一次运行会要求输入手机号,然后输入登录验证码。如果账号开启了双重验证,还要再输入密码。登录成功后,目录下会生成一个search_session.session文件,这个文件保存了登录状态,后续运行不需要重新输入验证码。

如果要用 Bot 模式启动,代码会稍有不同:

from telethon import TelegramClient api_id = 123456 api_hash = "0123456789abcdef0123456789abcdef" bot_token = "123456:ABC..." client = TelegramClient("search_bot_session", api_id, api_hash) async def main(): await client.start(bot_token=bot_token) me = await client.get_me() print("Bot 登录:", me.username) if __name__ == "__main__": import asyncio asyncio.run(main())

这里要注意,Bot 模式下client.get_me()返回的是机器人账号,而不是你的个人账号。Bot 消息读取范围更小,但好处是更适合部署在群聊中给多个成员共用,不会把个人账号会话暴露出去。

启动脚本的方式很简单,确认屏幕上出现登录账号信息,就说明环境准备完成。这个阶段的常见问题是验证码输入错误、手机号不匹配、历史 session 被风控,排查思路放在第九章统一处理。

5. 功能测试与效果验证

5.1 在指定聊天中搜索关键词

最小客户端跑通后,先测最简单的关键词搜索。新建search_test.py:

from telethon import TelegramClient api_id = 123456 api_hash = "0123456789abcdef0123456789abcdef" client = TelegramClient("search_session", api_id, api_hash) async def main(): await client.start() chat = await client.get_entity("目标频道的username") count = 0 async for msg in client.iter_messages(chat, search="Python", limit=30): text = (msg.text or "").replace("\n", " ")[:60] print(msg.date, msg.sender_id, text) count += 1 print("命中条数:", count) if __name__ == "__main__": import asyncio asyncio.run(main())

关键点有三个:

  • get_entity支持频道/群组的 username、链接、邀请链接中的 ID。如果目标聊天是私密群,账号必须已经加入。
  • iter_messages的search参数指定关键词,Telethon 会把请求转换为服务端的消息搜索。
  • limit限制返回条数,不传 limit 时会从头到尾遍历所有命中消息。

运行后输出每一条命中的消息时间和前 60 个字符,方便快速确认搜索是否生效。

测试成功的判断标准很简单:能打印出与关键词匹配的消息,并且消息内容确实来自目标聊天。如果打印为空,优先检查关键词是否真的存在于该聊天中,以及账号是否加入了目标聊天。

5.2 按发送人过滤与组合条件

搜索通常需要组合条件。Telethon 的iter_messages还支持from_user参数,用来限定发送人:

# 搜索某个用户发表的包含关键词的消息 async for msg in client.iter_messages( chat, search="Python", from_user="目标userId或username", limit=20 ): print(msg.date, msg.text[:80])

这种过滤适合做定向内容监测,例如查看某一频道内某个作者发布的特定主题内容。Telethon 还支持时间范围过滤,但需要拼接offset_date或处理日期边界,实际使用中按需查阅官方方法签名即可。

5.3 自定义搜索 Bot 指令

客户端测试没问题后,可以做一个 Bot 模式搜索机器人。用户向 Bot 发送/search 关键词,Bot 返回当前聊天中最近命中的消息。先设置环境变量:

export TG_API_ID=123456 export TG_API_HASH=0123456789abcdef0123456789abcdef export TG_BOT_TOKEN=123456:ABC...

然后新建search_bot.py:

import os from telethon import TelegramClient, events api_id = int(os.getenv("TG_API_ID", "0")) api_hash = os.getenv("TG_API_HASH", "") bot_token = os.getenv("TG_BOT_TOKEN", "") client = TelegramClient("search_bot_session", api_id, api_hash) @client.on(events.NewMessage(pattern="/search")) async def handler(event): parts = event.raw_text.split(maxsplit=1) if len(parts) < 2: await event.reply("用法:/search 关键词") return keyword = parts[1] chat = event.chat hits = [] async for msg in client.iter_messages(chat, search=keyword, limit=10): text = (msg.text or "").replace("\n", " ")[:100] hits.append(f"[{msg.date:%m-%d %H:%M}] {text}") result = "\n".join(hits) if hits else "当前聊天没有命中消息。" await event.reply(result) async def main(): await client.start(bot_token=bot_token) print("搜索 Bot 已启动") await client.run_until_disconnected() if __name__ == "__main__": import asyncio asyncio.run(main())

启动:

python search_bot.py

把 Bot 拉入目标群,然后在群里给 Bot 发送/search 某关键词。如果一切正常,Bot 会回复最近 10 条与关键词匹配的消息。

这里要说明 Bot 模式的限制:Telethon 以 Bot Token 启动后,只能读取当前聊天中 Bot 有权访问的消息。对于默认开启了隐私模式的群聊,Bot 未必能看到所有历史消息,所以搜索结果可能比个人客户端模式少。要做更完整的搜索,建议使用个人客户端模式,或者把 Bot 设置为允许读取全部消息。

6. 消息采集入库与基础搜索引擎

实时搜索的问题在于,每次都要请求 Telegram 服务器,消息一多速度就慢,而且容易碰到接口限流。更实用的方式是先采集、后搜索:把消息落到本地 SQLite,再用 SQL 查。

先建表:

CREATE TABLE IF NOT EXISTS messages ( id INTEGER PRIMARY KEY, chat_id INTEGER, msg_id INTEGER, sender_id INTEGER, date TEXT, text TEXT, UNIQUE(chat_id, msg_id) );

UNIQUE(chat_id, msg_id)可以避免同一聊天内的同一条消息重复入库,这是后期增量采集的基础。

采集函数:

import sqlite3 from telethon import TelegramClient conn = sqlite3.connect("telegram.db") async def archive_chat(client, chat, keyword=None, limit=200): async for msg in client.iter_messages(chat, search=keyword, limit=limit): text = msg.text or "" if not text.strip(): continue conn.execute( "INSERT OR IGNORE INTO messages(chat_id, msg_id, sender_id, date, text) VALUES (?, ?, ?, ?, ?)", (chat.id, msg.id, msg.sender_id, msg.date.isoformat(), text) ) conn.commit()

这里保存的是消息文本,媒体消息的说明文字一般也在msg.text里。

落库完成后,就可以用本地 SQLite 做搜索:

def local_search(keyword, chat_id=None, limit=50): if chat_id: rows = conn.execute( "SELECT date, sender_id, text FROM messages " "WHERE chat_id = ? AND text LIKE ? " "ORDER BY date DESC LIMIT ?", (chat_id, f"%{keyword}%", limit) ).fetchall() else: rows = conn.execute( "SELECT date, sender_id, text FROM messages " "WHERE text LIKE ? " "ORDER BY date DESC LIMIT ?", (f"%{keyword}%", limit) ).fetchall() return rows

这个函数的优势是访问本地数据库,不需要请求 Telegram,速度明显更快,而且可以跨多个聊天统一检索。数据量在万级到十万级的时候,LIKE 查询的表现够用;再往上就需要考虑 SQLite FTS5 全文索引或外部搜索引擎。

7. 接口 API 与批量任务

7.1 封装 HTTP 搜索接口

本地搜索函数写好后,可以用 Flask 暴露成接口。新建api_app.py:

from flask import Flask, request, jsonify app = Flask(__name__) @app.route("/search") def search(): q = request.args.get("q", "") if not q: return jsonify({"error": "缺少 q 参数"}), 400 rows = local_search(q) return jsonify({ "count": len(rows), "items": [list(r) for r in rows] }) if __name__ == "__main__": app.run(host="127.0.0.1", port=8765, debug=False)

启动:

python api_app.py

测试接口:

curl "http://127.0.0.1:8765/search?q=Python"

返回结果是一段 JSON,包含命中的数量和时间、发送人、消息文本。接口只绑定127.0.0.1,默认只允许本机访问,避免直接暴露到局域网。如果需要外部服务调用,建议在前面加网关或限制来源 IP。

7.2 批量采集与定时任务

批量任务的核心逻辑是循环频道列表,逐个调用采集函数:

CHANNELS = [ "channel_a", "channel_b", "channel_c", ] async def run_batch(): for name in CHANNELS: try: chat = await client.get_entity(name) await archive_chat(client, chat) except Exception as exc: print("采集失败:", name, exc)

加上定时任务后,就能实现每天自动增量采集。最简单的方式是系统 crontab:

# crontab 示例:每天凌晨 2 点执行一次 0 2 * * * cd /path/to/project && python batch_collect.py >> collect.log 2>&1

批量采集最容易遇到的问题就是接口限流。Telethon 在遇到限流时会抛出FloodWaitError,代码里需要捕获:

from telethon.errors import FloodWaitError async def safe_archive(client, chat): while True: try: await archive_chat(client, chat) break except FloodWaitError as e: print("触发限流,等待", e.seconds, "秒") await asyncio.sleep(e.seconds)

等待时间以异常返回的秒数为主,不要为了赶进度频繁重试。更合理的做法是在任务里主动 sleep,降低请求频率,避免触发更长的限制。

8. 资源占用与性能观察

运行这套方案时,可以从几个角度观察资源占用。

进程内存方面,单个 Telethon 客户端常驻进程内存占用通常不大,具体取决于会话数量、缓存和并发任务数。之前说的“普通 1 核 2G 服务器能跑”,在实际部署中偏向保守估计,真实占用需要以本机观察为准。

显存和 GPU 完全用不到,这是这个方案对入门用户比较友好的地方。主要瓶颈在 Telegram 接口请求频率和 SQLite 查询速度。

影响性能的关键参数:

  • limit控制单次采集条数,设置过大会导致耗时长,容易触发限流。
  • 搜索范围越宽,耗时越长;限定chat_id查询通常比全库查询快。
  • SQLite 数据量越大,LIKE 全表扫描越慢。数据量明显增长后,建议切换 FTS5 全文索引。
  • 频繁的commit()可能影响写速度;大批量采集时可以采用批次提交。

如果是个人使用,建议在脚本里输出每批任务的耗时、入库数量和失败数量,方便判断任务是否正常运行。例如:

[2025-06-01 02:00:00] channel_a: 拉取 200 条,入库 180 条,耗时 12.3s [2025-06-01 02:00:15] channel_b: 拉取 200 条,入库 0 条,耗时 3.1s

这种日志对批量任务排查很有用。

9. 常见问题与排查方法

问题现象可能原因排查方式解决方案
登录时反复提示验证码错误手机号输入错误或会话触发风控检查手机号是否带国家区号,停止短时间频繁重试等待一段时间后再尝试,不要连续轮询验证码
提示找不到目标实体目标频道/群组 username 错误,或账号未加入在 Telegram 客户端确认目标聊天真实存在修正 username,先加入目标聊天
消息搜索没有命中结果关键词不存在、目标聊天无权限读历史在客户端手动搜索同一关键词换成已知存在的关键词,加入目标聊天
请求频繁报限流单次任务请求过多、频率过高查看异常信息中的等待秒数捕获 FloodWaitError,降低 limit,增加 sleep
大量消息没有入库消息为纯媒体消息,无文本打印消息类型观察使用 msg.text 或 msg.message 判断,必要时单独处理媒体文件
Bot 收不到搜索命令Bot 未加入聊天或被群权限限制检查群里 Bot 成员状态将 Bot 加入目标群,调整群内 Bot 消息权限
搜索接口响应越来越慢SQLite 数据量增大,LIKE 扫描变慢查看查询日志和表数据量增加索引、限制结果集条数、调研 FTS5 全文索引
session 文件损坏或登录态丢失session 被删除或账号触发风控检查 session 文件是否存在删除 session 后重新登录

这里强调一点:账号触发风控后,正确的做法是立即停止请求、等待限制自然解除。不要尝试任何绕过限制的方案,这既违反平台规则,也存在账号被封的风险。

10. 最佳实践与使用建议

把这套方案从“能跑”提升到“稳定跑”,下面几点值得做。

凭证管理:把api_id、api_hash、bot_token全部放到环境变量里,不要写死在代码里。代码仓库即使公开,也不应该带上凭证。

数据管理:消息表按聊天和时间周期性归档,避免单表无限增长。定期备份telegram.db,可以用 SQLite 的.backup命令或文件复制,备份文件放到独立目录。

任务设计:批量采集任务加入日志和失败重试,每次只处理一个频道,失败后跳过并记录错误。任务内部加锁,避免多个定时任务重复执行造成重复采集和限流。

接口访问控制:搜索接口默认只绑定本机,不要直接暴露公网。如果需要给团队使用,建议放在内网或加访问令牌。接口只做只读查询,不要在接口里暴露采集配置和凭证信息。

合规使用:只处理有权访问且授权允许的内容。涉及人脸、声音、个人信息时必须确认授权。不要采集私密聊天,不要传播未授权媒体文件,不要将抓取内容用于侵权或骚扰用途。

个人账号保护:如果使用个人主账号运行批量任务,控制任务频率和采集范围,避免触发风控。如果条件允许,单独使用 Bot 账号或只读账号执行采集,主账号保持可恢复的干净状态。

11. 总结与下一步

这一篇把 Telegram 搜索资源和搜索引擎搭建的完整链路串了一遍:先用 Telethon 做实时关键词搜索,再把消息批量采集到 SQLite,最后用 Flask 封装成 HTTP 搜索接口,配合定时任务实现了轻量级批量搜索引擎。

整个项目最值得优先验证的是基础关键词搜索,也就是 5.1 节的最小脚本。只要这一步能跑通,说明账号凭证、Telethon 环境和目标聊天权限都没有问题。最容易踩的坑是接口限流,几乎所有批量任务最终都会碰到 FloodWaitError,正确做法是捕获异常并等待自然解除,而不是提高请求频率。

后续可以继续扩展的方向也不少:把 SQLite 换成 FTS5 全文索引,搜索速度和准确度都会提升;增加时间范围和发送人过滤,让检索更精确;加一个简单的 Web 管理页面,方便查看采集状态;把采集任务接入告警系统,让新增消息能实时推送到自己的工具链里。

先从最小搜索脚本开始,跑通后再逐步加批量采集和接口,你的轻量 Telegram 搜索引擎就算是正式上线了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询