├── 1.png ├── 2.png ├── 3.png ├── README.md └── post_answer.py /1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Conastin/zhihuishuInteractiveScore/HEAD/1.png -------------------------------------------------------------------------------- /2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Conastin/zhihuishuInteractiveScore/HEAD/2.png -------------------------------------------------------------------------------- /3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Conastin/zhihuishuInteractiveScore/HEAD/3.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # -智慧树刷互动分 2 | # 运行环境 # 3 | > - **python3.X** 4 | > - **requests模块** 5 | # 介绍 # 6 | 1. 默认回答50个问题 7 | 2. 自动给自己的回答点赞 8 | # 注意 # 9 | 速度过快会封请求,解封时间半天到一天不等,time.sleep里的时间不要改 10 | # 使用教程 # 11 | 1. 浏览器打开[http://www.zhihuishu.com](http://www.zhihuishu.com "知到智慧树官网") 12 | 2. 登录你的账号 13 | 3. 访问随便一门课程的成绩分析(https://stuonline.zhihuishu.com/stuonline/stuLearnReportNew)前缀为这一网址,打开后再刷新一下 14 | 4. 访问随便一门课程的问答(https://creditqa-web.zhihuishu.com/shareCourse/qaAnswerIndexPage)前缀为这一网址,打开后再刷新一下 15 | 5. 返回智慧树个人首页(https://onlineh5.zhihuishu.com/onlineWeb.html#/studentIndex) 16 | 6. F12打开网络选项卡,刷新 17 | 7. CTRL+F搜索找到getLoginUserInfo这个名称,注意是xhr类型,复制该请求的cookie 18 | 8. 在postAnswer.py同目录下建立cookie.txt,打开cookie.txt,粘贴复制的cookie,保存 19 | 6. 运行postAnswer.py 20 | -------------------------------------------------------------------------------- /post_answer.py: -------------------------------------------------------------------------------- 1 | import json 2 | import random 3 | import time 4 | import os 5 | import requests 6 | import threading 7 | 8 | cookie = '' 9 | task = [] 10 | 11 | 12 | def read_cookie(): 13 | global cookie 14 | with open('cookie.txt') as f: 15 | cookie = f.read() 16 | 17 | 18 | def read_course(filename): 19 | with open('./course/' + filename + '.txt') as f: 20 | return json.loads(f.read()) 21 | 22 | 23 | def getLoginUserInfo() -> json: 24 | ''' 25 | 获取登录信息 26 | :return: 27 | ''' 28 | getInfo_url = 'https://onlineservice.zhihuishu.com/login/getLoginUserInfo' 29 | headers = { 30 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edg/81.0.416.77', 31 | 'Cookie': cookie, 32 | 'Host': 'onlineservice.zhihuishu.com', 33 | 'Origin': 'https://onlineh5.zhihuishu.com', 34 | 'Referer': 'https://onlineh5.zhihuishu.com/onlineWeb.html' 35 | } 36 | r = json.loads(requests.get(getInfo_url, headers=headers).text) 37 | return r 38 | 39 | 40 | def getCourseId(uuid) -> list: 41 | ''' 42 | 获取课程id 43 | :return: 44 | ''' 45 | getCourseId_url = 'https://onlineservice.zhihuishu.com/student/course/share/queryShareCourseInfo' 46 | data = { 47 | 'status': 0, 48 | 'pageNo': 1, 49 | 'pageSize': 50, 50 | 'uuid': uuid, 51 | } 52 | r = json.loads(requests.post(getCourseId_url, data=data).text) 53 | return r['result']['courseOpenDtos'] 54 | 55 | 56 | def isHaveInteractive(course_id, course_recruitId) -> bool: 57 | ''' 58 | 判断是否有互动分 59 | :param course_id: 课程id 60 | :return: True or False 61 | ''' 62 | check_url = 'https://stuonline.zhihuishu.com/stuonline/json/stuLearnReportNew/loadCourseForum/' 63 | data = { 64 | 'courseId': course_id, 65 | 'recruitId': course_recruitId, 66 | 'type': 'l', 67 | } 68 | r = json.loads(requests.post(check_url, data=data).text) 69 | interactiveScore = r['learnedInteractiveScore'] 70 | if interactiveScore == '0': 71 | return False 72 | return True 73 | 74 | 75 | def getInteractiveScore(course_id, course_recruitId) -> int: 76 | ''' 77 | 获得互动成绩 78 | :param course_id: 课程id 79 | :param course_recruitId: 课程recruitId 80 | :return: 返回还差多少互动分 81 | ''' 82 | getInteractiveScore_url = 'https://stuonline.zhihuishu.com/stuonline/json/stuLearnReportNew/loadCourseForum/' 83 | headers = { 84 | 'User-Agent': 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edg/81.0.416.77', 85 | 'Host': 'stuonline.zhihuishu.com', 86 | 'Origin': 'https://stuonline.zhihuishu.com', 87 | 'Referer': 'https://stuonline.zhihuishu.com/stuonline/stuLearnReportNew/index?recruitId=' + str( 88 | course_recruitId) + '&recruitId=' + str(course_id), 89 | 'Cookie': 'JSESSIONID=3E61714D8F18C66143C05EA18FE268E8; Z_LOCALE=1; exitRecod_dDQoqmlK=2; acw_tc=2f624a1b15913336014474538e47513802fdae9bd673ea0d7cacd79113d86d; privateCloudSchoolInfo_189362841=",1,#003333,https://image.zhihuishu.com/testzhs/myuni/home/201607/d99cafd14fd94370a8d991519ed445d1.png,https://image.zhihuishu.com/testzhs/myuni/home/201608/65046fface9e4795aa6c75eb484d7f4b.png,1511,//school.zhihuishu.com/sdmu,"; CASTGC=TGT-2340486-Q6QsZO5EJcwmfVm4qCIOz5EOlkxdccaekuHH2ysF1C9xFkglFa-passport.zhihuishu.com; CASLOGC=%7B%22realName%22%3A%22%E7%8E%8B%E5%AE%89%E7%90%AA%22%2C%22myuniRole%22%3A0%2C%22myinstRole%22%3A0%2C%22userId%22%3A189362841%2C%22headPic%22%3A%22https%3A%2F%2Fimage.zhihuishu.com%2Fzhs%2Fablecommons%2Fdemo%2F201804%2F586a2783a3054bd9a751dbbe5979b530_s3.jpg%22%2C%22uuid%22%3A%22dDQoqmlK%22%2C%22mycuRole%22%3A0%2C%22username%22%3A%22abc9ff5cf3c74fd88d9b227bd51448e5%22%7D; o_session_id=F3BAE46D8A54BDC865AA27C74CA2BA83; u_asec=099%23KAFEH7EKExSEhYTLEEEEEpEQz0yFD6fJSryoa6thSri7W6gTZcvMV6PHBYFETEEEbORuE7EFNIaHFXYTEHIEj%2FYEjrozRhj2iEAkWw7e0HzcmCXGkLFABFt05cToKi7bkfMWVDGt0HzqwHyu0HUAqmoRyUQAqHGtkfMWVDGNqCA0DLO4BwSG35t3yUQAqHGbBEFE13iSEqmrwTbUsYFET%2FyZTEwmLuGTE1LSt3llF4qRd%2FiS1JRP%2F3oGt37MlXZddqLStTLSsyaGC3iS1RRP%2F3w3AYFE4GEAb%2FZdCwUQrjDt929irOon6YA6b0dt6R7SwGCvasUBbyo6929irOon6YA6b0WVcOU81Ge8C18CcRfcaVOlrVXS6dbROKqVbOFVwGCYWipXh0%2Bu%2FrRFbyXWcMQRv98XhjYy9nsvSa7WcL%2Bc73%2F5rieWqgwqQodt6R7SwGCvasUBbyo692RRqOpneod3bq4B6weZa5MTEEySt9llsya5E7EFt37EFE%3D%3D; SERVERID=472b148b148a839eba1c5c1a8657e3a7|1591347313|1591347291' 90 | } 91 | data = { 92 | 'courseId': course_id, 93 | 'recruitId': course_recruitId, 94 | 'type': 'l' 95 | } 96 | r = json.loads(requests.post(getInteractiveScore_url, data=data, headers=headers).text) 97 | learnedInteractiveScore = int(r['learnedInteractiveScore']) 98 | learnedInteractiveTotalScore = int(r['learnedInteractiveTotalScore']) 99 | return learnedInteractiveTotalScore - learnedInteractiveScore 100 | 101 | 102 | def getQaNum(course_id, course_recruitId) -> int: 103 | ''' 104 | 获得答题数量 105 | :param course_id: 课程id 106 | :param course_recruitId: 课程recruitId 107 | :return: 返回当前课程下目前的答题数量 108 | ''' 109 | getQaNum_url = 'https://creditqa.zhihuishu.com/creditqa/web/qa/myParticipateQaNum' 110 | data = { 111 | 'uuid': uuid, 112 | 'sourceType': 2, 113 | 'courseId': course_id, 114 | 'recruitId': course_recruitId, 115 | } 116 | headers = { 117 | 'User-Agent': 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edg/81.0.416.77', 118 | 'Host': 'creditqa.zhihuishu.com', 119 | 'Origin': 'https://qah5.zhihuishu.com', 120 | 'Referer': 'https://qah5.zhihuishu.com/', 121 | 'Cookie': cookie 122 | } 123 | r = json.loads(requests.post(getQaNum_url, data=data, headers=headers).text) 124 | return r['rt']['answerNum'] 125 | 126 | 127 | def getQuestionId(course_id, course_recruitId, num=500) -> list: 128 | ''' 129 | 获取问题id 130 | :param course_id: 课程id 131 | :param course_recruitId: 课程recruitId 132 | :param num: 获取问题数量 默认500 133 | :return: 返回包含问题id的集合 134 | ''' 135 | getQuestionId_url = 'https://creditqa.zhihuishu.com/creditqa/web/qa/getHotQuestionList' 136 | headers = { 137 | 'Referer': 'https://qah5.zhihuishu.com/', 138 | 'Host': 'creditqa.zhihuishu.com', 139 | 'Origin': 'https://qah5.zhihuishu.com', 140 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edg/81.0.416.77', 141 | 'Cookie': cookie 142 | } 143 | data = { 144 | 'recruitId': course_recruitId, 145 | 'courseId': course_id, 146 | 'pageSize': num, 147 | 'pageIndex': 0, 148 | 'uuid': uuid 149 | } 150 | r = json.loads(requests.post(getQuestionId_url, data=data, headers=headers).text) 151 | # print(r) 152 | question_list = r['rt']['questionInfoList'] 153 | # for question in question_list: 154 | # # 获取到问题id, 获取别人的回答 155 | # print(question['questionId'], question['content']) 156 | return question_list 157 | 158 | 159 | def getAnswer(course_recruitId, course_id, question_id): 160 | ''' 161 | 获取别人的回答 162 | :param course_id: 课程id 163 | :param course_recruitId: 课程recruitId 164 | :param question_id: 165 | :return: 166 | ''' 167 | getAnser_url = 'https://creditqa.zhihuishu.com/creditqa/web/qa/getAnswerInInfoOrderByTime' 168 | headers = { 169 | 'Cookie': cookie, 170 | 'Referer': 'https://qah5.zhihuishu.com/', 171 | 'Host': 'creditqa.zhihuishu.com', 172 | 'Origin': 'https://qah5.zhihuishu.com', 173 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edg/81.0.416.77' 174 | } 175 | data = { 176 | 'pageSize': 100, 177 | 'pageIndex': 0, 178 | 'questionId': question_id, 179 | 'sourceType': 2, 180 | 'recruitId': course_recruitId, 181 | 'courseId': course_id, 182 | 'uuid': uuid 183 | } 184 | r = json.loads(requests.post(getAnser_url, data=data, headers=headers).text) 185 | answer_list = r['rt']['answerInfos'] 186 | return answer_list 187 | 188 | 189 | def postAnswer(question_id, answer, course_id, course_recruitId): 190 | postAnswer_url = 'https://creditqa.zhihuishu.com/creditqa/web/qa/saveAnswer' 191 | headers = { 192 | 'Cookie': cookie, 193 | 'Referer': 'https://qah5.zhihuishu.com/', 194 | 'Host': 'creditqa.zhihuishu.com', 195 | 'Origin': 'https://qah5.zhihuishu.com', 196 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edg/81.0.416.77' 197 | } 198 | data = { 199 | 'qid': question_id, 200 | 'aContent': answer, 201 | 'source': 2, 202 | 'uuid': uuid 203 | } 204 | requests.post(postAnswer_url, data=data, headers=headers) 205 | 206 | 207 | def getMyAnswerList(course_id, course_recruitId): 208 | url = 'https://creditqa.zhihuishu.com/creditqa/web/qa/myParticipateQaNum' 209 | headers = { 210 | 'Referer': 'https://qah5.zhihuishu.com/', 211 | 'Host': 'creditqa.zhihuishu.com', 212 | 'Origin': 'https://qah5.zhihuishu.com', 213 | 'cookie': cookie, 214 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 Edg/83.0.478.45' 215 | } 216 | data = { 217 | 'sourceType': 2, 218 | 'courseId': course_id, 219 | 'recruitId': course_recruitId, 220 | 'uuid': uuid 221 | } 222 | r = json.loads(requests.post(url, headers=headers, data=data).text) 223 | if r['status'] == '200': 224 | num = r['rt']['answerNum'] 225 | print(num) 226 | else: 227 | return 'error' 228 | url = 'https://creditqa.zhihuishu.com/creditqa/web/qa/myAnswerList' 229 | headers = { 230 | 'Referer': 'https://qah5.zhihuishu.com/', 231 | 'Host': 'creditqa.zhihuishu.com', 232 | 'Origin': 'https://qah5.zhihuishu.com', 233 | 'cookie': cookie, 234 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36 Edg/83.0.478.45' 235 | } 236 | answer = [] 237 | i = 0 238 | while num > 0: 239 | num -= 200 240 | data = { 241 | 'courseId': course_id, 242 | 'recruitId': course_recruitId, 243 | 'pageSize': 200, 244 | 'pageIndex': i, 245 | 'uuid': uuid 246 | } 247 | r = json.loads(requests.post(url, headers=headers, data=data).text) 248 | if r['status'] == '200': 249 | answer += r['rt']['myAnswers'] 250 | i += 1 251 | return answer 252 | 253 | 254 | def postLike(answer_id, course_id, course_recruitId): 255 | url = 'https://creditqa.zhihuishu.com/creditqa/web/qa/updateOperationToLike' 256 | headers = { 257 | 'Referer': 'https://qah5.zhihuishu.com/', 258 | 'Host': 'creditqa.zhihuishu.com', 259 | 'Origin': 'https://qah5.zhihuishu.com', 260 | 'cookie': cookie 261 | } 262 | data = { 263 | 'answerId': answer_id, 264 | 'islike': 0, 265 | 'sourceType': 2, 266 | 'uuid': uuid 267 | } 268 | r = json.loads(requests.post(url, headers=headers, data=data).text) 269 | if r['status'] == '200': 270 | print(' answer_id:', answer_id, ' 点赞成功') 271 | else: 272 | print(' answer_id:', answer_id, ' 点赞失败:', r) 273 | 274 | 275 | def func_getAllCourse(): 276 | userInfo = getLoginUserInfo() 277 | course_save = [] 278 | if userInfo['code'] == 403: 279 | print('未登录') 280 | else: 281 | # print(userInfo) 282 | userName = userInfo['result']['realName'] 283 | global uuid 284 | uuid = userInfo['result']['uuid'] 285 | print(userName, uuid) 286 | course_list = getCourseId(uuid) 287 | for course in course_list: 288 | course_id = course['courseId'] 289 | course_name = course['courseName'] 290 | course_recruitId = course['recruitId'] 291 | print(course_id, course_recruitId, course_name, end=' ') 292 | # if course_recruitId == 21383 and course_id == 2066435: 293 | # continue 294 | if isHaveInteractive(course_id, course_recruitId): 295 | course_save.append( 296 | { 297 | 'course_id': course_id, 298 | 'course_recruitId': course_recruitId, 299 | } 300 | ) 301 | with open('./course/course_' + uuid + '_' + userName + '.txt', 'w') as f: 302 | f.write(json.dumps(course_save)) 303 | return 'course_' + uuid + '_' + userName 304 | 305 | 306 | def func_postAnswer(filename, number=50): 307 | courses = read_course(filename) 308 | for course in courses: 309 | course_id = course['course_id'] 310 | course_recruitId = course['course_recruitId'] 311 | print(course_id, course_recruitId) 312 | # score = getInteractiveScore(course_id, course_recruitId) 313 | # print('还需要', score, '分') 314 | count = 0 315 | print('开始时作答数目: ', getQaNum(course_id, course_recruitId)) 316 | question_list = getQuestionId(course_id, course_recruitId, num=number) 317 | for question in question_list: 318 | question_id = question['questionId'] 319 | questionInfo = question['content'] 320 | answer_list = getAnswer(course_id, course_recruitId, question_id) 321 | try: 322 | if len(answer_list) == 0: 323 | continue 324 | answer = answer_list[random.randint(0, len(answer_list) - 1)]['answerContent'] 325 | count += 1 326 | print(count, '. ', question_id, ' -> ', questionInfo, ' : ', answer, end=' ') 327 | postAnswer(question_id, answer, course_id, course_recruitId) 328 | time.sleep(3) 329 | QaNum = getQaNum(course_id, course_recruitId) 330 | print(QaNum) 331 | if QaNum == number: 332 | break 333 | except: 334 | print('ERROR: ', question) 335 | print('结束时作答数目: ', getQaNum(course_id, course_recruitId)) 336 | print('共提交题目:', count) 337 | 338 | 339 | def func_getAllAnswer(filename): 340 | courses = read_course(filename) 341 | for course in courses: 342 | course_id = course['course_id'] 343 | course_recruitId = course['course_recruitId'] 344 | answerList = { 345 | 'course_id': course_id, 346 | 'course_recruitId': course_recruitId, 347 | 'aid': [] 348 | } 349 | MyAnswerList = getMyAnswerList(course_id, course_recruitId) 350 | for answer in MyAnswerList: 351 | answerList['aid'].append(answer['aid']) 352 | print(answerList) 353 | with open('./answer/answer_' + str(course_id) + '_' + str(answerList['aid'][0]) + '.txt', 'w') as f: 354 | f.write(json.dumps(answerList)) 355 | 356 | 357 | def func_like(): 358 | files = os.listdir('./answer') 359 | for file in files: 360 | with open('./answer/' + file) as f: 361 | answerList = json.loads(f.read()) 362 | course_id = answerList['course_id'] 363 | course_recruitId = answerList['course_recruitId'] 364 | print(course_id, course_recruitId) 365 | # for answer_id in answerList['aid']: 366 | # print(i, ' : ', answer_id) 367 | task.append( 368 | threading.Thread(target=thread_postLike, args=(answerList['aid'], course_id, course_recruitId,))) 369 | for thread in task: 370 | thread.start() 371 | for thread in task: 372 | thread.join() 373 | 374 | 375 | def thread_postLike(answerList, course_id, course_recruitId): 376 | for answer_id in answerList: 377 | postLike(answer_id, course_id, course_recruitId) 378 | 379 | 380 | if __name__ == '__main__': 381 | read_cookie() 382 | filename = func_getAllCourse() 383 | func_postAnswer(filename) 384 | func_getAllAnswer(filename) 385 | func_like() 386 | --------------------------------------------------------------------------------