ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

从零构建Telegram Bot:Python开发、部署与实用技巧全指南

从零构建Telegram Bot:Python开发、部署与实用技巧全指南 我最初接触 Telegram bot就是想在群里搞个自动回复的小玩意省得每天手动回答重复问题。后来发现这东西能做的事远不止聊天定时推送、服务器监控告警、RSS 订阅转发、小工具集成都行而且 Telegram 官方 API 文档清晰、生态成熟用 Python 写一个能用的 bot 其实门槛很低。这篇博文我会从一个完全空白的项目开始带你走完从创建机器人到部署上线的完整流程。你不需要有很深的基础装好 Python 能跑脚本就行。我会把每一步的“为什么这么做”讲清楚也会把文档里不会写的那些坑一个个指出来。这篇内容适合三种人想用 Python 练手做点实际东西的初学者、需要给团队或群组做个自动化小工具的开发者、以及想把自己的服务告警或数据推送集成到 Telegram 的人。1. 开发前必须想清楚的事1.1 先说结论这个项目到底在解决什么问题写 blog 之前我一直在想到底应该给你一个“照抄就能跑”的代码还是把核心机制讲透最后我的结论是两者都要。一个 Telegram bot 本质上是跑在你电脑或服务器上的一个 Python 进程它通过 HTTPS 长轮询或 Webhook 的方式接收 Telegram 服务器转发过来的用户消息然后根据你写的逻辑返回回复。核心就三件事拿 Token向 Telegram 官方的 BotFather 申请一个唯一标识相当于你机器人的门牌号和钥匙。接收消息让程序一直监听 Telegram 服务器有人给你的 bot 发消息时你能收到通知。响应消息根据收到的内容调用 Telegram API 发回文字、图片、按钮等。想清楚这三件事你就会发现写一个 bot 不神秘它就是一个有网络通信能力的 Python 程序。我们这次选择用python-telegram-bot这个库而不是直接去调 HTTP API。为什么因为直接调 API 虽然可行但你要自己处理认证、超时、重试、消息类型解析、长轮询偏移量维护等一堆脏活。用成熟的库可以让你专注在业务逻辑上而且这个库的维护状态非常活跃文档也完整是社区里用的人最多的方案。1.2 先准备环境Python 版本与虚拟环境如果你机器上还没装 Python先去 Python 官网下载安装时记得勾选“Add Python to PATH”否则 cmd 或终端里敲 python 会提示找不到命令。版本选 3.8 或更新的版本我目前用的是 3.10。装好之后强烈建议你创建一个虚拟环境再装依赖。虚拟环境的作用就是给每个项目隔离一套独立的第三方库避免不同项目之间依赖版本互相打架。我见过太多人把包全装到全局环境结果某个库升级后另一个项目直接跑不起来。# 创建项目目录 mkdir tg_bot_demo cd tg_bot_demo # 创建虚拟环境 python -m venv venv # 激活虚拟环境 # Windows: venv\Scripts\activate # macOS / Linux: source venv/bin/activate激活之后你的命令行提示符前面会出现(venv)这就说明你现在在虚拟环境里了。然后安装这次的核心依赖pip install python-telegram-bot注意一下版本。这个库在 v20 版本做了一次比较大的重构写法从同步变成了异步。现在你 pip 安装默认会装最新的 v20 版本我们下面按新版的异步方式写这是目前官方推荐、也是未来继续维护的方向。你可以验证一下安装是否成功python -c import telegram; print(telegram.__version__)能打印出版本号就说明环境没问题。2. 从 BotFather 拿到你的门票2.1 一步一步创建你自己的机器人这一步是在 Telegram 客户端里完成的不需要写代码。你需要在 Telegram 里找到BotFather他是 Telegram 官方用来管理机器人的“机器人之父”。搜索到之后给他发一条/newbot命令然后按提示操作先给你的机器人起一个显示名称比如我的实用小助手这个可以随便起用户看到的就是这个名字。再给它一个用户名必须以bot结尾比如my_useful_helper_bot这个相当于机器人的唯一 ID创建之后就不能改了。操作成功后BotFather 会返回一条类似这样的消息Done! Congratulations on your new bot. You will find it at t.me/my_useful_helper_bot. You can now add a description, about section and profile picture for your bot, see /help for a list of commands. Use this token to access the HTTP API: 1234567890:AAF4aBcDeFgHiJkLmNoPqRsTuVwXyZ最后的这串1234567890:AAF4aBcDeFgHiJkLmNoPqRsTuVwXyZ就是 Token是你的机器人的 API 密钥。这串字符相当于你机器人的总钥匙任何人拿到它就可以完全控制你的机器人一定要保密。我之前见过有人把 Token 直接提交到公开的 GitHub 仓库里结果是机器人半小时内就被别人接管恶意群发消息最后只能找 BotFather 用/revoke把这个 Token 作废重发。拿到 Token 之后还有几件小事建议你顺手做掉用/setdescription设置机器人简介别人打开你的机器人详情页能看到。用/setabouttext设置关于文本内容简短即可。用/setuserpic上传一个头像有头像的 bot 看起来更可信。这一步做完你的 bot 其实已经可以被人搜到、加进群了但它还不会回复任何消息因为后面根本没有程序在跑。那我们就来写这个“跑起来的程序”。2.2 环境变量管理 Token别硬编码进代码很多新手会顺手把 Token 直接写在 Python 文件里这在本地自己玩玩没太大问题但一旦这个项目要分享给别人或者上传到 GitHub、部署到服务器Token 就暴露了。推荐的做法是用环境变量来存 Token。具体实现有很多方式比如直接用os.environ或用.env文件配合python-dotenv库。为了保持简单我会在代码里用os.getenv去读环境变量并在本地用一个.env文件记录同时把.env加进.gitignore。这样即使代码公开别人也看不到你的真实 Token。3. 写出第一个能对话的机器人3.1 最小可运行的代码一个能回应你的 echo bot我建议第一版做的事很简单用户发什么bot 就原样回什么。这个版本的目的是让你体会“接收消息-处理-回复”的完整链路跑通了后面的功能都基于这个链路进行扩展。新建一个bot.py文件把下面的内容放进去import os import asyncio import logging from telegram import Update from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes # 1. 配置日志模块 logging.basicConfig( format%(asctime)s - %(name)s - %(levelname)s - %(message)s, levellogging.INFO ) # 2. 读取 Token TOKEN os.getenv(TG_BOT_TOKEN, 在这里粘贴你的token) # 3. 定义 /start 命令处理函数 async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) - None: user update.effective_user await update.message.reply_text( f你好 {user.first_name}我收到了你的 /start 命令。你现在可以给我发任意消息我会原样回复你。 ) # 4. 定义普通消息处理函数 async def echo(update: Update, context: ContextTypes.DEFAULT_TYPE) - None: user_text update.message.text await update.message.reply_text(f你说了{user_text}) # 5. 主函数组装 application 并启动 def main() - None: application Application.builder().token(TOKEN).build() # 注册 handler application.add_handler(CommandHandler(start, start)) application.add_handler(MessageHandler(filters.TEXT ~filters.COMMAND, echo)) # 启动轮询 application.run_polling() if __name__ __main__: main()这个代码很短但每个部分都有讲究下面拆开讲。3.2 逐段解释这段代码到底在干嘛第一部分是日志配置。这一行logging.basicConfig(...)是很多新手会忽略但极其关键的一步。你用run_polling()跑起来之后如果没有日志输出程序到底在不在跑、收没收到消息、有没有报错全都是黑盒。加上日志之后每一条收到的更新、每一次异常你都能在终端里看到实时的处理记录排查问题会轻松一个量级。我强烈建议任何阶段都不要省掉这行。format字符串里%(asctime)s是时间%(name)s是日志来源%(levelname)s是级别INFO/WARNING/ERROR%(message)s是具体内容。levellogging.INFO表示只显示 INFO 及更高级别的日志。你要是想看到更详细的网络调试信息可以临时改成DEBUG但要小心日志会变得非常多容易刷屏。第二行是 Token 获取。用了os.getenv第一个参数是环境变量名第二个参数是默认值。我们在.env里设置TG_BOT_TOKENxxxx配合python-dotenv加载或者你在系统环境变量里设置也行。为了演示方便我这里把默认值写成了占位符但你在本地跑的时候可以直接把 Token 填进去。第三和第四是处理函数。你会发现这两个async def函数长得一模一样接收update和context两个参数然后在函数体里做具体处理。update里面装的是 Telegram 推送给你的所有信息包括用户、消息内容、聊天来源等。context是一个上下文对象可以理解为你这个 bot 的“工具箱”后面我们会用到它来存数据、设置定时任务等。这里的两个函数都用await调用reply_text这是异步操作的标志表示这个操作不会阻塞主线程。第五部分是组装与启动。Application.builder().token(TOKEN).build()是 python-telegram-bot v20 的标准写法构建了你的应用实例。然后通过add_handler注册两个处理器。CommandHandler用于匹配以/开头的命令MessageHandler用于匹配普通文本消息。最后run_polling()就是启动一个循环不断向 Telegram 服务器询问有没有新消息有就分发给你注册的处理器去处理。3.3 运行你的 bot 并验证链路在项目目录下运行python bot.py如果一切正常日志里会出现类似Application started的提示。这个时候你打开 Telegram找到你的 bot就是 BotFather 告诉你的那个t.me/xxx链接点进去发一条/start它会回复你好再随便发一句“hello”它会回复“你说了hello”。就这样你的第一个 Telegram bot 已经跑通了。这个过程其实就完成了整个 bot 的 30% 工作量剩下的都是在加功能、优化体验。4. webhook vs polling轮询与推送的取舍4.1 为什么开发阶段用 polling刚才代码使用了run_polling()中文叫轮询模式。原理是你的程序每隔一小段时间向 Telegram 服务器问一次“有我的新消息吗”有就取走并处理。这是开发调试阶段最好的方式不需要公网 IP你的电脑只要能正常访问 Telegram 服务器就行。启动简单本地跑个 Python 脚本即可。代码改动后按 CtrlC 停掉重新运行就生效迭代很快。轮询模式在 v20 库内部使用了Updater组件和Application.run_polling它会自动维护偏移量也就是不用担心漏消息或重复处理。对个人项目来说基本够用了。4.2 什么阶段该考虑 webhookWebhook 是另一种接收消息的模式Telegram 服务器在有新消息时主动向你配置的 HTTPS 地址发一个 POST 请求。这要求你有一个公网可达的地址而且必须是 HTTPSTelegram 要求有合法证书对本地调试很不友好。我给你的建议是本地开发、学习、调试用 polling。部署到服务器上、并且对消息实时性要求高、希望省一点网络请求开销用 webhook。多数个人小项目和内部工具一直用 polling 也没问题Telegram 对 polling 的频率限制并不苛刻。如果日后真要切 webhook你要在Application构建后调用application.run_webhook()而不是run_polling()并且设置好监听地址、端口和证书。这一块等需要的时候再看文档即可现在不用纠结。5. 给机器人加点常用功能命令参数、键盘和回调5.1 带参数的自定义命令单纯的 echo 太没意思了我们加一个/sum命令让它计算两个数字相加的结果。这个功能虽然小但能展示“如何处理用户传入的参数”。async def sum_command(update: Update, context: ContextTypes.DEFAULT_TYPE) - None: # context.args 是用户输入命令时跟在命令后面的内容已按空格切分好 args context.args if len(args) ! 2: await update.message.reply_text(请按这个格式输入/sum 数字1 数字2) return try: num1 float(args[0]) num2 float(args[1]) except ValueError: await update.message.reply_text(你输入的不是有效数字请重新输入。) return result num1 num2 await update.message.reply_text(f{num1} {num2} {result})这段代码展示了两个重要技巧。一是context.args的用法用户在 Telegram 里发/sum 3 5时Telegram 服务器会把命令和参数拆开context.args就是一个[3, 5]的列表。二是容错处理用户很可能不按规矩输比如只输了一个数字或者输入了非数字字符。好的 bot 应该在这种时候给出友好提示而不是直接抛出异常让程序崩溃。注册方式一样application.add_handler(CommandHandler(sum, sum_command))这样的命令可以无限扩展。比如/weather 城市名查天气、/joke讲个笑话、/translate 单词查翻译。每条命令就是一个函数逻辑清晰拓展起来非常舒服。5.2 让对话更顺手自定义键盘按钮如果你加了很多命令用户记不住怎么办Telegram 提供了一个很方便的 UI 组件自定义键盘。它在输入框上方显示一排按钮用户点一下按钮就相当于发送了对应文字不用手动敲命令。from telegram import ReplyKeyboardMarkup, KeyboardButton async def show_menu(update: Update, context: ContextTypes.DEFAULT_TYPE) - None: buttons [ [KeyboardButton(/start), KeyboardButton(/help)], [KeyboardButton(/sum), KeyboardButton(/echo)], ] reply_markup ReplyKeyboardMarkup(buttons, resize_keyboardTrue) await update.message.reply_text(请选择一个功能, reply_markupreply_markup)ReplyKeyboardMarkup的参数第一项是一个二维列表每一行是一个列表里面的KeyboardButton就是按钮。resize_keyboardTrue让 Telegram 自动调整按钮大小避免按钮太大占满屏幕。用户点按钮时会自动在输入框填入对应的文字并发送跟你手动打字完全等价。这种键盘非常适合做“菜单引导”把命令列表直接展示在用户面前降低使用门槛。尤其是给不太懂技术的群成员用的群管理 bot一个按钮比让用户输命令友好得多。5.3 内联键盘与回调让 bot 变得真正“智能”自定义键盘只是快捷输入内联键盘才是能让用户“对话之后产生状态变化”的利器。内联键盘直接依附在消息下面用户点击按钮时不会发消息而是触发一个回调callback。你的程序可以根据回调数据来更新当前消息的内容或执行某个动作。举个例子我写过一个排行榜 bot用内联键盘做翻页from telegram import InlineKeyboardButton, InlineKeyboardMarkup from telegram.ext import CallbackQueryHandler # 示例数据模拟排行榜 rank_data [ {name: 张三, score: 100}, {name: 李四, score: 90}, {name: 王五, score: 80}, ] async def show_rank(update: Update, context: ContextTypes.DEFAULT_TYPE) - None: keyboard [ [ InlineKeyboardButton(上一页, callback_dataprev), InlineKeyboardButton(下一页, callback_datanext), ] ] reply_markup InlineKeyboardMarkup(keyboard) # 先展示第一页 text \n.join([f{i1}. {item[name]} - {item[score]}分 for i, item in enumerate(rank_data)]) await update.message.reply_text(text, reply_markupreply_markup) async def rank_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) - None: query update.callback_query await query.answer() # 必须调用否则用户端按钮会一直转圈 data query.data # 用户点击的按钮的 callback_data if data prev: new_text 这是上一页的内容 elif data next: new_text 这是下一页的内容 else: new_text 未知操作 await query.edit_message_text(new_text) application.add_handler(CommandHandler(rank, show_rank)) application.add_handler(CallbackQueryHandler(rank_callback))这里有两个非常容易踩的坑。第一所有CallbackQueryHandler函数里面第一件事必须是await query.answer()这个回答告诉 Telegram“我收到你按钮的回调了”如果你不调用用户手机上按钮会一直处于“加载中”状态体验极差。第二操作完消息内容用query.edit_message_text这样不会新增消息而是直接修改原消息内容保持聊天界面整洁。内联键盘 回调是 Telegram bot 最灵活的地方几乎所有的交互式功能投票、翻页、确认框、订单状态切换都是基于这套机制。6. 部署上线让机器人 7x24 小时在线6.1 本地跑起来和“真正能用”是两回事你的电脑关了或者终端窗口关了机器人就下线了。如果这个 bot 只是自己临时用用那没问题但如果你要把它分享给别人或者作为团队工具就需要把它部署到一台常开的服务器上。部署方案上有几个选择按推荐度排序一台便宜的 VPS / 云主机在 Linux 服务器上用 systemd 守护进程跑最可控。容器化部署写 Dockerfile构建镜像docker run 就能跑。免费层级 PaaS 平台可以部署在某些 free tier 服务上但受限于平台策略。我平时自己用、帮朋友部署最常用的是 Linux VPS systemd 方案因为免费、稳定、不用额外学 Docker。下面就把这套流程讲清楚。6.2 systemd 守护进程配置让 bot 崩溃后自动重启假设你的项目已经上传到服务器路径是/opt/tg_bot_demo里面已经激活了虚拟环境并装好依赖。接下来创建一个 systemd 服务文件。在服务器上创建/etc/systemd/system/tg-bot.service[Unit] DescriptionTelegram Bot Demo Afternetwork.target [Service] Userroot WorkingDirectory/opt/tg_bot_demo EnvironmentTG_BOT_TOKEN你的实际Token ExecStart/opt/tg_bot_demo/venv/bin/python /opt/tg_bot_demo/bot.py Restartalways RestartSec5 [Install] WantedBymulti-user.target然后执行systemctl daemon-reload systemctl enable tg-bot.service systemctl start tg-bot.service这里有个多人都踩过的坑Environment 里写 Token。因为服务在系统启动时由 systemd 加载它不会读取你的.env文件。你可以在 Environment 里直接把 Token 写进去这是最直观的但要注意这个文件 root 可读如果你是多人共用服务器建议改成用 EnvironmentFile 指向一个权限 600 的配置文件。说实话个人用直接写 Environment 够用了顺手就好。Restartalways表示如果进程异常退出systemd 会在 5 秒后自动拉起。有了这行bot 就算因为网络抖动或者个别 bug 崩了也会自动恢复不会一直躺尸。查看状态和日志的命令systemctl status tg-bot journalctl -u tg-bot -fjournalctl -f可以实时滚动日志是远程排查问题最好的工具。7. 常见问题与排查技巧实录7.1 更新里明明有消息bot 却不回复这是新手问得最多的问题。通常有四个原因Token 不对。确认你复制的是完整的 Token没有多空格少字符。可以到 BotFather 那发送/token查看当前的 Token 并一键复制。handler 没匹配上。比如用户发的是/foo但你注册的是/start和/sum那 bot 当然没反应。用MessageHandler(filters.COMMAND, ...)可以拦截所有未注册命令然后给出提示。程序根本没在跑。去服务器上systemctl status tg-bot看看或者本地看终端有没有日志。很多“bot 不回复”其实是服务挂了。隐私模式拦截了群聊消息。如果你把 bot 加进群但 bot 在群里不能回复普通用户消息很可能是你用了默认的 privacy mode。去群管理设置里关闭隐私模式或者在 BotFather 用/setprivacy改成 Disabledbot 就能在群里收到所有消息。7.2 触发了 Telegram 的限流怎么办Telegram API 有频率限制如果短时间内发送太多消息会返回 429 错误。这个限制不是写死的而是按“每个 chat 每秒钟最多约 1 条消息”来算的如果你的 bot 会批量推送消息就需要在代码里做节流。我写批量通知的时候会用一个简单的 sleep 来控制频率import asyncio async def send_batch(chat_id, messages): for msg in messages: try: await application.bot.send_message(chat_idchat_id, textmsg) await asyncio.sleep(1.2) # 稍微大于每秒一条的阈值 except Exception as e: logging.error(f发送失败: {e})库本身在收到 429 时会自动等待并重试但保险起见自己加上限速更可靠。7.3 本地跑得好好的部署到服务器就出问题最常见的原因是路径问题和环境变量问题。sys.path找不模块、open(file.txt)找不到文件很多都是因为服务的工作目录和你在本地不一致。所以在 systemd 配置里一定要写WorkingDirectory代码里读取文件也建议用绝对路径或者基于__file__动态计算路径import os BASE_DIR os.path.dirname(os.path.abspath(__file__)) file_path os.path.join(BASE_DIR, data.txt)还有一个问题就是时区。Telegram 返回的时间是 UTC你本地可能是 UTC8。如果需要展示时间记得用pytz或zoneinfo转换否则推送的提醒时间会对不上。7.4 我的 bot 被人恶意刷消息怎么办如果 bot 是对外公开的一定会遇到无聊的人刷消息、发广告。最简单有效的措施是加“用户白名单”或“群白名单”。ALLOWED_USER_IDS {123456789, 987654321} # 你的 Telegram User ID async def restricted_echo(update: Update, context: ContextTypes.DEFAULT_TYPE) - None: user_id update.effective_user.id if user_id not in ALLOWED_USER_IDS: await update.message.reply_text(抱歉你没有权限使用此机器人。) return await echo(update, context)自己怎么看 User ID在 Telegram 里找一个叫userinfobot的机器人发任意消息它会告诉你的用户 ID。对内部工具来说白名单是最简单也最有效的保护。如果你怕别人从代码里看到 ID就把白名单也放到环境变量或配置文件里。8. 日志与安全我踩过的最贵的坑8.1 一开始就把日志做好后面会感谢自己很多自学的初学者不重视日志觉得程序能跑就行。但 bot 这种长驻进程日志是唯一能告诉你“刚才发生了什么”的东西。没有日志线上出事你只能干瞪眼。我给你一份可以直接抄的日志配置import logging from logging.handlers import RotatingFileHandler # 屏幕输出 console_handler logging.StreamHandler() console_handler.setLevel(logging.INFO) # 文件输出5MB 一个文件最多保留 3 个 file_handler RotatingFileHandler(bot.log, maxBytes5 * 1024 * 1024, backupCount3) file_handler.setLevel(logging.DEBUG) logging.basicConfig( format%(asctime)s - %(name)s - %(levelname)s - %(message)s, levellogging.INFO, handlers[console_handler, file_handler], )这样配置之后信息同时输出到终端和bot.log文件。日志文件超过 5MB 自动轮转不会无限膨胀。排查问题的时候grep ERROR bot.log一查一个准。8.2 Token 泄露了怎么办如果你不小心把 Token 提交到公开仓库或者发给不该发的人不用慌。回到 BotFather发送/revoke选择你的 bot然后重新生成 Token。旧 Token 会立刻失效然后把新 Token 更新到你的环境变量或配置文件重启服务即可。这里有个细节/revoke只会让你 bot 的 API Token 失效不会影响 bot 的用户名和已经添加它的群。群里的配置、命令都还在只是 API 鉴权换了钥匙。还有一个安全习惯不要在自己代码里写调试用的print(TOKEN)。我见过有人调试时把 Token 直接打印到了日志里然后日志被传到了日志聚合平台等于变相公开。正经做法是任何时候都不要在日志里输出 Token配置解析时也不要把完整 Token 打出来。9. 进一步扩展的方向一旦你的 bot 跑起来了功能扩展就是水到渠成的事情。我自己做完基础版本之后持续加了很多功能这里列几个可以拓展的方向供参考定时任务用Application.job_queue跑定时任务比如每天早上 8 点推送天气、每周一发送周报。实现方式是在main()里注册job_queue.run_daily(my_callback, timedatetime.time(hour8, minute0))回调函数里写你的推送逻辑。数据库持久化如果用ConversationHandler做多轮问答或需要记录用户状态建议引入 SQLite 或 PostgreSQL。python-telegram-bot 官方有PicklePersistence/DictPersistence但对复杂业务还是自己上数据库更稳。与外部 API 集成bot 最迷人的地方是作为入口它可以调用任意第三方 API。比如对接天气 API、翻译 API、大模型 API、股票数据 API把结果推回 Telegram。多 bot 管理如果你有很多群、多个 bot可以考虑做一个统一的管理平台用同一个代码框架跑多个 bot 实例。重点提醒一句扩展功能时优先保证核心链路稳定。一个 bot 的百分之九十价值在于它能不能稳定地每天跑着不出错、不丢失消息。功能再多崩溃了都是零。10. 写在最后一点个人体会文章篇幅不短能读到这里的朋友我相信是真的想动手做点东西的人。如果只记住一句话我会说先让最小用例跑起来再考虑功能复杂度。刚开始别想着一上来就写一个带内联键盘、多轮对话、数据库、定时任务的“全家桶”大概率写到一半就被一堆概念劝退了。先做 echo bot跑通了再一个个加命令、加键盘、加回调每一步都有明确的反馈学习曲线会平滑很多。我在实际做这个项目时最大的一个教训是不要长时间不重启不更新就让 bot 一直跑着。依赖库会升级、Telegram API 会调整、消息格式可能变这些都会导致某些功能悄悄失效。养成定期看日志、手动测试核心功能的习惯比任何花哨的架构都重要。如果你做到一半卡住了建议按顺序排查Token 是否有权限、网络是否能连通 Telegram、依赖库版本是否匹配、处理逻辑是否抛了异常。四个方向检查完百分之九十的问题都能定位。希望这篇内容能帮你写出人生中第一个可以骄傲地发给朋友看的 Telegram bot。动手建个目录装好依赖马上开始吧。
返回列表