├── .github └── workflows │ └── report.yml ├── .gitignore ├── LICENSE ├── README.md ├── data.json ├── data_center.json ├── data_east.json ├── data_north.json ├── data_south.json ├── data_west.json ├── imgs ├── 1.png ├── 2.png └── image-20200826215037042.png ├── report.py └── requirements.txt /.github/workflows/report.yml: -------------------------------------------------------------------------------- 1 | # Auto-report action script, 3 times a day 2 | 3 | name: Auto-report action 4 | 5 | on: 6 | push: 7 | branches: 8 | - master 9 | schedule: 10 | - cron: '30 3,12 * * *' 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Set up Python 3.8 20 | uses: actions/setup-python@v2 21 | with: 22 | python-version: 3.8 23 | - name: Install dependencies 24 | run: | 25 | python -m pip install --upgrade pip 26 | pip install -r requirements.txt 27 | - name: Run report script 28 | env: 29 | STUID: ${{ secrets.Stuid }} 30 | PASSWORD: ${{ secrets.Password }} 31 | run: | 32 | python report.py data.json "$STUID" "$PASSWORD" 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ./nohup.out 2 | nohup.out 3 | .idea -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 BwZhang 4 | Copyright (c) 2020 Violin Wang 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 中国滑稽大学(University of Ridiculous of China)健康打卡平台自动打卡脚本 2 | 3 | ![Auto-report action](https://github.com/Violin9906/USTC-ncov-AutoReport/workflows/Auto-report%20action/badge.svg?branch=master&event=schedule) 4 | ![School](https://img.shields.io/badge/School-URC-blue.svg) 5 | ![Language](https://img.shields.io/badge/language-Python3-yellow.svg) 6 | ![GitHub stars](https://img.shields.io/github/stars/Violin9906/USTC-ncov-AutoReport) 7 | ![GitHub forks](https://img.shields.io/github/forks/Violin9906/USTC-ncov-AutoReport) 8 | 9 | ## 说明 10 | 11 | **本打卡脚本仅供学习交流使用,请勿过分依赖。开发者对使用或不使用本脚本造成的问题不负任何责任,不对脚本执行效果做出任何担保,原则上不提供任何形式的技术支持。** 12 | 13 | ## 更新记录 14 | 15 | - 20200831:增强稳定性 16 | - 20200827:增加打卡失败重试功能,增加License 17 | - 20200826:为配合学校最新规定,切换至Github Actions实现一天三次打卡 18 | 19 | ## 使用方法 20 | 21 | 0. **写在前面:请在自己fork的仓库中修改,并push到自己的仓库,不要直接修改本仓库,也不要将您的修改pull request到本仓库(对本仓库的改进除外)!如果尚不了解github的基本使用方法,请参阅[使用议题和拉取请求进行协作/使用复刻](https://docs.github.com/cn/github/collaborating-with-issues-and-pull-requests/working-with-forks)和[使用议题和拉取请求进行协作/通过拉取请求提议工作更改](https://docs.github.com/cn/github/collaborating-with-issues-and-pull-requests/proposing-changes-to-your-work-with-pull-requests)。** 22 | 23 | 1. 将本代码仓库fork到自己的github。 24 | 25 | 2. 根据自己的实际情况修改`data.json`的数据,参看下文。这里给出了东、西、南、北、中五个校区正常在校的模板,默认的`data.json`是西区正常在校。**开发者不保证这些模板的正确性。** 26 | 27 | 3. 将修改好的代码push至master分支。如果不需要修改 `data.json`,请在 `README.md` 里添加一个空格并push,否则不会触发之后的步骤。**请在自己的仓库中修改,不要pull request到本仓库!** 28 | 29 | 4. 点击Actions选项卡,点击`I understand my workflows, go ahead and enable them`. 30 | 31 | 5. 点击Settings选项卡,点击左侧Secrets,点击New secret,创建名为`STUID`,值为自己学号的secret。用同样方法,创建名为`PASSWORD`,值为自己中国滑稽大学统一身份认证密码的secret。这两个值不会被公开。 32 | 33 | ![secrets](imgs/image-20200826215037042.png) 34 | 35 | 6. 默认的打卡时间是每天的早上7:30、中午12:30和晚上19:30,可能会有数分钟的浮动。如需选择其它时间,可以修改`.github/workflows/report.yml`中的`cron`,详细说明参见[安排的事件](https://docs.github.com/cn/actions/reference/events-that-trigger-workflows#scheduled-events),请注意这里使用的是**国际标准时间UTC**,北京时间的数值比它大8个小时。建议修改默认时间,避开打卡高峰期以提高成功率。 36 | 37 | 7. 在Actions选项卡可以确认打卡情况。如果打卡失败(可能是临时网络问题等原因),脚本会自动重试,五次尝试后如果依然失败,将返回非零值提示构建失败。 38 | 39 | 8. 在Github个人设置页面的Notifications下可以设置Github Actions的通知,建议打开Email通知,并勾选"Send notifications for failed workflows only"。 40 | 41 | ## 在本地运行测试 42 | 43 | 要在本地运行测试,需要安装python 3。我们假设您已经安装了python 3和pip 3,并已将其路径添加到环境变量。 44 | 45 | ### 安装依赖 46 | 47 | ```shell 48 | pip install -r requirements.txt 49 | ``` 50 | 51 | ### 运行打卡程序 52 | 53 | ```shell 54 | python report.py [DATA] [STUID] [PASSWORD] 55 | ``` 56 | 其中,`[DATA]`是存放打卡数据的json文件的路径,`[STUID]`是学号,`[PASSWORD]`是统一身份认证的密码明文。 57 | 58 | ## data.json 数据获取方法 59 | 60 | 使用 F12 开发者工具抓包之后得到数据,按照 json 格式写入 `data.json` 中。 61 | 62 | 1. 登录进入 `https://weixine.歪比巴卜.edu.cn/2020/`,打开开发者工具(Chrome 可以使用 F12 快捷键),选中 Network 窗口: 63 | 64 | ![](./imgs/1.png) 65 | 66 | 2. 点击确认上报,点击抓到的 `daliy_report` 请求,在 `Headers` 下面找到 `Form Data` 这就是每次上报提交的信息参数。 67 | 68 | ![](./imgs/2.png) 69 | 70 | 3. 将找到的 Data 除 `_token` (每次都会改变,所以不需要复制,脚本中会每次获取新的 token 并添加到要提交的数据中)外都复制下来,存放在 `data.json` 中,并参考示例文件转换为对应的格式。 71 | 72 | 4. 通过push操作触发构建任务,检查上报数据是否正确。 73 | 74 | ## 许可 75 | 76 | MIT License 77 | 78 | Copyright (c) 2020 BwZhang 79 | 80 | Copyright (c) 2020 Violin Wang 81 | 82 | Permission is hereby granted, free of charge, to any person obtaining a copy 83 | of this software and associated documentation files (the "Software"), to deal 84 | in the Software without restriction, including without limitation the rights 85 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 86 | copies of the Software, and to permit persons to whom the Software is 87 | furnished to do so, subject to the following conditions: 88 | 89 | The above copyright notice and this permission notice shall be included in all 90 | copies or substantial portions of the Software. 91 | 92 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 93 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 94 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 95 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 96 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 97 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 98 | SOFTWARE. 99 | 100 | -------------------------------------------------------------------------------- /data.json: -------------------------------------------------------------------------------- 1 | { 2 | "now_address": "1", 3 | "gps_now_address": "", 4 | "now_province": "340000", 5 | "gps_province": "", 6 | "now_city": "340100", 7 | "gps_city": "", 8 | "now_detail": "", 9 | "is_inschool": "6", 10 | "body_condition": "1", 11 | "body_condition_detail": "", 12 | "now_status": "1", 13 | "now_status_detail": "", 14 | "has_fever": "0", 15 | "last_touch_sars": "0", 16 | "last_touch_sars_date": "", 17 | "last_touch_sars_detail": "", 18 | "other_detail": "" 19 | } -------------------------------------------------------------------------------- /data_center.json: -------------------------------------------------------------------------------- 1 | { 2 | "now_address": "1", 3 | "gps_now_address": "", 4 | "now_province": "340000", 5 | "gps_province": "", 6 | "now_city": "340100", 7 | "gps_city": "", 8 | "now_detail": "", 9 | "is_inschool": "4", 10 | "body_condition": "1", 11 | "body_condition_detail": "", 12 | "now_status": "1", 13 | "now_status_detail": "", 14 | "has_fever": "0", 15 | "last_touch_sars": "0", 16 | "last_touch_sars_date": "", 17 | "last_touch_sars_detail": "", 18 | "other_detail": "" 19 | } -------------------------------------------------------------------------------- /data_east.json: -------------------------------------------------------------------------------- 1 | { 2 | "now_address": "1", 3 | "gps_now_address": "", 4 | "now_province": "340000", 5 | "gps_province": "", 6 | "now_city": "340100", 7 | "gps_city": "", 8 | "now_detail": "", 9 | "is_inschool": "2", 10 | "body_condition": "1", 11 | "body_condition_detail": "", 12 | "now_status": "1", 13 | "now_status_detail": "", 14 | "has_fever": "0", 15 | "last_touch_sars": "0", 16 | "last_touch_sars_date": "", 17 | "last_touch_sars_detail": "", 18 | "other_detail": "" 19 | } -------------------------------------------------------------------------------- /data_north.json: -------------------------------------------------------------------------------- 1 | { 2 | "now_address": "1", 3 | "gps_now_address": "", 4 | "now_province": "340000", 5 | "gps_province": "", 6 | "now_city": "340100", 7 | "gps_city": "", 8 | "now_detail": "", 9 | "is_inschool": "5", 10 | "body_condition": "1", 11 | "body_condition_detail": "", 12 | "now_status": "1", 13 | "now_status_detail": "", 14 | "has_fever": "0", 15 | "last_touch_sars": "0", 16 | "last_touch_sars_date": "", 17 | "last_touch_sars_detail": "", 18 | "other_detail": "" 19 | } -------------------------------------------------------------------------------- /data_south.json: -------------------------------------------------------------------------------- 1 | { 2 | "now_address": "1", 3 | "gps_now_address": "", 4 | "now_province": "340000", 5 | "gps_province": "", 6 | "now_city": "340100", 7 | "gps_city": "", 8 | "now_detail": "", 9 | "is_inschool": "3", 10 | "body_condition": "1", 11 | "body_condition_detail": "", 12 | "now_status": "1", 13 | "now_status_detail": "", 14 | "has_fever": "0", 15 | "last_touch_sars": "0", 16 | "last_touch_sars_date": "", 17 | "last_touch_sars_detail": "", 18 | "other_detail": "" 19 | } -------------------------------------------------------------------------------- /data_west.json: -------------------------------------------------------------------------------- 1 | { 2 | "now_address": "1", 3 | "gps_now_address": "", 4 | "now_province": "340000", 5 | "gps_province": "", 6 | "now_city": "340100", 7 | "gps_city": "", 8 | "now_detail": "", 9 | "is_inschool": "6", 10 | "body_condition": "1", 11 | "body_condition_detail": "", 12 | "now_status": "1", 13 | "now_status_detail": "", 14 | "has_fever": "0", 15 | "last_touch_sars": "0", 16 | "last_touch_sars_date": "", 17 | "last_touch_sars_detail": "", 18 | "other_detail": "" 19 | } -------------------------------------------------------------------------------- /imgs/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xbb1973/USTC-ncov-AutoReport/cb82b6432e68f55948559b3dc7c72df1a6402b18/imgs/1.png -------------------------------------------------------------------------------- /imgs/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xbb1973/USTC-ncov-AutoReport/cb82b6432e68f55948559b3dc7c72df1a6402b18/imgs/2.png -------------------------------------------------------------------------------- /imgs/image-20200826215037042.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xbb1973/USTC-ncov-AutoReport/cb82b6432e68f55948559b3dc7c72df1a6402b18/imgs/image-20200826215037042.png -------------------------------------------------------------------------------- /report.py: -------------------------------------------------------------------------------- 1 | # encoding=utf8 2 | import requests 3 | import json 4 | import time 5 | import datetime 6 | import pytz 7 | import re 8 | import sys 9 | import argparse 10 | from bs4 import BeautifulSoup 11 | 12 | class Report(object): 13 | def __init__(self, stuid, password, data_path): 14 | self.stuid = stuid 15 | self.password = password 16 | self.data_path = data_path 17 | 18 | def report(self): 19 | loginsuccess = False 20 | retrycount = 5 21 | while (not loginsuccess) and retrycount: 22 | session = self.login() 23 | cookies = session.cookies 24 | getform = session.get("http://weixine.ustc.edu.cn/2020") 25 | retrycount = retrycount - 1 26 | if getform.url != "https://weixine.ustc.edu.cn/2020/home": 27 | print("Login Failed! Retry...") 28 | else: 29 | print("Login Successful!") 30 | loginsuccess = True 31 | if not loginsuccess: 32 | return False 33 | data = getform.text 34 | data = data.encode('ascii','ignore').decode('utf-8','ignore') 35 | soup = BeautifulSoup(data, 'html.parser') 36 | token = soup.find("input", {"name": "_token"})['value'] 37 | 38 | with open(self.data_path, "r+") as f: 39 | data = f.read() 40 | data = json.loads(data) 41 | data["_token"]=token 42 | 43 | headers = { 44 | 'authority': 'weixine.ustc.edu.cn', 45 | 'origin': 'http://weixine.ustc.edu.cn', 46 | 'upgrade-insecure-requests': '1', 47 | 'content-type': 'application/x-www-form-urlencoded', 48 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.100 Safari/537.36', 49 | 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 50 | 'referer': 'http://weixine.ustc.edu.cn/2020/', 51 | 'accept-language': 'zh-CN,zh;q=0.9', 52 | 'Connection': 'close', 53 | 'cookie': 'PHPSESSID=' + cookies.get("PHPSESSID") + ";XSRF-TOKEN=" + cookies.get("XSRF-TOKEN") + ";laravel_session="+cookies.get("laravel_session"), 54 | } 55 | 56 | url = "http://weixine.ustc.edu.cn/2020/daliy_report" 57 | session.post(url, data=data, headers=headers) 58 | data = session.get("http://weixine.ustc.edu.cn/2020").text 59 | soup = BeautifulSoup(data, 'html.parser') 60 | pattern = re.compile("2020-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}") 61 | token = soup.find( 62 | "span", {"style": "position: relative; top: 5px; color: #666;"}) 63 | flag = False 64 | if pattern.search(token.text) is not None: 65 | date = pattern.search(token.text).group() 66 | print("Latest report: " + date) 67 | date = date + " +0800" 68 | reporttime = datetime.datetime.strptime(date, "%Y-%m-%d %H:%M:%S %z") 69 | timenow = datetime.datetime.now(pytz.timezone('Asia/Shanghai')) 70 | delta = timenow - reporttime 71 | print("{} second(s) before.".format(delta.seconds)) 72 | if delta.seconds < 120: 73 | flag = True 74 | if flag == False: 75 | print("Report FAILED!") 76 | else: 77 | print("Report SUCCESSFUL!") 78 | return flag 79 | 80 | def login(self): 81 | url = "https://passport.ustc.edu.cn/login?service=http%3A%2F%2Fweixine.ustc.edu.cn%2F2020%2Fcaslogin" 82 | data = { 83 | 'model': 'uplogin.jsp', 84 | 'service': 'http://weixine.ustc.edu.cn/2020/caslogin', 85 | 'username': self.stuid, 86 | 'password': str(self.password), 87 | } 88 | session = requests.Session() 89 | session.post(url, data=data) 90 | 91 | print("login...") 92 | return session 93 | 94 | 95 | if __name__ == "__main__": 96 | parser = argparse.ArgumentParser(description='URC nCov auto report script.') 97 | parser.add_argument('data_path', help='path to your own data used for post method', type=str) 98 | parser.add_argument('stuid', help='your student number', type=str) 99 | parser.add_argument('password', help='your CAS password', type=str) 100 | args = parser.parse_args() 101 | autorepoter = Report(stuid=args.stuid, password=args.password, data_path=args.data_path) 102 | count = 5 103 | while count != 0: 104 | ret = autorepoter.report() 105 | if ret != False: 106 | break 107 | print("Report Failed, retry...") 108 | count = count - 1 109 | if count != 0: 110 | exit(0) 111 | else: 112 | exit(-1) -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xbb1973/USTC-ncov-AutoReport/cb82b6432e68f55948559b3dc7c72df1a6402b18/requirements.txt --------------------------------------------------------------------------------