├── PRO-test ├── chaoxingsign.py └── conf.json ├── README.md ├── chaoxingsign.py ├── config.json ├── old ├── .gitignore ├── account.json.example ├── chaoxingSignServerless.py ├── chaoxingsign.py └── 多用户-test │ ├── chaoxingsign.py │ ├── conf.json │ └── 云函数版 │ ├── cloud.py │ └── conf.json ├── tools ├── 刷关注.py ├── 刷收藏量.py └── 刷笔记.py └── 异步版 └── emmm.py /PRO-test/chaoxingsign.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | import time 4 | import datetime 5 | import numpy as np 6 | import re 7 | import urllib3 8 | #from retrying import retry 9 | 10 | headers = { 11 | 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36'}#这个头目前没什么用,留着备用... 12 | try: 13 | with open('conf.json', 'r', encoding='utf-8') as f: # 读取配置文件 14 | conf = json.loads(f.read()) 15 | print('获取配置成功') 16 | except FileNotFoundError: 17 | print('未找到配置文件') 18 | print('软件退出') 19 | exit() 20 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) 21 | 22 | # def retry_if_connection_error(exception): 23 | # return isinstance(exception, requests.exceptions.ConnectionError) 24 | class CxSign(): 25 | def __init__(self,conf_user): # 转换一下配置文件 26 | self.username = conf_user['username'] 27 | self.passwd = conf_user['passwd'] 28 | self.SCKEY = conf_user['SCKEY'] 29 | self.name = conf_user['name'] 30 | self.address = conf_user['address'] 31 | self.longitude = conf_user['longitude'] 32 | self.latitude = conf_user['latitude'] 33 | self.picname = conf_user['picname'] 34 | self.item_all=[] 35 | self.aid_all=[] 36 | try: 37 | self.activates=np.load('activates.npy').tolist() 38 | except IOError: #文件不存在 39 | self.activates=[] 40 | # @retry(retry_on_exception=retry_if_connection_error) 41 | def login(self): # 获取cookie 42 | url = 'https://passport2-api.chaoxing.com/v11/loginregister' 43 | data = {'uname': self.username, 'code': self.passwd } 44 | self.session = requests.session() 45 | cookie_jar = self.session.post(url=url, data=data, headers=headers).cookies 46 | self.session.cookies=cookie_jar 47 | self.cookie = requests.utils.dict_from_cookiejar(cookie_jar) 48 | print('获取cookie成功') 49 | 50 | # @retry(retry_on_exception=retry_if_connection_error) 51 | def subject(self): # 获取课程 52 | url = "http://mooc1-api.chaoxing.com/mycourse/backclazzdata" 53 | res = requests.get(url, headers=headers, cookies=self.cookie) 54 | cdata = json.loads(res.text) 55 | if (cdata['result'] != 1): 56 | print("课程列表获取失败\n重试中") 57 | raise(requests.exceptions.ConnectionError) 58 | for item in cdata['channelList']: 59 | if ("course" in item['content']): 60 | self.item_all.append(item['content']) 61 | # # pushdata['user'] = str(i) # 插入用户标记 62 | # courseid.append(item['content']['course']['data'][0]['id']) 63 | # name.append(item['content']['course']['data'][0]['name']) 64 | # classid.append(item['content']['id']) 65 | #print(self.item_all) 66 | 67 | # @retry(retry_on_exception=retry_if_connection_error) 68 | def taskactivelist(self): # 查找签到任务 69 | url = "https://mobilelearn.chaoxing.com/ppt/activeAPI/taskactivelist" 70 | for i in self.item_all: 71 | payload={'courseId': str(i['course']['data'][0]['id']), 'classId': str(i['id']),'uid': self.cookie['UID']} 72 | print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),'正在查询课程:', i['course']['data'][0]['name']) 73 | res = requests.get(url, params=payload, headers=headers, cookies=self.cookie) 74 | if res.status_code==200: #状态码正常 75 | data = json.loads(res.text) 76 | for item in data['activeList']: #轮询签到任务 77 | if ("nameTwo" in item): 78 | if (item['activeType'] == 2 and item['status'] == 1): # 查找进行中的签到任务 79 | aid = item['id'] # 提取activePrimaryId 80 | if (aid not in self.activates): # 查看是否签到过 81 | print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 82 | '[签到]', i['course']['data'][0]['name'], '查询到待签到活动 活动名称:%s 活动状态:%s 活动时间:%s aid:%s' % ( 83 | item['nameOne'], item['nameTwo'], item['nameFour'], aid)) 84 | self.aid_all.append(aid) #所有进行中的签到任务 85 | self.sign(item['nameOne'],i['course']['data'][0]['id'],i['id'],i['course']['data'][0]['name'],aid) # 调用签到函数 86 | 87 | # @retry(retry_on_exception=retry_if_connection_error) 88 | def upload(self): # 上传图片 89 | if self.picname == '': 90 | return 91 | else: 92 | print('上传图片~~') 93 | tokenurl = 'https://pan-yz.chaoxing.com/api/token/uservalid' 94 | tokenres = requests.get(tokenurl, headers=headers, cookies=self.cookie) 95 | tokendict = json.loads(tokenres.text) 96 | token = tokendict['_token'] 97 | uploadurl = 'https://pan-yz.chaoxing.com/upload' 98 | picname = self.picname 99 | try: 100 | files = {'file': (picname, open(picname, 'rb'), 'image/webp,image/*')} 101 | except FileNotFoundError: 102 | print('图片不存在 不上传图片') 103 | return 104 | uploadres = requests.post(uploadurl, data={'puid': self.cookie['UID'], '_token': token}, files=files,headers=headers, cookies=self.cookie) 105 | resdict = json.loads(uploadres.text) 106 | return (resdict['objectId']) 107 | 108 | # @retry(retry_on_exception=retry_if_connection_error) 109 | def sign(self,sign_type,course_id,class_id,course_name,aid): # 签到,偷了个懒,所有的签到类型都用这个,我测试下来貌似都没问题 110 | status=False #一般签到就直接签完了 要加状态判断以用于决定后面的sever酱是否推送 111 | url = "https://mobilelearn.chaoxing.com/pptSign/stuSignajax" 112 | if '位置' in sign_type: 113 | data = { 114 | 'name': self.name, 115 | 'address': self.address, 116 | 'activeId': aid, 117 | 'uid': self.cookie['UID'], 118 | 'longitude': self.longitude, 119 | 'latitude': self.latitude, 120 | } 121 | elif '手势' in sign_type: 122 | data = { 123 | 'name': self.name, 124 | 'activeId': aid, 125 | 'uid': self.cookie['UID'], 126 | 'longitude': -1, 127 | 'latitude': -1, 128 | } 129 | elif '二维码' in sign_type: 130 | data = { 131 | 'name': self.name, 132 | 'activeId': aid, 133 | 'uid': self.cookie['UID'], 134 | 'longitude': -1, 135 | 'latitude': -1, 136 | } 137 | else: 138 | r = self.session.get('https://mobilelearn.chaoxing.com/widget/sign/pcStuSignController/preSign?activeId={}&classId={}&fid=39037&courseId={}'.format(aid,class_id,course_id),headers=headers,verify=False) 139 | title = re.findall('(.*)', r.text)[0] 140 | if "签到成功" not in title: 141 | objectId = self.upload() 142 | data = { 143 | 'name': self.name, 144 | 'address': self.address, 145 | 'activeId': aid, 146 | 'uid': self.cookie['UID'], 147 | 'longitude': self.longitude, 148 | 'latitude': self.latitude, 149 | 'objectId': objectId 150 | } 151 | else: 152 | status=True 153 | if not status: 154 | res = requests.post(url, data=data, headers=headers, cookies=self.cookie) 155 | text=res.text 156 | else: 157 | text="success" 158 | print("签到状态:", text) 159 | #这边不直接append的原因是长时间运行后这个列表肯定会越来越大 160 | #然后这边直接等于aid_all的话好像逻辑又有点奇怪 感觉好像activates是多余的 161 | self.activates=self.aid_all 162 | #存入所有正在进行中的且签到过的任务 这边的aid_all逻辑有点绕 但是试下来是可行的 163 | #如果是存入activates的话这个文件会越来越大 164 | try: 165 | np.save('activates.npy',np.array(self.aid_all)) 166 | except OSError: 167 | pass 168 | if ((not self.SCKEY.isspace()) and (not self.SCKEY=='')) and text=='success': 169 | print('推送中') 170 | self.push(course_name,text) 171 | 172 | # @retry(retry_on_exception=retry_if_connection_error) 173 | def push(self,course_name,status): 174 | api = 'https://sc.ftqq.com/' + self.SCKEY + '.send' 175 | title = u"签到辣!" 176 | content = '课程: '+ course_name+'\n\n签到状态:' + status 177 | data = { 178 | "text": title, 179 | "desp": content 180 | } 181 | requests.post(api, data=data) 182 | print('已推送~') 183 | 184 | 185 | if __name__ == "__main__": 186 | print("运行于普通模式") 187 | all_user=[] 188 | for user_conf in conf: 189 | user=CxSign(user_conf) 190 | all_user.append(user) 191 | print('用户'+user_conf['username']+'登陆中') 192 | user.login() 193 | print('拉取用户'+user_conf['username']+'课程中') 194 | user.subject() 195 | while(1): 196 | for user in all_user: 197 | user.taskactivelist() 198 | user.aid_all=[] 199 | else: 200 | print("运行于云函数模式") 201 | def main_handler(event, context): 202 | for user_conf in conf: 203 | user=CxSign(user_conf) 204 | print('用户'+user_conf['username']+'登陆中') 205 | user.login() 206 | print('拉取用户'+user_conf['username']+'课程中') 207 | user.subject() 208 | user.taskactivelist() 209 | -------------------------------------------------------------------------------- /PRO-test/conf.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "username": "", 3 | "passwd": "", 4 | "SCKEY": "", 5 | "name": "", 6 | "address": "", 7 | "latitude": "32.2829260000", 8 | "longitude": "43.9237990000", 9 | "picname": "" 10 | }] 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 超星学习通自动签到 2 | 原作者https://www.bilibili.com/video/av94208525 3 | 4 | 云函数完整食用方法https://yuban10703.xyz/archives/527 5 | 有问题直接issue提,别在blog写..... 6 | 7 | 支持学习通的所有签到 8 | 支持server酱推送 9 | 能自定义照片,地址以及名字 10 | 用screen后台挂住就好了,断网的话可能会boom(一般不会断网⑧..) 11 | ## 配置文件 12 | 1. "username":手机号 13 | 2. "passwd":密码 14 | 3. "SCKEY":server酱的key 15 | 4. "name":老师那里显示的名字,无特殊需要默认就行 16 | 5. "address":地址信息 17 | 6. "latitude":经度,同上 18 | 7. "longitude":纬度,同上 19 | 8. "picname":同目录的图片名字 20 | ## 本地使用教程 21 | 1. python3环境 22 | 2. 安装模块: pip install requests 23 | 3. 在同目录下的conf.json中写入配置 24 | 4. 双击运行... 25 | ## 云函数使用教程 26 | 1. 去腾讯云创建一个云函数,目前测试广州好像不能用.其他地区可以. 27 | 2. 环境选择`Python 3.6` 28 | 3. 内存最低实测`64M`可以跑. 29 | 4. 时间看个人课程数量.详细解释看下面 30 | 5. 测试运行,成功后设定定时触发.关于如何设定Cron也可以看下面 31 | 32 | #### 关于时间设定 33 | 34 | 35 | 在`Serverless`版里面,所有课程扫描/签到一次就会停止,这样做是为了符合云函数的设计,同时也节省运行时间. 36 | 最简单的估算办法就是: 37 | * 签到或扫描的请求撑死不会超过2S,记为`x` 38 | * 中间等待时间由`account.json`决定,记为`y` 39 | * 课程数量,记为`z` 40 | 那么最后总时间应该是: 41 | $$z*(x+y)$$ 42 | 43 | 绝大多数情况下这个请求时间可以直接忽略. 44 | 45 | 再懒人一点的话,可以直接在命令行运行并统计时间,参考Linux命令`time` 46 | 47 | #### 关于Cron设定 48 | 我们先来看一个例子 49 | 50 | ``` 51 | 0 */10 8-12,14-18 * * 1-5 52 | ``` 53 | 54 | 云函数的Cron跟Linux Cron非常相似,不过左边多了一个秒. 55 | 以上Cron可以解释为: 56 | 57 | ``` 58 | 0 */10 8-12,14-18 * * 1-5 59 | | | | | | | 60 | | | | | | .------- 在周几 (周一到周五) 61 | | | | | .---------- 在哪个月 (所有) 62 | | | | .------------ 在哪一天 (所有) 63 | | | .----------------------- 在几点 (8-12和14-18) 64 | | .---------------------------- 在第几分钟 (每隔10分钟) 65 | .------------------------------ 在第几秒 (第0秒) 66 | ``` 67 | 这是比较符合现在上课的情况的Cron,各位也可以根据这个列表进行自定义 68 | -------------------------------------------------------------------------------- /chaoxingsign.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | import time 4 | import datetime 5 | 6 | session = requests.session() 7 | headers = { 8 | 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36'} 9 | allsubject = [] 10 | allname = [] 11 | allclassid = [] 12 | allcourseid = [] 13 | activates = [] 14 | allaid = [] 15 | cook = [] 16 | allobjectid = [] 17 | with open('config.json', 'r', encoding='utf-8') as f: 18 | conf = json.loads(f.read()) 19 | print('获取配置成功') 20 | 21 | 22 | class CxSign(): 23 | def __init__(self, num): 24 | CxSign.username = conf['username'][num] 25 | CxSign.passwd = conf['passwd'][num] 26 | if len(conf['SCKEY']) == 1: 27 | CxSign.SCKEY = conf['SCKEY'][0] 28 | else: 29 | CxSign.SCKEY = conf['SCKEY'][num] 30 | 31 | if len(conf['name']) == 1: 32 | CxSign.name = conf['name'][0] 33 | else: 34 | CxSign.name = conf['name'][num] 35 | 36 | if len(conf['address']) == 1: 37 | CxSign.address = conf['address'][0] 38 | else: 39 | CxSign.address = conf['address'][num] 40 | 41 | if len(conf['longitude']) == 1: 42 | CxSign.longitude = conf['longitude'][0] 43 | else: 44 | CxSign.longitude = conf['longitude'][num] 45 | 46 | if len(conf['latitude']) == 1: 47 | CxSign.latitude = conf['latitude'][0] 48 | else: 49 | CxSign.latitude = conf['latitude'][num] 50 | 51 | if len(conf['picname']) == 1: 52 | CxSign.picname = conf['picname'][0] 53 | else: 54 | CxSign.picname = conf['picname'][num] 55 | # self.name = conf['name'][num] 56 | # self.address = conf['address'][num] 57 | # self.longitude = conf['longitude'][num] 58 | # self.latitude = conf['latitude'][num] 59 | # self.picname = conf['picname'][num] 60 | # self.speed = conf['speed'] 61 | 62 | def login(num): # 获取cookie 63 | url = 'https://passport2-api.chaoxing.com/v11/loginregister' 64 | data = {'uname': CxSign(num).username, 'code': CxSign(num).passwd, } 65 | session = requests.session() 66 | cookie_jar = session.post(url=url, data=data, headers=headers).cookies 67 | cookie_t = requests.utils.dict_from_cookiejar(cookie_jar) 68 | cook.append(cookie_t) 69 | print('用户:',num,'获取cookie成功') 70 | # return cookie_t 71 | 72 | def subject(i): # 获取课程 73 | url = "http://mooc1-api.chaoxing.com/mycourse/backclazzdata" 74 | res = requests.get(url, headers=headers, cookies=cook[i]) 75 | cdata = json.loads(res.text) 76 | # coursedata=[] 77 | # dict_n = {} 78 | name = [] 79 | classid = [] 80 | courseid = [] 81 | if (cdata['result'] != 1): 82 | print("课程列表获取失败") 83 | for item in cdata['channelList']: 84 | if ("course" not in item['content']): 85 | continue 86 | pushdata = {} 87 | # pushdata['user'] = str(i) # 插入用户标记 88 | courseid.append(item['content']['course']['data'][0]['id']) 89 | name.append(item['content']['course']['data'][0]['name']) 90 | classid.append(item['content']['id']) 91 | allname.append(name) 92 | allclassid.append(classid) 93 | allcourseid.append(courseid) 94 | # coursedata.append(pushdata) 95 | # allsubject.append(coursedata) 96 | # return coursedata 97 | 98 | def taskactivelist(i): # 查找签到任务 99 | global a 100 | aid = [] 101 | url = "https://mobilelearn.chaoxing.com/ppt/activeAPI/taskactivelist" 102 | for index in range(len(allname[i])): 103 | payload = {'courseId': str(allcourseid[i][index]), 'classId': str(allclassid[i][index]), 104 | 'uid': cook[i]['UID']} 105 | time.sleep(1.5) 106 | print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), '用户:', i, '正在查询课程:', allname[i][index]) 107 | res = requests.get(url, params=payload, headers=headers, cookies=cook[i]) 108 | respon = res.status_code 109 | # print(index) 110 | if respon == 200: # 网页状态码正常 111 | # print(res.text) 112 | data = json.loads(res.text) 113 | # print(data) 114 | activeList = data['activeList'] # 把所有任务提出来 115 | for item in activeList: # 轮询所有的任务 116 | if ("nameTwo" not in item): 117 | continue 118 | if (item['activeType'] == 2 and item['status'] == 1): # 查找进行中的签到任务 119 | # signurl = item['url'] # 提取activePrimaryId 120 | aid = item['id'] # 提取activePrimaryId 121 | if (aid not in activates): # 查看是否签到过 122 | print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 123 | '[签到]', allname[i][index], '查询到待签到活动 活动名称:%s 活动状态:%s 活动时间:%s aid:%s' % ( 124 | item['nameOne'], item['nameTwo'], item['nameFour'], aid)) 125 | CxSign.sign(aid, i, index) # 调用签到函数 126 | else: 127 | print('error', respon) # 不知道为啥... 128 | 129 | def token(self): # 获取上传图片用的token 130 | url = 'https://pan-yz.chaoxing.com/api/token/uservalid' 131 | res = requests.get(url, headers=headers, cookies=cook[0]) 132 | tokendict = json.loads(res.text) 133 | return (tokendict['_token']) 134 | 135 | def upload(i): # 上传图片 136 | try: 137 | picname = CxSign(i).picname 138 | except: 139 | picname = '' 140 | 141 | if picname.isspace() or len(picname) == 0: 142 | return 143 | else: 144 | url = 'https://pan-yz.chaoxing.com/upload' 145 | files = {'file': (picname, open(picname, 'rb'), 146 | 'image/webp,image/*',), } 147 | res = requests.post(url, data={'puid': cook[0]['UID'], '_token': CxSign.token(i)}, files=files, 148 | headers=headers, cookies=cook[0]) 149 | resdict = json.loads(res.text) 150 | allobjectid.append(resdict['objectId']) 151 | # return (resdict['objectId']) 152 | 153 | def sign(aid, i, index): # 签到,偷了个懒,所有的签到类型都用这个,我测试下来貌似都没问题 154 | url = "https://mobilelearn.chaoxing.com/pptSign/stuSignajax" 155 | if len(CxSign(i).picname) == 0: 156 | allobjectid.append('') 157 | objectId = '' 158 | 159 | else: 160 | CxSign.upload(i) 161 | objectId = allobjectid[i] 162 | try: 163 | name = CxSign(i).name 164 | except: 165 | try: 166 | name = CxSign.name 167 | except: 168 | name = '' 169 | 170 | try: 171 | address = CxSign(i).address 172 | except: 173 | try: 174 | address = CxSign.address 175 | except: 176 | address = '' 177 | 178 | try: 179 | longitude = CxSign(i).longitude 180 | except: 181 | try: 182 | longitude = CxSign.longitude 183 | except: 184 | longitude = '' 185 | try: 186 | latitude = CxSign(i).latitude 187 | except: 188 | try: 189 | latitude = CxSign.latitude 190 | except: 191 | latitude = '' 192 | 193 | data = {'name': name, 'address': address, 'activeId': aid, 'uid': cook[i]['UID'], 194 | 'longitude': longitude, 'latitude': latitude, 'objectId': objectId} 195 | # data = { 'activeId': aid, 'uid': cook[i]['UID'],} 196 | res = requests.post(url, data=data, headers=headers, cookies=cook[i]) 197 | print("签到状态:", res.text) 198 | if res.text == 'success': 199 | CxSign.push(i, index, res.text) 200 | activates.append(aid) 201 | 202 | def push(i, index, msg): 203 | try: 204 | E_SCKEY = CxSign(i).SCKEY 205 | except: 206 | try: 207 | E_SCKEY = CxSign.SCKEY 208 | except: 209 | E_SCKEY = '' 210 | if E_SCKEY.isspace() or len(E_SCKEY) == 0: 211 | 212 | return 213 | else: 214 | api = 'https://sc.ftqq.com/' + E_SCKEY + '.send' 215 | title = u"签到辣!" 216 | content = '用户:' + str(i) + '\n\n课程: ' + allname[i][index] + '\n\n签到状态:' + msg 217 | data = { 218 | "text": title, 219 | "desp": content 220 | } 221 | requests.post(api, data=data) 222 | print('已推送') 223 | 224 | number = len(conf['username']) 225 | if __name__ == "__main__": 226 | print("运行于普通模式") 227 | 228 | for n in range(number): 229 | CxSign.login(n) 230 | time.sleep(0.8) 231 | 232 | for m in range(number): 233 | CxSign.subject(m) 234 | time.sleep(0.8) 235 | while 1: 236 | for o in range(number): 237 | CxSign.taskactivelist(o) 238 | 239 | else: 240 | print("运行于云函数模式") 241 | def main_handler(event, context): 242 | for n in range(number): 243 | CxSign.login(n) 244 | time.sleep(0.5) 245 | 246 | for m in range(number): 247 | CxSign.subject(m) 248 | time.sleep(0.5) 249 | 250 | for o in range(number): 251 | CxSign.taskactivelist(o) 252 | 253 | 254 | if __name__ == "__main__": 255 | main_handler("", "") 256 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": [""], 3 | "passwd": [""], 4 | "SCKEY": [""], 5 | "name": [""], 6 | "address": [""], 7 | "latitude": ["32.2829260000"], 8 | "longitude": ["43.9237990000"], 9 | "picname": [""] 10 | } 11 | -------------------------------------------------------------------------------- /old/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | account.json -------------------------------------------------------------------------------- /old/account.json.example: -------------------------------------------------------------------------------- 1 | { 2 | "username": "", 3 | "passwd": "", 4 | "SCKEY": "", 5 | "name": "", 6 | "address": "火星", 7 | "latitude": "32.2829260000", 8 | "longitude": "43.9237990000", 9 | "picname": "a.png", 10 | "speed": 10 11 | } 12 | -------------------------------------------------------------------------------- /old/chaoxingSignServerless.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | import requests 4 | import json 5 | import time 6 | import datetime 7 | 8 | 9 | class CxSign: 10 | username = '' # 账号 11 | passwd = '' # 密码 12 | # server酱推送 13 | SCKEY = '' 14 | name = '' # 签到后老师那里显示的名字,空着的话就是默认 15 | address = '火星' # 地址 16 | latitude = '32.2829260000' # 纬度 17 | longitude = '43.9237990000' # 经度 18 | picname = 'a.png' # 同目录下的照片名字,如果不用就留空 picname='' 19 | # 设置轮询间隔(单位:秒,建议不低于5) 20 | speed = 10 21 | 22 | headers = { 23 | 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36' 24 | } 25 | coursedata = [] 26 | activeList = [] 27 | course_index = 0 28 | status = 0 29 | activates = [] 30 | a = 1 31 | index = 0 32 | cookie = '' 33 | uid = 0 34 | 35 | def __init__(self, account): 36 | CxSign.username = account['username'] # 账号 37 | CxSign.passwd = account['passwd'] # 密码 38 | # server酱推送 39 | CxSign.SCKEY = account['SCKEY'] 40 | CxSign.name = account['name'] # 签到后老师那里显示的名字,空着的话就是默认 41 | CxSign.address = account['address'] # 地址 42 | CxSign.latitude = account['latitude'] # 纬度 43 | CxSign.longitude = account['longitude'] # 经度 44 | CxSign.picname = account['picname'] # 同目录下的照片名字,如果不用就留空 picname='' 45 | # 设置轮询间隔(单位:秒,建议不低于5) 46 | CxSign.speed = account['speed'] 47 | CxSign.login(self) 48 | 49 | def login(self): # 获取cookie 50 | url = 'https://passport2-api.chaoxing.com/v11/loginregister' 51 | data = {'uname': CxSign.username, 'code': CxSign.passwd, } 52 | session = requests.session() 53 | cookie_jar = session.post( 54 | url=url, data=data, headers=CxSign.headers).cookies 55 | cookie_t = requests.utils.dict_from_cookiejar(cookie_jar) 56 | CxSign.cookie = cookie_t 57 | CxSign.uid = cookie_t['UID'] 58 | # return cookie_t 59 | 60 | def token(self): # 获取上传图片用的token 61 | url = 'https://pan-yz.chaoxing.com/api/token/uservalid' 62 | res = requests.get(url, headers=CxSign.headers, cookies=CxSign.cookie) 63 | tokendict = json.loads(res.text) 64 | return (tokendict['_token']) 65 | 66 | def upload(self): # 上传图片 67 | picname = CxSign.picname 68 | if picname.isspace() or len(picname) == 0: 69 | return 70 | else: 71 | url = 'https://pan-yz.chaoxing.com/upload' 72 | files = { 73 | 'file': (picname, open(picname, 'rb'), 74 | 'image/webp,image/*',), 75 | } 76 | res = requests.post(url, data={ 77 | 'puid': CxSign.uid, '_token': CxSign.token( 78 | ) 79 | }, files=files, headers=CxSign.headers, cookies=CxSign.cookie) 80 | resdict = json.loads(res.text) 81 | return (resdict['objectId']) 82 | 83 | def taskactivelist(self, courseId, classId): # 查找签到任务 84 | CxSign.a 85 | url = "https://mobilelearn.chaoxing.com/ppt/activeAPI/taskactivelist?courseId=" + \ 86 | str(courseId) + "&classId=" + str(classId) + "&uid=" + CxSign.uid 87 | res = requests.get(url, headers=CxSign.headers, cookies=CxSign.cookie) 88 | respon = res.status_code 89 | if respon == 200: # 网页状态码正常 90 | data = json.loads(res.text) 91 | activeList = data['activeList'] 92 | # print(activeList) 93 | for item in activeList: 94 | if "nameTwo" not in item: 95 | continue 96 | if item['activeType'] == 2 and item['status'] == 1: 97 | signurl = item['url'] # 提取activePrimaryId 98 | aid = CxSign.getvar(signurl) 99 | if aid not in CxSign.activates: 100 | print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 101 | '[签到]', CxSign.coursedata[i]['name'], '查询到待签到活动 活动名称:%s 活动状态:%s 活动时间:%s aid:%s' % ( 102 | item['nameOne'], item['nameTwo'], item['nameFour'], aid)) 103 | CxSign.sign(aid, CxSign.uid) # print('调用签到函数') 104 | 105 | CxSign.a = 2 106 | 107 | else: 108 | print('error', respon) # 不知道为啥... 109 | 110 | def getvar(self, url): # 查找activePrimaryId 111 | var1 = url.split("&") 112 | for var in var1: 113 | var2 = var.split("=") 114 | if (var2[0] == "activePrimaryId"): 115 | return var2[1] 116 | return "ccc" 117 | 118 | def sign(self, aid, uid): # 签到,偷了个懒,所有的签到类型都用这个,我测试下来貌似都没问题 119 | # CxSign.status, CxSign.activates 120 | url = "https://mobilelearn.chaoxing.com/pptSign/stuSignajax" 121 | objectId = CxSign.upload() 122 | res = requests.post(url, data={ 123 | "name": CxSign.name, "address": CxSign.address, 'activeId': aid, 'uid': uid, 124 | 'longitude': CxSign.longitude, 'latitude': CxSign.latitude, 'objectId': objectId 125 | }, headers=CxSign.headers, cookies=CxSign.cookie) 126 | CxSign.push(res.text) 127 | if (res.text == "success"): 128 | print("用户:" + uid + " 签到成功!") 129 | CxSign.activates.append(aid) 130 | CxSign.status = 2 131 | else: 132 | print(res.text, '签到失败') 133 | CxSign.activates.append(aid) 134 | 135 | def push(self, msg): 136 | if CxSign.SCKEY.isspace() or len(CxSign.SCKEY) == 0: 137 | return 138 | else: 139 | api = 'https://sc.ftqq.com/' + CxSign.SCKEY + '.send' 140 | title = u"签到辣!" 141 | content = '课程: ' + CxSign.coursedata[i]['name'] + '\n\n签到状态:' + msg 142 | data = { 143 | "text": title, 144 | "desp": content 145 | } 146 | req = requests.post(api, data=data) 147 | 148 | def doSign(self): 149 | url = "http://mooc1-api.chaoxing.com/mycourse/backclazzdata?view=json&rss=1" 150 | res = requests.get(url, headers=CxSign.headers, cookies=CxSign.cookie) 151 | cdata = json.loads(res.text) 152 | if (cdata['result'] != 1): 153 | print("课程列表获取失败") 154 | for item in cdata['channelList']: 155 | if ("course" not in item['content']): 156 | continue 157 | pushdata = {} 158 | pushdata['courseid'] = item['content']['course']['data'][0]['id'] 159 | pushdata['name'] = item['content']['course']['data'][0]['name'] 160 | # pushdata['imageurl']=item['content']['course']['data'][0]['imageurl'] 161 | pushdata['classid'] = item['content']['id'] 162 | CxSign.coursedata.append(pushdata) 163 | print("获取成功:") 164 | 165 | for item in CxSign.coursedata: # 打印课程 166 | print(str(CxSign.index) + ".课程名称:" + item['name']) 167 | CxSign.index += 1 168 | if __name__ == "__main__": 169 | print("运行于普通模式") 170 | while 1: 171 | for i in range(CxSign.index): 172 | CxSign.taskactivelist(self, CxSign.coursedata[i]['courseid'], 173 | CxSign.coursedata[i]['classid']) 174 | if CxSign.a == 2: 175 | CxSign.a = 0 176 | else: 177 | print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 178 | '[监控运行中]课程:', CxSign.coursedata[i]['name'], '未查询到签到活动') 179 | time.sleep(CxSign.speed) # 休眠 180 | else: 181 | print("运行于云函数模式") 182 | for i in range(CxSign.index): 183 | CxSign.taskactivelist(self, CxSign.coursedata[i]['courseid'], 184 | CxSign.coursedata[i]['classid']) 185 | if CxSign.a == 2: 186 | CxSign.a = 0 187 | else: 188 | print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 189 | '[监控运行中]课程:', CxSign.coursedata[i]['name'], '未查询到签到活动') 190 | time.sleep(CxSign.speed) # 休眠 191 | 192 | 193 | def main_handler(event, context): 194 | # 通过 __name__ 来确定是云函数还是普通模式 195 | # print(__name__) 196 | # 此处读取json文件获取信息 197 | with open("account.json", 'r') as f: 198 | account = json.loads(f.read()) 199 | sign = CxSign(account) 200 | sign.doSign() 201 | 202 | 203 | if __name__ == "__main__": 204 | main_handler("", "") 205 | -------------------------------------------------------------------------------- /old/chaoxingsign.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | import time 4 | import datetime 5 | 6 | username = '' # 账号 7 | passwd = '' # 密码 8 | # server酱推送 9 | SCKEY = '' 10 | name = '' # 签到后老师那里显示的名字,空着的话就是默认 11 | address = '火星' # 地址 12 | latitude = '32.2829260000' # 纬度 13 | longitude = '43.9237990000' # 经度 14 | picname = 'a.png' # 同目录下的照片名字,如果不用就留空 picname='',不然会报错... 15 | # 设置轮询间隔(单位:秒,建议不低于5) 16 | speed = 1 17 | 18 | headers = { 19 | 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36'} 20 | coursedata = [] 21 | activeList = [] 22 | course_index = 0 23 | status = 0 24 | activates = [] 25 | a = 1 26 | index = 0 27 | 28 | 29 | def login(username, passwd): # 获取cookie 30 | url = 'https://passport2-api.chaoxing.com/v11/loginregister' 31 | data = {'uname': username, 'code': passwd, } 32 | session = requests.session() 33 | cookie_jar = session.post(url=url, data=data, headers=headers).cookies 34 | cookie_t = requests.utils.dict_from_cookiejar(cookie_jar) 35 | return cookie_t 36 | 37 | 38 | cookie = login(username, passwd) 39 | uid = cookie['UID'] 40 | 41 | 42 | def token(): # 获取上传图片用的token 43 | url = 'https://pan-yz.chaoxing.com/api/token/uservalid' 44 | res = requests.get(url, headers=headers, cookies=cookie) 45 | tokendict = json.loads(res.text) 46 | return (tokendict['_token']) 47 | 48 | 49 | def upload(): # 上传图片 50 | if picname.isspace() or len(picname) == 0: 51 | return 52 | else: 53 | url = 'https://pan-yz.chaoxing.com/upload' 54 | files = {'file': (picname, open(picname, 'rb'), 55 | 'image/webp,image/*',), } 56 | res = requests.post(url, data={'puid': uid, '_token': token( 57 | )}, files=files, headers=headers, cookies=cookie) 58 | resdict = json.loads(res.text) 59 | return (resdict['objectId']) 60 | 61 | 62 | def taskactivelist(courseId, classId): # 查找签到任务 63 | global a 64 | url = "https://mobilelearn.chaoxing.com/ppt/activeAPI/taskactivelist" 65 | payload = {'courseId': str(courseId), 'classId': str(classId), 'uid': uid} 66 | res = requests.get(url, params=payload, headers=headers, cookies=cookie) 67 | respon = res.status_code 68 | if respon == 200: # 网页状态码正常 69 | data = json.loads(res.text) 70 | activeList = data['activeList'] # 把所有任务提出来 71 | for item in activeList: 72 | if ("nameTwo" not in item): 73 | continue 74 | if (item['activeType'] == 2 and item['status'] == 1): # 查找进行中的签到任务 75 | # signurl = item['url'] # 提取activePrimaryId 76 | aid = item['id'] # 提取activePrimaryId 77 | if (aid not in activates): # 查看是否签到过 78 | print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 79 | '[签到]', coursedata[i]['name'], '查询到待签到活动 活动名称:%s 活动状态:%s 活动时间:%s aid:%s' % ( 80 | item['nameOne'], item['nameTwo'], item['nameFour'], aid)) 81 | sign(aid, uid) # 调用签到函数 82 | a = 2 83 | else: 84 | print('error', respon) # 不知道为啥... 85 | 86 | 87 | def sign(aid, uid): # 签到,偷了个懒,所有的签到类型都用这个,我测试下来貌似都没问题 88 | global status, activates 89 | url = "https://mobilelearn.chaoxing.com/pptSign/stuSignajax" 90 | objectId = upload() 91 | data = {'name': name, 'address': address, 'activeId': aid, 'uid': uid, 92 | 'longitude': longitude, 'latitude': latitude, 'objectId': objectId} 93 | res = requests.post(url, data=data, headers=headers, cookies=cookie) 94 | push(SCKEY, res.text) 95 | print("签到状态:", res.text) 96 | activates.append(aid) 97 | status = 2 98 | 99 | 100 | def push(SCKEY, msg): 101 | if SCKEY.isspace() or len(SCKEY) == 0: 102 | return 103 | else: 104 | api = 'https://sc.ftqq.com/' + SCKEY + '.send' 105 | title = u"签到辣!" 106 | content = '课程: ' + coursedata[i]['name'] + '\n\n签到状态:' + msg 107 | data = { 108 | "text": title, 109 | "desp": content 110 | } 111 | req = requests.post(api, data=data) 112 | 113 | 114 | url = "http://mooc1-api.chaoxing.com/mycourse/backclazzdata?view=json&rss=1" 115 | res = requests.get(url, headers=headers, cookies=cookie) 116 | cdata = json.loads(res.text) 117 | if (cdata['result'] != 1): 118 | print("课程列表获取失败") 119 | for item in cdata['channelList']: 120 | if ("course" not in item['content']): 121 | continue 122 | pushdata = {} 123 | pushdata['courseid'] = item['content']['course']['data'][0]['id'] 124 | pushdata['name'] = item['content']['course']['data'][0]['name'] 125 | # pushdata['imageurl']=item['content']['course']['data'][0]['imageurl'] 126 | pushdata['classid'] = item['content']['id'] 127 | coursedata.append(pushdata) 128 | print("获取成功:") 129 | 130 | for item in coursedata: # 打印课程 131 | print(str(index) + ".课程名称:" + item['name']) 132 | index += 1 133 | 134 | while 1: 135 | for i in range(index): 136 | time.sleep(speed) # 休眠 137 | taskactivelist(coursedata[i]['courseid'], coursedata[i]['classid']) 138 | if a == 2: 139 | a = 0 140 | else: 141 | print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 142 | '[监控运行中]课程:', coursedata[i]['name'], '未查询到签到活动') 143 | -------------------------------------------------------------------------------- /old/多用户-test/chaoxingsign.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | import time 4 | import datetime 5 | # 用户写在同目录的json文件里 6 | # server酱推送 7 | SCKEY = '' 8 | name = '' # 签到后老师那里显示的名字,空着的话就是默认 9 | address = '火星' # 地址 10 | latitude = '32.2829260000' # 纬度 11 | longitude = '43.9237990000' # 经度 12 | picname = '' # 同目录下的照片名字,如果不用就留空 picname='' 13 | speed = 5 14 | with open('conf.json', 'r') as f: 15 | dict = json.load(f) 16 | print('获取配置成功') 17 | 18 | username = list(dict.keys()) 19 | passwd = list(dict.values()) # 将字典变成列表,方便操作 20 | session = requests.session() 21 | coursedata = [] 22 | activeList = [] 23 | activates = [] 24 | headers = { 25 | 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36'} 26 | 27 | 28 | def login(username, password): # 获取cookie 29 | url = 'https://passport2-api.chaoxing.com/v11/loginregister' 30 | data = {'uname': username, 'code': password, } 31 | session = requests.session() 32 | cookie_jar = session.post(url=url, data=data, headers=headers).cookies 33 | cookie_t = requests.utils.dict_from_cookiejar(cookie_jar) 34 | return cookie_t 35 | 36 | 37 | def subject(i): # 获取课程 38 | url = "http://mooc1-api.chaoxing.com/mycourse/backclazzdata" 39 | res = requests.get(url, headers=headers, cookies=cook[i]) 40 | cdata = json.loads(res.text) 41 | 42 | dict_n = {} 43 | if (cdata['result'] != 1): 44 | print("课程列表获取失败") 45 | for item in cdata['channelList']: 46 | if ("course" not in item['content']): 47 | continue 48 | pushdata = {} 49 | pushdata['user'] = str(i) # 插入用户标记 50 | pushdata['courseid'] = item['content']['course']['data'][0]['id'] 51 | pushdata['name'] = item['content']['course']['data'][0]['name'] 52 | pushdata['classid'] = item['content']['id'] 53 | 54 | coursedata.append(pushdata) 55 | # return coursedata 56 | 57 | 58 | def token(): # 获取上传图片用的token 59 | url = 'https://pan-yz.chaoxing.com/api/token/uservalid' 60 | res = requests.get(url, headers=headers, cookies=cook[0]) 61 | tokendict = json.loads(res.text) 62 | return (tokendict['_token']) 63 | 64 | 65 | def upload(): # 上传图片 66 | if picname.isspace() or len(picname) == 0: 67 | return 68 | else: 69 | url = 'https://pan-yz.chaoxing.com/upload' 70 | files = {'file': (picname, open(picname, 'rb'), 71 | 'image/webp,image/*',), } 72 | res = requests.post(url, data={'puid': str(cook[0]['UID']), '_token': token( 73 | )}, files=files, headers=headers, cookies=cook[0]) 74 | resdict = json.loads(res.text) 75 | return (resdict['objectId']) 76 | 77 | 78 | def taskactivelist(user, courseId, classId): # 查找签到任务 79 | global a 80 | url = "https://mobilelearn.chaoxing.com/ppt/activeAPI/taskactivelist?courseId=" + \ 81 | str(courseId) + "&classId=" + str(classId) + "&uid=" + str(cook[user]['UID']) 82 | res = requests.get(url, headers=headers, cookies=cook[user]) 83 | respon = res.status_code 84 | if respon == 200: # 网页状态码正常 85 | data = json.loads(res.text) 86 | activeList = data['activeList'] 87 | for item in activeList: 88 | if ("nameTwo" not in item): 89 | continue 90 | if (item['activeType'] == 2 and item['status'] == 1): 91 | aid = item['id'] # 提取activePrimaryId 92 | if (aid not in activates): 93 | print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 94 | '[签到]', coursedata[i]['name'], '查询到待签到活动 活动名称:%s 活动状态:%s 活动时间:%s aid:%s' % ( 95 | item['nameOne'], item['nameTwo'], item['nameFour'], aid)) 96 | sign(user, aid) # print('调用签到函数') 97 | a = 2 98 | else: 99 | print('error', respon) # 不知道为啥... 100 | 101 | 102 | def getvar(url): # 查找activePrimaryId 103 | var1 = url.split("&") 104 | for var in var1: 105 | var2 = var.split("=") 106 | if (var2[0] == "activePrimaryId"): 107 | return var2[1] 108 | return "ccc" 109 | 110 | 111 | def sign(user, aid): # 签到,偷了个懒,所有的签到类型都用这个,我测试下来貌似都没问题 112 | global status, activates 113 | url = "https://mobilelearn.chaoxing.com/pptSign/stuSignajax" 114 | objectId = upload() 115 | res = requests.post(url, data={"name": name, "address": address, 'activeId': aid, 'uid': str(cook[user]['UID']), 116 | 'longitude': longitude, 'latitude': latitude, 'objectId': objectId}, headers=headers, 117 | cookies=cook[user]) 118 | push(SCKEY, res.text) 119 | print("签到状态:", res.text) 120 | activates.append(aid) 121 | status = 2 122 | 123 | 124 | def push(SCKEY, msg): 125 | if SCKEY.isspace() or len(SCKEY) == 0: 126 | return 127 | else: 128 | api = 'https://sc.ftqq.com/' + SCKEY + '.send' 129 | title = u"签到辣!" 130 | content = '课程: ' + coursedata[i]['name'] + '\n\n签到状态:' + msg 131 | data = { 132 | "text": title, 133 | "desp": content 134 | } 135 | req = requests.post(api, data=data) 136 | 137 | 138 | cook = [] 139 | for i in range(len(dict)): 140 | a = login(username[i], passwd[i]) 141 | cook.append(a) 142 | 143 | for i in range(len(dict)): 144 | subject(i) 145 | index = 1 146 | for item in coursedata: # 打印课程 147 | if item['user'] != a: 148 | index = 1 149 | print("-" * 40) 150 | print('用户:' + item['user'], '-', str(index) + ".课程名称:" + item['name']) 151 | 152 | index += 1 153 | a = item['user'] 154 | 155 | while 1: 156 | for i in range(len(coursedata)): 157 | time.sleep(speed) # 休眠 158 | taskactivelist(eval(coursedata[i]['user']), coursedata[i]['courseid'], coursedata[i]['classid']) 159 | if a == 2: 160 | a = 0 161 | else: 162 | print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), '用户', coursedata[i]['user'], '[监控运行中]课程:', 163 | coursedata[i]['name'], '未查询到签到活动') 164 | -------------------------------------------------------------------------------- /old/多用户-test/conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "账号":"密码", 3 | "账号":"密码", 4 | "账号":"密码" 5 | } 6 | -------------------------------------------------------------------------------- /old/多用户-test/云函数版/cloud.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | import time 4 | import datetime 5 | session = requests.session() 6 | headers = { 7 | 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36'} 8 | allsubject = [] 9 | allname = [] 10 | allclassid = [] 11 | allcourseid=[] 12 | activates=[] 13 | allaid=[] 14 | cook=[] 15 | allobjectid=[] 16 | with open('conf.json', 'r', encoding='utf-8') as f: 17 | conf = json.loads(f.read()) 18 | print('获取配置成功') 19 | class CxSign(): #搞不懂class怎么用......... 20 | def __init__(self,num): #读取配置......(感觉可以写的更简单的......) 21 | CxSign.username = conf['username'][num] 22 | CxSign.passwd = conf['passwd'][num] 23 | if len(conf['SCKEY'])==1: 24 | CxSign.SCKEY = conf['SCKEY'][0] 25 | else: 26 | CxSign.SCKEY = conf['SCKEY'][num] 27 | 28 | if len(conf['name'])==1: 29 | CxSign.name = conf['name'][0] 30 | else: 31 | CxSign.name = conf['name'][num] 32 | 33 | if len(conf['address'])==1: 34 | CxSign.address = conf['address'][0] 35 | else: 36 | CxSign.address = conf['address'][num] 37 | 38 | if len(conf['longitude'])==1: 39 | CxSign.longitude = conf['longitude'][0] 40 | else: 41 | CxSign.longitude = conf['longitude'][num] 42 | 43 | if len(conf['latitude'])==1: 44 | CxSign.latitude = conf['latitude'][0] 45 | else: 46 | CxSign.latitude = conf['latitude'][num] 47 | 48 | if len(conf['picname'])==1: 49 | CxSign.picname = conf['picname'][0] 50 | else: 51 | CxSign.picname = conf['picname'][num] 52 | # self.name = conf['name'][num] 53 | # self.address = conf['address'][num] 54 | # self.longitude = conf['longitude'][num] 55 | # self.latitude = conf['latitude'][num] 56 | # self.picname = conf['picname'][num] 57 | # self.speed = conf['speed'] 58 | 59 | def login(num): # 获取cookie 60 | url = 'https://passport2-api.chaoxing.com/v11/loginregister' 61 | data = {'uname': CxSign(num).username, 'code': CxSign(num).passwd, } 62 | session = requests.session() 63 | cookie_jar = session.post(url=url, data=data, headers=headers).cookies 64 | cookie_t = requests.utils.dict_from_cookiejar(cookie_jar) 65 | cook.append(cookie_t) #把所有用户的cookie写进一个列表 66 | return cookie_t 67 | 68 | def subject(i): # 获取课程 69 | url = "http://mooc1-api.chaoxing.com/mycourse/backclazzdata" 70 | res = requests.get(url, headers=headers, cookies=cook[i]) 71 | cdata = json.loads(res.text) 72 | # coursedata=[] 73 | # dict_n = {} 74 | name = [] 75 | classid = [] 76 | courseid = [] 77 | if (cdata['result'] != 1): 78 | print("课程列表获取失败") 79 | for item in cdata['channelList']: 80 | if ("course" not in item['content']): 81 | continue 82 | pushdata = {} 83 | # pushdata['user'] = str(i) # 插入用户标记 84 | courseid.append(item['content']['course']['data'][0]['id']) 85 | name.append(item['content']['course']['data'][0]['name']) 86 | classid.append(item['content']['id']) 87 | allname.append(name)#把所有用户的数据存进列表...... 88 | allclassid.append(classid) 89 | allcourseid.append(courseid) 90 | # coursedata.append(pushdata) 91 | # allsubject.append(coursedata) 92 | # return coursedata 93 | 94 | def taskactivelist(i): # 查找签到任务 95 | global a 96 | aid=[] 97 | url = "https://mobilelearn.chaoxing.com/ppt/activeAPI/taskactivelist" 98 | for index in range(len(allname[i])):#轮询这个用户的所有课程... 99 | payload = {'courseId': str(allcourseid[i][index]), 'classId': str(allclassid[i][index]), 'uid': cook[i]['UID']} 100 | time.sleep(1.5) 101 | print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),'用户:',i,'正在查询课程:',allname[i][index]) 102 | res = requests.get(url, params=payload, headers=headers, cookies=cook[i]) 103 | respon = res.status_code 104 | # print(index) 105 | if respon == 200: # 网页状态码正常 106 | # print(res.text) 107 | data = json.loads(res.text) 108 | # print(data) 109 | activeList = data['activeList'] # 把所有任务提出来 110 | for item in activeList: # 轮询所有的任务 111 | if ("nameTwo" not in item): 112 | continue 113 | if (item['activeType'] == 2 and item['status'] == 1): # 查找进行中的签到任务 114 | # signurl = item['url'] # 提取activePrimaryId 115 | aid = item['id'] # 提取activePrimaryId 116 | if (aid not in activates): # 查看是否签到过 117 | print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 118 | '[签到]', allname[i][index], '查询到待签到活动 活动名称:%s 活动状态:%s 活动时间:%s aid:%s' % ( 119 | item['nameOne'], item['nameTwo'], item['nameFour'], aid)) 120 | CxSign.sign(aid,i,index) # 调用签到函数 121 | else: 122 | print('error', respon) # 不知道为啥... 123 | 124 | def token(self): # 获取上传图片用的token 125 | url = 'https://pan-yz.chaoxing.com/api/token/uservalid' 126 | res = requests.get(url, headers=headers, cookies=cook[0]) 127 | tokendict = json.loads(res.text) 128 | return (tokendict['_token']) 129 | 130 | def upload(i): # 上传图片 131 | try: 132 | picname=CxSign(i).picname 133 | except: 134 | picname='' 135 | 136 | if picname.isspace() or len(picname) == 0: 137 | return 138 | else: 139 | url = 'https://pan-yz.chaoxing.com/upload' 140 | files = {'file': (picname, open(picname, 'rb'), 141 | 'image/webp,image/*',), } 142 | res = requests.post(url, data={'puid': cook[0]['UID'], '_token': CxSign.token(i)}, files=files, headers=headers, cookies=cook[0]) 143 | resdict = json.loads(res.text) 144 | allobjectid.append(resdict['objectId']) 145 | # return (resdict['objectId']) 146 | 147 | def sign(aid,i,index): # 签到,偷了个懒,所有的签到类型都用这个,我测试下来貌似都没问题 148 | url = "https://mobilelearn.chaoxing.com/pptSign/stuSignajax" 149 | if len(CxSign(i).picname)==0: 150 | allobjectid.append('') #占位置,不然和用户ID对不上 151 | objectId ='' 152 | 153 | else: 154 | CxSign.upload(i) 155 | objectId=allobjectid[i] 156 | try: 157 | name=CxSign(i).name 158 | except: 159 | try: 160 | name = CxSign.name 161 | except: 162 | name='' 163 | 164 | try: 165 | address=CxSign(i).address 166 | except: 167 | try: 168 | address = CxSign.address 169 | except: 170 | address='' 171 | 172 | try: 173 | longitude = CxSign(i).longitude 174 | except: 175 | try: 176 | longitude = CxSign.longitude 177 | except: 178 | longitude='' 179 | try: 180 | latitude = CxSign(i).latitude 181 | except: 182 | try: 183 | latitude = CxSign.latitude 184 | except: 185 | latitude = '' 186 | 187 | data = {'name': name, 'address': address, 'activeId': aid, 'uid': cook[i]['UID'], 188 | 'longitude': longitude, 'latitude': latitude, 'objectId': objectId} 189 | # data = { 'activeId': aid, 'uid': cook[i]['UID'],} 190 | res = requests.post(url, data=data, headers=headers, cookies=cook[i]) 191 | print("签到状态:", res.text) 192 | if res.text == 'success': 193 | CxSign.push(i, index, res.text) 194 | 195 | def push(i,index, msg): 196 | try: 197 | E_SCKEY=CxSign(i).SCKEY 198 | except: 199 | try: 200 | E_SCKEY = CxSign.SCKEY 201 | except: 202 | E_SCKEY ='' 203 | if E_SCKEY.isspace() or len(E_SCKEY) == 0: 204 | 205 | return 206 | else: 207 | api = 'https://sc.ftqq.com/' +E_SCKEY + '.send' 208 | title = u"签到辣!" 209 | content ='用户:'+ str(i) + '\n\n课程: ' + allname[i][index] + '\n\n签到状态:' + msg 210 | data = { 211 | "text": title, 212 | "desp": content 213 | } 214 | requests.post(api, data=data) 215 | print('已推送') 216 | 217 | def main_handler(event, context): 218 | number=len(conf['username']) 219 | for n in range(number): 220 | CxSign.login(n) 221 | time.sleep(0.5) 222 | 223 | for m in range(number): 224 | CxSign.subject(m) 225 | time.sleep(0.5) 226 | 227 | for o in range(number): 228 | CxSign.taskactivelist(o) 229 | 230 | 231 | if __name__ == "__main__": 232 | main_handler("", "") 233 | -------------------------------------------------------------------------------- /old/多用户-test/云函数版/conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": [""], 3 | "passwd": [""], 4 | "SCKEY": [""], 5 | "name": [""], 6 | "address": [""], 7 | "latitude": ["32.2829260000"], 8 | "longitude": ["43.9237990000"], 9 | "picname": [""] 10 | } 11 | -------------------------------------------------------------------------------- /tools/刷关注.py: -------------------------------------------------------------------------------- 1 | import time,hashlib,requests,json 2 | b=53551893#用户开始的ID,一般不用改 3 | username=''#账号 4 | passwd=''#密码 5 | 6 | def enc(): 7 | m_time=str(int(time.time()*1000)) 8 | m_token='4faa8662c59590c6f43ae9fe5b002b42' 9 | m_encrypt_str='token='+m_token+'&_time='+m_time+'&DESKey=Z(AfY@XS' 10 | md5=hashlib.md5() 11 | md5.update(m_encrypt_str.encode('utf-8')) 12 | m_inf_enc=md5.hexdigest() 13 | return m_time,m_inf_enc 14 | def login(username,passwd): 15 | payload={'uname':username,'code':passwd,'roleSelect':'true','loginType':'1'} 16 | # headers1 = { 17 | # 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 6.0.1; HUAWEI ALE-CL00 Build/MOB31T) com.chaoxing.mobile/ChaoXingStudy_3_4.3.6_android_phone_496_27 (@Kalimdor)_57c3eb14b06a443db750026b3754a8ad',} 18 | 19 | s = requests.session() 20 | url='https://passport2-api.chaoxing.com/v11/loginregister' 21 | cookie_jar = s.post(url=url, params=payload, ) 22 | 23 | url2='https://sso.chaoxing.com/apis/login/userLogin4Uname.do' 24 | cookie_jar2 = s.get(url=url2,).cookies 25 | cookie_full = requests.utils.dict_from_cookiejar(cookie_jar2) 26 | return cookie_full 27 | 28 | cookie=login(username,passwd) 29 | headers = {'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 6.0.1; HUAWEI ALE-CL00 Build/MOB31T) com.chaoxing.mobile/ChaoXingStudy_3_4.3.6_android_phone_496_27 (@Kalimdor)_57c3eb14b06a443db750026b3754a8ad', 30 | 'Connection': 'Keep-Alive'} 31 | url='http://learn.chaoxing.com/apis/friend/addUserFollow' 32 | 33 | 34 | for i in range(50000): 35 | a = enc() 36 | payload = {'token': '4faa8662c59590c6f43ae9fe5b002b42', 37 | '_time': a[0], 38 | 'uid': '42528010', 39 | 'puid': b, 40 | 'followedUid': cookie['_tid'], 41 | 'followedPuid': cookie['_uid'], 42 | 'inf_enc': a[1], 43 | } 44 | b+=1 45 | req=requests.get(url,params=payload,cookies=cookie,headers=headers,allow_redirects=False) 46 | print(req.text) 47 | print(b) 48 | time.sleep(0.2) 49 | -------------------------------------------------------------------------------- /tools/刷收藏量.py: -------------------------------------------------------------------------------- 1 | import time,hashlib,requests,json,time 2 | 3 | username=''#账号 4 | passwd=''#密码 5 | book='nmsl'#书名 6 | writer='nmsl'#作者名字 7 | folder='109687111'#文件夹ID随便填就行 8 | 9 | picurl="https://i.loli.net/2020/04/03/kbzNxYAL7fstuoX.png"#图片链接 10 | 11 | 12 | data = [] 13 | data.append('--bBtm2w4jqNNple2J0jfYCgGEwpfAgF2zTaZZqG6Q\r\n') 14 | data.append('Content-Disposition: form-data; name="uid"\r\n') 15 | data.append('Content-Type: text/plain; charset=UTF-8\r\n') 16 | data.append('Content-Transfer-Encoding: 8bit\r\n') 17 | data.append('\r\n') 18 | data.append('117729841'+ '\r\n') 19 | data.append('--bBtm2w4jqNNple2J0jfYCgGEwpfAgF2zTaZZqG6Q\r\n') 20 | data.append('Content-Disposition: form-data; name="cfid"\r\n') 21 | data.append('Content-Type: text/plain; charset=UTF-8\r\n') 22 | data.append('Content-Transfer-Encoding: 8bit\r\n') 23 | data.append('\r\n') 24 | data.append(folder + '\r\n') 25 | data.append('--bBtm2w4jqNNple2J0jfYCgGEwpfAgF2zTaZZqG6Q\r\n') 26 | data.append('Content-Disposition: form-data; name="source"\r\n') 27 | data.append('Content-Type: text/plain; charset=UTF-8\r\n') 28 | data.append('Content-Transfer-Encoding: 8bit\r\n') 29 | data.append('\r\n') 30 | data.append('0\r\n') 31 | data.append('--bBtm2w4jqNNple2J0jfYCgGEwpfAgF2zTaZZqG6Q\r\n') 32 | data.append('Content-Disposition: form-data; name="resinfo"\r\n') 33 | data.append('Content-Type: text/plain; charset=UTF-8\r\n') 34 | data.append('Content-Transfer-Encoding: 8bit\r\n') 35 | datas = '' 36 | for i in data: 37 | datas += i 38 | data2=[] 39 | data2.append('\r\n') 40 | data2.append('--bBtm2w4jqNNple2J0jfYCgGEwpfAgF2zTaZZqG6Q\r\n') 41 | data2.append('Content-Disposition: form-data; name="version"\r\n') 42 | data2.append('Content-Type: text/plain; charset=UTF-8\r\n') 43 | data2.append('Content-Transfer-Encoding: 8bit\r\n') 44 | data2.append('\r\n') 45 | data2.append('8.6' + '\r\n') 46 | data2.append('--bBtm2w4jqNNple2J0jfYCgGEwpfAgF2zTaZZqG6Q--\r\n') 47 | datas2 = '' 48 | for i in data2: 49 | datas2 += i 50 | headers = {'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 6.0.1; HUAWEI ALE-CL00 Build/MOB31T) com.chaoxing.mobile/ChaoXingStudy_3_4.3.6_android_phone_496_27 (@Kalimdor)_57c3eb14b06a443db750026b3754a8ad', 51 | 'Content-Type':'multipart/form-data; boundary=bBtm2w4jqNNple2J0jfYCgGEwpfAgF2zTaZZqG6Q', 52 | 'Host':'apps.chaoxing.com', 53 | 'Connection': 'Keep-Alive'} 54 | 55 | def login(username,passwd): 56 | payload={'uname':username,'code':passwd,'roleSelect':'true','loginType':'1'} 57 | # headers1 = { 58 | # 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 6.0.1; HUAWEI ALE-CL00 Build/MOB31T) com.chaoxing.mobile/ChaoXingStudy_3_4.3.6_android_phone_496_27 (@Kalimdor)_57c3eb14b06a443db750026b3754a8ad',} 59 | 60 | s = requests.session() 61 | url='https://passport2-api.chaoxing.com/v11/loginregister' 62 | cookie_jar = s.post(url=url, params=payload, ) 63 | 64 | url2='https://sso.chaoxing.com/apis/login/userLogin4Uname.do' 65 | cookie_jar2 = s.get(url=url2,).cookies 66 | cookie_full = requests.utils.dict_from_cookiejar(cookie_jar2) 67 | return cookie_full 68 | 69 | cookie=login(username,passwd) 70 | 71 | 72 | def enc(): 73 | m_time=str(int(time.time()*1000)) 74 | m_token='4faa8662c59590c6f43ae9fe5b002b42' 75 | m_encrypt_str='token='+m_token+'&_time='+m_time+'&DESKey=Z(AfY@XS' 76 | md5=hashlib.md5() 77 | md5.update(m_encrypt_str.encode('utf-8')) 78 | m_inf_enc=md5.hexdigest() 79 | return m_time,m_inf_enc 80 | a=enc() 81 | print(a[0],a[1]) 82 | 83 | def favorite(time,enc): 84 | data1 = {"cataid": "100000001", "cataName": "专题", "key": 'mooc_'+id, 85 | "content": {"accountKey": "cx_fanya", "aid": "mooc_211237260", "appid": "024f788b762eefd3ea71e05d0c8e003f", 86 | "appname": book, "appurl": "https://special.zhexuezj.cn/mobile/mooc/tocourse/211237260", 87 | "available": 1, "bind": 1, "cataid": "100000001", "clientType": 127, "description": "", 88 | "focus": 0, "id": -1, "isPrivate": 1, "isWebapp": 1, "loginId": 2, "loginUrl": "", 89 | "logopath": picurl, 90 | "logoshowtype": 1, "needLogin": 0, "needRegist": 0, "norder": 0, 91 | "otherConfig": {"author": writer, "id": "mooc_211237260", "authorPuid": "126098093", "level": 1000}, 92 | "productId": 3, "properties": "", "rights": 1, "usable": "", "useClientTool": 2, 93 | "res_src": "market"}, "collectionFolder": 0,} 94 | alldata = datas + '\r\n' + json.dumps(data1) + '\r\n' + datas2 95 | 96 | url='http://apps.chaoxing.com/apis/subscribe/addExternalSubscribe.jspx?token=4faa8662c59590c6f43ae9fe5b002b42'+'&_time='+time+'&inf_enc='+enc 97 | res = requests.post(url,data=alldata,cookies=cookie, headers=headers,allow_redirects=False) 98 | print(res.text) 99 | # print(url) 100 | for x in range(5000): 101 | id=str(x) 102 | a = enc() 103 | favorite(a[0],a[1]) 104 | time.sleep(0.5) 105 | print(x) 106 | -------------------------------------------------------------------------------- /tools/刷笔记.py: -------------------------------------------------------------------------------- 1 | import time,hashlib,requests,json 2 | username=''#账号 3 | passwd=''#密码 4 | text='text' 5 | title='title' 6 | id=30000 #笔记编号 7 | D='b06d289b-b69a-44d8-a7ef-'#笔记编号 8 | #如果提示非个人笔记就改上面这些值,貌似是随机的,随便改,但是格式不能变, 9 | headers = {'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 6.0.1; HUAWEI ALE-CL00 Build/MOB31T) com.chaoxing.mobile/ChaoXingStudy_3_4.3.6_android_phone_496_27 (@Kalimdor)_57c3eb14b06a443db750026b3754a8ad', 10 | 'Connection': 'Keep-Alive'} 11 | def login(username,passwd): 12 | payload={'uname':username,'code':passwd,'roleSelect':'true','loginType':'1'} 13 | # headers1 = { 14 | # 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 6.0.1; HUAWEI ALE-CL00 Build/MOB31T) com.chaoxing.mobile/ChaoXingStudy_3_4.3.6_android_phone_496_27 (@Kalimdor)_57c3eb14b06a443db750026b3754a8ad',} 15 | 16 | s = requests.session() 17 | url='https://passport2-api.chaoxing.com/v11/loginregister' 18 | cookie_jar = s.post(url=url, params=payload, ) 19 | 20 | url2='https://sso.chaoxing.com/apis/login/userLogin4Uname.do' 21 | cookie_jar2 = s.get(url=url2,).cookies 22 | cookie_full = requests.utils.dict_from_cookiejar(cookie_jar2) 23 | return cookie_full 24 | 25 | cookie=login(username,passwd) 26 | def enc(): 27 | m_time=str(int(time.time()*1000)) 28 | m_token='4faa8662c59590c6f43ae9fe5b002b42' 29 | m_encrypt_str='token='+m_token+'&_time='+m_time+'&DESKey=Z(AfY@XS' 30 | md5=hashlib.md5() 31 | md5.update(m_encrypt_str.encode('utf-8')) 32 | m_inf_enc=md5.hexdigest() 33 | return m_time,m_inf_enc 34 | 35 | 36 | 37 | 38 | for i in range(20000): 39 | id+=1 40 | a=enc() 41 | url='https://noteyd.chaoxing.com/apis/note_note/uploadNote' 42 | payload={'token':'4faa8662c59590c6f43ae9fe5b002b42', 43 | '_time':a[0], 44 | 'inf_enc':a[1] 45 | } 46 | cid = D + str(id) 47 | data = {'action': '1', 48 | 'attachment': '', 49 | 'cid': cid, 50 | 'content': text, 51 | 'delete': '0', 52 | 'describes': 'Test3', 53 | 'files_url': '', 54 | 'isRtf': '1', 55 | 'notebookCid': '0', 56 | 'puid': cookie['_uid'], 57 | 'rtf_content': '%3Cp%3ETest1%3C%2Fp%3E', 58 | 'sort': '0.0', 59 | 'tag': '', 60 | 'title': title, 61 | 'top': '0', 62 | 'version': '0'} 63 | req=requests.post(url,params=payload,data=data,headers=headers,cookies=cookie) 64 | print(req.text) 65 | time.sleep(0.5) 66 | -------------------------------------------------------------------------------- /异步版/emmm.py: -------------------------------------------------------------------------------- 1 | import aiohttp 2 | import asyncio 3 | import requests 4 | import json 5 | 6 | 7 | headers = { 8 | 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.37'} 9 | name = '' 10 | address = '' 11 | longitude = '' 12 | latitude = '' 13 | objectId = '' 14 | 15 | 16 | class Objects: 17 | def __init__(self, item): 18 | self.courseid = item['content']['course']['data'][0]['id'] 19 | self.name = item['content']['course']['data'][0]['name'] 20 | self.classid = item['content']['id'] 21 | 22 | 23 | def login(username, passwd): # 获取cookie 24 | url = 'https://passport2-api.chaoxing.com/v11/loginregister' 25 | data = {'uname': username, 'code': passwd, } 26 | session = requests.session() 27 | cookie_jar = session.post(url=url, data=data,).cookies 28 | cookie_t = requests.utils.dict_from_cookiejar(cookie_jar) 29 | return cookie_t 30 | 31 | 32 | cookies = login('', '') 33 | uid = cookies['UID'] 34 | 35 | tasks1 = [] 36 | 37 | async def taskactivelist(courseId, classId, session): 38 | url = "https://mobilelearn.chaoxing.com/ppt/activeAPI/taskactivelist" 39 | payload = {'courseId': str(courseId), 'classId': str(classId), 'uid': uid} 40 | async with session.get(url, headers=headers, params=payload) as resp: 41 | if resp.status == 200: 42 | # print(await resp.text()) 43 | cdata = json.loads(await resp.text()) 44 | # activeList = cdata['activeList'] 45 | for item in cdata['activeList']: # 轮询所有的任务 46 | # print('>>>',item) 47 | if ("nameTwo" not in item): 48 | continue 49 | if (item['activeType'] == 2 and item['status'] == 1): # 查找进行中的签到任务 50 | aid = item['id'] # 提取activePrimaryId 51 | # print(item) 52 | print('>>>',aid) 53 | tasks1.append(asyncio.create_task(sign(aid, session))) 54 | await asyncio.gather(*tasks1) 55 | # sign(aid) 56 | 57 | async def sign(aid, session): # 签到,偷了个懒,所有的签到类型都用这个,我测试下来貌似都没问题 58 | await asyncio.sleep(2) 59 | url = "https://mobilelearn.chaoxing.com/pptSign/stuSignajax" 60 | data = { 'activeId': aid, 'uid': uid,} 61 | print(data) 62 | async with session.post(url, data=data) as resp: 63 | print(resp.status) 64 | # print(await resp.text()) 65 | 66 | # def sign(aid,): # 签到,偷了个懒,所有的签到类型都用这个,我测试下来貌似都没问题 67 | # url = "https://mobilelearn.chaoxing.com/pptSign/stuSignajax" 68 | # data = {'name': name, 'address': address, 'activeId': str(aid), 'uid': uid, 69 | # 'longitude': longitude, 'latitude': latitude, 'objectId': objectId} 70 | # res = requests.post(url, data=data, headers=headers, cookies=cookies) 71 | # print("签到状态:", res.text) 72 | 73 | async def subject(): # 获取课程 74 | url = "http://mooc1-api.chaoxing.com/mycourse/backclazzdata" 75 | async with aiohttp.ClientSession(cookies=cookies) as session: 76 | async with session.get(url) as resp: 77 | cdata = json.loads(await resp.text()) 78 | print(cdata) 79 | tasks = [] 80 | for item in cdata['channelList']: 81 | if ("course" not in item['content']): 82 | continue 83 | a = Objects(item) 84 | tasks.append(asyncio.create_task(taskactivelist(a.courseid, a.classid, session))) 85 | await asyncio.gather(*tasks) 86 | 87 | 88 | async def main(): 89 | await asyncio.create_task(subject()) 90 | 91 | 92 | asyncio.run(main()) 93 | --------------------------------------------------------------------------------