互联网上充斥着有关在 Telegram 等平台上构建聊天机器人的文章。然而,在本文中,读者可以了解如何使用 Python 编写聊天机器人代码。了解本文中使用的包将使喜欢冒险的人能够自己用 Python 扩展这个聊天机器人的功能。
要开始实时构建聊天机器人,有一些先决条件,如下所示:
- 具备 Python 基础知识以及使用 Pip/Conda 安装包的基础知识。
- Python IDE(我使用 Jupyter Notebook,而您可以选择任何流行的选项,如 Spyder、PyCharm、Visual Studio Code 或 Eclipse(带有 PyDev))。
- 您需要在手机和桌面上安装 Telegram。
- 您将需要 Python 库 python-telegram-bot。
机器人计划如何运作
您需要了解该方案中有三个参与者 - 机器人用户、托管机器人的 Telegram 服务器和机器人控制器(来自我们编写和执行的 Python 脚本)。
另请注意,您可以使用以下两种方式来控制机器人:
“投票”计划
这里,Python 脚本(控制机器人)将定期访问,即“轮询”Telegram 服务器上的机器人,检查是否有来自机器人用户的任何新消息,并做出相应响应。
Webhook 方案
这是更有效的方案。这里机器人控制器脚本不会“轮询”机器人;相反,是机器人通知机器人控制器机器人用户已发送新消息。然而,这种方案还需要两个额外的条件:机器人控制器所在服务器的永久 IP 地址,以及托管机器人控制器的服务器必须启用 HTTPS。在本文中,我仅描述“轮询”方案。
使用 @BotFather 创建您的机器人
创建 Telegram 机器人的步骤如下:
1. Telegram 有一个名为@BotFather 的机器人,它可以为您创建一个机器人。因此,第一步,转到您的 Telegram 应用程序并搜索 @BotFather。
2. 然后向其发送消息/start。该方案的工作原理如下:如果它是一条没有前导斜杠 (/) 的消息,那么它将被解释为文本消息。但是,如果它有一个前导斜杠,那么它将被解释为函数/方法。 Telegram 机器人无法自行响应(以减少机器人发送垃圾邮件)。它必须接收一条文本消息(没有正斜杠的消息)或命令(带有前导正斜杠的消息)才能响应此类消息。
3. 现在使用命令 /newbot 创建一个新机器人并为其指定一个适当的名称,该名称必须以单词 bot 结尾。 @BotFather 将向您发送一条消息,其中包含一个令牌。该令牌应如下所示:
1104497538:AAEbXXXi PegAxUXXXX_
特维米PG01GnXXLY
(为了保护隐私,一些字母已替换为 X。)图 3 显示了 Telegram 应用程序上的流程。
4. 请注意,您新创建的机器人托管在 Telegram 服务器上,您现在可以使用以下格式的命令在 Web 浏览器上访问您的机器人:
https://api.telegram.org/bot/getme
上述 URL 分为三部分: (1) https://api.telegram.org/bot ; (2);和(3)/getme。 URL 的前两部分将允许您的浏览器访问您的机器人(驻留在 Telegram 服务器上),最后一部分将向您的机器人提供适当的命令。这里的命令是 /getme,因此它将以 JSON 对象的形式提供您的机器人的详细信息(类似于 Python 字典)。图 4 展示了这一点。
现在有两种与机器人交互的方式。当然,第一种是我们之前使用的方法,我们使用 Web 浏览器和以下格式的 URL https://api.telegram.org/bot/getme
然而,还有第二种方法,我们可以使用 Python 脚本来访问从机器人用户发送到托管在 Telegram 服务器上的机器人的消息/命令。在下一节中,我们将研究通过用 Python 编写的脚本创建机器人控制器。
使用 python-library-telegram 编写 Python 脚本来创建机器人控制器
要创建机器人控制器脚本,我们将使用 Python 库 python-telegram-bot;所以使用 Pip 下载它:
pip 安装 python-telegram-bot
如图 5 所示。
要编写 Python 脚本,您可以使用任何流行的 IDE。一些常见的有 PyCharm、Visual Studio Code 和 Eclipse(带有 PyDev)。您需要了解该库的一些类和方法才能真正理解代码的工作原理。请记住,我们使用的是轮询而不是 Webhook 技术。
我们将使用 telegram.ext 子模块中两个类的实例(即,我们将创建其对象),即 telegram.ext.Updater 和 telegram.ext.Dispatcher。 Updater 类从 Telegram 获取更新并将其传递给 Dispatcher 类。
当你创建一个 Updater 对象时,它会为你创建一个 Dispatcher 对象,并用一个 Queue 将它们链接在一起。然后,可以使用此 Dispatcher 对象根据您注册的处理程序对 Updater 获取的更新进行排序,并将它们传递到您定义的回调函数。
上面这段可能有点混乱,所以我详细说明一下,如下:
步骤1
创建一个 telegram.ext.Updater 类的对象(我们将其称为 my_updater)。为此,您需要从 telegram.ext 导入 Updater 类。此外,当您创建 Updater 对象(即 my_updater)时,您将需要之前创建的机器人的 HTTP API 密钥。创建该对象的代码如下所示:
my_updater = 更新程序(令牌='your_bot_
令牌', use_context=True)
笔记
在网站上的示例代码中(参考文献 2 和 3),此变量通常称为 Dispatcher,但我使用 my_dispatcher 来指定这不是类的某些方法,而是我创建的类 Updater 的对象。
第2步
现在,这个 Updater 类有一个名为 Dispatcher 的属性。此属性返回 telegram.ext.Dispatcher 类的对象。不要对这个方案感到困惑。这是许多 Python 库工作的典型方法。因此,您可以使用Updater类对象(这里是my_updater)的dispatcher属性来创建Dispatcher类的对象(我们将其称为my_dispatcher)。以下代码片段显示了这一点:
my_dispatcher = my_updater.dispatcher
步骤3
在这里,我们将编写一个名为 start 的函数。因此,每当机器人用户键入消息 /start 时,就会触发此函数。 Telegram 包的编写方式是这样的,当您编写一个函数(例如这里的 /start)时,Telegram 服务器将向其传递两个属性。因此,您的函数定义中必须有两个属性,按照惯例,它们称为更新和上下文。我不想太技术性,但对于那些感兴趣的人来说,属性更新将获得 telegram.update.Update 类的对象。而属性 context 会得到一个 telegram.ext.callbackcontext.CallbackContext 类的对象
属性更新实际上是一个Python字典。您可以通过在 get() 函数中的某处放置 print(update) 命令来确认这一点。该字典有一个名为 effective_chat 的键,该键的值是另一个字典,其中包含 ID、first_name、last_name 等键。因此,使用 update. effective_chat.id 类型的格式,您可以获得聊天的 ID 。在我们的机器人代码中,我们将“提取”机器人用户的三个参数 - (1) id、(2)first_name 和 (3)last_name
在这一步中,我们将做以下几件事:
- 从参数更新中提取 id、first_name 和 last_name。
- 我们将使用名字和姓氏将回复发送回机器人用户。
- 要将回复发送回机器人用户,我们需要使用以下命令:
context.bot.send_message(chat_id, text=out_text)
为了使代码更具可读性和更易于理解,我将其分为两行:
my_bot = 上下文.bot
my_bot.send_message(chat_id, text= out_text)
对于技术爱好者来说,您可能会注意到 my_bot (即 context.bot 的返回值)是 telegram.Bot 类的对象。此外,该对象(即 my_bot)是 telegram.Bot 类的对象,具有方法 send_message()。因此,您可以使用此方法向机器人用户发送消息。
笔记
通过查看文件callbackcontext.py中的源代码,您可以确认context.bot的返回实际上是telegram.Bot类的对象。您可以通过此链接在 GitHub 上找到此文件。您将在第 155-157 行左右找到 bot() 的定义。此外,通过查看链接中提供的文件 bot.py 的源代码,telegram.Bot 类有一个方法 send_message() 。您将在第 265-275 行左右获得 send_message() 方法的代码。
但是,在上面的方案中,有一个问题——你需要在调度程序中注册这个命令,即 get()。为此,模块有一个 Handler 类,并且从该类继承了许多其他类,例如 CommandHandler、MessageHandler 等。这里,由于 get() 是一个命令,因此我们将使用特定的 Handler 来处理命令,这是命令处理程序。请注意,Commandhandler 类是 Handler 类的子类,即它继承自 Handler 类。所以,该计划是这样运作的。
首先创建 CommandHandler 类的对象(我将其命名为 start_handler),并将命令名称作为第一个参数传递给它,将回调函数的名称作为第二个参数传递给它。因此,该行代码将如下所示:
start_handler = CommandHandler('开始', 开始)
笔记
您可以在此链接的文件dispatcher.py 中查看Dispatcher 类的源代码。
创建 CommandHandler 类型的对象后,您可以使用 Dispatcher 类的 add_handler() 方法将其添加到 Dispatcher 类对象(在我们的代码中为 my_dispatcher)。因此,代码如下:
1 从 telegram.ext 导入 Updater、CommandHandler
2 my_updater = 更新程序(token='Your_token_here', use_context=True)
3 my_dispatcher = my_updater.dispatcher
4
5 def start(更新,上下文):
6 chat_id = update. effective_chat.id # 获取聊天的id。
7 f_name = update. effective_chat.first_name # 机器人用户的名字
8 l_name = update. effective_chat.last_name # 机器人用户的姓氏
9 full_name = f_name + ‘’ + l_name # 机器人用户的全名
10 out_text = ‘嗨,来自机器人的 {0} {1}’.format(f_name, l_name)
11 # 打印函数是显示变量的内容
12 # 可以去掉打印功能
13 打印(更新)
14 print(' effective_chat ->',update. effective_chat)
15 print('chat_id->', chat_id)
16 print('bot->', context.bot)
17 号
18 my_bot = context.bot # my_bot 是 telegram.Bot 类型的对象
19 # 打印(my_bot)
20 my_bot.send_message(chat_id, text=out_text)
21 start_handler = CommandHandler('开始', 开始)
22 my_dispatcher.add_handler(start_handler)
23 # my_updater.start_polling()启动机器人,机器人开始
24 # 开始轮询 Telegram 以获取任何聊天更新。
25 # 机器人有自己独立的线程,所以它不会停止你的Python脚本。
26 my_updater.start_polling()
27 # my_updater.idle() 命令用于阻止脚本执行,直到
28 # 用户发送一个命令来中断Python脚本,例如ctrl-c
Windows 上为 29
30 my_updater.idle()
此机器人的完整代码可通过 GitHub 链接获取。
进一步扩展
您可以即兴创作并扩展机器人的功能。该机器人仅接受一个命令,即/start。您可以创建消息处理程序。为此,您需要一个 MessageHandler 类的对象。您还可以尝试使用 Webhooks 或将机器人安装在远程服务器上,例如 Heroku、PythonAnywhere 等。
阿努拉格·古普塔 (Anurag Gupta) 的学历是工程师,职业是警察。他是一名 Python 爱好者,最近与人合着了一本关于 Python 的书,名为《Python 编程:问题解决、包和库》。
本文首次发表于 Open Source For You 2020 年 8 月号