做 APP 运营、运维的同学,一定有过这样的困扰:每天固定时间登录第三方后台,手动查询 APP 活跃用户数、复制数据、计算环比涨跌,再整理成文案发到钉钉群,一套流程下来,十几分钟就没了,枯燥又容易出错。今天不绕弯子,直接上 生产环境可直接部署 的 Python 自动化方案——不掺多余代码、不装无用依赖,只专注 3 件事:自动获取 APP 日活、自动算环比、自动推钉钉,配合定时任务,彻底解放双手,每天多睡十分钟~- ✅ 自动拉取 Android + iOS 双端 今日/昨日活跃用户数
- ✅ 可自定义监控指定 APP 版本,自动统计累计用户
- ✅ 支持 Linux 定时任务,实现每日无人值守推送
无需复杂配置,终端执行以下命令,安装 2 个核心依赖即可:pip install requests aop-python
说明:requests 用于发起 HTTP 请求,aop-python 是友盟 API 官方 SDK,无其他冗余依赖。代码已做精简和注释,替换配置项就能直接运行,无需修改逻辑:#!/usr/local/python39/bin/python3import timefrom datetime import datetimeimport requestsimport jsonimport hmacimport hashlibimport base64import urllib.parseimport datetimefrom decimal import Decimal# -------------------------- 钉钉消息推送(加密签名) --------------------------def send_dd_message(msg): timestamp = str(round(time.time() * 1000)) secret = '你的钉钉密钥' # 替换成自己的钉钉机器人密钥 secret_enc = secret.encode('utf-8') string_to_sign = '{}\n{}'.format(timestamp, secret) string_to_sign_enc = string_to_sign.encode('utf-8') # HMAC-SHA256 加密 + Base64 编码 + URL 转义 hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest() sign = urllib.parse.quote_plus(base64.b64encode(hmac_code)) # 拼接钉钉推送地址(替换自己的 access_token) url = 'https://oapi.dingtalk.com/robot/send?access_token=你的access_token×tamp=' + timestamp + '&sign=' + sign HEADERS = {"Content-Type": "application/json;charset=utf-8"} # 构造文本消息体 String_textMsg = { "msgtype": "text", "text": {"content": msg} } # 转JSON格式并推送 String_textMsg = json.dumps(String_textMsg).encode('utf-8') requests.post(url, data=String_textMsg, headers=HEADERS)# -------------------------- 获取 APP 日活、版本数据 --------------------------def get_ylxf_app(): # 导入友盟 API SDK 并配置 import aop import aop.api aop.set_default_server('gateway.open.umeng.com') # 友盟 API 网关地址(固定) aop.set_default_appinfo(8****55, "***UMno") # 替换成自己的友盟 appId 和密钥 # 配置 Android + iOS 双端 appkey(替换成自己的) datas = [ ['Android', '安卓appkey'], ['ios', 'iOSappkey'], ] today_activityUsers = 0 # 今日总活跃数 yesterday_activityUsers = 0 # 昨日总活跃数 today = datetime.datetime.now() now = today.strftime('%Y-%m-%d %H:%M:%S') # 当前时间戳,用于推送文案 # 1. 获取双端今日/昨日活跃用户 req = aop.api.UmengUappGetTodayYesterdayDataRequest() for data in datas: try: # 调用友盟接口,获取单端数据 resp = req.get_response(None, appkey=data[1]) # 累加双端今日、昨日活跃数 today_activityUsers += int(resp['todayData']['activityUsers']) yesterday_activityUsers += int(resp['yesterdayData']['activityUsers']) except Exception as e: print(e) # 异常捕获,避免脚本崩溃 # 2. 高精度计算环比涨跌(保留2位小数) activityUsers_per = (Decimal(today_activityUsers - yesterday_activityUsers) / Decimal(yesterday_activityUsers)).quantize(Decimal('0.00')) # 3. 拼接推送文案 text = f"截止:{now}" text += f"\nAPP日活跃数 {today_activityUsers} 个(昨日:{yesterday_activityUsers} 个)," # 自动判断增长/下降 if activityUsers_per > Decimal(0): text += f"活跃用户环比增长 {activityUsers_per} %;" else: text += f"活跃用户环比下降 {abs(activityUsers_per)} %;" # 4. 统计指定版本累计用户(可自定义版本号) versions = ['2.4.0', '3.0.0'] # 替换成自己要监控的版本 req = aop.api.UmengUappGetVersionDataRequest() for version in versions: version_total_user = 0 # 该版本双端累计用户 for data in datas: try: # 调用友盟版本分布接口,获取当日版本数据 resp = req.get_response(None, appkey=data[1], date=f'{today.date()}') # 匹配目标版本,累加用户数 for versioninfo in resp['versionInfos']: if versioninfo['version'] == version: version_total_user += int(versioninfo['totalUser']) except Exception as e: print(e) text += f"\nAPP {version} 版本累计用户:{version_total_user} 人;" return text# -------------------------- 主执行入口 --------------------------if __name__ == "__main__": # 获取推送文案 msg = f'\n\n1.{get_ylxf_app()}' msg += f'\n(按添加时间统计)' # 推送到钉钉 send_dd_message(msg) # 控制台打印日志,方便调试 print(msg)
四、核心模块代码 + 逐行讲解(纯干货,新手也能懂)
很多同学拿到代码不敢改,其实拆解开来很简单,每个模块独立封装,看懂逻辑就能灵活调整,逐段讲解安排上:钉钉机器人不能直接调用,必须做签名加密,否则会被拦截,这段代码直接实现加密+推送,无需额外修改:def send_dd_message(msg): timestamp = str(round(time.time() * 1000)) secret = '你的钉钉密钥' secret_enc = secret.encode('utf-8') string_to_sign = '{}\n{}'.format(timestamp, 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)) url = 'https://oapi.dingtalk.com/robot/send?access_token=你的access_token×tamp=' + timestamp + '&sign=' + sign HEADERS = {"Content-Type": "application/json;charset=utf-8"} String_textMsg = { "msgtype": "text", "text": {"content": msg} } String_textMsg = json.dumps(String_textMsg).encode('utf-8') requests.post(url, data=String_textMsg, headers=HEADERS)
- `timestamp = str(round(time.time() * 1000))`:生成毫秒级时间戳,钉钉签名必需,用于防篡改;
- `secret_enc = secret.encode('utf-8')`:将钉钉密钥转为 UTF-8 编码,满足加密格式要求;
- `string_to_sign = '{}\n{}'.format(timestamp, secret)`:拼接时间戳和密钥,中间用换行分隔(钉钉固定要求);
- `hmac_code = ...`:使用 HMAC-SHA256 算法对拼接内容加密,保证请求安全;
- `sign = ...`:将加密结果做 Base64 编码,再做 URL 转义,避免特殊字符报错;
- `url`:拼接钉钉推送地址,替换自己的 `access_token` 即可;
- `String_textMsg`:构造文本消息体,固定格式,`content` 就是要推送的内容;
- `requests.post(...)`:发起 POST 请求,推送消息到钉钉群。
我们通过友盟 API 获取 APP 日活数据,这段代码是接口调用的基础,只需替换自己的配置:import aopimport aop.apiaop.set_default_server('gateway.open.umeng.com')aop.set_default_appinfo(8689055, "zwXyKehUMno")datas = [ ['Android', '安卓appkey'], ['ios', 'iOSappkey'],]
- `import aop; import aop.api`:导入友盟官方 SDK,用于调用接口;
- `aop.set_default_server(...)`:设置友盟 API 网关地址(固定值,不用改);
- `aop.set_default_appinfo(...)`:填入友盟后台获取的 `appId` 和 `appKey`(登录友盟后台可查);
- `datas`:配置 Android 和 iOS 双端的 `appkey`,后续循环遍历,自动汇总双端数据,不用分开查询。
核心业务逻辑,自动拉取双端日活数据并累加,避免人工统计:req = aop.api.UmengUappGetTodayYesterdayDataRequest()for data in datas: try: resp = req.get_response(None, appkey=data[1]) today_activityUsers += int(resp['todayData']['activityUsers']) yesterday_activityUsers += int(resp['yesterdayData']['activityUsers']) except Exception as e: print(e)
- `req = aop.api.UmengUappGetTodayYesterdayDataRequest()`:实例化友盟“获取今日/昨日数据”接口;
- `for data in datas`:循环遍历 Android、iOS 双端配置;
- `resp = req.get_response(None, appkey=data[1])`:调用接口,传入单端 `appkey`,获取接口返回数据;
- `today_activityUsers += ...`:从返回结果中提取今日活跃数 `activityUsers`,累加得到双端总今日活;
- `yesterday_activityUsers += ...`:同理,累加双端总昨日活;
- `try-except`:捕获接口调用异常(如网络问题、appkey 错误),打印错误信息,保证脚本不崩溃。
普通浮点除法容易出现小数错乱,这段代码用高精度运算,保证环比结果准确:activityUsers_per = (Decimal(today_activityUsers - yesterday_activityUsers) / Decimal(yesterday_activityUsers)).quantize(Decimal('0.00'))text = f"截止:{now}"text += f"\nAPP日活跃数 {today_activityUsers} 个(昨日:{yesterday_activityUsers} 个),"if activityUsers_per > Decimal(0): text += f"活跃用户环比增长 {activityUsers_per} %;"else: text += f"活跃用户环比下降 {abs(activityUsers_per)} %;"
- `Decimal(...)`:将数字转为高精度类型,避免浮点运算误差;
- `(今日 - 昨日) / 昨日`:环比计算公式,`quantize(Decimal('0.00'))` 保留 2 位小数,格式更规范;
- `text`:拼接推送文案,包含当前时间、今日/昨日活数据;
- `if-else`:自动判断环比正负,正数显示“增长”,负数显示“下降”,无需人工干预。
可自定义监控版本,自动统计该版本双端累计用户,适合版本迭代后监控覆盖进度:versions = ['2.4.0', '3.0.0']req = aop.api.UmengUappGetVersionDataRequest()for version in versions: version_total_user = 0 for data in datas: try: resp = req.get_response(None, appkey=data[1], date=f'{today.date()}') for versioninfo in resp['versionInfos']: if versioninfo['version'] == version: version_total_user += int(versioninfo['totalUser']) except Exception as e: print(e) text += f"\nAPP {version} 版本累计用户:{version_total_user} 人;"
- `versions = ['2.4.0', '3.0.0']`:自定义需要监控的版本号,可添加/删除;
- `req = aop.api.UmengUappGetVersionDataRequest()`:实例化友盟“版本分布”接口;
- `for version in versions`:遍历每个需要监控的版本;
- `for data in datas`:遍历双端,获取单端该版本数据;
- `resp = req.get_response(...)`:调用接口,传入 `appkey` 和当日日期,获取版本明细;
- `for versioninfo in resp['versionInfos']`:遍历接口返回的所有版本,匹配目标版本;
- `version_total_user += ...`:累加双端该版本的累计用户数 `totalUser`;
if __name__ == "__main__": msg = f'\n\n1.{get_ylxf_app()}' msg += f'\n(按添加时间统计)' send_dd_message(msg) print(msg)
- `if __name__ == "__main__":`:Python 程序入口,只有直接运行脚本时才会执行;
- `msg = f'\n\n1.{get_ylxf_app()}'`:调用 `get_ylxf_app()` 方法,获取拼接好的推送文案;
- `msg += ...`:追加说明文案,让推送内容更清晰;
- `send_dd_message(msg)`:调用钉钉推送方法,将文案推送到钉钉群;
- `print(msg)`:在控制台打印推送内容,方便本地调试、查看日志。
脚本运行后,钉钉群会自动收到标准化报表,示例如下(实际效果以你的截图为准):- 替换代码中的 5 个配置项:钉钉密钥、钉钉 access_token、友盟 appId、友盟 appKey、双端 appkey;
- (可选)修改 `versions` 列表,替换成自己要监控的 APP 版本号;
- 将脚本上传到 Linux 服务器(本地测试可直接运行);
- 配置 crontab 定时任务,例如每天早上 9 点自动推送:
0 9 * * * /usr/local/python39/bin/python3 /home/script/app_report.py
说明:`/usr/local/python39/bin/python3` 是你的 Python 路径,`/home/script/app_report.py` 是脚本存放路径,根据自己的服务器配置修改即可。- APP 运营:日常日活监控、自动化日报输出,减少重复工作;
- 开发人员:快速实现数据自动化推送,二次扩展成本低;
- 团队管理:无需登录后台,打开钉钉就能掌握 APP 核心数据。
这套脚本是我线上投产使用的版本,经过实际测试,稳定运行无报错。核心优势就是“轻量、实用、可落地”,不用花时间研究复杂框架,替换配置就能用,每天能帮你节省十几分钟的重复工作。如果需要修改推送格式、新增数据指标(如新增用户、留存率),也可以基于现有代码轻松扩展。觉得有用的话,收藏起来,转发给身边做运营、运维的同学,一起解放双手~