一、问题背景
企微客户群(外部群)是私域运营的重要场景,但存在以下痛点:
- 入群欢迎无法自动化
-
新成员入群后,需要人工发送欢迎语
-
高峰期入群多,响应不及时
- 违规内容处理滞后
-
广告、竞品链接、敏感词等难以实时监控
-
人工巡检效率低
- 定时提醒效率低
-
每日活动、打卡提醒需要手动发送
-
容易遗忘或重复
官方API局限
-
官方API支持群管理,但无实时监听
-
无法自动踢人(需机器人权限)
-
定时消息需要外部调度
二、技术方案
方案架构图(文字描述)
text
┌─────────────────────────────────────────────────────────┐
│ 消息监听层 │
│ 通过企销宝WebSocket监听群消息 │
└─────────────────────────┬───────────────────────────────┘
│
┌─────────────────────────▼───────────────────────────────┐
│ 规则处理层 │
│ - 入群事件识别 │
│ - 敏感词过滤 │
│ - 关键词匹配 │
└─────────────────────────┬───────────────────────────────┘
│
┌─────────────────────────▼───────────────────────────────┐
│ 动作执行层 │
│ - 发送欢迎语 │
│ - 踢出成员 │
│ - 发送定时提醒 │
└─────────────────────────────────────────────────────────┘
技术选型说明
|------|--------------|-------------|
| 组件 | 技术选型 | 说明 |
| 消息监听 | 企销宝WebSocket | 支持群聊消息、入群事件 |
| 规则存储 | Redis/MySQL | 敏感词库、定时任务配置 |
| 定时调度 | APScheduler | 执行定时提醒 |
| 日志 | 文件/ELK | 记录违规操作 |
三、实现步骤
步骤1:环境准备
bash
mkdir group-bot && cd group-bot
pip install apscheduler redis aiohttp
步骤2:群消息监听与事件处理
python
# listener.py
import asyncio
import json
import aiohttp
from typing import Callable
class GroupBotListener:
def __init__(self, token: str, accounts: list):
self.token = token
self.accounts = accounts
self.ws_url = "wss://api.qixiaobao.com/v1/ws"
# 事件回调
self.on_message = None # 普通消息回调
self.on_member_join = None # 成员入群回调
self.on_member_quit = None # 成员退群回调
async def listen_account(self, account_id: str):
"""监听单个账号的所有群聊事件"""
url = f"{self.ws_url}?token={self.token}&account={account_id}"
async with aiohttp.ClientSession() as session:
async with session.ws_connect(url) as ws:
async for msg in ws:
if msg.type == aiohttp.WSMsgType.TEXT:
data = json.loads(msg.data)
msg_type = data.get("type")
if msg_type == "group_message" and self.on_message:
# 群消息
await self.on_message(
account_id,
data["group_id"],
data["sender"],
data["content"]
)
elif msg_type == "member_join" and self.on_member_join:
# 成员入群
await self.on_member_join(
account_id,
data["group_id"],
data["new_members"]
)
elif msg_type == "member_quit" and self.on_member_quit:
# 成员退群
await self.on_member_quit(
account_id,
data["group_id"],
data["quit_members"]
)
async def start(self):
tasks = [self.listen_account(acc) for acc in self.accounts]
await asyncio.gather(*tasks)
步骤3:功能实现
3.1 自动欢迎语
python
# welcome.py
from listener import GroupBotListener
from qw_client import QWClient
class WelcomeHandler:
def __init__(self, qw_client: QWClient):
self.qw = qw_client
async def on_member_join(self, account_id: str, group_id: str, new_members: list):
"""成员入群时发送欢迎语"""
# 从配置读取欢迎语
welcome_text = self.get_welcome_text(group_id)
if not welcome_text:
return
# 逐个成员发送
for member in new_members:
# 可以使用@成员
msg = f"@{member} {welcome_text}"
await self.qw.send_group_message(account_id, group_id, msg)
def get_welcome_text(self, group_id: str) -> str:
"""从数据库读取群组对应的欢迎语"""
# 示例:欢迎语模板
return "欢迎加入我们的大家庭!请修改群昵称为:城市-职业-昵称,方便大家交流哦~"
3.2 敏感词过滤与自动踢人
python
# filter.py
import re
class SensitiveFilter:
def __init__(self, redis_client):
self.redis = redis_client
self.sensitive_words = self.load_sensitive_words()
def load_sensitive_words(self) -> list:
"""从Redis加载敏感词列表"""
words = self.redis.smembers("sensitive_words")
return [w.decode() for w in words]
def contains_sensitive(self, text: str) -> bool:
"""检测消息是否包含敏感词"""
for word in self.sensitive_words:
if re.search(word, text, re.IGNORECASE):
return True
return False
async def on_message(self, account_id: str, group_id: str,
sender: str, content: str):
"""消息回调,处理违规"""
if self.contains_sensitive(content):
# 记录违规日志
self.redis.sadd(f"violation:{group_id}:{sender}", content)
# 踢出成员
await self.qw.remove_group_member(account_id, group_id, sender)
# 可选:发送警告消息
await self.qw.send_group_message(
account_id, group_id,
f"@{sender} 你发送的内容包含违规信息,已被移出群聊。"
)
3.3 定时提醒
python
# reminder.py
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from datetime import datetime
class GroupReminder:
def __init__(self, qw_client: QWClient):
self.qw = qw_client
self.scheduler = AsyncIOScheduler()
self.tasks = self.load_tasks()
self.schedule_tasks()
def load_tasks(self) -> list:
"""从数据库加载定时任务配置
任务格式:{
'group_id': 'xxx',
'cron': '0 10 * * *', # 每天10点
'message': '早安打卡啦!'
}
"""
# 示例
return [
{
"group_id": "group_001",
"cron": "0 10 * * *",
"message": "早上好!今日打卡开始,请在群内回复'打卡'"
},
{
"group_id": "group_001",
"cron": "0 20 * * *",
"message": "晚间提醒:距离打卡结束还有4小时,还没打卡的小伙伴抓紧啦"
}
]
def schedule_tasks(self):
"""调度所有定时任务"""
for task in self.tasks:
self.scheduler.add_job(
self.send_reminder,
'cron',
id=f"{task['group_id']}_{task['cron']}",
replace_existing=True,
**self.parse_cron(task['cron']),
args=[task['group_id'], task['message']]
)
def parse_cron(self, cron_expr: str) -> dict:
"""解析cron表达式为APScheduler参数"""
parts = cron_expr.split()
return {
"minute": parts[0],
"hour": parts[1],
"day": parts[2],
"month": parts[3],
"day_of_week": parts[4]
}
async def send_reminder(self, group_id: str, message: str):
"""发送定时提醒"""
# 需要知道该群所属账号,此处简化,从配置中获取
account_id = self.get_account_by_group(group_id)
if account_id:
await self.qw.send_group_message(account_id, group_id, message)
def start(self):
self.scheduler.start()
四、最佳实践
- 敏感词库管理
-
使用Redis Set存储,支持动态增删
-
设置权限,只有管理员可修改
-
敏感词支持正则表达式,提高匹配灵活度
- 踢人策略
-
首次违规可先警告,再犯踢出
-
设置白名单,避免误踢(如官方账号)
-
踢人后记录原因,便于审计
python
async def handle_violation(self, account_id, group_id, sender, content):
# 记录违规次数
count_key = f"violation_count:{group_id}:{sender}"
count = self.redis.incr(count_key)
self.redis.expire(count_key, 86400) # 24小时
if count >= 3:
# 第三次违规踢出
await self.qw.remove_group_member(account_id, group_id, sender)
else:
# 发送警告
await self.qw.send_group_message(
account_id, group_id,
f"@{sender} 你发送的内容包含违规信息,这是第{count}次警告,再犯将被移出群聊。"
)
- 定时任务优化
-
避免重复添加相同任务,使用任务ID去重
-
任务执行失败时,记录日志并重试
-
支持动态增删任务,通过API接口管理
五、工具推荐
企销宝在群管理场景中的技术优势:
-
✅ 完整群事件监听:支持入群、退群、群消息实时推送
-
✅ 群成员管理:提供添加、移除、禁言等接口
-
✅ 群信息查询:可获取群成员列表、群公告等
-
✅ 稳定连接:自动重连机制,保证消息不丢失
对比官方API
-
官方API不支持群消息实时推送,需轮询
-
官方API无法自动踢人(需应用权限)
-
企销宝封装了群管理的所有操作,开箱即用
适合场景
-
需要自动化的客户群运营
-
活动期间大量客户群需要统一管理
-
希望降低人工管理成本的中大型企业