├── requirements.txt ├── img ├── 0.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png ├── 6.png ├── 7.png ├── 8.png └── 9.png ├── .gitattributes ├── __pycache__ ├── Wecom.cpython-39.pyc ├── constant.cpython-39.pyc └── serverJiang.cpython-39.pyc ├── .github └── workflows │ └── main.yml ├── LICENSE ├── Wecom.py ├── README.md ├── constant.py └── main.py /requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | lxml -------------------------------------------------------------------------------- /img/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RunpuWei/BUPT-Auto-Report/HEAD/img/0.png -------------------------------------------------------------------------------- /img/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RunpuWei/BUPT-Auto-Report/HEAD/img/2.png -------------------------------------------------------------------------------- /img/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RunpuWei/BUPT-Auto-Report/HEAD/img/3.png -------------------------------------------------------------------------------- /img/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RunpuWei/BUPT-Auto-Report/HEAD/img/4.png -------------------------------------------------------------------------------- /img/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RunpuWei/BUPT-Auto-Report/HEAD/img/5.png -------------------------------------------------------------------------------- /img/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RunpuWei/BUPT-Auto-Report/HEAD/img/6.png -------------------------------------------------------------------------------- /img/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RunpuWei/BUPT-Auto-Report/HEAD/img/7.png -------------------------------------------------------------------------------- /img/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RunpuWei/BUPT-Auto-Report/HEAD/img/8.png -------------------------------------------------------------------------------- /img/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RunpuWei/BUPT-Auto-Report/HEAD/img/9.png -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /__pycache__/Wecom.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RunpuWei/BUPT-Auto-Report/HEAD/__pycache__/Wecom.cpython-39.pyc -------------------------------------------------------------------------------- /__pycache__/constant.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RunpuWei/BUPT-Auto-Report/HEAD/__pycache__/constant.cpython-39.pyc -------------------------------------------------------------------------------- /__pycache__/serverJiang.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RunpuWei/BUPT-Auto-Report/HEAD/__pycache__/serverJiang.cpython-39.pyc -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: BUPT ncov auto-report Python+Actions V3.0 2 | 3 | on: 4 | schedule: 5 | - cron: "*/30 */4 * * *" 6 | workflow_dispatch: 7 | 8 | jobs: 9 | build: 10 | 11 | runs-on: ubuntu-latest 12 | strategy: 13 | matrix: 14 | python-version: [3.7] 15 | 16 | steps: 17 | - uses: actions/checkout@v2 18 | - name: Set up Python ${{ matrix.python-version }} 19 | uses: actions/setup-python@v2 20 | with: 21 | python-version: ${{ matrix.python-version }} 22 | - name: Install dependencies 23 | run: | 24 | python -m pip install --upgrade pip 25 | if [ -f requirements.txt ]; then pip install -r requirements.txt; fi 26 | - name: Run BUPT ncov Auto-report Script 27 | run: | 28 | python3 main.py 29 | env: 30 | USERS: ${{ secrets.USERS }} 31 | WECOM: ${{ secrets.WECOM }} 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 zzp-seeker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Wecom.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import datetime 3 | import json,requests 4 | 5 | def send_to_wecom(text,wecom_cid,wecom_aid,wecom_secret,wecom_touid='@all'): 6 | get_token_url = f"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={wecom_cid}&corpsecret={wecom_secret}" 7 | response = requests.get(get_token_url).content 8 | access_token = json.loads(response).get('access_token') 9 | if access_token and len(access_token) > 0: 10 | send_msg_url = f'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={access_token}' 11 | data = { 12 | "touser":wecom_touid, 13 | "agentid":wecom_aid, 14 | "msgtype":"text", 15 | "text":{ 16 | "content":text 17 | }, 18 | "duplicate_check_interval":600 19 | } 20 | response = requests.post(send_msg_url,data=json.dumps(data)).content 21 | return response 22 | else: 23 | return False 24 | def send_to_wecom_image(base64_content,wecom_cid,wecom_aid,wecom_secret,wecom_touid='@all'): 25 | get_token_url = f"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={wecom_cid}&corpsecret={wecom_secret}" 26 | response = requests.get(get_token_url).content 27 | access_token = json.loads(response).get('access_token') 28 | if access_token and len(access_token) > 0: 29 | upload_url = f'https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token={access_token}&type=image' 30 | upload_response = requests.post(upload_url, files={ 31 | "picture": base64.b64decode(base64_content) 32 | }).json() 33 | if "media_id" in upload_response: 34 | media_id = upload_response['media_id'] 35 | else: 36 | return False 37 | 38 | send_msg_url = f'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={access_token}' 39 | data = { 40 | "touser":wecom_touid, 41 | "agentid":wecom_aid, 42 | "msgtype":"image", 43 | "image":{ 44 | "media_id": media_id 45 | }, 46 | "duplicate_check_interval":600 47 | } 48 | response = requests.post(send_msg_url,data=json.dumps(data)).content 49 | return response 50 | else: 51 | return False 52 | 53 | def send_to_wecom_markdown(text,wecom_cid,wecom_aid,wecom_secret,wecom_touid='@all'): 54 | get_token_url = f"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={wecom_cid}&corpsecret={wecom_secret}" 55 | response = requests.get(get_token_url).content 56 | access_token = json.loads(response).get('access_token') 57 | if access_token and len(access_token) > 0: 58 | send_msg_url = f'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={access_token}' 59 | data = { 60 | "touser":wecom_touid, 61 | "agentid":wecom_aid, 62 | "msgtype":"markdown", 63 | "markdown":{ 64 | "content":text 65 | }, 66 | "duplicate_check_interval":600 67 | } 68 | response = requests.post(send_msg_url,data=json.dumps(data)).content 69 | return response 70 | else: 71 | return False 72 | 73 | #ret = send_to_wecom("推送测试\r\n测试换行", "企业ID③", "应用ID①", "应用secret②"); 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

:helicopter:北邮疫情自动填报(Python+Github Actions)长期维护

2 |

3 | 4 | Action Badge 5 | 6 | Python Version 7 |

8 | 9 | 10 | 11 | ## 特点: 12 | 13 | - cron设置自动多次填报(可通过main.yml修改) 14 | - 支持晨午晚检 15 | - 运行失败会自动往邮箱(注册github所用邮箱)发送邮件 16 | - 可以多人同时填报(可以帮小伙伴一起打卡哦) 17 | - 填报情况可以使用上一次打卡数据(如需更换请于当日脚本运行前手动打卡),也可以使用固定数据(填报地点始终位于北邮西土城校区) 18 | - **(可选)** 填报结果自动推送至微信 19 | ​ 20 | 21 |
22 | 23 |
24 | 25 | 26 | 27 | 28 | ## 使用详解 29 | 30 | 1. 点击右上角的 **Use this template** 然后给仓库随便起一个名字,点击 **Create repository from template** 31 | 2. 点击 **Settings** ,进入 **Secrets** 页面,点击右上角的 **New repository secret**,流程如下图所示 32 |
33 | 34 |
35 | 36 | 3. 一共有**两**个secret,第一个Name填**USERS**,Value按照如下格式填写: 37 | 38 | ```python 39 | [ 40 | (学号:str,密码:str,用户名:str,0 or 1), 41 | (学号:str,密码:str,用户名:str,0 or 1), 42 | (学号:str,密码:str,用户名:str,0 or 1), 43 | ... 如果还有则继续往后面加 44 | ] 45 | ``` 46 | 47 | 相当于**列表**里面有很多**元组**,每个元组代表一个用户,可以有任意多个。每个元组有**四个元素**,前两个分别为**学号**和**密码**,字符串格式(可自行通过 [https://app.bupt.edu.cn/ncov/wap/default/index](https://app.bupt.edu.cn/ncov/wap/default/index) 登陆验证账号密码正确性,密码一般为身份证后8位),第三个为**用户名**(随便填,用于控制台与Server显示),第四个为是否用上一次打卡数据,**0或者1**,0代表使用上一次打卡数据(**某一次自己在脚本运行前打卡之后都采用这次打卡数据**),1代表使用固定数据(固定数据的地点始终位于北邮)。该USERS在代码中会以python的eval(USERS)执行,故USERS符合python语法即可。以下是一个样例: 48 | 49 |
50 | 51 |
52 | 53 | 54 | 4. 第二个secret的Name填写**WECOM**,如果不配置微信推送,那么Value里填写 **("0","0","0")** 即可,如果想配置的话看下一点 55 | 5. **(可选)** Value填写 **("企业ID", "应用ID agentid", "应用 secret")** ,Value按照如下格式填写(注意都写成字符串形式,加引号!!!): 56 | ```python 57 | ("ww52940bxxxxxxxxxx", "1000001", "xxxxxxfOpyabbbbHo-xxxxxxxxxx6BfAgcbaaaaaaaa") 58 | ``` 59 | 具体配置说明在这里查看 [https://github.com/easychen/wecomchan](Wecom酱——企业微信应用消息配置说明)),在此之前需要微信注册企业号,并自定义创建一个应用,对照上述链接内的前四步说明照做即可(第五步不用管,只做前四步获取你的企业ID、应用ID、应用secret)。 60 | 61 | 最后Actions secrets效果: 62 | 63 |
64 | 65 |
66 | 67 | 6. 点击上方**Actions**按钮: 68 | 69 | 70 | 71 | 点击左侧的**BUPT ncov auto-report Python**,再点击右侧的**Run workflow**,如下图所示: 72 | 73 |
74 | 75 |
76 | 77 | 点击这个workflow(没看到的话请刷新一下),然后再次点进去jobs查看执行情况 78 | 79 |
80 | 81 |
82 | 83 | 7. 如果准确按照上述步骤执行,你应该会看到类似的如下输出: 84 | 85 |
86 | 87 |
88 | 89 | 90 | **恭喜你,你还有你的小伙伴不用为被催打卡而烦恼了~** 91 | 92 | 93 | ## 参数更改: 94 | ### 更改每日打卡时间 95 | 在 .github/workflows/main.yml 中来设置每天运行的时间: 96 | ```python 97 | on: 98 | schedule: 99 | - cron: "*/30 */4 * * *" 100 | ``` 101 | cron里的"*/30 */4 * * *"代表 At every 30th minute past every 4th hour ,注意github服务器时间是UTC,北京时间是UTC +8 ,所以如果要自己改时间打卡,请注意打卡时间写提前8小时(例如北京时间12点,写成4点) 102 | [https://crontab.guru/#/30_*/4_*_*_*](https://crontab.guru/#/30_*/4_*_*_*) 用这个网站来选取你想要的时间 103 | ### 更改每日填报的固定数据 104 | 在 [https://app.bupt.edu.cn/ncov/wap/default/index](https://app.bupt.edu.cn/ncov/wap/default/index) 进行填报,全部填完后最后不要提交,f12打开控制台,在Console页面下输入代码vm.info回车得到填报数据,替换掉 constant.py 里的INFO变量 105 | ### 更改晨午晚填报的固定数据 106 | 直接打开 [https://app.bupt.edu.cn/xisuncov/wap/open-report/index](https://app.bupt.edu.cn/xisuncov/wap/open-report/index) ,根据显示数据修改 constant.py 里的INFO_E变量 107 | 108 | 109 | ## Credit 110 | 项目修改自 [zzp-seeker/bupt-ncov-report-action](https://github.com/zzp-seeker/bupt-ncov-auto-report), 十分感谢! 111 | 112 | ## License 113 | MIT © [RunpuWei](https://github.com/RunpuWei) 114 | 115 | ### 好用的话别忘了:star:哦 :wink: 116 | 117 | 118 | -------------------------------------------------------------------------------- /constant.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | from typing import Optional 3 | import os 4 | 5 | 6 | """ 7 | USERS=[("学号","密码","姓名/昵称",0)] 8 | WECOM=("企业ID③", "应用ID①", "应用secret②") 9 | """ 10 | USERS = eval(os.environ['USERS']) 11 | WECOM = eval(os.environ['WECOM']) 12 | 13 | LOGIN_API = 'https://auth.bupt.edu.cn/authserver/login' 14 | GET_API = 'https://app.bupt.edu.cn/ncov/wap/default/index' 15 | REPORT_API = 'https://app.bupt.edu.cn/ncov/wap/default/save' 16 | # 重要: CAS认证的跳转地址记录 17 | SERVICE = 'https://app.bupt.edu.cn/a_bupt/api/sso/cas?redirect=https%3A%2F%2Fapp.bupt.edu.cn%2Fncov%2Fwap%2Fdefault%2Findex&from=wap' 18 | # 模拟浏览器信息 19 | USER_AGENT = 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0' 20 | # Execution信息的xpath 21 | EXECUTION_XPATH = '/html/body/div[1]/div/form/div[5]/input[2]/@value' 22 | GETEven_API = 'https://app.bupt.edu.cn/xisuncov/wap/open-report/index' 23 | POSTEven_API = 'https://app.bupt.edu.cn/xisuncov/wap/open-report/save' 24 | 25 | 26 | # 当今日没有填报时,在https://app.bupt.edu.cn/ncov/wap/default/index下进行填报, 27 | # 全部填完,不要提交,f12打开控制台,在Console页面下输入代码 console.log(vm.info) 就会得到以下信息,之后每天就默认填以下信息 28 | INFO = r"""{ 29 | "address":"北京市海淀区北太平庄街道北京邮电大学计算机学院北京邮电大学海淀校区", 30 | "area":"北京市 海淀区", 31 | "bztcyy":"", 32 | "city":"北京市", 33 | "csmjry":"0", 34 | "fjqszgjdq":"", 35 | "geo_api_info":"{\"type\":\"complete\",\"position\":{\"Q\":39.960390625,\"R\":116.356397569445,\"lng\":116.356398,\"lat\":39.960391},\"location_type\":\"html5\",\"message\":\"Get ipLocation failed.Get geolocation success.Convert Success.Get address success.\",\"accuracy\":23,\"isConverted\":true,\"status\":1,\"addressComponent\":{\"citycode\":\"010\",\"adcode\":\"110108\",\"businessAreas\":[{\"name\":\"北下关\",\"id\":\"110108\",\"location\":{\"Q\":39.955976,\"R\":116.33873,\"lng\":116.33873,\"lat\":39.955976}},{\"name\":\"西直门\",\"id\":\"110102\",\"location\":{\"Q\":39.942856,\"R\":116.34666099999998,\"lng\":116.346661,\"lat\":39.942856}},{\"name\":\"小西天\",\"id\":\"110108\",\"location\":{\"Q\":39.957147,\"R\":116.364058,\"lng\":116.364058,\"lat\":39.957147}}],\"neighborhoodType\":\"科教文化服务;学校;高等院校\",\"neighborhood\":\"北京邮电大学\",\"building\":\"北京邮电大学计算机学院\",\"buildingType\":\"科教文化服务;学校;高等院校\",\"street\":\"西土城路\",\"streetNumber\":\"10号\",\"country\":\"中国\",\"province\":\"北京市\",\"city\":\"\",\"district\":\"海淀区\",\"township\":\"北太平庄街道\"},\"formattedAddress\":\"北京市海淀区北太平庄街道北京邮电大学计算机学院北京邮电大学海淀校区\",\"roads\":[],\"crosses\":[],\"pois\":[],\"info\":\"SUCCESS\"}", 36 | "glksrq":"", 37 | "gllx":"", 38 | "gtjzzchdfh":"", 39 | "gtjzzfjsj":"", 40 | "ismoved":"0", 41 | "jcbhlx":"", 42 | "jcbhrq":"", 43 | "jchbryfs":"", 44 | "jcjgqr":"0", 45 | "jcwhryfs":"", 46 | "jhfjhbcc":"", 47 | "jhfjjtgj":"", 48 | "jhfjrq":"", 49 | "mjry":"0", 50 | "province":"北京市", 51 | "qksm":"", 52 | "remark":"", 53 | "sfcxtz":"0", 54 | "sfcxzysx":"0", 55 | "sfcyglq":"0", 56 | "sfjcbh":"0", 57 | "sfjchbry":"0", 58 | "sfjcwhry":"0", 59 | "sfjzdezxgym":"1", 60 | "sfjzxgym":"1", 61 | "sfsfbh":"0", 62 | "sftjhb":"0", 63 | "sftjwh":"0", 64 | "sfxk":"0", 65 | "sfygtjzzfj":"", 66 | "sfyyjc":"0", 67 | "sfzx":1, 68 | "szcs":"", 69 | "szgj":"", 70 | "szsqsfybl":"0", 71 | "tw":"2", 72 | "xjzd":"", 73 | "xkqq":"", 74 | "xwxgymjzqk":"3", 75 | "ymjzxgqk":"已接种", 76 | "zgfxdq":"0" 77 | }""" 78 | 79 | INFO_E = r"""{ 80 | "sfzx": "0", 81 | "tw":"1", 82 | "area":"北京市 海淀区", 83 | "city":"北京市", 84 | "province":"北京市", 85 | "address":"北京市海淀区北太平庄街道北京邮电大学计算机学院北京邮电大学海淀校区", 86 | "geo_api_info": "{\"type\":\"complete\",\"info\":\"SUCCESS\",\"status\":1,\"fEa\":\"jsonp_940261_\",\"position\":{\"Q\":39.960,\"R\":116.35640,\"lng\":116.356340,\"lat\":39.960},\"message\":\"Get geolocation time out.Get ipLocation success.Get address success.\",\"location_type\":\"ip\",\"accuracy\":null,\"isConverted\":true,\"addressComponent\":{\"citycode\":\"010\",\"adcode\":\"100876\",\"businessAreas\":[],\"neighborhoodType\":\"科教文化服务;学校;高等院校\",\"neighborhood\":\"北京邮电大学\",\"building\":\"北京邮电大学计算机学院\",\"buildingType\":\"科教文化服务;学校;高等院校\",\"street\":\"西土城路\",\"streetNumber\":\"10号\",\"country\":\"中国\",\"province\":\"北京市\",\"city\":\"\",\"district\":\"海淀区\",\"towncode\":\"\",\"township\":\"北太平庄街道\"},\"formattedAddress\":\"北京市海淀区北太平庄街道北京邮电大学计算机学院北京邮电大学海淀校区\",\"roads\":[],\"crosses\":[],\"pois\":[]}", 87 | "sfcyglq": "0", 88 | "sfyzz": "0","qtqk": "","askforleave": "0" 89 | }""" 90 | 91 | 92 | REASONABLE_LENGTH = 24 93 | TIMEOUT_SECOND = 25 94 | 95 | 96 | class HEADERS: 97 | REFERER_LOGIN_API = 'https://app.bupt.edu.cn/uc/wap/login' 98 | REFERER_POST_API = 'https://app.bupt.edu.cn/ncov/wap/default/index' 99 | ORIGIN_BUPTAPP = 'https://app.bupt.edu.cn' 100 | 101 | UA = ('Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) ' 102 | 'Mobile/15E148 MicroMessenger/7.0.11(0x17000b21) NetType/4G Language/zh_CN') 103 | ACCEPT_JSON = 'application/json' 104 | ACCEPT_HTML = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' 105 | REQUEST_WITH_XHR = 'XMLHttpRequest' 106 | ACCEPT_LANG = 'zh-cn' 107 | CONTENT_TYPE_UTF8 = 'application/x-www-form-urlencoded; charset=UTF-8' 108 | 109 | def __init__(self) -> None: 110 | raise NotImplementedError 111 | 112 | 113 | COMMON_HEADERS = { 114 | 'User-Agent': HEADERS.UA, 115 | 'Accept-Language': HEADERS.ACCEPT_LANG, 116 | } 117 | COMMON_POST_HEADERS = { 118 | 'Accept': HEADERS.ACCEPT_JSON, 119 | 'Origin': HEADERS.ORIGIN_BUPTAPP, 120 | 'X-Requested-With': HEADERS.REQUEST_WITH_XHR, 121 | 'Content-Type': HEADERS.CONTENT_TYPE_UTF8, 122 | } -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from constant import * 2 | from Wecom import * 3 | 4 | import requests, re, json, copy, traceback 5 | from lxml import etree 6 | 7 | 8 | def ncov_report(data, headers, is_useold): 9 | print('登录北邮 nCoV 上报网站') 10 | login_res = session.post( 11 | url=LOGIN_API, headers=headers, data=data 12 | ) 13 | 14 | if login_res.status_code != 200: 15 | raise RuntimeError('login_res 状态码不是 200') 16 | 17 | get_res = session.get( 18 | GET_API, 19 | headers={**COMMON_HEADERS, 'Accept': HEADERS.ACCEPT_HTML}, 20 | ) 21 | if get_res.status_code != 200: 22 | raise RuntimeError('get_res 状态码不是 200') 23 | try: 24 | old_data = json.loads('{' + re.search(r'(?<=oldInfo: {).+(?=})', get_res.text)[0] + '}') 25 | except: 26 | raise RuntimeError('未获取到昨日打卡数据,请今日手动打卡明日再执行脚本或使用固定打卡数据') 27 | 28 | post_data = json.loads(copy.deepcopy(INFO).replace("\n", "").replace(" ", "")) 29 | if is_useold: 30 | try: 31 | for k, v in old_data.items(): 32 | if k in post_data: 33 | post_data[k] = v 34 | geo = json.loads(old_data['geo_api_info']) 35 | 36 | province = geo['addressComponent']['province'] 37 | city = geo['addressComponent']['city'] 38 | if geo['addressComponent']['city'].strip() == "" and len(re.findall(r'北京市|上海市|重庆市|天津市', province)) != 0: 39 | city = geo['addressComponent']['province'] 40 | area = province + " " + city + " " + geo['addressComponent']['district'] 41 | address = geo['formattedAddress'] 42 | post_data['province'] = province 43 | post_data['city'] = city 44 | post_data['area'] = area 45 | post_data['address'] = address 46 | 47 | # 强行覆盖一些字段 48 | post_data['ismoved'] = 0 # 是否移动了位置?否 49 | post_data['bztcyy'] = '' # 不在同城原因?空 50 | post_data['sfsfbh'] = 0 # 是否省份不合?否 51 | except: 52 | print("加载昨日数据错误,采用固定数据") 53 | post_data = json.loads(copy.deepcopy(INFO).replace("\n", "").replace(" ", "")) 54 | report_res = session.post( 55 | REPORT_API, 56 | data=post_data, 57 | headers=headers, 58 | ) 59 | if report_res.status_code != 200: 60 | raise RuntimeError('report_res 状态码不是 200') 61 | return post_data,report_res.text 62 | 63 | def ncov_even_report(data,headers, is_useold): 64 | print('登录北邮 nCoV 上报网站') 65 | login_res = session.post( 66 | url=LOGIN_API, headers=headers, data=data 67 | ) 68 | 69 | if login_res.status_code != 200: 70 | raise RuntimeError('login_res 状态码不是 200') 71 | 72 | get_res = session.get( 73 | GET_API, 74 | headers={**COMMON_HEADERS, 'Accept': HEADERS.ACCEPT_HTML}, 75 | ) 76 | if get_res.status_code != 200: 77 | raise RuntimeError('get_res 状态码不是 200') 78 | try: 79 | old_data = json.loads('{' + re.search(r'(?<=oldInfo: {).+(?=})', get_res.text)[0] + '}') 80 | except: 81 | raise RuntimeError('未获取到昨日打卡数据,请今日手动打卡明日再执行脚本或使用固定打卡数据') 82 | 83 | get_res = session.get( 84 | GETEven_API, 85 | headers={**COMMON_HEADERS, 'Accept': HEADERS.ACCEPT_HTML}, 86 | ) 87 | if get_res.status_code != 200: 88 | raise RuntimeError('get_res 状态码不是 200') 89 | 90 | post_data = json.loads(copy.deepcopy(INFO_E)) 91 | if is_useold: 92 | try: 93 | for k, v in old_data.items(): 94 | if k in post_data: 95 | post_data[k] = v 96 | geo = old_data 97 | info=geo['geo_api_info'] 98 | geo=json.loads(info) 99 | 100 | province = geo['addressComponent']['province'] 101 | city = geo['addressComponent']['city'] 102 | district=geo['addressComponent']['district'] 103 | if geo['addressComponent']['city'].strip() == "" and len(re.findall(r'北京市|上海市|重庆市|天津市', province)) != 0: 104 | city = geo['addressComponent']['province'] 105 | 106 | #area = province + " " + city + " " + geo['addressComponent']['district'] 107 | area = province+city+district 108 | address = geo['formattedAddress'] 109 | post_data['geo_api_info']=info 110 | post_data['province'] = province 111 | post_data['city'] = city 112 | post_data['area'] = area 113 | post_data['address'] = address 114 | 115 | 116 | # 强行覆盖一些字段 117 | except: 118 | print("加载上次晨午晚检数据错误,采用固定数据") 119 | post_data = json.loads(copy.deepcopy(INFO_E).replace("\n", "").replace(" ", "")) 120 | report_res = session.post( 121 | POSTEven_API, 122 | data=post_data, 123 | headers=headers, 124 | ) 125 | if report_res.status_code != 200: 126 | raise RuntimeError('report_res 状态码不是 200') 127 | return post_data,report_res.text 128 | 129 | successs,ress,usernames,names,datas = [],[],[],[],[] 130 | for user in USERS: 131 | # 设置连接 132 | session = requests.Session() 133 | wecom_cid,wecom_aid,wecom_secret=WECOM 134 | 135 | # 发送请求,设置cookies 136 | headers = { "User-Agent": USER_AGENT} 137 | params = { "service": SERVICE } 138 | responce = session.get(url=LOGIN_API, headers=headers, params=params) 139 | 140 | # 获取execution 141 | html = etree.HTML(responce.content) 142 | execution = html.xpath(EXECUTION_XPATH)[0] 143 | 144 | username,password,name,useold=user 145 | # 构造表单数据 146 | data = { 147 | 'username': username, 148 | 'password': password, 149 | 'submit': "登录", 150 | 'type': 'username_password', 151 | 'execution': execution, 152 | '_eventId': "submit" 153 | } 154 | 155 | success=True 156 | try: 157 | data,res = ncov_report(data,headers,is_useold=(useold==0)) 158 | data_even,res_even = ncov_even_report(data,headers,is_useold=(useold==0)) 159 | except: 160 | success = False 161 | data,res = '',traceback.format_exc() 162 | 163 | msg1=f' {datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")} {name}《每日填报》填报成功!服务器返回数据:\n{res}\n\n每日填报填报数据:\n{data}\n' if success else f'{name}《每日填报》填报失败!发生如下异常:\n{res}' 164 | print(msg1) 165 | send_to_wecom(msg1,wecom_cid, wecom_aid, wecom_secret) 166 | 167 | msg2=f' {datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")} {name}《晨午晚检》填报成功!服务器返回数据:\n{res_even}\n\n晨午晚检填报数据:\n{data_even}\n' if success else f'{name}《晨午晚检》填报失败!发生如下异常:\n{res}' 168 | print(msg2) 169 | send_to_wecom(msg2,wecom_cid, wecom_aid, wecom_secret) --------------------------------------------------------------------------------