构思
整体思路
通过API调用获取错题信息,将数据存入数据库(保证可长期查看),通过python+django将数据库数据在前端呈现。
实施思路
1、通过抓包获取到小程序相对应的错题集API信息(url、path、参数、请求方法),分析响应信息,分析获取API之间的关联关系,输出API文档。
2、通过数据关系,搭建数据库结构,创建数据库表。
3、设计方法类:
1)调用API,获取响应数据
2)将响应数据存入数据库
3)后端读取数据库数据,并返回前端界面。
4)前端设计错题以卡片的形式展示错题集。
实施过程
调用API获取响应数据
抓包获取API信息
使用charles进行抓包,因为小程序使用的是HTTPS请求,此处代理需要开启HTTPS代理请求,建议开启全局代理(即计算机代理),其实在开始charles时会默认开启。在此需要设置HTTPS的代理端口。
【问题】
1、抓包小程序需要清理小程序缓存,查询WMPFRuntime文件夹所在位置,删除该文件夹即可。
2、抓包小程序过程中,总提示小程序认证失败,再次登录却提示“设备参数缺失”,此时可以先退出charles,登陆后再打开charles,即可正常获取认证信息。
3、获取的API信息,其中的token,在python设置参数时需要进行url解码,再进行请求。
python发送HTTPS请求
1 def GetExercisebook(): 2 # SQL集 3 4 pmpExerciseManualInsertSQL = \"INSERT INTO `mysql_python`.`pmp_exercise_manual` (`id`, `history_id`, `subject`, `name`, `exam_type_id`) VALUES (%s, %s, %s, %s, %s);\" 5 pmpManualSubjectInsertSQL = \"INSERT INTO `mysql_python`.`pmp_manual_subject` (`manual`, `subject`) VALUES (%s, %s);\" 6 pmpSubjectInsertSQL = \"INSERT INTO `mysql_python`.`pmp_subject` (`subjectId`, `type_name`, `content`, `opt`, `correct_answer`, `analysis`, `label_text`) VALUES (%s, %s, %s, %s, %s, %s, %s);\" 7 8 # token 值(不同设备登陆后需要更新此部分) 9 TOKEN_NEW = \'********\' 10 11 # 获取问题集---请求参数params 12 VALUE = {\"clienttype\": \"2\", 13 \"exam_type\": \"****\", 14 \"isBusy\": \"true\", 15 \"isOver\": \"false\", 16 \"loadingTips\": \"*******\", 17 \"login_status\": \"2\", 18 \"page\": \"0\", 19 \"pageSize\": \"100\", 20 \"login_status\": \"2\", 21 \"token\": TOKEN_NEW 22 } 23 url = \"https://*******/api/v2/****/****/history/exercise\" 24 payload = \"\" 25 headers = { 26 } 27 print(\"*********************开始发送请求********************\") 28 ResponseProblemBook = requests.request(\"GET\", url, headers=headers, data=payload, params=VALUE) 29 print(ResponseProblemBook.request) 30 ProblemBook = ResponseProblemBook.json() 31 subjectDetailList = ProblemBook[\'data\'] 32 print(\"*********************获取响应成功********************\") 33 34 # 遍历获取习题信息 35 num = 0 36 pmpExerciseManualInsertVal = [] 37 for num in range(len(subjectDetailList)): 38 pmpManualSubjectInsertVal = [] 39 pmpSubjectInsertVal = [] 40 id = subjectDetailList[num][\'id\'] 41 history_id = subjectDetailList[num][\'history_id\'] 42 name = subjectDetailList[num][\'name\'] 43 exam_type_id = subjectDetailList[num][\'exam_type_id\'] 44 subject = subjectDetailList[num][\'subject\'] 45 bSubject = qieString(subject) 46 for subjectId in bSubject: 47 pmpManualSubjectInsertResult = (id, subjectId) 48 pmpManualSubjectInsertVal.append(pmpManualSubjectInsertResult) 49 url_2 = \"https://*******/api/v2/****/****/\" + subjectId + \"/analysis\" 50 VALUE_2 = {\"id\": subjectId, 51 \"exam_type\": \"****\", 52 \"clienttype\": \"2\", 53 \"login_status\": \"2\", 54 \"token\": TOKEN_NEW 55 } 56 response_2 = requests.request(\"GET\", url_2, headers=headers, data=payload, params=VALUE_2) 57 response_b = response_2.json() 58 subjectDetailList_b = response_b[\'data\'] 59 type_name_b = subjectDetailList_b[\'type_name\'] # 题目类型 60 correct_answer_b = subjectDetailList_b[\'correct_answer\'] # 答案 61 content_b = subjectDetailList_b[\'content\'] # 问题 62 analysis_b = subjectDetailList_b[\'analysis\'] # 分析 63 opt_b = subjectDetailList_b[\'opt\'] # 选项 64 label_text_b = subjectDetailList_b[\'label_text\'] # 分类标准 65 pmpSubjectInsertResult = ( 66 subjectId, type_name_b, content_b, opt_b, correct_answer_b, analysis_b, label_text_b) 67 pmpSubjectInsertVal.append(pmpSubjectInsertResult) 68 Save_Mysql(pmpManualSubjectInsertSQL, pmpManualSubjectInsertVal) 69 Save_Mysql(pmpSubjectInsertSQL, pmpSubjectInsertVal) 70 print(\'获取关联表成功:\', pmpManualSubjectInsertVal) 71 pmpExerciseManualInsertResult = (id, history_id, subject, name, exam_type_id) 72 pmpExerciseManualInsertVal.append(pmpExerciseManualInsertResult) 73 # print(\'获取习题集成功:\', name) 74 num = num + 1 75 Save_Mysql(pmpExerciseManualInsertSQL, pmpExerciseManualInsertVal)
将响应值存入数据库
1 # 将题目存入数据库,无返回值 2 def Save_Mysql(sql, val): 3 HOST = \'localhost\' 4 PORT = 3306 5 USER = \'root\' 6 PASSWORD = \'XF950701.\' 7 8 connection = pymysql.connect(host=HOST, port=PORT, user=USER, password=PASSWORD, db=\'mysql_python\', charset=\'utf8\') 9 try: 10 cursor = connection.cursor() 11 12 cursor.executemany(sql, val) 13 connection.commit() 14 print(\"插入成功数据:\", cursor.rowcount) 15 except Exception: 16 print(\"插入失败\") 17 finally: 18 cursor.close() # 关闭游标连接 19 connection.close() 20 21 22 # 读取数据库数据输出表格 23 def qieString(subject): 24 aString = subject 25 bString = re.sub(u\"\\\\[|\\\\]\", \'\', aString) 26 cString = bString.split(\',\') 27 return cString
获取数据库数据
1 def GetPnP(sql): 2 HOST = \'localhost\' 3 PORT = 3306 4 USER = \'root\' 5 PASSWORD = \'XF950701.\' 6 7 conn = pymysql.connect(host=HOST, port=PORT, user=USER, password=PASSWORD, 8 db=\'mysql_python\', 9 charset=\'utf8\') 10 # 生成sql语句 利用传入的BankConsentId进行条件查询 11 authorize_sql = sql 12 cursor = conn.cursor() 13 try: 14 cursor.execute(authorize_sql) 15 desc = cursor.description # 获取字段的描述 16 data = [dict(zip([col[0] for col in desc], row)) for row in 17 cursor.fetchall()] 18 except: 19 conn.rollback() 20 cursor.close() 21 conn.close() 22 return data
将数据格式化后返回前端页面
1 def GetExercisebook(request): 2 p1 = \"<p>|</p>\" 3 from Myapp.Dao.HttpsRequest.getpnp import GetPnP 4 5 authorize_sql = \"SELECT Id,subjectId,type_name,content,correct_answer,analysis FROM pmp_subject\" 6 data = GetPnP(authorize_sql) 7 context = {\"code\": 200, \"data\": data} 8 JsonDupsContext = json.dumps(context) 9 opt_demo = re.sub(p1, \'\', JsonDupsContext) 10 JsonLoadsContext = json.loads(opt_demo) 11 return render(request, \'Exercisebook.html\', JsonLoadsContext) 12 13 14 def GetOpt(request): 15 p1 = \"<p>|</p>\" 16 from Myapp.Dao.HttpsRequest.getpnp import GetPnP 17 subjectId = request.GET[\'subjectId\'] 18 authorize_sql = \"SELECT opt FROM pmp_subject where subjectId = \"+subjectId 19 opt =GetPnP(authorize_sql) 20 opt_demo = re.sub(p1, \"\", opt[0][\'opt\']) 21 context = json.loads(opt_demo) 22 return JsonResponse(context, safe=False)
前端呈现
1 <!DOCTYPE html> 2 <html lang=\"en\"> 3 <head> 4 <meta charset=\"UTF-8\"> 5 6 7 <title>Exercisebook</title> 8 <meta charset=\"UTF-8\"> 9 <title>卡片效果</title> 10 <style type=\"text/css\"> 11 .cardBox { 12 width: 200px; 13 box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); 14 text-align: center; 15 float: left; 16 margin-right: 10px; 17 padding: 5px; 18 padding-top: 15px; 19 } 20 21 .headerBox { 22 color: #fff; 23 padding: 10px; 24 font-size: 15px; 25 height: 60px; 26 } 27 28 .bodyBox { 29 padding: 10px; 30 } 31 32 .bodyBox p { 33 margin-left: 5px; 34 } 35 </style> 36 <script> 37 function GetOpt(data) { 38 var subjectId = data; 39 $.get(\'/GetOpt/\',{ 40 \'subjectId\': subjectId 41 },function (ret){ 42 var a = \"\"; 43 opt = ret; 44 console.log(opt) 45 for(var i = ret.length -1; i >=0 ; i--) { 46 a = ret[i][\'label\']+\":\"+ret[i][\'content\']+\'<br>\'+a; 47 document.getElementById(subjectId).innerHTML=a; 48 } 49 } 50 ) 51 } 52 </script> 53 </head> 54 </head> 55 <body> 56 <div style=\"text-align: center;width: 90%\"> 57 <div hidden=\'1000\'> 58 <h1 style=\"text-align: center\">错题集 </h1> 59 </div> 60 61 <div style=\"text-align: center;width: 100%\"> 62 <div style=\"text-align: center\"> 63 {% for List in data %} 64 <div class=\"cardBox\" style=\"text-align:center;width: 22%;height: 600px\"> 65 66 <!--卡片头部标签--> 67 <div class=\"headerBox\" style=\"background-color: #3c5bc2;height: 40px\"> 68 <p> 69 <a title=\"查看详情\" style=\"cursor: pointer; color:white\">第{{ List.Id }}题({{ List.type_name }})</a> 70 </p> 71 </div> 72 <!--题目--> 73 <div class=\"bodyBox\"> 74 <p style=\"text-align: left\">{{ List.content }}</p> 75 </div> 76 <!--选项--> 77 <div class=\"bodyBox\"> 78 <script> 79 window.onload=GetOpt({{ List.subjectId }}); 80 </script> 81 <p id=\"{{ List.subjectId }}\" style=\"text-align: left\"> 82 </p> 83 </div> 84 <!--答案 分析--> 85 <div class=\"bodyBox\"> 86 <p style=\"text-align: left\">{{ List.correct_answer }}</p> 87 <br> 88 <p style=\"text-align: left\">{{ List.analysis }}</p> 89 </div> 90 </div> 91 {% endfor %} 92 </div> 93 </div> 94 </div> 95 96 </body> 97 </html>
来源:https://www.cnblogs.com/yunxike/p/16575040.html
本站部分图文来源于网络,如有侵权请联系删除。