123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382 |
- """
- 接口
- """
- import os
- import time
- import bs4
- import requests
- import common
- import config
- import warnings
- warnings.filterwarnings("ignore")
- errCount = 0
- def calctime(m_func):
- def decorter(*args, **kwargs):
- start = time.time()
- res = m_func(*args, **kwargs)
- end = time.time()
- # print(m_func.__name__+" spend time is "+str(end-start))
- return res
- return decorter
- @calctime
- def login():
- url = "https://" + config.domain + "/api/ecs_core/auth/login"
- data = {"rootOrgId": None, "domain": config.domain.replace("exam-cloud.cn", "ecs.qmth.com.cn"),
- "accountType": "COMMON_LOGIN_NAME", "accountValue": config.username, "password": config.password,
- "smsCode": None}
- result = requests.post(url, json=data, verify=False)
- if result.status_code == 200:
- config.header = {
- "key": result.json()["key"],
- "token": result.json()['token']
- }
- config.rootOrgId = result.json()["rootOrgId"]
- print('登录成功!')
- else:
- print('登录失败,请检查配置参数或网络是否正常!')
- raise Exception("登录失败")
- @calctime
- def doExport():
- print('')
- if len(config.examIds) == 0:
- print("配置参数“examIds”不能为空!")
- return None
- login()
- print('examIds:' + config.examIds)
- print('courseIds:' + config.courseIds)
- print('queryStudentCodes:' + config.queryStudentCodes)
- print('skipStudentCodes:' + config.skipStudentCodes)
- print('useStudentCodePath:' + config.useStudentCodePath)
- print('outputPath:' + config.outputpath)
- examIds = config.examIds.split(',')
- for examId in examIds:
- if len(config.courseIds) > 0:
- courseIds = config.courseIds.split(',')
- for courseId in courseIds:
- if len(config.queryStudentCodes) > 0:
- studentCodes = config.queryStudentCodes.split(',')
- for studentCode in studentCodes:
- querydetail(1, examId, courseId, studentCode)
- else:
- querydetail(1, examId, courseId, None)
- else:
- if len(config.queryStudentCodes) > 0:
- studentCodes = config.queryStudentCodes.split(',')
- for studentCode in studentCodes:
- querydetail(1, examId, None, studentCode)
- else:
- querydetail(1, examId, None, None)
- print('')
- print("全部执行完成,失败数:" + str(errCount))
- @calctime
- def querydetail(curpage, examId, courseId, studentCode):
- print('')
- global errCount
- url = "https://" + config.domain + "/api/ecs_oe_admin/exam/record/detail/list"
- params = {"rootOrgId": config.rootOrgId, "examRecordDataId": None, "hasStranger": None, "courseId": courseId,
- "courseLevel": None,
- "examId": examId, "faceSuccessPercentLower": None, "faceSuccessPercentUpper": None,
- "identityNumber": None,
- "orgId": None, "studentCode": studentCode, "studentName": None, "isWarn": None, "pageNo": curpage,
- "pageSize": 500,
- "startTime": None, "endTime": None, "infoCollector": None, "hasVirtual": None, "ORG_FIND_ALL": True,
- "examStageId": "", "examType": "ONLINE"}
- result = requests.post(url, json=params, headers=config.header, verify=False)
- if result.status_code == 200:
- contents = result.json()["content"]
- totalPages = result.json()["totalPages"]
- totalElements = result.json()["totalElements"]
- print("---> totalElements=" + str(totalElements) + " totalPages=" + str(totalPages)
- + " curPage=" + str(curpage) + " examId=" + str(examId) + " courseId=" + str(courseId))
- for content in contents:
- try:
- solveexamRecord(examId, content)
- except Exception as e:
- errCount += 1
- print("网络异常,下载失败! " + content["courseCode"] + "_" + content["identityNumber"]
- + "_" + content["studentName"] + " 失败数:" + str(errCount))
- if curpage < totalPages:
- querydetail(curpage + 1, examId, courseId)
- else:
- raise Exception("获取数据失败,请检查配置参数或网络是否正常!")
- @calctime
- def findExamRecordDataEntity(examRecordId):
- url = "https://" + config.domain + "/api/ecs_oe_admin/exam/record/data/findExamRecordDataEntity"
- params = {
- "examRecordDataId": examRecordId
- }
- result = requests.get(url, params=params, headers=config.header, verify=False)
- # print(result.json())
- if result.status_code == 200:
- return result.json()
- else:
- # print(result.status_code)
- # print(result.json())
- return None
- @calctime
- def getExamRecordPaperStruct(examRecordDataId):
- url = "https://" + config.domain + "/api/ecs_oe_admin/examRecordPaperStruct/getExamRecordPaperStruct"
- params = {
- "examRecordDataId": examRecordDataId
- }
- result = requests.get(url, params=params, headers=config.header, verify=False)
- if result.status_code == 200:
- return result.json()
- else:
- return None
- @calctime
- def getExamRecordQuestions(examRecordDataId):
- url = "https://" + config.domain + "/api/ecs_oe_admin/examRecordQuestions/getExamRecordQuestions"
- params = {
- "examRecordDataId": examRecordDataId,
- "withScore": True,
- }
- result = requests.get(url, params=params, headers=config.header, verify=False)
- if result.status_code == 200:
- return result.json()
- else:
- return None
- @calctime
- def getQuesitons(examId, courseCode, groupCode, questionId):
- url = "https://" + config.domain + "/api/ecs_ques/default_question/question"
- data = {"examId": examId, "courseCode": courseCode, "groupCode": groupCode, "questionId": questionId}
- result = requests.post(url, json=data, headers=config.header, verify=False)
- if result.status_code == 200:
- return result.json()
- else:
- return None
- def solveexamRecord(examId, examRecorddetail):
- identityNumber = examRecorddetail["identityNumber"]
- studentName = examRecorddetail["studentName"]
- examrRecordDataId = examRecorddetail["id"]
- courseCode = examRecorddetail["courseCode"]
- courseName = examRecorddetail["courseName"]
- studentCode = examRecorddetail["studentCode"]
- if len(config.skipStudentCodes) > 0:
- # print(studentCode + ' ' + str(config.skipStudentCodes.find(studentCode)))
- if config.skipStudentCodes.find(studentCode) > -1:
- print("配置为跳过! " + courseCode + "_" + identityNumber + "_" + studentName + ".pdf")
- return None
- record = bs4.BeautifulSoup(
- open(common.resource_path(os.path.join("template", "template.html")), "r", encoding="utf-8"),
- features="html.parser")
- if config.useStudentCodePath == 'true':
- filepath = config.outputpath + os.sep + str(
- examId) + os.sep + courseCode + "_" + studentCode + "_" + studentName + ".pdf"
- else:
- filepath = config.outputpath + os.sep + str(
- examId) + os.sep + courseCode + "_" + identityNumber + "_" + studentName + ".pdf"
- if os.path.exists(filepath):
- print("已处理,跳过! " + courseCode + "_" + identityNumber + "_" + studentName + ".pdf")
- return None
- result = findExamRecordDataEntity(examrRecordDataId)
- # print(result)
- groupCode = result["examRecord"]["paperType"]
- defaultPaper = getExamRecordPaperStruct(examrRecordDataId)["defaultPaper"]
- papername = defaultPaper["name"]
- record.select_one("#paperName").string = str(papername)
- record.select_one("#studentInfoTable > tbody > tr > td:nth-of-type(1)").string = str(examrRecordDataId)
- record.select_one("#studentInfoTable > tbody > tr > td:nth-of-type(2)").string = str(studentCode)
- record.select_one("#studentInfoTable > tbody > tr > td:nth-of-type(3)").string = str(studentName)
- record.select_one("#studentInfoTable > tbody > tr > td:nth-of-type(4)").string = str(courseName) + "(" + str(
- courseCode) + ")"
- paperViewTag = record.select_one("#paperView")
- questionGroupList = defaultPaper["questionGroupList"]
- quesitonEntites = getExamRecordQuestions(examrRecordDataId)["examQuestionEntities"]
- main_number = 1
- sub_number = 1
- for questionGroup in questionGroupList:
- groupName = questionGroup["groupName"]
- groupScore = questionGroup["groupScore"]
- mainQuestionDiv = record.new_tag("div", attrs={"class": "mainQuestionDiv", "data-v-3575fe23": ""})
- paperViewTag.append(mainQuestionDiv)
- groupDiv = record.new_tag("div", attrs={"data-v-3575fe23": "", "style": "font-size: 16px; font-weight: bold;"})
- mainQuestionDiv.append(groupDiv)
- mainQuestionDiv.append(record.new_tag("div", attrs={"data-v-3575fe23": ""}))
- datadiv = record.new_tag("div", attrs={"data-v-3575fe23": ""})
- mainQuestionDiv.append(datadiv)
- datadiv1 = record.new_tag("div", attrs={"data-v-3575fe23": ""})
- datadiv.append(datadiv1)
- questionWrapperList = questionGroup["questionWrapperList"]
- groupDiv.string = common.four_to_han(str(main_number)) + "、" + groupName + "(" + str(groupScore) + "分" + ")"
- for questionWrapper in questionWrapperList:
- questionId = questionWrapper["questionId"]
- quesitondetail = getQuesitons(examId, courseCode, groupCode, questionId)
- main_body = record.new_tag("div",
- attrs={"data-v-3575fe23": "", "style": "display: flex; flex-direction: row;"})
- datadiv1.append(main_body)
- if quesitondetail["masterVersion"]["body"]:
- main_body_div = record.new_tag("div", attrs={"data-v-3575fe23": ""})
- main_body.append(main_body_div)
- soup = bs4.BeautifulSoup(quesitondetail["masterVersion"]["body"], features="html.parser")
- main_body_div.append(soup)
- questionUnitList = quesitondetail["masterVersion"]["questionUnitList"]
- for questionUnit in questionUnitList:
- questionType = questionUnit["questionType"]
- questiondiv = record.new_tag("div", attrs={"data-v-3575fe23": "", "style": "clear:both"})
- datadiv1.append(questiondiv)
- bodydiv = record.new_tag("div",
- attrs={"data-v-3575fe23": "", "style": "display: flex; flex-direction: row;"})
- questiondiv.append(bodydiv)
- sub_number_div = record.new_tag("div", attrs={"data-v-3575fe23": "", "style": "float:left"})
- sub_number_div.string = str(sub_number) + "、"
- content_div = record.new_tag("div", attrs={"data-v-3575fe23": "", "style": "float:left"})
- score_span = record.new_tag("span", attrs={"data-v-3575fe23": "", "style": "float:left"})
- bodydiv.append(sub_number_div)
- bodydiv.append(content_div)
- bodydiv.append(score_span)
- body = questionUnit["body"]
- soup = bs4.BeautifulSoup(body, features="html.parser")
- # content_div.append(str(sub_number)+"、")
- content_div.append(soup)
- rightAnswer = questionUnit["rightAnswer"]
- curRightAnswer = ''
- if rightAnswer and len(rightAnswer) > 0:
- curRightAnswer = rightAnswer[0]
- quesitonEntity = quesitonEntites[sub_number - 1]
- optionorder = quesitonEntity["optionPermutation"]
- questionScore = quesitonEntity["questionScore"]
- studentAnswer = quesitonEntity["studentAnswer"]
- studentScore = quesitonEntity["studentScore"]
- questionOptionList = questionUnit["questionOptionList"]
- score_span.string = "(" + str(questionScore) + "分)"
- if questionOptionList:
- option_idex = 0
- for option in optionorder:
- optiondetail = questionOptionList[option]
- optiondiv = record.new_tag("div", attrs={"data-v-3575fe23": "", "style": "clear:both"})
- datadiv1.append(optiondiv)
- optiondiv1 = record.new_tag("div", attrs={"data-v-3575fe23": "",
- "style": "display: flex; flex-direction: row;"})
- optiondiv.append(optiondiv1)
- optionIndexdiv = record.new_tag("div", attrs={"data-v-3575fe23": "", "style": "float:left"})
- optiondiv1.append(optionIndexdiv)
- optionContentdiv = record.new_tag("div", attrs={"data-v-3575fe23": "", "style": "float:left"})
- optiondiv1.append(optionContentdiv)
- optionIndexdiv.string = chr(65 + int(option_idex)) + "、"
- soup = bs4.BeautifulSoup(optiondetail["body"], features="html.parser")
- optionContentdiv.append(soup)
- option_idex = option_idex + 1
- answerdiv = record.new_tag("div", attrs={"data-v-3575fe23": "", "style": "clear:both"})
- datadiv1.append(answerdiv)
- rightAnswerdiv = record.new_tag("div", attrs={"data-v-3575fe23": "",
- "style": "display: flex; flex-direction: row; color: green; font-weight: bold;"})
- rightAnswerdivtitle = record.new_tag("div", attrs={"data-v-3575fe23": "", "style": "float:left"})
- rightAnswerdivcontent = record.new_tag("span", attrs={"data-v-3575fe23": "", "style": "float:left"})
- answerdiv.append(rightAnswerdiv)
- rightAnswerdiv.append(rightAnswerdivtitle)
- rightAnswerdiv.append(rightAnswerdivcontent)
- rightAnswerdivtitle.string = "标准答案:"
- studentAnswerdiv = record.new_tag("div", attrs={"data-v-3575fe23": "",
- "style": "color: blue; font-weight: bold;clear:both"})
- answerdiv.append(studentAnswerdiv)
- studentAnswerdiv.string = "学生答案:"
- studentAnswercontentspan = record.new_tag("span", attrs={"data-v-3575fe23": ""})
- studentAnswerdiv.append(studentAnswercontentspan)
- if questionType == "SINGLE_CHOICE" or questionType == "MULTIPLE_CHOICE":
- correctAnswer = quesitonEntity["correctAnswer"]
- # print(correctAnswer,studentAnswer)
- rightAnswerdivcontent.append(
- selectorder(correctAnswer, optionorder))
- studentAnswercontentspan.append(
- selectorder(studentAnswer, optionorder))
- elif questionType == "TRUE_OR_FALSE":
- f = lambda x: "" if not x else "正确" if x == "true" else "错误"
- # print(f(curRightAnswer))
- rightAnswerdivcontent.append(f(curRightAnswer))
- studentAnswercontentspan.append(f(studentAnswer))
- else:
- rightAnswerdivcontent.append(
- bs4.BeautifulSoup(curRightAnswer if curRightAnswer else '', features="html.parser"))
- studentAnswercontentspan.append(
- bs4.BeautifulSoup(studentAnswer if studentAnswer else '', features="html.parser"))
- student_score_div = record.new_tag("div", attrs={"data-v-3575fe23": "",
- "style": "color: red; font-weight: bold;clear:both"})
- answerdiv.append(student_score_div)
- right_score_div_title = record.new_tag("div", attrs={"data-v-3575fe23": "", "style": "float:left"})
- right_score_div_title.string = "得分:"
- student_score_div.append(right_score_div_title)
- student_score_content_span = record.new_tag("span", attrs={"data-v-3575fe23": ""})
- if studentScore is None:
- student_score_content_span.string = "--分"
- else:
- student_score_content_span.string = str(studentScore) + "分"
- student_score_div.append(student_score_content_span)
- # print(main_number, " ", sub_number, " ", questionScore, " ", studentScore,
- # " ", rightAnswer, " ", studentAnswer)
- sub_number = sub_number + 1
- main_number = main_number + 1
- with open(common.resource_path(os.path.join("template", "temp.html")), 'w', encoding="utf-8") as fp:
- fp.write(record.prettify())
- if not os.path.exists(config.outputpath + os.sep + str(examId)):
- os.makedirs(config.outputpath + os.sep + str(examId))
- common.convert_to_pdf(common.resource_path(os.path.join("template", "temp.html")), filepath)
- print("已完成! " + courseCode + "_" + identityNumber + "_" + studentName + ".pdf examrRecordDataId=" + str(
- examrRecordDataId))
- def selectorder(answer, optionpremutation):
- if answer:
- answerstr = []
- for answerorder in answer:
- # print(optionpremutation)
- index = optionpremutation.index(int(answerorder))
- answerstr.append(chr(65 + index))
- answerstr.sort()
- return ",".join(answerstr)
- else:
- return ""
|