如何基于 Python 快速搭建 QQ 开放平台 QQ 群官方机器人详细教程(更新中)

news2025/1/12 23:34:04

注册 QQ 开放平台账号

账号注册

QQ 机器人:一个机器人可以被添加到 群聊/频道 内对话,QQ 用户也可以直接跟机器人 单独对话。

开发者账号主体要求

单聊对话:【定向邀请】
群聊场景:仅支持企业主体【个人主体暂不支持】
频道场景:企业主体与个人主体均可申请

注册地址:QQ 开放平台(opens new window)

注册创建机器人:获得的开发机器人接入票据 AppID AppSecret Token

创建机器人:https://q.qq.com/#/app/create-bot

在这里插入图片描述

开发设置:https://q.qq.com/qqbot/#/developer/developer-setting

在这里插入图片描述

查询官方文档

新版机器人官方文档:https://bot.q.qq.com/wiki/develop/api-v2/

GitHub 地址

在这里插入图片描述

安装 qq-botpy 环境

更新包的话需要添加 --upgrade 兼容版本:python3.8+

pip install qq-botpy

使用

需要使用的地方import botpy

import botpy

兼容提示

原机器人的老版本qq-bot仍然可以使用,但新接口的支持上会逐渐暂停,此次升级不会影响线上使用的机器人。

基础案例演示

通过继承实现bot.Client, 实现自己的机器人Client

实现机器人相关事件的处理方法,如 on_at_message_create, 详细的事件监听列表,请参考 事件监听.md

定义机器人被@的后自动回复

import botpy
from botpy.message import Message

class MyClient(botpy.Client):
    async def on_at_message_create(self, message: Message):
        await message.reply(content=f"机器人{self.robot.name}收到你的@消息了: {message.content}")

注意:每个事件会下发具体的数据对象,如message相关事件是message.Message的对象 (部分事件透传了后台数据,暂未实现对象缓存)

设置机器人需要监听的事件通道并启动client

import botpy
from botpy.message import Message

class MyClient(botpy.Client):
    async def on_at_message_create(self, message: Message):
        await self.api.post_message(channel_id=message.channel_id, content="content")

intents = botpy.Intents(public_guild_messages=True) 
client = MyClient(intents=intents)
client.run(appid="12345", token="xxxx")

其他案例

examples 目录下存放示例机器人 具体使用可参考 Readme.md:https://github.com/tencent-connect/botpy/blob/master/examples/README.md

examples/
.
├── README.md
├── config.example.yaml          # 示例配置文件(需要修改为config.yaml)
├── demo_announce.py             # 机器人公告API使用示例
├── demo_api_permission.py       # 机器人授权查询API使用示例
├── demo_at_reply.py             # 机器人at被动回复async示例
├── demo_at_reply_ark.py         # 机器人at被动回复ark消息示例
├── demo_at_reply_embed.py       # 机器人at被动回复embed消息示例
├── demo_at_reply_command.py     # 机器人at被动使用Command指令装饰器回复消息示例
├── demo_at_reply_file_data.py   # 机器人at被动回复本地图片消息示例
├── demo_at_reply_keyboard.py    # 机器人at被动回复md带内嵌键盘的示例
├── demo_at_reply_markdown.py    # 机器人at被动回复md消息示例
├── demo_at_reply_reference.py   # 机器人at被动回复消息引用示例
├── demo_dms_reply.py            # 机器人私信被动回复示例
├── demo_get_reaction_users.py   # 机器人获取表情表态成员列表示例
├── demo_guild_member_event.py   # 机器人频道成员变化事件示例
├── demo_interaction.py          # 机器人互动事件示例(未启用)
├── demo_pins_message.py         # 机器人消息置顶示例
├── demo_recall.py               # 机器人消息撤回示例
├── demo_schedule.py             # 机器人日程相关示例

配置 IP 白名单

部分之前就注册的机器人可能不需要进行配置,但是新注册的机器人在进行腾讯开放平台的提审之前,需要进行 IP 白名单的配置。

注意:只有白名单内的IP可以在沙箱环境外成功调用openAPI接口,机器人上线提审前IP白名单不可为空。

在这里插入图片描述

配置 Sandbox QQ 群

在QQ群配置

如需开发在QQ群使用的机器人功能请完成此项配置

在这里插入图片描述
管理员QQ在沙箱群需为群主/管理员,且群成员数不大于20人。建议沙箱群包含「测试」相关字眼,且群头像与其他群区分开。配置完成后,群主可从沙箱群“设置-群机器人”打开机器人列表页添加测试机器人进行开发调试。

案例:OpenAi 问答

常用镜像源

清华:https://pypi.tuna.tsinghua.edu.cn/simple
阿里云:http://mirrors.aliyun.com/pypi/simple/
中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/
华中理工大学:http://pypi.hustunique.com/
山东理工大学:http://pypi.sdutlinux.org/
豆瓣:http://pypi.douban.com/simple/

配置镜像源

pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
Writing to C:\Users\Administrator\AppData\Roaming\pip\pip.ini

然后我们把这个 C:\Users\Administrator\AppData\Roaming\pip\pip.ini 路径添加到系统环境变量就好了(怎么添加环境变量?跟给 pip 添加环境变量一样操作,只是路径不一样)

安装 openai 库

pip install openai==1.33.0 -i 镜像源

项目结构

bot.py      					机器人主函数
plugins/chat_api.py 		    调用查询 OpenAi 接口插件
config.yaml						机器人基本信息
.env 					        OpenAi token 和 中转路径配置

配置 Token 和 中转地址

在项目同级目录创建 .env 文件

OPENAI_API_KEY=sk-······
OPENAI_BASE_URL=https://api.······

./plugins/chat_api.py 调用查询 OpenAi 接口

from openai import OpenAI
import dotenv
dotenv.load_dotenv(".env")

client = OpenAI()


def chat_answer(text):
    response = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": text}
        ]
    )
    return response.choices[0].message.content

查询 openai bot.py 源码

import os

import botpy
from botpy import logging
from botpy.ext.cog_yaml import read
from botpy.message import GroupMessage
from plugins import chat_api

test_config = read(os.path.join(os.path.dirname(__file__), "config.yaml"))
_log = logging.get_logger()


class MyClient(botpy.Client):
    async def on_ready(self):
        _log.info(f"robot 「{self.robot.name}」 on_ready!")

    async def on_group_at_message_create(self, message: GroupMessage):
        openid = message.author.member_openid
        _log.info(f"robot {openid} on_ready!")
        msg = message.content.strip()

        result = chat_api.chat_answer(text=msg)
        await message._api.post_group_message(
            group_openid=message.group_openid,
            msg_type=0,
            msg_id=message.id,
            content=f"{result}")
        return

if __name__ == "__main__":
    intents = botpy.Intents(public_messages=True)
    client = MyClient(intents=intents)
    client.run(appid=test_config["appid"], secret=test_config["secret"])

运行效果

在这里插入图片描述

案例:查询天气信息

项目结构

bot.py      					机器人主函数
plugins/weather_api.py 		    调用查询天气接口插件
config.yaml						机器人基本信息

./plugins/weather_api.py 调用查询天气接口

import requests


def get_weather(city_name):
    # 设置请求的URL和参数
    url = f'https://apis.juhe.cn/simpleWeather/query?key=50a3bd415158e186903d6e6994157589&city={city_name}'
    # 发送GET请求
    response = requests.get(url)
    # 检查请求是否成功
    if response.status_code == 200:
        # 解析返回的JSON数据
        data = response.json()

        # 检查是否查询成功
        if data['reason'] == '查询成功!':
            # 返回天气数据
            return data['result']
        else:
            return {"error": "查询失败: " + data['reason']}
    else:
        return {"error": "请求失败,状态码: " + str(response.status_code)}


# 调用函数并处理返回的天气数据
def format_weather(city_name):
    # 假设这里你已经有了城市的URL编码,这里用'%E9%87%8D%E5%BA%86'作为示例
    city_encoded = city_name  # 重庆的URL编码
    weather_data = get_weather(city_encoded)

    # 检查是否返回了错误
    if 'error' in weather_data:
        return weather_data['error']
    else:
        # 实时天气
        realtime_weather = weather_data['realtime']
        result = f"实时天气:" + "\n" +  f"{realtime_weather['info']}, 温度: {realtime_weather['temperature']}℃, 湿度: {realtime_weather['humidity']}%, 风向: {realtime_weather['direct']}, 风力: {realtime_weather['power']}级, AQI: {realtime_weather['aqi']}"
        # 未来几天的天气
        result = result + "\n" + "未来几天的天气:"
        for day in weather_data['future']:
            result = result + "\n" + f"日期: {day['date']}, 天气: {day['weather']}, 温度: {day['temperature']}, 风向: {day['direct']}"
        return result

查询天气信息 bot.py 源码

import os

import botpy
from botpy import logging
from botpy.ext.cog_yaml import read
from botpy.message import GroupMessage
from plugins import weather_api

config = read(os.path.join(os.path.dirname(__file__), "config.yaml"))
_log = logging.get_logger()


class MyClient(botpy.Client):
    async def on_ready(self):
        _log.info(f"robot 「{self.robot.name}」 on_ready!")

    async def on_group_at_message_create(self, message: GroupMessage):
        openid = message.author.member_openid
        _log.info(f"robot {openid} on_ready!")
        msg = message.content.strip()

        if msg.startswith("/天气"):
            city_name = msg.replace("/天气", "").strip()
            result = weather_api.format_weather(city_name)
            await message._api.post_group_message(
                group_openid=message.group_openid,
                msg_type=0,
                msg_id=message.id,
                content=f"{result}")


if __name__ == "__main__":
    intents = botpy.Intents(public_messages=True)
    client = MyClient(intents=intents)
    client.run(appid=config["appid"], secret=config["secret"])

运行结果预览

在这里插入图片描述

案例:配置关键词回复

项目结构

bot.py      					机器人主函数
plugins/match_question.py 		查询本地 excel 问答表插件
config.yaml						机器人基本信息
关键词.xlsx						关键词问答表

在这里插入图片描述

./plugins/match_question.py 查询本地 excel 问答表

from openpyxl import load_workbook

# 加载工作簿
wb = load_workbook('关键词.xlsx')
# 选择活动工作表,或者通过名称或索引选择其他工作表
sheet = wb.active  # 或者 wb['Sheet1'] 或 wb.worksheets[0]
question_list = []

# 遍历行和列(从第二行开始,假设第一行是标题)
for row in sheet.iter_rows(min_row=2, values_only=True):  # 添加 values_only=True 以只获取单元格的值
    question = {
        "question": row[0] if row[0] is not None else '',  # 确保如果单元格为空,则使用空字符串
        "answer": row[1] if row[1] is not None else '',
    }
    question_list.append(question)  # 添加创建的字典到列表中,而不是原始的 row


def match(word):
    """
    匹配关键词
    :param word:
    :return:
    """
    for question in question_list:
        if word in question['question']:
            return question['answer']

    for question in question_list:
        if word == question['question']:
            return question['answer']

    return ""

bot.py 源码

import os

import botpy
from botpy import logging
from botpy.ext.cog_yaml import read
from botpy.message import GroupMessage
from plugins import match_question

test_config = read(os.path.join(os.path.dirname(__file__), "config.yaml"))
_log = logging.get_logger()


class MyClient(botpy.Client):
    async def on_ready(self):
        _log.info(f"robot 「{self.robot.name}」 on_ready!")

    async def on_group_at_message_create(self, message: GroupMessage):
        openid = message.author.member_openid
        _log.info(f"robot {openid} on_ready!")
        msg = message.content.strip()

        if match_question.match(msg):
            result = match_question.match(msg)
            await message._api.post_group_message(
                group_openid=message.group_openid,
                msg_type=0,
                msg_id=message.id,
                content=f"{result}")
            return


if __name__ == "__main__":
    intents = botpy.Intents(public_messages=True)
    client = MyClient(intents=intents)
    client.run(appid=test_config["appid"], secret=test_config["secret"])

运行效果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1819879.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringAI学习及搭建AI原生应用

文章目录 一、SpringAI是什么二、准备工作1.GPT-API-free2.AiCore3.eylink 三、对话案例实现1.创建项目2.实现简单的对话 四、聊天客户端ChatClient1.角色预设2.流式响应3.call和stream的区别 五、聊天模型提示词提示词模板 六、图像模型(文生图)七、语音模型1.文字转语音(文生…

数据结构之线性表(2)

顺序表中的动态存储 上文我们了解到了顺序表中的静态顺序表的相关操作,今天我们来学习动态顺序表的知识。 为什么会存在动态顺序表呢?? 原因:静态顺序表给定的数据容量固定,多了浪费,少了不够用。 首先我…

基于jeecgboot-vue3的Flowable流程-流程处理(二)

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 对应VForm3&#xff0c;原先的后端解析也要做调整 1、获取历史任务的表单信息 // 获取历史任务节点表单数据值List<HistoricVariableInstance> listHistoricVariableInstance his…

API工具--Apifox和Postman对比(区别)

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

Web端在线/离线Stomp服务测试与WebSocket服务测试

Stomp服务测试 支持连接、发送、订阅、接收&#xff0c;可设置请求头、自动重连 低配置云服务器&#xff0c;首次加载速度较慢&#xff0c;请耐心等候 预览页面&#xff1a;http://www.daelui.com/#/tigerlair/saas/preview/lxbho9lkzvgc 演练页面&#xff1a;http://www.da…

Linux_应用篇(17) FrameBuffer 应用编程

本章学习 Linux 下的 Framebuffer 应用编程&#xff0c; 通过对本章内容的学习&#xff0c; 大家将会了解到 Framebuffer 设备究竟是什么&#xff1f;以及如何编写应用程序来操控 FrameBuffer 设备。 本章将会讨论如下主题。 ⚫ 什么是 Framebuffer 设备&#xff1f; ⚫ LCD 显…

vscode 连接 GitHub

文章目录 连接 GitHub一、通过 SSH 连接 github二、通过 HTTPS 连接 github 连接 GitHub 在 vscode 中首次使用 git push 命令时会要求输入 github 账户的 username 和 password&#xff0c;这种基本身份验证在 2021.8.13 以前还是可以的&#xff0c;之后的话&#xff0c;就会…

【太原理工大学】软件安全技术—书本重点梳理、带背

收回我上一篇的话&#xff0c;这科挂人还是挺狠的&#xff0c;去年好像挂了四十号人 ( 老师没有划重点&#xff0c;这篇是我自己根据之前的博主的和课本总结的一些重点&#xff0c;本篇为理解性带背。(&#xff61; _ &#xff61;) ### 第一章&#xff1a;软件安全基础 - **零…

大厂Java面试题:MyBatis是中如何将结果集映射到Java持久化对象?都有哪些方式?有什么区别?

大家好&#xff0c;我是王有志。今天给大家带来的是一道来自京东的 MyBatis 面试题&#xff1a;MyBatis是中如何将结果集映射到Java持久化对象&#xff1f;都有哪些方式&#xff1f;有什么区别&#xff1f; MyBatis 提供了两种实现结果集到 Java 持久化对象的映射方式&#xf…

springbot 界面美观的超市收银管理系统。

springbot 界面美观的超市收银管理系统。 功能&#xff1a;登录&#xff0c;用户管理&#xff0c;权限菜单管理&#xff0c;首页订单&#xff0c;收入&#xff0c;用户统计&#xff0c; 收银台&#xff0c;销售账单&#xff0c;库存管理&#xff0c;商品分类&#xff0c;供应…

一张图读懂天然气气源

一张图读懂天然气气源

Dev-C++安装及使用

起因&#xff1a;我写的游戏都是用DEV-C 写的&#xff1b; Dev的介绍&#xff1a; Dev-C&#xff08;或者叫做 Dev-Cpp&#xff09;是 Windows 环境下的一个轻量级 C/C 集成开发环境&#xff08;IDE&#xff09;。非常适合于C/C语言初学者使用。 它是一款自由软件&#xff0c;…

npm login 或者 npm adduser 之后 遇见 Public registration is not allowed

npm login 或者 npm adduser 之后 遇见 Public registration is not allowed 其实是因为npm镜像地址有问题 使用下方指令 将镜像切回即可正确完成登录操作 npm config set registry https://registry.npmjs.org/ 今天就总结到这里啦&#xff01; 后续会不定时更新哦&#xff…

Linux Debian12使用podman安装xss-labs靶场环境

一、xss-labs简介 xss-labs靶场是一个专门用于学习和练习跨站脚本攻击&#xff08;XSS&#xff09;技术的在线平台。它提供了一系列的实验场景和演示&#xff0c;帮助安全研究人员、开发人员和安全爱好者深入了解XSS攻击的原理和防御方法。 二、安装podman环境 Linux Debian…

计算机msvcp100.dll丢失怎么办,分享5种亲测有效的解决方法

电脑已经成为我们生活中不可或缺的一部分。然而&#xff0c;在使用电脑的过程中&#xff0c;我们常常会遇到一些问题&#xff0c;其中之一就是电脑提示缺失msvcp100.dll。这个问题可能会让我们感到困惑和烦恼&#xff0c;但是只要我们了解其原因并采取相应的解决方法&#xff0…

FPGA+金融|硬件行情加速系统 打造极速交易场景

会议时间&#xff1a;2024年06月20日&#xff08;周四&#xff09;下午13:50 FPGA金融|硬件行情加速系统 打造极速交易场景_中科亿海微_芯有灵犀 智创未来

6.12ctf练习

[西湖论剑 2022]Node Magical Login 源码在这里&#xff1a;GitHub - CTF-Archives/2022-xhlj-web-node_magical_login: A web challenge in 2022 西湖论剑大赛打开 打开环境是个登录框&#xff0c;先进行了扫描和抓包都没有看见什么有价值的东西&#xff0c;看源码 大致连接…

因数与倍数 初级题目

最近又来更题了。这一次是《第三单元 因数与倍数第一部分》的初级题目。 参考答案见文尾 参考答案&#xff1a; CBDAABCBBACCCCCBCDCC

Airtest 使用指南

Airtest 介绍 准备工作 AirtestIDE 安装与启动: https://airtest.doc.io.netease.com/IDEdocs/getting_started/AirtestIDE_install/ 电脑端的准备工作完成后,对于手机端只需要打开允许USB调试,当首次运行时会提示安装PocoService,同意即可。 界面介绍

仲恺ZK——信计专业《软件体系结构》24年试卷回忆

以下是我在总结的复习内容&#xff0c;有需要可以参考借鉴一下。我的主页还有另外一篇复习总结《仲恺ZK——信计专业《软件体系结构》&#xff0c;两者结合起来复习&#xff0c;帮助你轻松过考试&#x1f60a;。总的来说&#xff0c;考试不会太难&#xff0c;只要你了解了各类设…