├── README.md └── 学习通实习打卡签到.py /README.md: -------------------------------------------------------------------------------- 1 | # ChaoXingshixidaka 2 | 学习通实习打卡签到python程序 3 | 4 | 本程序仅在部分学校进行测试,可能不适用于所有存在实习打卡的学校 5 | 6 | 使用前先用下列命令安装requests库和filetype库 7 | ``` 8 | pip install requests filetype 9 | ``` 10 | -------------------------------------------------------------------------------- /学习通实习打卡签到.py: -------------------------------------------------------------------------------- 1 | import json 2 | import re 3 | import time 4 | from tkinter import filedialog 5 | 6 | import filetype 7 | import requests 8 | 9 | headers = { 10 | 'User-Agent': 'Mozilla/5.0 (Linux; Android 12; Redmi K30 Pro Zoom Edition Build/SKQ1.211006.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/95.0.4638.74 Mobile Safari/537.36 (device:Redmi K30 Pro Zoom Edition) Language/zh_CN com.chaoxing.mobile/ChaoXingStudy_3_6.2.8_android_phone_1050_234 (@Kalimdor)_8c0587fc07ee4c25bdbbb5d7a90d8152' 11 | } 12 | # 学习通用户名,手机号或者学号 13 | username = "" 14 | # 学习通密码 15 | password = "" 16 | # 学校ID,当用户名为学号时需要填写,为手机号时不需要填写 17 | schoolid = "" 18 | # 要打卡的地址名称、经度和纬度,可在http://api.map.baidu.com/lbsapi/getpoint/index.html中获取相应位置的坐标 19 | address = "河南省郑州市金水区商务内环路15号绿地中心千玺广场" 20 | # 打卡位置坐标,通过上面网址查询到的的坐标点可直接粘贴在这里 21 | location = "113.733731,34.777027" 22 | # 这个是学习通实习打卡中的“如果发生特殊情况未能正常打卡,可以在此填写理由”中的内容,可自行填写 23 | remark = "" 24 | # 新版实习打卡中要提交的图片列表,填写时请使用引号包裹后写在中括号内,如下面注释所示 25 | # pictureAry = ["3acf16259def65456fc2a68ab5e10d96"] 26 | # 要设置多个图片请用英文逗号隔开,如下面注释所示 27 | # pictureAry = ["3acf16259def65456fc2a68ab5e10d96","3acf16259def65456fc2a68ab5e10d95","3acf16259def65456fc2a68ab5e10d94"] 28 | pictureAry = [] 29 | 30 | 31 | def new_clockin(session): 32 | url = "https://sx.chaoxing.com/internship/planUser/myPlanList" 33 | res = session.get(url, headers=headers) 34 | if res.url == url: 35 | res = res.json() 36 | else: 37 | return [0, "登录失败,请检查用户名密码后重试"] 38 | if res["result"] == 0 and len(res["data"]) > 0: 39 | planlist = [] 40 | for d in res["data"]: 41 | tempdict = {"planName": d["planName"], "planId": d["planId"], "fid": d["fid"], "planUserId": d["id"]} 42 | if d["planStatus"] == 1: 43 | tempdict["planStatus"] = "进行中" 44 | elif d["planStatus"] == 2: 45 | tempdict["planStatus"] = "已结束" 46 | elif d["planStatus"] == 3: 47 | tempdict["planStatus"] = "未开始" 48 | if d["sxStatus"] == 0: 49 | tempdict["sxStatus"] = "未实习" 50 | elif d["sxStatus"] == 1: 51 | tempdict["sxStatus"] = "实习中" 52 | elif d["sxStatus"] == 2: 53 | tempdict["sxStatus"] = "免实习" 54 | elif d["sxStatus"] == 3: 55 | tempdict["sxStatus"] = "终止实习" 56 | tempdict["planStartTime"] = d["planStartTime"] 57 | tempdict["planEndTime"] = d["planEndTime"] 58 | tempdict["recruitNames"] = d["recruitNames"] 59 | planlist.append(tempdict) 60 | print("{} {:<50} {:<10} {:<6} {:<23} {}".format("ID", "实习计划名称", "实习计划状态", "实习状态", "实习时间", "实习岗位")) 61 | print("-" * 120) 62 | inputid = 0 63 | for d in planlist: 64 | inputid += 1 65 | print("{:<2} {:<40} {:<12} {:<7} {:<25} {}".format(inputid, d["planName"], d["planStatus"], d["sxStatus"], d["planStartTime"] + "-" + d["planEndTime"], d["recruitNames"])) 66 | while True: 67 | inputid = input("输入要进行实习打卡的ID:") 68 | try: 69 | inputid = int(inputid) 70 | if 0 < inputid <= len(planlist): 71 | break 72 | else: 73 | print("ID输入错误,请重新输入") 74 | except ValueError: 75 | print("ID输入错误,请重新输入") 76 | select_plan = planlist[inputid-1] 77 | getDataByIdurl = "https://sx.chaoxing.com/internship/planUser/getDataById?planId={}&planUserId={}".format(select_plan["planId"], select_plan["planUserId"]) 78 | res = session.get(getDataByIdurl, headers=headers) 79 | if res.url == getDataByIdurl: 80 | res = res.json() 81 | if res["result"] == 0 and res["data"] is not None: 82 | if len(res["data"]["userPeriods"]) > 0: 83 | workStart = res["data"]["userPeriods"][0]["planUserRecruit"]["recruitVo"]["workStart"] 84 | workEnd = res["data"]["userPeriods"][0]["planUserRecruit"]["recruitVo"]["workEnd"] 85 | else: 86 | workStart = "" 87 | workEnd = "" 88 | dgsxpcurl = "https://sx.chaoxing.com/internship/dgsxpc/{}".format(select_plan["planId"]) 89 | res = session.get(dgsxpcurl, headers=headers) 90 | if res.url == dgsxpcurl: 91 | res = res.json() 92 | if res["result"] == 0 and res["data"] is not None: 93 | isontimesign = res["data"]["isontimesign"] 94 | allowOffset = res["data"]["offset"] or 2000 95 | dateurl = "https://sx.chaoxing.com/internship/clockin-user/get/stu/{}/date?date={}".format(select_plan["planId"], time.strftime("%Y-%m-%d")) 96 | res = session.get(dateurl, headers=headers) 97 | if res.url == dateurl: 98 | res = res.json() 99 | if res["result"] == 0 and res["data"] is not None: 100 | cxid = res["data"]["cxid"] 101 | clockinId = res["data"]["id"] 102 | while True: 103 | clockintype = input("请输入上下班打卡状态,输入0为上班打卡,输入1为下班打卡:") 104 | if clockintype != "0" and clockintype != "1": 105 | print("输入错误,请重新输入") 106 | elif clockintype == "0": 107 | statusName = "上班" 108 | break 109 | else: 110 | statusName = "下班" 111 | break 112 | recruitId = res["data"]["recruitId"] 113 | pcid = res["data"]["pcid"] 114 | pcmajorid = res["data"]["pcmajorid"] 115 | offduty = 0 116 | if isontimesign: 117 | addclockinurl = "https://sx.chaoxing.com/internship/clockin-user/stu/addclockin/{}".format(cxid) 118 | else: 119 | addclockinurl = "https://sx.chaoxing.com/internship/clockin-user/stu/addclockinOnceInDay/{}".format(cxid) 120 | data = { 121 | "id": clockinId, 122 | "type": clockintype, 123 | "recruitId": recruitId, 124 | "pcid": pcid, 125 | "pcmajorid": pcmajorid, 126 | "address": address, 127 | "geolocation": location, 128 | "remark": remark, 129 | "workStart": workStart, 130 | "workEnd": workEnd, 131 | "images": json.dumps(pictureAry) if len(pictureAry) > 0 else "", 132 | "allowOffset": allowOffset, 133 | "offset": "NaN", 134 | "offduty": offduty, 135 | "codecolor": "", 136 | "havestar": "", 137 | "worktype": "", 138 | "changeLocation": "", 139 | "statusName": statusName, 140 | "shouldSignAddress": "" 141 | } 142 | res = session.post(addclockinurl, headers=headers, data=data) 143 | if res.url == addclockinurl: 144 | return [1, res.text] 145 | else: 146 | return [0, "登录失败,请检查用户名密码后重试"] 147 | else: 148 | return [2, res["errorMsg"]] 149 | else: 150 | return [0, "登录失败,请检查用户名密码后重试"] 151 | else: 152 | return [2, res["errorMsg"]] 153 | else: 154 | return [0, "登录失败,请检查用户名密码后重试"] 155 | else: 156 | return [2, res["errorMsg"]] 157 | else: 158 | return [0, "登录失败,请检查用户名密码后重试"] 159 | else: 160 | return [2, "未找到新版实习打卡任务"] 161 | 162 | 163 | def old_clockin1(session): 164 | res = session.get("https://www.dgsx.chaoxing.com/form/mobile/signIndex", headers=headers) 165 | txt = res.text 166 | if txt != "您还没有被分配实习计划。": 167 | if "用户登录状态异常,请重新登录!" not in txt: 168 | planName = re.search(r"planName: '(.*)',", txt, re.I).groups()[0] 169 | clockin_type = re.search(r"type: '(.*)',", txt, re.I).groups()[0] 170 | signType = re.search(r"signType: '(.*)',", txt, re.I).groups()[0] 171 | workAddress = re.search(r'', txt, re.I).groups()[0] 172 | geolocation = re.search(r'', txt, re.I).groups()[0] 173 | allowOffset = re.search(r'', txt, re.I).groups()[0] 174 | signSettingId = re.search(r'', txt, re.I).groups()[0] 175 | data = { 176 | "planName": planName, 177 | "type": clockin_type, 178 | "signType": signType, 179 | "address": workAddress, 180 | "geolocation": geolocation, 181 | "remark": remark, 182 | "images": "", 183 | "offset": 0, 184 | "allowOffset": allowOffset, 185 | "signSettingId": signSettingId 186 | } 187 | res = session.post("https://www.dgsx.chaoxing.com/form/mobile/saveSign", headers=headers, data=data) 188 | return [1, res.text] 189 | else: 190 | return [0, "登录失败,请检查用户名密码后重试"] 191 | else: 192 | return [2, "未找到旧版页面1实习打卡任务"] 193 | 194 | 195 | def old_clockin2(session): 196 | res = session.get("https://i.chaoxing.com/base/cacheUserOrg", headers=headers).json() 197 | site = res["site"] 198 | is_find = False 199 | for d in site: 200 | fid = str(d["fid"]) 201 | session.cookies.set("wfwfid", fid) 202 | res = session.get("https://www.dgsx.chaoxing.com/mobile/clockin/show", headers=headers) 203 | txt = res.text 204 | if res.status_code == 200: 205 | if "alert('请先登录');" in txt or 'alert("实习计划已进入总结期或实习已终止,无法签到");' in txt: 206 | continue 207 | elif "用户登录状态异常,请重新登录!" not in txt: 208 | clockinId = re.search(r'', txt, re.I).groups()[0] 209 | recruitId = re.search(r'', txt, re.I).groups()[0] 210 | pcid = re.search(r'', txt, re.I).groups()[0] 211 | pcmajorid = re.search(r'', txt, re.I).groups()[0] 212 | geolocation = location 213 | should_bntover = re.search(r'''