自动化系列(四)Python实现钉钉机器人
定期数据需求除了以邮件的形式交付外,也可以发送到工作群里通知相关人员及时关注,本文将介绍如何推送数据到钉钉群里并@相关人员及时关注。
添加自定义机器人
- 创建群聊:右上角+号 -> 选择任意一个场景群 -> 点击创建即可
- 添加群机器人:点击群设置 -> 群智能助手 -> 添加机器人 -> 选择自定义 -> 添加后安全模式选择加签 -> 完成
- 查看Webhook和加签密钥:点击群设置 -> 群智能助手 -> 点击刚才创建的自定义机器人。
发送文本类消息
# 导入相关库
import json
import hashlib
import base64
import hmac
import os
import time
import requests
from urllib.parse import quote_plus
# 构造函数生成timestamp和sign
def creat_sign(secret):
timestamp = str(round(time.time() * 1000))
se = secret.encode('utf-8')
tse = '{}\n{}'.format(timestamp, secret)
tsee = tse.encode('utf-8')
hmac_code = hmac.new(se, tsee, digestmod=hashlib.sha256).digest()
sign = quote_plus(base64.b64encode(hmac_code))
return timestamp,sign
# 发送文本消息
def send_text(token, secret, content, Mobiles=None, UserIds=None, isAtAll=False):
# 构造post参数
url = "https://oapi.dingtalk.com/robot/send"
headers = {'Content-Type': 'application/json'}
timestamp,sign = creat_sign(secret)
params = {
'access_token': token,
"sign": sign,
"timestamp":timestamp
}
# 构造数据集
data = {
"at": {
"atMobiles":Mobiles,
"atUserIds":UserIds,
"isAtAll": isAtAll
},
"text": {
"content":content
},
"msgtype":"text"
}
# 发送消息
requests.post(
url=url,
data=json.dumps(data),
params=params,
headers=headers
)
# 发送markdown消息
def send_md(token, secret, title, text, Mobiles=None, UserIds=None, isAtAll=False):
# 构造post参数
url = "https://oapi.dingtalk.com/robot/send"
headers = {'Content-Type': 'application/json'}
timestamp,sign = creat_sign(secret)
params = {
'access_token': token,
"sign": sign,
"timestamp":timestamp
}
# 构造数据集
data = {
"at": {
"atMobiles":Mobiles,
"atUserIds":UserIds,
"isAtAll": isAtAll
},
"markdown": {
"title":title
,'text':text
},
"msgtype":"markdown"
}
# 发送消息
requests.post(
url=url,
data=json.dumps(data),
params=params,
headers=headers
)
token = '****' # Webhook里的token
secret = '****' # 加签里的密钥
send_text(token, secret, content='HsuHeinrich', Mobiles=[1****])
send_md(token, secret, title="测试md", text="# 一级标题 \n 微信搜索HsuHeinrich,发现更多精彩👍", isAtAll=True)
结果如下图:
UserIds为钉钉用户的数字ID,非钉钉号,一般只有企业管理员才能看到。所以常用手机号来@相关人员。
发送文件
钉钉正常无法推送文件信息,需要管理员登陆开发者后台创建相关的小程序。感兴趣的同学可以根据钉钉推送文件这个博客自行尝试,这里介绍一种曲线的方式。
我们知道,markdown可以添加图片连接,因此我们只需要将数据表转换成图片,然后将该图片上传至图床并获得链接,最后将图片链接加到markdown消息里就可以了,方法总比困难多~
import pandas as pd
from faker import Faker
from faker.providers import BaseProvider, internet
from random import randint
# 构造pandas数据
# 自定义fake
fake = Faker('zh_CN')
class MyProvider(BaseProvider):
def myCityLevel(self):
cl = ["一线", "二线", "三线", "四线+"]
return cl[randint(0, len(cl) - 1)]
def myGender(self):
g = ['F', 'M']
return g[randint(0, len(g) - 1)]
def myDevice(self):
d = ['Ios', 'Android']
return d[randint(0, len(d) - 1)]
fake.add_provider(MyProvider)
# 构造假数据
uid=[]
cityLevel=[]
gender=[]
device=[]
age=[]
activeDays=[]
for i in range(10):
uid.append(i+1)
cityLevel.append(fake.myCityLevel())
gender.append(fake.myGender())
device.append(fake.myDevice())
age.append(fake.random_int(min=18, max=65))
activeDays.append(fake.random_int(min=0, max=180))
raw_data= pd.DataFrame({'uid':uid,
'cityLevel':cityLevel,
'gender':gender,
'device':device,
'age':age,
'activeDays':activeDays,
})
raw_data.head()
uid | cityLevel | gender | device | age | activeDays | |
0 | 1 | 一线 | F | Android | 61 | 151 |
1 | 2 | 一线 | F | Ios | 32 | 140 |
2 | 3 | 三线 | M | Android | 58 | 122 |
3 | 4 | 三线 | M | Ios | 41 | 94 |
4 | 5 | 三线 | M | Ios | 44 | 19 |
# 通过table转图片
from pandas.plotting import table
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
# 设置图片参数
fig = plt.figure(dpi=800)
ax = fig.add_subplot(111, frame_on=False)
ax.xaxis.set_visible(False) # 隐藏x轴
ax.yaxis.set_visible(False) # 隐藏y轴
# df存为图片
table(ax, raw_data, loc='center')
plt.savefig('df2img.jpg')
# 默认的表格着实不太好看,通过style美化后,利用dataframe_image转图片
import dataframe_image as dfi
# 通过style美化df
# 增加色阶、标题,隐藏索引、uid列
title = '活跃统计'
df = raw_data.style\
.background_gradient(cmap='Pastel1',subset=['activeDays'])\
.set_caption(title)\
.hide_index()\
.hide_columns(subset=['uid'])
# 导出图片,留着后用
dfi.export(obj=df, filename='df2img.jpg', fontsize=30, max_cols=-1, max_rows=-1)
# 上传图片至gitee的个人图床,并获取图片链接
import base64,time,hashlib
import requests
def img2Gitee(token, owner, repo, file_path, message='pic'):
'''上传图片至gitee的个人图床
token: 图床设置时的token
owner: 仓库所有者
repo: 仓库名
file_path: 文件地址(含文件名)
message: 不重要,是commit的信息。默认为pic
return: 图片url链接
'''
# 读取图片
with open(file_path, "rb") as pic:
base64_data = base64.b64encode(pic.read()).decode(encoding = "utf-8")
# 构造上传文件名
path = f"{time.strftime('%Y%m%d%H%M%S')}{hashlib.md5(base64_data.encode('utf-8')).hexdigest()}.{file_path.split('.')[1]}"
# 生成上传url
upload_url = "https://gitee.com/api/v5/repos/%s/%s/contents/" % (owner, repo)
url = f"{upload_url}{path}"
# 上传至gitee
result = requests.post(url, data = {
"access_token": token,
"content": base64_data,
"message": message
}).json()
# 获取图片线上url
content = result.get("content",None)
if content:
pic_url = content.get("download_url", None)
if pic_url:
return pic_url
return pic_url
img_token='****' # 你的gitee图床的token
owner = "HsuHeinrich" # gitee仓库的owner
repo = "images" # gitee仓库的名称
file_path = "df2img.jpg"
pic_url=img2Gitee(img_token, owner, repo, file_path)
# 将图片链接插入markdown
send_md(token, secret, title="数据表转图片", text=f"![img]({pic_url})", isAtAll=True)
最终结果如下:
style可以生成更加美观的数据框,可以参考内置样式或者官方手册
如何创建自己的gitee图床,可以参考开篇中提到的利用
Typora+PicGo+Gitee
进行Markdown写作
其他类型消息
日常工作最常见的就是文本消息和文件推送,当然,钉钉群机器人还支持其他类型的消息,例如链接、各种卡片。只要按照钉钉开放文档定义数据类型,替换上面函数定义的data
即可,喜欢折腾的同学可以自行尝试~
总结
结合上期的定邮,就可以实现定时在工作群里推送消息或数据了,以后再看谁敢说你数据推送不及时。
共勉~