ujsAutoClock 江苏大学自动健康打卡项目(Chrome 扩展 & Android APP)
- 设置简单,通知推送,QQ 接龙,熄屏运行(不同系统环境、Chrome 版本可能不一定有效)
(妈妈再也不用担心没打卡啦 - Chrome 扩展项目地址:https://github.com/tagbug/ujsAutoClock
- Android 项目地址:https://github.com/tagbug/ujsAutoClock.apk
# 食用方法
下面是 Chrome 扩展的使用说明,Android 版本直接下载就行了,应该不用说明了
-
1. 在 Github 上下载扩展
-
2. 打开 Chrome 扩展程序的开发者模式
-
3. 选择
加载已解压的扩展程序
-
4. 选择 ujsAutoClock 文件夹
-
5. 允许 Chrome 在后台运行(占用系统资源很小)
-
6. 首次安装会自动弹出设置页,填写好配置后保存,就可以自动运行了
-
7. 如果想测试打卡效果直接在 Chrome 地址栏旁边的扩展程序里点击扩展图标
- 8. 最新版增加 QQ 群自动接龙功能,接龙是接群的第一个,因为有 QQ 密码这种敏感信息,需要右键扩展,在选项中配置
- 附。在 Chrome 扩展程序页选择选择
ujs自动健康打卡
-> 查看视图背景页
可以在Console
里看到自动打卡记录。
使用截图:
# 开发思路
# Chrome 扩展
其实一开始,我是拒绝的,一是因为写代码麻烦,二是因为觉得不重要,每天手动打卡就顺手的事,然而我错了,对于尤其像我这种昼夜时差颠倒的人,一不小心就会忘记,然后被打电话,所以…╮( ̄▽ ̄")╭
# 登录认证
- 打卡界面本来是在微信上的,选择
在浏览器打开
会得到一个打卡网址serviceUrl="http://yun.ujs.edu.cn/xxhgl/yqsb/index"
,很显然需要用户认证,通过"https://pass.ujs.edu.cn/cas/login?service="+serviceUrl
进行统一身份认证,浏览器会自动保存 Cookie(或者直接"https://pass.ujs.edu.cn/cas/login"
好像也可以,这个参数的作用好像不是很明显,我没深究) - 对登陆页的 form.submit 进行分析,可知 POST 有以下参数:
username
|password
|captchaResponse
|lt
|dllt
|execution
|_eventId
|rmShown
- 后面五个参数都是隐藏在 form 表单中,每次请求内容好像都没变过,前三个参数都是需要用户填写的,其中 password 字段在 POST 提交时还会被用 AES 加密(AES 用到的密钥也放在了表单中,每次请求都会改变)
- 知道了这些后,就可以写登录认证方法了,前面两个参数用户提供,每次不变,后面五个参数直接从 document 中提取,唯一比较棘手的就是验证码的处理,验证码每次从
'https://pass.ujs.edu.cn/cas/captcha.html?ts=' + new Date().getMilliseconds()
中随机生成 - 想到可以用 OCR 识别,在网上找了很多 OCR 的 API,要么是要钱,要么是效果不好,还好知道一个效果不错的免费 OCR,但是却没有开放的 API 接口,无奈只好自己扒
- 其实扒这个 OCR 的接口才是最耗时间精力的,中间踩了不少坑,反复用浏览器 F12 下断点调试 + BurpSuite 抓包,最后总算也是解决了,太过冗长也就不细讲了(其实这里用图像处理来对付验证码也可以,但是对于 JS 来说显然调 API 更省力)
- 到这里终于是可以写自动化脚本把这个流程串联起来了(访问
https://pass.ujs.edu.cn/cas/login
获取表单参数 -> 访问'https://pass.ujs.edu.cn/cas/captcha.html?ts=' + new Date().getMilliseconds()
获取验证码图片信息 -> 丢给 OCR 处理 -> 返回验证码后把表单参数接起来 ->POST 获取返回数据 -> 检查登录状态是否成功(因为 OCR 有一定几率识别有误差,如果是验证码错误就重试,如果用户名密码错误直接结束,其他错误抛出异常))
# 定时打卡任务
- 在登录认证后直接访问
'http://yun.ujs.edu.cn/xxhgl/yqsb/grmrsb?v=' + parseInt(Math.random() * 10000)
就可以看到保存的打卡表单信息,注意到只有下午温度
、上午温度
和其他异常
三个字段每天刷新,需要填写,这里用 Chrome 扩展强大的脚本插入功能,在页面加载完成后自动填写空缺字段提交,并返回提交结果 - 最后实现每天定时执行,用 Chrome 扩展的消息通信功能协调各个子模块的运行,用
chrome.storage.local
储存用户名
、密码
和每日自动执行时间
,用chrome.notifications
实现桌面通知,popup.html
和options.html
实现设置的读取和保存,方便用户操作
# Android 应用
这个是后来开发的,因为吧,虽然 Chrome 扩展开发起来简单,但最大的不足之处就在于无法同步通知到手机上,本来是想用发邮件的方式,找了很久也没发现什么用 JS 实现起来较为简单的方案,然后呢,我想着干脆直接在手机上开发一个应用,这样不就方便多了,而且实现原理都差不多… 嗯,原理是差不多,细节就差远了,本来以为一两天就能写完,最后边学边写写了四五天…
# 基本逻辑
- Get 登录页 -> 拿到一部分 Post 表单数据 ->Get 验证码 -> 用 OCR 读取 -> 整合表单 Post 登录 ->Get 打卡表单 -> 填补空缺项后 Post 打卡
# 细节
-
整个流程都是需要 HTTP 协议来进行数据交换的,原生的 Java HTTP API 效率太低了,用了开源软件 OkHttp,而且还需要实现 Cookie 的存储、更新和提交,Chrome 中浏览器就已经做好了这些,而在 Java 中只能自己来处理
解决方法:实现 OkHttp 中的 CookieJar 接口来自动处理 Cookie(缓存、读取、过期更新、本地化)
这里参考了:OkHttp 官方文档和 OkHttp3 实现 Cookies 管理及持久化 -
然后第二个就是 Android 应用运行机制,包括应用组件:Activity、Service、BroadcastReceiver 和 ContentProvider(虽然我只用到了第一个和第三个…),清单文件,应用资源(布局、图标等),Intent、Context、Bundle…
不得不说,相当复杂…(关键是官方 API 文档还全是英文,看都看不懂) -
第三个是用闹钟 AlarmManager 实现定时执行任务
(这个东西是真迷幻,不知道为什么定时总会有几分钟偏差)(用 setExactAndAllowWhileIdle 方法即可准时广播) -
最后用 Notification 推送通知(这个东西也是,不同的 API 所要求的实现方法有细微区别,不注意就会导致通知推送不出来,找半天都不知道是哪的问题…)
-
Android 系统的开放性、既要兼顾不同的 Android 系统版本(从高到低的 SDK 版本)、又因为各种厂商对自家手机系统的魔改,导致 Android 开发是个相当不容易的工作… 很佩服
参考:
Chrome 插件 (扩展) 开发全攻略
Android 开发者