楔子
Telegram(电报)相信大家都知道,关于它的介绍和注册方式这里就跳过了,我假设你已经注册好了。本篇文章来聊一聊 Telegram 提供的机器人,以及如何用 Python 为机器人实现各种各样的功能。
创建机器人
首先我们使用浏览器打开 https://web.telegram.org,然后用手机上的 APP 扫码登录。
图片
登录之后搜索 BotFather,机器人需要通过 BotFather 来创建,当然 BotFather 本身也是一个机器人,但它同时管理着其它的机器人。
我们点击 BotFather,下面将通过和它聊天的方式来创建机器人,过程如下。
1)在页面中输入命令 /newbot 并回车,相当于给 BotFather 发指令,表示要创建机器人。注:命令要以 / 开头。
2)BotFather 收到之后会将机器人创建好,并提示我们给机器人起一个名字,这里我起名为:古明地觉。
3)回车之后,BotFather 会继续让我们给机器人起一个用户名,这个用户名会作为机器人的唯一标识,用于定位和查找。这里我起名为 Satori_Koishi_bot,注:用户名必须以 Bot 或 bot 结尾。
下面来实际演示一下。
图片
我们点击 t.me/Satori_Koishi_bot,看看结果如何。
图片
点击 t.me/Satori_Koishi_bot 之后,再点击屏幕中的 start(相当于发送了一条 /start 指令),就可以和机器人聊天了。因为我们还没有编写代码,来为机器人添加相应的功能,所以目前不会有任何事情发生。
然后我们给自定义的机器人添加一些描述信息,显然这依赖于 BotFather。向其发送 /mybots 指令,会返回我们创建的所有的机器人,当然这里目前只有一个。
图片
我们点击它,看看结果:
图片
里面提供了很多的选项,这里我们再点击 Edit Bot,来编辑机器人的相关信息。
图片
不难发现,我们除了给当前机器人一个名字之外,其它的信息就没有了,所以 Telegram 提供了一系列按钮,供我们进行编辑。比如我们点击 Edit Botpic,编辑头像。
图片
然后机器人的头像会发生改变,当然这些都属于锦上添花的东西,最重要的是 Edit Commands,它是机器人能够产生行为的核心,否则当前的机器人就是个绣花枕头,中看不中用。
下面我们点击 Edit Commands,添加一个 /help 命令。
图片
添加格式为命令 - 描述,可同时添加多个。
图片
目前机器人便支持了 /help 命令,另外如果点击 Edit Command 之后再输入 /empty,那么也可以将机器人现有的命令清空掉。
虽然 /help 命令有了,但发送这个命令之后,机器人不会有任何的反应,因为我们还没有给命令绑定相应的处理函数,下面就来看看如何绑定。当然啦,机器人不光要对命令做出反应,就算是普通的文本、表情、图片等消息,也应该做出反应。至于命令本质上就是一个纯文本,只不过它应该以 / 开头。
接收消息并处理
我们可以使用 Python 连接 Telegram 机器人,为它绑定处理函数,首先需要安装一个第三方库。
安装:pip3 install "python-telegram-bot[all]"
然后获取机器人的 Token,这个 Token 怎么获取呢?
图片
像 BotFather 发送 /mybots 命令,点击指定机器人的 API Token 即可获取。
图片
有了这个 Token 之后,就可以和机器人建立连接了。
返回值包含了机器人的具体信息,还是比较简单的,只需指定一个 Token 即可访问。当然啦,由于网络的原因还需要使用代理。
然后通过该模块还可以给机器人发消息,但这显然不是我们的重点,因为消息肯定是通过 APP 或者浏览器发送的。我们要做的是,定义机器人的回复逻辑,当用户给它发消息时,它应该做些什么事情。
先来一个简单的案例,当用户输入 /start 命令时,回复一段文本。
我们来测试一下:
图片
显然结果是成功的,不过目前这个机器人只能处理 /start 命令,如果希望它支持更多的命令,那么就定义多个 CommandHandler 即可。但是问题来了,如果我们希望这个机器人能处理普通文本的话,该怎么办呢?
测试一下:
图片
结果没有问题,并且 /start 命令也被当成普通的文本处理了,因为命令本质上就是一个文本。然后代码中的 filters,它里面除了有表示文本类型的 TEXT,还有很多其它类型。
然后注意一下里面的 filters.Sticker 和 filters.Document,这两个类型比较特殊,它们内部还可以细分,这里我们就不细分了,直接 .ALL 即可。
我们来测试一下,看看这些类型消息都长什么样子。
我们发几条消息,让机器人告诉我们消息的类型。
图片
至于其它类型,感兴趣可以测试一下。
update 和 context
处理函数里面有两个参数,分别是 update 和 context。它们非常重要,我们来打印一下,看看长什么样子。
下面发送一条文本消息。
图片
然后查看 update.to_dict() 的输出是什么,为了方便理解,我将字段顺序调整了一下。
以上就是 update.to_dict() 的输出结果,当用户向 bot 发送消息时,Telegram 服务器会将这些数据以 JSON 的形式发送给当前的应用程序,以便 bot 可以处理和响应这些消息。当然啦,我们这里使用的库会将数据封装成 Update 对象,因此获取数据时,可以有以下两种获取方式。
以上是当用户发送文本消息时,Telegram 发送的数据,我们再试一下其它的,比如上传一个文档。
至于其它的类型也是类似的,可以自己试一下,比如上传一段视频,看看打印的输出是什么。
不过还有一个问题,就是当用户上传音频、视频、文档等,bot 如何获取它们呢?显然要依赖里面的 file_id。
我们上传几个文件试试。
图片
结果没有问题,用户上传的文件也下载到了本地。
回复富文本消息
目前机器人回复的都是普通的纯文本,但也可以回复富文本消息。
测试一下:
图片
结果没有问题,另外我们看到 a 标签自带预览功能,如果不希望预览,那么也可以禁用掉。
图片
将 disable_web_page_preview 参数指定为 False,即可禁用 a 标签的预览功能。另外发送的消息除了可以按照 HTML 格式解析,还可以按照 Markdown 格式解析,将 parse_mode 参数指定为 "Markdown" 或者 "MarkdownV2" 即可。
回复其它类型的消息
目前机器人回复的都是文本,那么能不能回复音频、视频、图片呢?显然是可以的,并且它们还可以和文本一起返回。
除了以上这些,还可以发送其它类型的消息,不过不常用,有兴趣的话可以自己看一下,这些方法都以 send_ 开头。然后我们来发几条消息,测试一下。
图片
结果没有问题。
媒体组
现在我们已经知道如何让机器人回复不同种类的消息了,但如果我想实现更复杂的功能,比如同时发送多张图片、多个视频,并且还配带文字,要怎么做呢?可能有人觉得这还不简单,写个循环不就行了,比如要发送 5 个视频,那么调用 5 次 send_video 方法不就好了。
首先这是一种方法,但循环 5 次,那么这 5 个视频是作为不同的消息分开发送的。更多时候,我们是希望作为一个整体发送,那么此时可以使用媒体组功能。
我们输入命令 /satori,应该会返回 4 张图片。
图片
结果没有问题,并且这 4 张图片是整体作为一条消息发送的。然后我们在代码中还指定了一个 caption 参数,它是做什么的呢?我们点击一下图片就知道了。
图片
点击图片放大查看时,captaion 会显示在图片下方。另外,如果发送了多张图片,但只有一张图片指定了 caption 参数,那么该 caption 会和图片一起显示,我们举例说明。
只有一张图片指定了 caption 参数,我们看看效果。
图片
此时图片会和文字一起显示,当然你也可以不指定 caption 参数,而是在发送完图片之后,再调用一次 send_message。这种做法也是可以的,只不过此时图片和文字会作为两条消息分开显示。
以上是发送图片,除了图片之外还可以发送音频、视频、文档,并且只支持这 4 种。但要注意:它们不能混在一起发,只有图片和视频可以,我们测试一下。
测试一下:
图片
结果正常,只是因为视频和图片是一起返回的,所以没有预览功能,需要点击之后才会播放。并且我们只给视频指定了 caption 参数,所以文字直接显示在了下方,如果媒体组中有多个 caption,那么就不会单独显示了,需要点击放大之后才能看到。
当然啦,如果你不需要同时发送多个媒体文件,那么就没必要调用 send_media_group 方法了,直接使用之前的方法即可。
- send_photo;
- send_audio;
- send_video;
- send_document;
这些方法一次性只能发送一个媒体文件,比如发送视频。
测试一下:
图片
怎么样,是不是很有趣呢?另外 caption 还可以是富文本,只需将 parse_mode 参数指定为 "HTML"、"Markdown" 或 "MarkdownV2" 即可。
关于机器人如何回复不同种类的消息,以及同时回复多条消息,相关内容我们就说完了。有了这些功能,我们的机器人就已经很强大了,你也可以把它和公司的业务结合起来。
比如创建一个命令:/get,它的功能如下。
图片
然后在代码中添加一个 CommandHandler("get", get_table),便可让用户通过 Telegram 查询数据库表,当然这里只是打个比方,具体怎么做取决于你的想法。另外多说一句,如果你希望输入 / 之后能像上面那样有提示,那么需要通过 BotFather 进行设置。
图片
要强调的是,这种方式只是起到一个提示作用,提示机器人支持 /get 命令。但机器人实际上是否支持,取决于代码中是否为机器人实现了 /get。所以当我们在代码中为机器人添加完命令之后,可以再通过 Edit Commands 进行设置,这样当用户输入 / 之后,机器人有哪些命令以及描述都会显示出来。
当然啦,如果你不通过 Edit Commands 进行设置的话,也是可以的,只是用户输入 / 之后不会有提示罢了,但命令是会回复的,只要在代码中实现了。同理,如果通过 Edit Commands 设置了,但代码中没实现,那么该命令也不会有效果。
自定义按钮
虽然目前的机器人已经很强大了,但是还不够,我们看一下 BotFather。
图片
你会发现它下面带了很多的按钮,点击按钮之后会执行相应的逻辑,那我们要怎么实现这些按钮呢?
测试一下:
图片
此时按钮就实现了,由于在 InlineKeyboardButton 里面指定的是 url,所以这是跳转按钮,点击之后会打开指定的页面。并且按钮的右上角还有一个小箭头,表示按钮是跳转按钮。
但除了跳转按钮之外,还有回调按钮,也就是点击按钮之后会执行回调函数,我们举例说明。
测试一下效果:
图片
点击油管和 B站的时候会执行回调函数,结果没有问题。但是我们发现,这些文字是单独发送的,那可不可以本地修改呢,也就是将按钮上方的文字替换掉。答案是可以的,我们来测试一下。
测试一下:
图片
然后点击按钮,看看文字内容有没有发生改变。
图片
点击按钮,文字的内容被替换了。所以当机器人回复一条消息时,只需知道 chat_id 即可。但如果是修改某条消息,那么除了 chat_id 之外,还要知道 message_id。
修改文字调用的方法是 edit_message_text,但除了修改文字之外,还可以修改其它内容。
图片
比如修改媒体文件,修改媒体文件的 caption,修改按钮等等。
修改消息综合案例
关于修改消息我们已经知道怎么做了,下面来做一个综合案例。假设当前有 N 张图片,用户默认会看到第一张,然后点击按钮可以查看下一张图片,当然也可以查看上一张。那么这个需求怎么实现呢?
测试一下:
图片
此时点击按钮下一张,就会返回下一张图片,同理也可以返回上一张图片。如果已经是最后一张图片了,那么点击下一张,会返回第一张图片。
但问题来了,程序要如何得知用户正在浏览的是第几张图片呢?显然要借助于按钮。在创建按钮时,参数 callback_data 里面保存了 index,当点击下一张或上一张时,更新 index,返回新的图片,同时刷新按钮。
以上返回的是图片,你也可以换成视频,并增加一些点赞、是否喜欢等按钮。
小结
以上就是 Python 操作 Telegram 相关的内容,当然这里只介绍了一部分,还有一些更复杂的功能没有说,比如按钮的嵌套等等。另外目前是用户和机器人一对一私聊,但我们还可以创建一个组,让机器人回复组成员的消息。而关于这些内容,后续有空补上,本文就先到这儿,写的有点累了。