├── img ├── baidu │ ├── 1领取资源.jpg │ ├── 2确认领取.jpg │ ├── 3创建应用.jpg │ ├── 5创建完成.jpg │ ├── 4填写应用信息.jpg │ └── 6Key复制.jpg └── actions │ ├── 5最终结果.jpg │ ├── 8查看日志.jpg │ ├── 2确认fork.jpg │ ├── 7点击build.jpg │ ├── 1点击fork按钮.jpg │ ├── 3settings界面.jpg │ ├── 4secrets界面.jpg │ └── 6查看workflow.jpg ├── requirements.txt ├── Dockerfile ├── timer.py ├── Dockerfile_arm ├── .github └── workflows │ ├── build_docker_image.yml │ └── jksb_schedule.yml ├── parameter.py ├── readme.md ├── jksb.py └── utils.py /img/baidu/1领取资源.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yann-zhou/zzu_auto_jksb/HEAD/img/baidu/1领取资源.jpg -------------------------------------------------------------------------------- /img/baidu/2确认领取.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yann-zhou/zzu_auto_jksb/HEAD/img/baidu/2确认领取.jpg -------------------------------------------------------------------------------- /img/baidu/3创建应用.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yann-zhou/zzu_auto_jksb/HEAD/img/baidu/3创建应用.jpg -------------------------------------------------------------------------------- /img/baidu/5创建完成.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yann-zhou/zzu_auto_jksb/HEAD/img/baidu/5创建完成.jpg -------------------------------------------------------------------------------- /img/actions/5最终结果.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yann-zhou/zzu_auto_jksb/HEAD/img/actions/5最终结果.jpg -------------------------------------------------------------------------------- /img/actions/8查看日志.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yann-zhou/zzu_auto_jksb/HEAD/img/actions/8查看日志.jpg -------------------------------------------------------------------------------- /img/baidu/4填写应用信息.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yann-zhou/zzu_auto_jksb/HEAD/img/baidu/4填写应用信息.jpg -------------------------------------------------------------------------------- /img/baidu/6Key复制.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yann-zhou/zzu_auto_jksb/HEAD/img/baidu/6Key复制.jpg -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | APScheduler==3.7.0 2 | requests~=2.27.1 3 | urllib3~=1.26.9 4 | # Pillow==9.2.0 5 | -------------------------------------------------------------------------------- /img/actions/2确认fork.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yann-zhou/zzu_auto_jksb/HEAD/img/actions/2确认fork.jpg -------------------------------------------------------------------------------- /img/actions/7点击build.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yann-zhou/zzu_auto_jksb/HEAD/img/actions/7点击build.jpg -------------------------------------------------------------------------------- /img/actions/1点击fork按钮.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yann-zhou/zzu_auto_jksb/HEAD/img/actions/1点击fork按钮.jpg -------------------------------------------------------------------------------- /img/actions/3settings界面.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yann-zhou/zzu_auto_jksb/HEAD/img/actions/3settings界面.jpg -------------------------------------------------------------------------------- /img/actions/4secrets界面.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yann-zhou/zzu_auto_jksb/HEAD/img/actions/4secrets界面.jpg -------------------------------------------------------------------------------- /img/actions/6查看workflow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yann-zhou/zzu_auto_jksb/HEAD/img/actions/6查看workflow.jpg -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # python版本,可根据需求进行修改 2 | FROM python:3.8-alpine3.15 3 | RUN mkdir /code 4 | # 将python程序添加到镜像 5 | ADD ./*.py /code/ 6 | # 将项目依赖添加到镜像 7 | ADD requirements.txt /code/ 8 | WORKDIR /code 9 | RUN pip install -i https://mirrors.aliyun.com/pypi/simple/ -U pip && \ 10 | pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ && \ 11 | pip install -r requirements.txt 12 | # 设置该项以忽略证书错误(alpine镜像内不存在该文件,暂时舍弃该命令) 13 | # RUN sed -i -E 's/MinProtocol[=\ ]+.*/MinProtocol = TLSv1.0/g' /etc/ssl/openssl.cnf 14 | 15 | # 调整时间 16 | ENV TZ=Asia/Shanghai \ 17 | DEBIAN_FRONTEND=noninteractive 18 | 19 | # 镜像运行时执行的命令,这里的配置等于运行 python timer.py 20 | ENTRYPOINT ["python","timer.py"] -------------------------------------------------------------------------------- /timer.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import time 3 | from apscheduler.schedulers.blocking import BlockingScheduler 4 | from parameter import jksb_timer, logger_level 5 | import jksb 6 | import logging 7 | 8 | logging.basicConfig(level=logger_level, format='%(asctime)s - %(name)s - [%(levelname)s] - %(message)s') 9 | logger = logging.getLogger('jksb_timer') 10 | 11 | 12 | def run_jksb(): 13 | jksb.run() 14 | 15 | 16 | if __name__ == '__main__': 17 | schedular = BlockingScheduler() 18 | time_list = eval(jksb_timer) 19 | for idt, t in enumerate(time_list): 20 | schedular.add_job(run_jksb, "cron", hour=t[0], minute=t[1], jitter=t[2]) 21 | logger.info("已添加第"+str(idt+1)+"个计划任务,预计在"+str(t[0])+"时"+str(t[1])+"分打卡,随机偏移量为"+str(t[2])+"秒") 22 | schedular.start() 23 | -------------------------------------------------------------------------------- /Dockerfile_arm: -------------------------------------------------------------------------------- 1 | # python版本,可根据需求进行修改 2 | FROM python:3.8-alpine3.15 3 | RUN mkdir /code 4 | # 将python程序添加到镜像 5 | ADD ./*.py /code/ 6 | # 将项目依赖添加到镜像 7 | ADD requirements.txt /code/ 8 | WORKDIR /code 9 | RUN apk --update add libxml2-dev libxslt-dev libffi-dev gcc musl-dev libgcc openssl-dev curl && \ 10 | apk add jpeg-dev zlib-dev freetype-dev lcms2-dev openjpeg-dev tiff-dev tk-dev tcl-dev 11 | RUN pip install -i https://mirrors.aliyun.com/pypi/simple/ -U pip && \ 12 | pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ && \ 13 | pip install -r requirements.txt 14 | # 设置该项以忽略证书错误(alpine镜像内不存在该文件,暂时舍弃该命令) 15 | # RUN sed -i -E 's/MinProtocol[=\ ]+.*/MinProtocol = TLSv1.0/g' /etc/ssl/openssl.cnf 16 | 17 | # 调整时间 18 | ENV TZ=Asia/Shanghai \ 19 | DEBIAN_FRONTEND=noninteractive 20 | 21 | # 镜像运行时执行的命令,这里的配置等于运行 python timer.py 22 | ENTRYPOINT ["python","timer.py"] -------------------------------------------------------------------------------- /.github/workflows/build_docker_image.yml: -------------------------------------------------------------------------------- 1 | name: Build Docker Image 2 | on: 3 | push: 4 | branches: 5 | - master 6 | 7 | env: 8 | APP_NAME: zzu_auto_jksb 9 | DOCKERHUB_REPO: yannzhou/zzu_auto_jksb 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v2 17 | - name: Set up QEMU 18 | uses: docker/setup-qemu-action@v1 19 | - name: Set up Docker Buildx 20 | uses: docker/setup-buildx-action@v1 21 | - name: Login to DockerHub 22 | uses: docker/login-action@v1 23 | with: 24 | username: ${{ secrets.DOCKERHUB_USERNAME }} 25 | password: ${{ secrets.DOCKERHUB_TOKEN }} 26 | - name: Build and push amd64/arm64 Docker Image 27 | id: docker_build 28 | uses: docker/build-push-action@v2 29 | with: 30 | push: true 31 | platforms: | 32 | linux/amd64 33 | linux/arm64/v8 34 | build-args: | 35 | APP_NAME=${{ env.APP_NAME }} 36 | APP_VERSION=${{ env.APP_VERSION }} 37 | tags: | 38 | ${{ env.DOCKERHUB_REPO }}:latest 39 | # - name: Build and push arm64 Docker image 40 | # run: docker buildx build --file ./Dockerfile_arm --platform linux/arm64/v8 -t yannzhou/zzu_auto_jksb:arm64 . --push -------------------------------------------------------------------------------- /.github/workflows/jksb_schedule.yml: -------------------------------------------------------------------------------- 1 | name: Start jksb 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: '05 16,17,23 * * *' 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2 13 | - name: Set up Python 3.8 14 | uses: actions/setup-python@v2 15 | with: 16 | python-version: 3.8 17 | - name: Install dependencies 18 | run: | 19 | python -m pip install --upgrade pip 20 | if [ -f requirements.txt ]; then pip install -r requirements.txt; fi 21 | - name: Start zzu_auto_jksb 22 | env: 23 | jksb_username: ${{ secrets.jksb_username }} 24 | jksb_password: ${{ secrets.jksb_password }} 25 | jksb_code_province: ${{ secrets.jksb_code_province }} 26 | jksb_code_city: ${{ secrets.jksb_code_city }} 27 | jksb_location: ${{ secrets.jksb_location }} 28 | jksb_vaccine: ${{ secrets.jksb_vaccine }} 29 | jksb_jingdu: ${{ secrets.jksb_jingdu }} 30 | jksb_weidu: ${{ secrets.jksb_weidu }} 31 | jksb_send_type: ${{ secrets.jksb_send_type }} 32 | jksb_send_parameter: ${{ secrets.jksb_send_parameter }} 33 | jksb_baidu_API_Key: ${{ secrets.jksb_baidu_API_Key }} 34 | jksb_baidu_Secret_Key: ${{ secrets.jksb_baidu_Secret_Key }} 35 | jksb_zhb_parameter: ${{ secrets.jksb_zhb_parameter }} 36 | run: | 37 | python jksb.py -------------------------------------------------------------------------------- /parameter.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import os 3 | 4 | # 获取需要的各个参数 5 | username = os.getenv('jksb_username') 6 | password = os.getenv('jksb_password') 7 | code_province = os.getenv('jksb_code_province') 8 | code_city = os.getenv('jksb_code_city') 9 | location = os.getenv('jksb_location') 10 | vaccine = os.getenv('jksb_vaccine') 11 | jingdu = os.getenv('jksb_jingdu') 12 | weidu = os.getenv('jksb_weidu') 13 | send_type = os.getenv('jksb_send_type') # send_type可选bark,serverchan,email 14 | send_parameter = os.getenv('jksb_send_parameter') # send_type为email时,send_parameter应为json字符串,格式为:{"host": "smtp服务器地址", "user": "邮箱登录名", "password": "邮箱密码", "receiver": "接收邮件的邮箱"} 15 | zhb_parameter = os.getenv('jksb_zhb_parameter') 16 | logger_level = os.getenv('jksb_logger_level') 17 | jksb_timer = os.getenv('jksb_timer') 18 | # baidu_API_Key = os.getenv("jksb_baidu_API_Key") 19 | # baidu_Secret_Key = os.getenv("jksb_baidu_Secret_Key") 20 | 21 | # 检查参数是否都有值 22 | if username is None: 23 | raise Exception("参数jksb_username无值") 24 | if password is None: 25 | raise Exception("参数jksb_password无值") 26 | if code_province is None: 27 | raise Exception("参数jksb_code_province无值") 28 | if code_city is None: 29 | raise Exception("参数jksb_code_city无值") 30 | if location is None: 31 | raise Exception("参数jksb_location无值") 32 | if vaccine is None: 33 | raise Exception("参数jksb_vaccine无值") 34 | if jingdu is None: 35 | raise Exception("参数jksb_jingdu无值") 36 | if weidu is None: 37 | raise Exception("参数jksb_weidu无值") 38 | if send_type is None: 39 | raise Exception("参数jksb_send_type无值") 40 | if send_parameter is None: 41 | raise Exception("参数jksb_send_parameter无值") 42 | # if baidu_API_Key is None: 43 | # raise Exception("参数jksb_baidu_API_Key无值") 44 | # if baidu_Secret_Key is None: 45 | # raise Exception("参数jksb_baidu_Secret_Key无值") 46 | 47 | # 设置日志等级 48 | if logger_level == 'DEBUG': 49 | logger_level = logging.DEBUG 50 | elif logger_level == 'WARNING': 51 | logger_level = logging.WARNING 52 | elif logger_level == 'ERROR': 53 | logger_level = logging.ERROR 54 | elif logger_level == 'INFO': 55 | logger_level = logging.CRITICAL 56 | else: 57 | logger_level = logging.INFO 58 | 59 | 60 | url_login = 'https://jksb.v.zzu.edu.cn/vls6sss/zzujksb.dll/login' 61 | header = { 62 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 Safari/537.36', 63 | 'Content-Type': 'application/x-www-form-urlencoded', 64 | } 65 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | --- 2 | ### 由于国家政策的调整以及学校相关措施的落实,现在学校已不进行每日打卡,该项目从2022年12月25日起停止更新,希望大家做好防护,祝大家有一个健康强健的身体,有缘再见! 3 | 4 | --- 5 | 6 | # ZZU_auto_jksb 7 | 8 | [![Build Docker Image](https://github.com/Yann-zhou/zzu_auto_jksb/actions/workflows/build_docker_image.yml/badge.svg)](https://github.com/Yann-zhou/zzu_auto_jksb/actions/workflows/build_docker_image.yml) 9 | ![watchers](https://img.shields.io/github/watchers/Yann-zhou/zzu_auto_jksb) 10 | ![forks](https://img.shields.io/github/forks/Yann-zhou/zzu_auto_jksb) 11 | ![stars](https://img.shields.io/github/stars/Yann-zhou/zzu_auto_jksb) 12 | 13 | ## 一、项目简介 14 | 15 | 该项目可以帮助你自动进行每日健康上报,项目使用python作为后台,只需简单配置即可自动运行,已添加docker与GitHub Actions支持 16 | 如果有可以长时间开机的服务器或者可以使用docker的软路由或树莓派,**强烈建议**您使用docker模式进行打卡,学校后台会记录打卡机器的IP地址,如果使用GitHub Actions的话,IP地址会显示在国外,使用docker就不会有这个问题了。 17 | 18 | **如果觉得本项目不错的话,请watch本项目及时获取更新** 19 | 20 | --- 21 | ### 更新日志 22 | 23 | - 2022.12.25 停止项目的所有功能 24 | - 2022.11.27 更新打卡系统参数名称 25 | - 2022.09.09 打卡系统删除了验证码 26 | - 2022.09.07 打卡系统验证码变更为了手写汉字,增加对应的手写汉字识别功能 27 | - 2022.09.06 打卡系统添加汉语验证码,添加汉语大写数字识别功能 28 | - 2022.09.04 打卡系统添加了验证码,使用百度云API进行在线识别,[百度云API获取教程](#2) 29 | 30 | --- 31 | 32 | ## 二、使用方法 33 | ### 1. 直接调用原始文件 34 | (1) 将以下值加入系统环境变量 35 | ``` 36 | jksb_username 健康上报系统中的用户名 37 | jksb_password 健康上报系统中的密码 38 | jksb_code_province 当前所在省份代码(河南为41) 39 | jksb_code_city 当前所在城市代码(郑州为4101) 40 | jksb_location 当前所在地详细地址 41 | jksb_vaccine 疫苗接种情况 42 | jksb_jingdu 当前所在地经度 43 | jksb_weidu 当前所在地纬度 44 | jksb_send_type 后续通知方法类型(可选bark,serverchan,email) 45 | jksb_send_parameter 根据send_type进行选择, 46 | send_type为bark时,该项为推送URL, 47 | send_type为serverchan时,该项为SCT开头的sendkey 48 | send_type为email时,该项格式为:{"host": "smtp服务器地址", "user": "邮箱登录名", "password": "邮箱密码", "receiver": "接收邮件的邮箱"} 49 | jksb_baidu_API_Key (已废弃,不要使用该参数)百度手写文字识别APIKey 50 | jksb_baidu_Secret_Key (已废弃,不要使用该参数)百度手写文字识别SecretKey 51 | jksb_zhb_parameter (已废弃,不要使用该参数)郑好办核酸检测查询抓包内容,留空则默认将“昨天是否进行过核酸检测”项填写为“做了” 52 | jksb_logger_level (可选)日志等级 53 | ``` 54 | 参数填写规则请参考[参数填写详细规则](#1) 55 | 56 | (2) 调用jksb.py中的run方法即可运行 57 | 58 | ### 2. 使用docker容器 59 | 本项目已构建完成amd64与适用于树莓派4B的armv8架构的docker镜像,使用以下命令可以启动docker容器 60 | 61 | 参数填写规则请参考[参数填写详细规则](#1) 62 | ```bash 63 | docker run -d -e jksb_username=学号 \ 64 | -e jksb_password=密码 \ 65 | -e jksb_code_province=省份代码 \ 66 | -e jksb_code_city=城市代码 \ 67 | -e jksb_location=位置信息 \ 68 | -e jksb_vaccine=疫苗情况 \ 69 | -e jksb_jingdu=所在地经度 \ 70 | -e jksb_weidu=所在地纬度 \ 71 | -e jksb_send_type=通知类型 \ 72 | -e jksb_send_parameter=通知参数 \ 73 | -e jksb_timer=运行时间 \ 74 | --restart always \ 75 | yannzhou/zzu_auto_jksb:latest 76 | ``` 77 | 如您想自己构建docker镜像: 78 | 79 | 本仓库内已集成dockerfile,在仓库根目录执行以下命令即可自动构建docker镜像 80 | ```bash 81 | docker build -t 镜像名:版本号 . 82 | ``` 83 | > 注意命令最后有一个点 84 | 85 | 构建完成后,按照“直接调用原始文件”部分提到的参数列表在docker的运行命令内或yaml文件内加入相应的环境变量即可 86 | 87 | ### 3. 使用GitHub Actions 88 | 本仓库内已集成GitHub Actions配置文件,您只需Fork本仓库后配置以下Secrets即可在每日0点5分、1点5分、7点5分进行自动打卡 89 | 90 | 参数填写规则请参考[参数填写详细规则](#1) 91 | ``` 92 | jksb_username: 学号 93 | jksb_password: 密码 94 | jksb_code_province: 省份代码 95 | jksb_code_city: 城市代码 96 | jksb_location: 具体地址 97 | jksb_vaccine: 疫苗情况 98 | jksb_jingdu: 经度 99 | jksb_weidu: 纬度 100 | jksb_send_type: 通知类型 101 | jksb_send_parameter: 通知参数 102 | jksb_baidu_API_Key: (已废弃,不要使用该参数)百度手写文字识别APIKey 103 | jksb_baidu_Secret_Key: (已废弃,不要使用该参数)百度手写文字识别SecretKey 104 | zhb_parameter: (已废弃,不要使用该参数)郑好办查询参数 105 | ``` 106 | --- 107 | 108 | #### GitHub Actions配置教程 109 | 1. 首先fork本项目 110 | ![点击fork按钮](img/actions/1点击fork按钮.jpg "点击fork按钮") 111 | 2. 确认fork操作 112 | ![确认fork操作](img/actions/2确认fork.jpg "确认fork操作") 113 | 3. 添加secret 114 | ![添加secret](img/actions/3settings界面.jpg "添加secret") 115 | 4. 重复执行该步骤直到所有变量均已添加 116 | ![确认添加secret](img/actions/4secrets界面.jpg "确认添加secret") 117 | 5. 最终添加后的结果 118 | ![最后结果](img/actions/5最终结果.jpg "最后结果") 119 | 120 | #### 查看GitHub Actions日志 121 | 1. 打开Actions页面 122 | ![打开Actions页面](img/actions/6查看workflow.jpg "打开Actions页面") 123 | 2. 打开具体的job 124 | ![打开job](img/actions/7点击build.jpg "打开job") 125 | 3. 打开详细日志 126 | ![打开详细日志](img/actions/8查看日志.jpg "打开详细日志") 127 | 128 | --- 129 | 130 |
131 | 132 | ## 参数填写详细规则 133 | - jksb_username: 学号 134 | - jksb_password: 密码 135 | - jksb_code_province:所在地身份证号编码的前两位 136 | - jksb_code_city:所在地身份证号编码的前四位 137 | (例如人在河南郑州就是jksb_code_province=41,jksb_code_city=4101) 138 | - jksb_location:填写实际地址 139 | - jksb_vaccine:按照以下情况填写数字1~5 140 | (1: 接种一针,2: 接种两针,3:尚未接种,4:有禁忌症无法接种,5:接种三针) 141 | - jksb_jingdu与jksb_weidu:在这个网站中拾取经纬度后填入即可:https://jingweidu.bmcx.com/ 142 | - jksb_send_type:共有三种:{email, serverchan, bark},配置该参数的目的是在打卡完成后给您发送通知,请尽量使用serverchan方式进行通知,出错概率较低。 143 | - jksb_send_parameter:与上一项搭配使用。 144 | send_type为bark时,该项为推送URL, 145 | send_type为serverchan时,该项为SCT开头的sendkey 146 | send_type为email时,该项格式为:{"host": "smtp服务器地址", "user": "邮箱登录名", "password": "邮箱授权码", "receiver": "接收邮件的邮箱"} 147 | *例如当您使用sereverchan模式时,jksb_send_type=serverchan, jksb_send_parameter=SCTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx* 148 | *当您使用email模式时,jksb_send_type=email, jksb_send_parameter={"host": "smtp.163.com", "user": "example@163.com, "password": "yourIdentifyCode", "receiver": "example@163.com"}* 149 | - ~~zhb_parameter相关参数:默认情况下,脚本会将核酸检测情况填写为“做了”,如您想自动采集核酸检测信息,请使用fiddler抓取您使用手机扫描任一场所码时对URL `https://unified-area-code-n-service.jianguan.henan.gov.cn/nucleicapi/nucvac/info` 发送的请求中"param"项的参数填到此处即可。~~ 150 | - ~~jksb_baidu_API_Key:百度手写文字识别APIKey~~ 151 | ~~jksb_baidu_Secret_Key:百度手写文字识别SecretKey~~ 152 | 153 | 154 | --- 155 |
156 | 157 | #### 百度云API获取教程 158 | 1. 注册并登录百度智能云平台,按照网页要求进行实名认证 159 | 2. 打开手写文字识别应用页面,点击页面上方的“立即使用” 160 | 3. 领取百度云手写识别免费API资源 161 | ![控制台](img/baidu/1领取资源.jpg "控制台") 162 | ![确认领取](img/baidu/2确认领取.jpg "确认领取") 163 | 4. 创建OCR应用 164 | ![创建应用](img/baidu/3创建应用.jpg "创建应用") 165 | ![填写应用详细信息](img/baidu/4填写应用信息.jpg "填写应用详细信息") 166 | ![创建完成](img/baidu/5创建完成.jpg "创建完成") 167 | 5. 复制API Key与Secret Key 168 | ![复制两个Key](img/baidu/6Key复制.jpg "复制两个Key") 169 | --- 170 | 171 | ## 三、待添加功能 172 | - [x] 自动采集郑好办核酸检测信息 173 | - [x] docker支持 174 | - [x] Github Actions支持 175 | - [x] 验证码识别 176 | - [x] 汉字验证码识别 177 | - [x] 手写汉字验证码识别 -------------------------------------------------------------------------------- /jksb.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | 4 | import requests 5 | import logging 6 | 7 | from time import sleep 8 | # from requests.packages.urllib3.exceptions import InsecureRequestWarning 9 | 10 | from parameter import * 11 | import utils 12 | 13 | logging.basicConfig(level=logger_level, format="%(asctime)s - %(name)s - [%(levelname)s] - %(message)s") 14 | logger = logging.getLogger('jksb') 15 | # 忽略证书错误 16 | # requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 17 | # requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS = 'DEFAULT:@SECLEVEL=1' 18 | 19 | # 输出参数状态 20 | logger.info("脚本启动成功!请验证你的信息:") 21 | logger.info("学号:" + username) 22 | logger.info("密码:" + password) 23 | logger.info("省份编号:" + code_province) 24 | logger.info("城市编号:" + code_city) 25 | logger.info("详细位置:" + location) 26 | logger.info("疫苗情况:" + vaccine) 27 | logger.info("经度:" + jingdu) 28 | logger.info("纬度:" + weidu) 29 | logger.info("通知方法:" + send_type) 30 | logger.info("通知参数:" + send_parameter) 31 | 32 | 33 | def run(): 34 | # 打卡进程 35 | try: 36 | logger.info("正在检查是否已经打卡...") 37 | response_data = utils.get_signin_status() 38 | if response_data[0] is True and logger_level is not logging.DEBUG: 39 | logger.info("今日已成功打卡!") 40 | else: 41 | # ----------------------------登录后的首个页面---------------------------- 42 | logger.info("今日尚未打卡!") 43 | logger.info("开始今日打卡进程...") 44 | did = re.search('(?<=did" value=")[0-9a-zA-Z]*(?=")', response_data[1]).group() 45 | door = re.search('(?<=door" value=")[0-9a-zA-Z]*(?=")', response_data[1]).group() 46 | # ghdn28 = re.search('(?<=ghdn28" value=")[0-9a-zA-Z]*(?=")', response_data[1]).group() 47 | sid1 = re.findall('(?<=sid" value=")[0-9a-zA-Z]*(?=")', response_data[1])[0] 48 | sid2 = re.findall('(?<=sid" value=")[0-9a-zA-Z]*(?=")', response_data[1])[1] 49 | men6 = re.search('(?<=men6" value=")[0-9a-zA-Z]*(?=")', response_data[1]).group() 50 | ptopid = re.search('(?<=ptopid" value=")[0-9a-zA-Z]*(?=")', response_data[1]).group() 51 | 52 | logger.debug("jksb页面中did参数值为:"+did) 53 | logger.debug("jksb页面中door参数值为:"+door) 54 | # logger.debug("jksb页面中ghdn28参数值为:"+ghdn28) 55 | logger.debug("jksb页面中sid1参数值为:"+sid1) 56 | logger.debug("jksb页面中men6参数值为:"+men6) 57 | logger.debug("jksb页面中ptopid参数值为:"+ptopid) 58 | logger.debug("jksb页面中sid2参数值为:"+sid2) 59 | 60 | data_jksb_info = { 61 | 'did': did, 62 | 'door': door, 63 | # 'ghdn28': ghdn28, 64 | 'sid': [sid1, sid2], 65 | 'men6': men6, 66 | 'ptopid': ptopid, 67 | } 68 | url_jksb_info = "https://jksb.v.zzu.edu.cn/vls6sss/zzujksb.dll/jksb" 69 | sleep(3) 70 | logger.info("正在获取打卡页面表单数据...") 71 | response_data = utils.http.request(method='POST', url=url_jksb_info, body=utils.urlencode(data_jksb_info), headers=header) 72 | # response_data = requests.post(url=url_jksb_info, data=data_jksb_info, headers=header, verify=False) 73 | logger.info("成功获取打卡页面表单数据!") 74 | # ----------------------------提交信息页面---------------------------- 75 | sheng6 = re.search('(?<=sheng6" value=")[0-9a-zA-Z]*(?=")', response_data.data.decode()) 76 | shi6 = re.search('(?<=shi6" value=")[0-9a-zA-Z]*(?=")', response_data.data.decode()) 77 | # ghdn28 = re.search('(?<=ghdn28" value=")[0-9a-zA-Z]*(?=")', response_data.data.decode()).group() 78 | fun3 = re.search('(?<=fun3" value=")[0-9a-zA-Z]*(?=")', response_data.data.decode()) 79 | ptopid = re.search('(?<=ptopid" value=")[0-9a-zA-Z]*(?=")', response_data.data.decode()) 80 | sid = re.search('(?<=sid" value=")[0-9a-zA-Z]*(?=")', response_data.data.decode()) 81 | # CAPTCHA_url = re.search('(?<=).*?(?=
).*?(?=
1: 83 | logger.info('郑好办查询结果:昨日未做核酸') 84 | result = 'x' 85 | else: 86 | logger.info('郑好办查询结果:昨日已做核酸') 87 | result = 'y' 88 | except Exception as err: 89 | send_message("郑好办查询失败!") 90 | logger.error("郑好办查询失败!") 91 | finally: 92 | return result 93 | 94 | 95 | # 发送通知的方法 96 | def send_message(message: str): 97 | if send_type == 'bark': 98 | if send_parameter[-1] != '/': 99 | http.request(method='GET', url=send_parameter + '/健康打卡/' + message) 100 | else: 101 | http.request(method='GET', url=send_parameter + '健康打卡/' + message) 102 | logger.info("已使用"+send_type+"模式发送消息“"+message+"”") 103 | 104 | elif send_type == 'serverchan': 105 | http.request(method='GET', url='https://sctapi.ftqq.com/' + send_parameter + '.send?title=' + quote(message)) 106 | logger.info("已使用"+send_type+"模式发送消息“"+message+"”") 107 | 108 | elif send_type == 'email': 109 | # send_parameter应为json字符串,格式为:{"host": "smtp服务器地址", "user": "邮箱登录名", "password": "邮箱密码", "receiver": "接收邮件的邮箱"} 110 | try: 111 | par = json.loads(send_parameter) 112 | mail_host = par['host'] # 设置服务器 113 | mail_user = par['user'] # 用户名 114 | mail_pass = par['password'] # 口令 115 | 116 | sender = par['user'] 117 | receivers = [par['receiver']] 118 | logger.info(receivers) 119 | 120 | message_mime = MIMEText(message, 'plain', 'utf-8') 121 | message_mime['From'] = Header(par['user'], 'utf-8') 122 | message_mime['To'] = Header(par['receiver'], 'utf-8') 123 | 124 | message_mime['Subject'] = Header("健康上报结果", 'utf-8') 125 | 126 | smtp_obj = smtplib.SMTP_SSL(mail_host, 465) 127 | smtp_obj.login(mail_user, mail_pass) 128 | smtp_obj.sendmail(sender, receivers, message_mime.as_string()) 129 | logger.info("已使用"+send_type+"模式发送消息“"+message+"”") 130 | except smtplib.SMTPException: 131 | logger.error('无法发送邮件') 132 | except json.decoder.JSONDecodeError: 133 | logger.critical("邮件参数异常!") 134 | else: 135 | logger.warning('未设置通知方法,待通知消息为:' + message) 136 | 137 | 138 | # # 简单文字识别,现在打卡系统已升级为手写问题,该方法暂时废弃 139 | # def detect_CAPTCHA_ez(url: str): 140 | # acc_token = json.loads( 141 | # requests.get( 142 | # url='https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id='+baidu_API_Key+'&client_secret='+baidu_Secret_Key, 143 | # headers=header 144 | # ).text)['access_token'] 145 | # 146 | # CAPTCHA = "" 147 | # times = 0 148 | # nums = {"零": 0, "壹": 1, "贰": 2, "叁": 3, "肆": 4, "伍": 5, "陆": 6, "柒": 7, "捌": 8, "玖": 9} 149 | # while len(CAPTCHA) != 4 and times < 5: 150 | # CAPTCHA = "" 151 | # response_data = requests.post( 152 | # url="https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic?access_token="+acc_token, 153 | # data="url="+url, 154 | # headers=header) 155 | # response_json = json.loads(response_data.text) 156 | # times += 1 157 | # if response_json["words_result_num"] != 1: 158 | # continue 159 | # for i in response_json["words_result"][0]["words"]: 160 | # if "0" <= i <= "9": 161 | # CAPTCHA += i 162 | # if i in nums: 163 | # CAPTCHA += str(nums[i]) 164 | # logger.info("本次打卡验证码为:"+CAPTCHA) 165 | # return CAPTCHA 166 | # 167 | # 168 | # # 手写文字验证码识别 169 | # def detect_CAPTCHA(url: str): 170 | # CAPTCHA = "" 171 | # acc_token = json.loads( 172 | # requests.get( 173 | # url='https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=' + baidu_API_Key + '&client_secret=' + baidu_Secret_Key, 174 | # headers=header 175 | # ).text)['access_token'] 176 | # 177 | # nums = {"零": 0, "壹": 1, "贰": 2, "叁": 3, "肆": 4, "伍": 5, "陆": 6, "柒": 7, "捌": 8, "玖": 9} 178 | # response_data = requests.post( 179 | # url="https://aip.baidubce.com/rest/2.0/ocr/v1/handwriting?access_token=" + acc_token, 180 | # data="url=" + url, 181 | # headers=header) 182 | # response_json = json.loads(response_data.text) 183 | # for i in response_json["words_result"][0]["words"]: 184 | # if "0" <= i <= "9": 185 | # CAPTCHA += i 186 | # if i in nums: 187 | # CAPTCHA += str(nums[i]) 188 | # 189 | # # 如果识别不成功,将图片放大并二值化后再次进行尝试 190 | # if len(CAPTCHA) != 4: 191 | # def pil2base64(image): 192 | # img_buffer = BytesIO() 193 | # image.save(img_buffer, format='JPEG') 194 | # byte_data = img_buffer.getvalue() 195 | # base64_str = b64encode(byte_data) 196 | # return base64_str 197 | # 198 | # CAPTCHA = "" 199 | # img = BytesIO(requests.get(url).content) 200 | # img = Image.open(img) 201 | # 202 | # threshold = 183 203 | # table = [] 204 | # for i in range(256): 205 | # if i < threshold: 206 | # table.append(0) 207 | # else: 208 | # table.append(1) 209 | # img_base64_urlencode = quote(pil2base64(img.convert('L').resize((880, 220)).point(table, '1'))) 210 | # 211 | # response_data = requests.post( 212 | # url="https://aip.baidubce.com/rest/2.0/ocr/v1/handwriting?access_token=" + acc_token, 213 | # data="image=" + img_base64_urlencode, 214 | # headers=header) 215 | # response_json = json.loads(response_data.text) 216 | # for i in response_json["words_result"][0]["words"]: 217 | # if "0" <= i <= "9": 218 | # CAPTCHA += i 219 | # if i in nums: 220 | # CAPTCHA += str(nums[i]) 221 | # 222 | # logger.info("本次打卡验证码为:" + CAPTCHA) 223 | # return CAPTCHA 224 | --------------------------------------------------------------------------------