西洲渡

一只还没迈入IC领域的小菜鸡

基于Python的晨午检自动填报脚本

前言

由于疫情爆发,学校要求每次填报定位信息,但是鉴于我也不怎么出去,外加上记忆力比较差,所以只能想个办法替我去完成这些重复性操作了。脚本是原来有的西电大佬写好的,在这里我只是借用稍加修改了一下(仅适用于广州研究院,因为定位在广州)。脚本可以从我的GitHub仓库中下载。

实现原理

  • 首先微信的晨午检虽然在微信中,但其实只是一个网页,上面的填的信息都可以认为是一些个表单,只需要一个脚本能够自动把表单存下来,然后代替人去将表单数据提交个后台服务器就行了,唯一难搞的就是需要的定位信息。

  • 那么表单我们怎么生成呢,直接生成有点不利于观看,因此用代码交互填进去。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    #!/usr/bin/python3
    # -*- coding: UTF-8 -*-

    import json

    def AskInteractive(description, options, delta=0):
    print(description)
    for index in range(len(options)):
    print(str(index)+". "+options[index])
    while True:
    ret = input("你的选择: ")
    try:
    val = int(ret)
    if val >= 0 and val < len(options):
    return val+delta
    except:
    pass

    def AskText(description):
    return input(description)

    def AskBoolean(description):
    while True:
    ret = input(description+'<Y/N> ').upper()
    if ret == "Y":
    return 1
    elif ret == "N":
    return 0


    # Configuration

    # 具体填报项目

    print("#####\n温馨提示: 不外出、不聚集、不吃野味, 戴口罩、勤洗手、咳嗽有礼,开窗通风,发热就诊\n#####\n\n")

    data = {}

    # 统一认证账号密码
    data.update({"_u":AskText("统一认证账号: ")})
    data.update({"_p":AskText("统一认证密码: ")})

    # 今日是否在校
    data.update({"sfzx":AskBoolean("今日是否在校:")})

    # 定位
    data.update({"geo_api_info": '{"type":"complete","position":{"Q":23.285822043836,"R":113.606406850871,"lng":113.6064068,"lat":23.2858220},"location_type":"html5","message":"Get ipLocation failed.Get geolocation success.Convert Success.Get address success.","accuracy":65,"isConverted":true,"status":1,"addressComponent":{"citycode":"020","adcode":"440112","businessAreas":[],"neighborhoodType":"","neighborhood":"","building":"","buildingType":"","street":"九龙大道","streetNumber":"108号","country":"中国","province":"广东省","city":"广州市","district":"黄埔区","township":"九龙镇"},"formattedAddress":"广东省广州市黄埔区九龙镇御禾田公寓广州绿地城","roads":[],"crosses":[],"pois":[],"info":"SUCCESS"}'})

    geo = json.loads(data["geo_api_info"])
    data.update({"address":geo["formattedAddress"],"area":geo["addressComponent"]["province"] + ' ' + geo["addressComponent"]["city"] + ' ' + geo["addressComponent"]["district"],"province":geo["addressComponent"]["province"],"city":geo["addressComponent"]["city"]})


    if data["city"].strip() == "" and data["province"] in ["北京市","上海市","重庆市","天津市"]:
    data["city"] = data["province"]



    # 体温范围
    data.update({"tw":AskInteractive("今日体温范围(℃): ",["(-inf, 36]","(36, 36.5]","(36.5, 36.9]","(36.9, 37.3]","(37.3, 38]","(38, 38.5]","(38.5, 39]","(39, 40]","(40, +inf)"],0)})

    # 今日是否出现发热、乏力、干咳、呼吸困难等症状
    data.update({"sfyzz":AskBoolean("今日是否出现发热、乏力、干咳、呼吸困难等症状: ")})

    # 是否处于隔离期
    data.update({"sfcyglq":AskBoolean("是否处于隔离期: ")})

    # 一码通颜色
    data.update({"ymtys":AskInteractive("西安一码通颜色: ",["绿","黄","红"])})

    # 其他信息
    data.update({"qtqk":AskText("其他信息: ")})

    with open("data_3chk.json","w") as fd:
    json.dump(data,fd)
    print("保存成功")

  • 通过上面的配置文件,我们把每天要填写的信息都生成一个json文件,然后就是这个文件可以用我们的脚本提交上去,其中的定位信息是通过浏览器抓取的经纬度信息,手动填上去的,应该有一些api接口可以自动获取,但本人学艺不精,暂时还不会。

  • 然后生成完的数据我们就剩下一个提交了,提交也只是python模拟浏览器进行的动作。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    #!/usr/bin/python3
    # -*- coding: UTF-8 -*-

    import json
    import requests
    import re
    import sys
    import os
    import time

    if os.path.exists("NOSUBMIT"):
    exit()

    data = {}

    with open("data_3chk.json","r") as fd:
    data=json.load(fd)

    conn = requests.Session()

    # Login
    result = conn.post('https://xxcapp.xidian.edu.cn/uc/wap/login/check',data={'username':data['_u'],'password':data['_p']})
    if result.status_code != 200:
    print('认证大失败')
    exit()

    # Submit
    del data['_u']
    del data['_p']


    result = conn.post('https://xxcapp.xidian.edu.cn/xisuncov/wap/open-report/save',data=data)
    print(result.text)

    time.sleep(5) //

使用前须知

为了脚本的更好体验,本程序有两种使用方法,由于程序仅仅具备一键提交的功能,因此在使用时需要配合电脑操作系统的定时任务功能才能实现完全自动化填写(电脑或服务器白天时段必须保证开机)。

  1. 如拥有云服务器、树莓派、自建服务器(其实用腾讯的云函数理论上也以)等长期保持开机状态的linux设备的兄弟,自然不用我多说,Linux的crontab 定时跑脚本就行了。
  2. 在工位或使用自己电脑等windows系统的朋友,因为我的电脑设置的每天早上八点到晚上十一点自动开关机(这个百度好多教程,自动开机需要改bios,自动关机只需要定时执行shutdown命令即可),因此也不用担心漏报。当然懒得搞得话也可以每天手动开关机。
  3. 由于原来脚本中的定位api我没看懂,因此改成手动定位了,所以这个脚本可以在任何地方运行,都可以填报,例如家里一直开机的树莓派、阿里腾讯华为甚至国外搬瓦工等服务器。

使用方法(windows)

安装Python环境

  • 打开官网https://www.python.org/ 下载最新版的python即可,建议直接默认安装,在安装的最后一步 勾选 Add Python to PATH 否则的话就要自己百度添加环境变量

安装request库

  • 操作:win+R 输入cmd

  • 在黑框程序里面输入 pip install requests (因为我已经安装过,所以显示下图)

生成表单

  • 先打开表单配置文件,然后点击运行

  • 运行成功后会出现表单填入信息,逐步填入个人信息即可(注意账号密码必须用英文状态下输入否则会失败)

  • 保存成功之后文件夹中会多出一个json文件,这是浏览器需要提交的表单文件

脚本提交表单

  • 可以使用了,双击submit_3chk.Py,如果档时段未填报则显示,“操作成功”,否则显示“你已上报过”


至此已经实现了一键填报功能,

配置定时提交

  • 文件夹选择电脑的一个位置放下,我是放在了桌面
  • 新建文本文档

  • 输入两行命令,(如果你放在了C盘以外的位置(例如D盘)第一条命令要换成cd \d D:\XXX\XXX

  • 写完之后将文本文件的后缀名改成.bat 例如login.bat
  • 双击此文件也可以填报

  • 右键点击此电脑,打开管理,创建基本定时任务

  • 输入计划任务的名称和描述——下一步选择每天——设定时间,例如早上八点——操作是启动程序——下一步选择程序或脚本 浏览找到刚才的批处理文件,例如我的——最后保存

  • 在任务列表中找到刚才新建的定时任务,选择触发器,新建几个不同时间的触发任务,即可实现完全自动填报