第一章 Python 获取钉钉OA审批流数据
前言
随着社会的不断发展,使用钉钉的企业也越来越多,本文就介绍了python获取钉钉审批流数据。
一、钉钉是什么?
钉钉是一款由阿里巴巴集团开发的企业通讯和协作工具,类似于Slack或Microsoft Teams。它提供了即时通讯、视频会议、日程安排、文件共享等功能,旨在帮助企业提高沟通效率和团队协作能力。钉钉在中国以及全球范围内被广泛应用于企业办公和团队协作中。。
二、使用步骤
1.准备条件
需要去钉钉后台获取开发者权限,新建一个应用,将OA权限赋予该应用,并获得appkey ,appscret
2.引入库
代码如下(示例):
import os, sys, time, datetime, traceback
import ast
import requests
from cffi.backend_ctypes import long
from alibabacloud_dingtalk.workflow_1_0.client import Client as dingtalkworkflow_1_0Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_dingtalk.workflow_1_0 import models as dingtalkworkflow__1__0_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_util.client import Client as UtilClient
3.写代码
代码如下(示例):
# 固定- 将当前py文件所在文件夹加入环境
present_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.append(present_dir)
# 固定- 将当前py文件所在文件夹的上级文件夹路径加入环境
father_dir = os.path.dirname(present_dir)
sys.path.append(father_dir)
# 初始化路径
token_path = os.path.join(present_dir, 'token.txt')
process_path = os.path.join(present_dir, 'process.txt')
def strtime_to_datetime(timestr):
"""将字符串格式的时间 (含毫秒) 转为 datetime 格式
:param timestr: {str}'2016-02-25 20:21:04.242'
:return: {datetime}2016-02-25 20:21:04.242000
"""
res = datetime.datetime.strptime(timestr, "%Y-%m-%d %H:%M:%S")
res = datetime.datetime.strftime(res, "%Y-%m-%d %H:%M:%S.%f")
local_datetime = datetime.datetime.strptime(res, "%Y-%m-%d %H:%M:%S.%f")
return local_datetime
def datetime_to_timestamp(datetime_obj):
"""将本地(local) datetime 格式的时间 (含毫秒) 转为毫秒时间戳
:param datetime_obj: {datetime}2016-02-25 20:21:04.242000
:return: 13 位的毫秒时间戳 1456402864242
"""
local_timestamp = long(time.mktime(datetime_obj.timetuple()) * 1000.0 + datetime_obj.microsecond / 1000.0)
return local_timestamp
def strtime_to_timestamp(local_timestr):
"""将本地时间 (字符串格式,含毫秒) 转为 13 位整数的毫秒时间戳
:param local_timestr: {str}'2016-02-25 20:21:04.242'
:return: 1456402864242
"""
local_datetime = strtime_to_datetime(local_timestr)
timestamp = datetime_to_timestamp(local_datetime)
return timestamp
class DingTalkClass:
def __init__(self, appkey, appsecret):
self.appkey = appkey
self.appsecret = appsecret
self.access_token = {'access_token': '', 'get_time': ''}
def get_token(self):
"""
获取 token token 有效期两个小时
:return:
"""
if os.path.exists(token_path):
with open(token_path, 'r+') as f:
res = f.read()
if res != '':
self.access_token = ast.literal_eval(res)
# 比较时间
now_time = datetime.datetime.now()
if self.access_token['get_time'] != '':
last_get_time = strtime_to_datetime(self.access_token['get_time'])
# 上一次的token 时间加上120分钟
minutes_120 = last_get_time + datetime.timedelta(minutes=120)
# 判断上一次获取token 的时间是否小于当前时间
if minutes_120 < now_time:
print('重新获取token')
else:
print('历史获取token')
return
else:
print('获取token')
get_token_url = "https://oapi.dingtalk.com/gettoken?appkey={}&appsecret={}".format(self.appkey, self.appsecret)
try:
resp = requests.get(url=get_token_url).json()
self.access_token['access_token'] = resp['access_token']
self.access_token['get_time'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
# 更新token.txt 的内容
with open(token_path, 'w') as f:
f.write(str(self.access_token))
except Exception as e:
print(e)
@staticmethod
def create_client() -> dingtalkworkflow_1_0Client:
"""
使用 Token 初始化账号Client
@return: Client
@throws Exception
"""
config = open_api_models.Config()
config.protocol = 'https'
config.region_id = 'central'
return dingtalkworkflow_1_0Client(config)
def get_userVisibilities(self):
"""
获取指定用户可见的审批表单列表
:return:
"""
client = DingTalkClass.create_client()
list_user_visible_bpms_processes_headers = dingtalkworkflow__1__0_models.ListUserVisibleBpmsProcessesHeaders()
list_user_visible_bpms_processes_headers.x_acs_dingtalk_access_token = self.access_token['access_token']
list_user_visible_bpms_processes_request = dingtalkworkflow__1__0_models.ListUserVisibleBpmsProcessesRequest(
max_results=100,
next_token=0
)
try:
res = client.list_user_visible_bpms_processes_with_options(list_user_visible_bpms_processes_request,
list_user_visible_bpms_processes_headers,
util_models.RuntimeOptions())
res_dict = {}
for i in res.body.result.process_list:
res_dict[i.name] = i.process_code
with open(process_path, 'w+') as f:
f.write(str(res_dict))
except Exception as e:
traceback.print_exc()
# if not UtilClient.empty(err.code) and not UtilClient.empty(err.message):
# err 中含有 code 和 message 属性,可帮助开发定位问题
# pass
def get_process_code(self, pro_name):
"""
获取流程得 code
:param pro_name:
:return:
"""
if os.path.exists(process_path):
print('获取历史数据')
else:
self.get_userVisibilities()
with open(process_path, 'r+') as f:
res = ast.literal_eval(f.read())
return res[pro_name]
def get_instanceIds_query(self, process_code, next_token, max_results, start_time, end_time):
"""
获取审批实例ID列表
:return:
"""
print('获取审批实例ID列表')
client = DingTalkClass.create_client()
list_process_instance_ids_headers = dingtalkworkflow__1__0_models.ListProcessInstanceIdsHeaders()
list_process_instance_ids_headers.x_acs_dingtalk_access_token = self.access_token['access_token']
list_process_instance_ids_request = dingtalkworkflow__1__0_models.ListProcessInstanceIdsRequest(
process_code=process_code,
next_token=next_token,
max_results=max_results,
start_time=start_time,
end_time=end_time
)
try:
res = client.list_process_instance_ids_with_options(list_process_instance_ids_request,
list_process_instance_ids_headers,
util_models.RuntimeOptions())
all_sl_list = res.body.result.list
return all_sl_list
except Exception as err:
print(err)
if not UtilClient.empty(err.code) and not UtilClient.empty(err.message):
# err 中含有 code 和 message 属性,可帮助开发定位问题
pass
def get_processInstances(self, process_instance_id):
"""
获取单个审批实例详情
:return:
"""
client = DingTalkClass.create_client()
get_process_instance_headers = dingtalkworkflow__1__0_models.GetProcessInstanceHeaders()
get_process_instance_headers.x_acs_dingtalk_access_token = self.access_token['access_token']
get_process_instance_request = dingtalkworkflow__1__0_models.GetProcessInstanceRequest(
process_instance_id=process_instance_id
)
try:
res = client.get_process_instance_with_options(get_process_instance_request, get_process_instance_headers,
util_models.RuntimeOptions())
data = []
for one in ast.literal_eval(res.body.result.form_component_values[0].value):
data.append({two['label']: two['value'] for two in one['rowValue']})
return data
except Exception as err:
if not UtilClient.empty(err.code) and not UtilClient.empty(err.message):
# err 中含有 code 和 message 属性,可帮助开发定位问题
pass
def start():
# 获取配置参数
appkey = 'AppKey'
appsecret = 'AppSecret'
ding_cls = DingTalkClass(appkey, appsecret)
ding_cls.get_token() # 获取token
# 查询数据的开始时间和结束时间
start_time = '2024-01-01 20:08:43'
end_time = '2024-01-07 20:08:43'
# 流程名称
process_name = '流程名称'
print('start_time:', start_time, 'end_time:', end_time)
start_time_c = strtime_to_timestamp(start_time) # 1678032000000
end_time_c = strtime_to_timestamp(end_time)
data = []
print('process_name', process_name)
process_code3 = ding_cls.get_process_code(process_name)
print('process_code3', process_code3)
# 前20条
process_list = ding_cls.get_instanceIds_query(process_code3, 0, 20, start_time_c, end_time_c) # 查询时间下得表单
for one in process_list:
one_process_instance_id = one
res3 = ding_cls.get_processInstances(one_process_instance_id) # 查询时间下得表单
data.extend(res3)
print(data)
print('钉钉数据{}条'.format(len(data)))
return data
if __name__ == '__main__':
start()
总结
以上就是今天要讲的内容,本文仅仅简单介绍了python获取钉钉数据流方式