影刀RPA新手教程:钉钉机器人消息推送完全指南——内部群通知、Webhook配置与消息格式
影刀RPA新手教程:钉钉机器人消息推送完全指南——内部群通知、Webhook配置与消息格式
作者:林焱 | 真实案例驱动,每篇覆盖12大核心模块,禁止空话。
案例背景:钉钉群里每天8次的自动播报
我们公司的销售数据,以前是运营同学每天手动在钉钉群里发四次播报。
早上到岗、午饭后、晚饭前、下班前,各发一次。
这个人休年假,播报就断了。老板问起来,运营说"我忘了"。
用影刀RPA + 钉钉机器人,现在每天自动播报8次,一次不落。
一、安装与准备工作
钉钉机器人的配置在企业钉钉电脑端完成。
打开钉钉群 → 群设置 → 智能群助手 → 添加机器人 → 自定义。
钉钉和飞书不一样,添加机器人时要选安全设置:
- 自定义关键词(推荐)
- 加签(更安全)
- IP地址段(最安全,但固定IP才能用)
我选的是"自定义关键词",简单够用。
设置一个或多个关键词,消息里必须包含其中至少一个,否则钉钉会拒绝。
比如关键词设成"销售播报",发消息时content里必须包含"销售播报"四个字。
我当时踩过这个坑:关键词设成了"销售",消息里写的是"今日销量为120000",没包含完整关键词"销售",全部被钉钉拦截了。
关键词是"包含"关系,不是"等于",但必须是连续的子串。
二、元素定位:获取钉钉Webhook地址
钉钉机器人的Webhook URL在添加完成后显示,只显示一次。
没保存的话,要去群里的机器人列表,找到对应机器人,重新查看详情。
URL格式:
https://oapi.dingtalk.com/robot/send?access_token=xxxxxx如果开了"加签"安全设置,每次发消息还要计算签名。
签名计算用Python实现(在影刀"执行Python代码"指令里调用):
importtimeimporthmacimporthashlibimportbase64importurllib.parsedefcalc_sign(secret):timestamp=str(round(time.time()*1000))secret_enc=secret.encode('utf-8')string_to_sign=f'{timestamp}\n{secret}'string_to_sign_enc=string_to_sign.encode('utf-8')hmac_code=hmac.new(secret_enc,string_to_sign_enc,digestmod=hashlib.sha256).digest()sign=urllib.parse.quote_plus(base64.b64encode(hmac_code))returntimestamp,sign把timestamp和sign作为URL参数拼到Webhook地址后面:
https://oapi.dingtalk.com/robot/send?access_token=xxxx×tamp=xxx&sign=xxx我当时没做签名计算,每次发消息都要去钉钉后台重新拿Webhook地址,极其麻烦。
三、变量与数据类型:钉钉消息格式详解
钉钉支持的消息格式:文本、Markdown、链接、ActionCard、FeedCard。
最常用的是文本和Markdown。
文本消息格式:
{"msgtype":"text","text":{"content":"销售播报\n今日销售额:120000"},"at":{"isAtAll":false,"atMobiles":["13800138000"]}}@功能用at字段控制:
isAtAll: true = @所有人atMobiles: 数组,填手机号,@特定人(对方钉钉绑定了这个手机号才行)
Markdown消息格式:
{"msgtype":"markdown","markdown":{"title":"销售播报","text":"## 今日销售数据\n> 销售额:**120000**\n> 完成率:120%"}}钉钉的Markdown和标准Markdown有差异,支持的语法有限:
- 标题:
## 标题 - 加粗:
**文本** - 引用:
> 文本 - 链接:
[文字](url) - 图片:
—— 但图片URL必须是公网可访问的
在影刀里组装消息体,用"配置参数"指令,注意所有字符串值里如果包含双引号,要转义。
拼多多店群自动化报活动上架!
四、流程控制:按时间段发送不同内容
每天8次播报,每次的内容格式不一样。
早上第一次播报,要包含昨日汇总和今日实时数据。
中午播报,只发当前实时数据。
用影刀的"获取当前时间"指令,拿到当前小时,再用"如果…否则"判断:
获取当前小时 → 存到变量 hour 如果 hour == 9 播报类型 = "早间完整版" 包含昨日数据 = true 否则如果 hour == 12 播报类型 = "午间简报" 包含昨日数据 = false 否则如果 hour >= 18 播报类型 = "晚间汇总" 包含昨日数据 = true 包含预测 = true 否则 播报类型 = "实时播报" 包含昨日数据 = false 结束如果循环用在多群推送。
公司有多个销售群,每个群都要发播报。
把Webhook地址存到影刀的列表变量里,用"遍历循环"逐个发送。
钉钉Webhook的限频比飞书严格:每个机器人每分钟最多20条,每天最多1000条。
我当时没注意这个限制,有200个销售群要发,一次性循环发送,直接被限频了。
正确做法:每次发送后加1-2秒等待,或者把群分组,错开时间发送。
五、网页自动化:从CRM抓取销售数据
播报的数据来自CRM系统,用影刀的"启动新浏览器"指令打开CRM页面。
元素定位四合一:
优先XPath:
//div[@id='sales-dashboard']//span[@class='amount']XPath找不到用CSS:
div#sales-dashboard span.amount动态内容用等待指令:
CRM页面用了异步加载,数据不是立刻出现的。
用影刀的"等待元素出现"指令,设置超时时间10秒,元素出现了再抓数据。
我当时踩过这个坑:页面还没加载完就去抓数据,抓到的是占位符或者空字符串,播报内容全是"今日销售额:0"。
后来在所有数据抓取前都加了"等待元素出现",还加了二次确认:抓到的值和上次比,变化超过50%要弹窗确认,防止抓到错误数据。
六、数据处理:把数字变成人话
从CRM抓到的销售额是一个数字,比如120000,直接发到群里不够直观。
处理成更友好的格式:
如果 销售额 >= 10000 显示值 = 销售额 / 10000 显示值 = round(显示值, 1) 显示文本 = 显示值 + "万" 否则 显示文本 = 销售额 + "元" 结束如果完成率要计算环比:
环比 = (今日销售额 - 昨日同期销售额) / 昨日同期销售额 * 100用影刀的"数学表达式"指令做计算,注意除以0的情况要处理:
如果 昨日同期销售额 == 0 环比文本 = "昨日无数据" 否则 环比 = (今日销售额 - 昨日同期销售额) / 昨日同期销售额 * 100 环比文本 = "环比" + round(环比, 1) + "%" 结束如果数据里有可能有异常值,比如销售额是负数(退款导致),要特殊处理:
如果 销售额 < 0 销售额文本 = "退款" + abs(销售额) + "元" 颜色标记 = "红色" 结束如果七、鼠标键盘图像:销售趋势图截图发送
纯数字播报有点枯燥,加上趋势图截图会直观很多。
用影刀的"截取网页元素截图"指令,把CRM里的销售趋势图截下来。
钉钉发送图片的方式和飞书不一样:
钉钉的群机器人Webhook不支持直接发图片(这是钉钉的一个限制)。
解决方案有两个:
方案一:把截图上传到图床(比如阿里云OSS),拿到公网URL,用Markdown消息的语法显示图片。
方案二:用钉钉的"自定义机器人"升级成"企业内部应用",通过应用API发送图片消息。
我用的是方案一,简单直接。
用Python把截图上传到OSS:
importoss2defupload_image(local_path,object_name):auth=oss2.Auth('access_key_id','access_key_secret')bucket=oss2.Bucket(auth,'https://oss-cn-hangzhou.aliyuncs.com','bucket-name')bucket.put_object_from_file(object_name,local_path)url=f"https://bucket-name.oss-cn-hangzhou.aliyuncs.com/{object_name}"returnurl八、进阶技能:ActionCard实现可操作消息
钉钉独有的ActionCard消息,可以在消息里加按钮,点击后触发一个HTTP请求。
ActionCard格式:
{"msgtype":"actionCard","actionCard":{"title":"销售播报","text":"","btnOrientation":"0","btns":[{"title":"查看详情","actionURL":"https://crm.example.com/detail"},{"title":"我要跟进","actionURL":"https://crm.example.com/follow"}]}}btnOrientation:0= 按钮竖直排列,1= 按钮横向排列。
点击按钮后,钉钉会打开actionURL指定的页面。
如果要实现点击按钮后触发一个API(而不是打开页面),要用钉钉的"互动卡片"功能,这个需要企业钉钉且开通了"互动卡片"权限。
我当时评估过,对于销售播报场景,ActionCard的按钮跳转页面已经够用了。
九、平台实战:在影刀配置分时段调度
8次播报,用影刀的定时任务来触发。
打开影刀控制台 → 任务中心 → 新建任务。
一个任务可以配置多个触发时间,用Cron表达式:
0 9,11,13,15,17,18,19,20 * * *意思是每天9、11、13、15、17、18、19、20点各触发一次。
但这样配置,每次触发的都是同一个流程,要在流程里判断当前时间,发送对应格式的内容。
更好的做法:建8个任务,每个任务对应一个时间段,每个任务传不同的参数。
这样每个时间段的播报逻辑可以独立调整,互不影响。
我当时把所有逻辑写在一个流程里,用一大堆if判断来区分时段,后来改一个时段的格式,不小心影响了其他时段。
十、系统联动:播报失败自动切换通知渠道
钉钉消息有可能发送失败(限频、网络问题、Webhook失效)。
设计降级方案:钉钉为主,企业微信为辅。
在影刀流程里,钉钉发送后检查返回码:
HTTP请求 POST 钉钉Webhook 如果 返回码 != 200 记录日志 "钉钉发送失败" + 返回消息 调用企业微信发送(从参数里读企业微信Webhook) 否则 记录日志 "钉报发送成功" 结束如果钉钉Webhook失效的情况,要在流程里检测错误码:
{"errcode":0,"errmsg":"ok"}errcode不是0就是失败。
常见错误码:
310000:消息内容与关键词不匹配310001:签名不正确(开了加签的情况下)429:发送消息太频繁404:Webhook地址无效
十一、工程化规范:多群管理的配置化
公司有200个销售群,不能把200个Webhook地址硬编码在流程里。
正确做法:把Webhook地址存到配置文件(或影刀的"数据表")里,流程运行时动态读取。
配置文件格式(CSV):
group_name,webhook_url,enabled 华东销售群,https://oapi.dingtalk.com/robot/send?access_token=xxx,true 华南销售群,https://oapi.dingtalk.com/robot/send?access_token=yyy,true在影刀里用"读取CSV"指令,把配置加载到列表变量里。
发送时遍历列表,只发给enabled=true的群。
TEMU店群矩阵自动化运营核价报活动
新增群、停用群,只需要改CSV文件,不用改流程。
我当时硬编码了20个群的Webhook地址在流程里,后来新增群只能改流程重新发版,极其麻烦。
从那以后,所有对外配置全部外置,流程只负责逻辑。
十二、速查表与常见报错
报错1:310000 keyword not in content
原因:消息内容不包含机器人设置的关键词。
解决:在消息content里加上关键词,或者去钉钉后台修改关键词设置。
报错2:429 too many requests
原因:超过发送频率限制。
解决:每次发送后加等待时间,或者申请提高限额(需要联系钉钉客服)。
报错3:errcode 404 webhook not found
原因:Webhook地址无效,或者机器人被删除了。
解决:去钉钉群里重新添加机器人,更新Webhook地址。
报错4:图片在消息里显示不出来
原因:图片URL不是公网可访问的,或者URL超时失效。
解决:用阿里云OSS或类似公网图床存储图片,注意设置合理的过期时间。
钉钉消息格式速查:
| 格式 | msgtype | 特点 |
|---|---|---|
| 文本 | text | 支持@人 |
| Markdown | markdown | 支持基础格式 |
| 链接 | link | 带标题和缩略图 |
| ActionCard | actionCard | 带按钮 |
| FeedCard | feedCard | 多图文 |
完整案例代码参考
签名计算(必须在每次请求前计算,Python实现):
importtime,hmac,hashlib,base64,urllib.parsedefdingtalk_sign(secret):timestamp=str(round(time.time()*1000))sign_str=f"{timestamp}\n{secret}"sign=base64.b64encode(hmac.new(secret.encode('utf-8'),sign_str.encode('utf-8'),hashlib.sha256).digest()).decode('utf-8')returntimestamp,urllib.parse.quote_plus(sign)# 发送文本消息defsend_text(webhook,content,at_all=False):importrequests data={"msgtype":"text","text":{"content":content},"at":{"isAtAll":at_all}}resp=requests.post(webhook,json=data,timeout=10)returnresp.json()XPath元素定位参考(CRM销售数据):
# 今日销售额 //div[contains(@class,'today-sales')]//span[@class='num']/text() # 完成率进度条 //div[@class='progress-bar']/@style # 表格中的销售额列 //table[@id='sales-table']//tr/td[position()=3]/text()CSS选择器:
/* 销售数据卡片 */.card.sales .value/* 完成率 */.progress-bar .percent/* 排名列表 */ul.rank-list li span.value我当时踩过这个坑:三个最深刻的教训
教训一:关键词设得太严格。
早期关键词设的是"【销售播报】",每次消息必须包含这个前缀。
后来运营说这个前缀太长不好看,要改成"销售播报",我没改流程里的消息内容,导致所有消息被拦截。
现在关键词设得尽量短且通用,比如"销售",消息里很容易包含。
教训二:没处理钉钉限频。
钉钉Webhook每分钟最多20条,我有200个群,循环发送不等待,直接被限频。
现在所有群发消息都加随机等待时间(1-3秒),还在流程里加了"失败重试"逻辑。
教训三:Webhook地址存在记事本里。
电脑重装系统,记事本没了,200个群的Webhook地址全丢了。
重新加200个机器人,花了整整一下午。
现在所有配置都存到影刀的数据表里,云端存储,换电脑也不怕。
延伸
钉钉机器人的完整配置脚本和200群批量管理工具,我整理到了 home.linyan.cloud。
包括Webhook地址的加密存储方案,防止泄露后被他人滥用。
#影刀RPA #RPA教程 #钉钉机器人 #消息推送 #销售播报 #自动化 #林焱
作者:林焱