exportjsonfile.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. """
  2. 功能:导出json试卷
  3. 作者:pengchen
  4. 时间:2020/3/10
  5. """
  6. import time
  7. import hashlib
  8. import requests
  9. import config
  10. import logger
  11. import json
  12. import os
  13. from bs4 import BeautifulSoup
  14. from bs4 import element
  15. import re
  16. def main():
  17. queryExamMarkingInfo()
  18. # questionlist=querySubjectInfo("8887593","A","B149")
  19. # with open("8887593.json", "w", encoding="utf-8") as file:
  20. # json_str = json.dumps(questionlist, indent=4, ensure_ascii=False)
  21. # file.write(json_str)
  22. def queryExamMarkingInfo():
  23. """
  24. 获取阅卷信息
  25. """
  26. url = config.oedomain + "api/core/oe/admin/examRecordForMarking/findExamRecordForMarkingInfo"
  27. data = {
  28. "examId": config.examId,
  29. "courseId": "",
  30. "batchNum": ""
  31. }
  32. headers = createRpcheader("4", "OE")
  33. result = requests.post(
  34. url, headers=headers,
  35. json=data)
  36. if result.status_code == 200:
  37. examRecordForMarkingBeanList = result.json()['examRecordForMarkingBeanList']
  38. for examRecordForMarkingBean in examRecordForMarkingBeanList:
  39. queryExamValidRecordData(examRecordForMarkingBean['courseId'], 1)
  40. else:
  41. print("查询阅卷信息失败")
  42. def queryExamValidRecordData(courseId, pageNo):
  43. """
  44. 获取全部考生的阅卷信息
  45. """
  46. url = config.oedomain + "api/core/oe/admin/examRecordForMarking/queryValidExamRecordInfoPage"
  47. data = {
  48. "examId": config.examId,
  49. "courseId": courseId,
  50. "start": pageNo,
  51. "size": 200
  52. }
  53. headers = createRpcheader("4", "OE")
  54. result = requests.post(
  55. url, headers=headers,
  56. json=data)
  57. if result.status_code == 200:
  58. examRecordForMarkingBeanList = result.json()['examRecordForMarkingBeanList']
  59. if len(examRecordForMarkingBeanList) > 0:
  60. for examRecordForMarkingBean in examRecordForMarkingBeanList:
  61. # examRecordDataId = str(examRecordForMarkingBean["examRecordDataId"]);
  62. # if examRecordDataId != "39881554" and examRecordDataId != "39879641":
  63. # # logger.info("不用处理,跳过!examRecordDataId = %s" % examRecordDataId)
  64. # continue
  65. # 取试卷题目
  66. course = getCourse(courseId)
  67. output = config.outputpath + "/" + str(config.examId) + "/" + str(course["code"]) + "-" + \
  68. examRecordForMarkingBean["paperType"]
  69. if not os.path.exists(output):
  70. os.makedirs(output)
  71. savepath = output + "/" + str(examRecordForMarkingBean["examRecordDataId"]) + ".json"
  72. if os.path.exists(savepath):
  73. logger.info("已处理,跳过!examRecordDataId = %s" % str(examRecordForMarkingBean["examRecordDataId"]))
  74. continue
  75. questionbeanlist = querySubjectInfo(examRecordForMarkingBean["examRecordDataId"],
  76. examRecordForMarkingBean["paperType"], course["code"])
  77. # 存储到本地
  78. time.sleep(1)
  79. with open(savepath, "w", encoding="utf-8") as file:
  80. json_str = json.dumps(questionbeanlist, indent=4, ensure_ascii=False)
  81. file.write(json_str)
  82. next = result.json()["next"]
  83. queryExamValidRecordData(courseId, next)
  84. else:
  85. print("没有剩余课程")
  86. def querySubjectInfo(examRecordDataId, paperType, courseCode):
  87. """
  88. paperId:
  89. paperType:
  90. courseCode:
  91. """
  92. print("开始处理%s" % (examRecordDataId))
  93. questionBeanList = []
  94. url = config.oedomain + "api/core/oe/admin/examRecordQuestions/querySubjectiveAnswerList"
  95. headers = createRpcheader("4", "OE")
  96. data = {
  97. "examRecordDataId": examRecordDataId
  98. }
  99. result = requests.post(
  100. url, headers=headers,
  101. json=data)
  102. if result.status_code == 200:
  103. querySubjectiveAnswerBeanList = result.json()["querySubjectiveAnswerBeanList"]
  104. question_unit_number = 1
  105. lastquestionId = None
  106. for querySubjectiveAnswerBean in querySubjectiveAnswerBeanList:
  107. questionId = querySubjectiveAnswerBean["questionId"]
  108. main_number = querySubjectiveAnswerBean["mainNumber"]
  109. sub_number = querySubjectiveAnswerBean["order"]
  110. studentanswer = querySubjectiveAnswerBean["studentAnswer"]
  111. print("studentanswer:", studentanswer)
  112. questiondata = getQuestion(questionId, courseCode, paperType)
  113. mainbodyblocklist = None
  114. if lastquestionId == questionId:
  115. question_unit_number = question_unit_number + 1 # 下一道主观题
  116. else:
  117. lastquestionId = questionId
  118. question_unit_number = 1
  119. if questiondata["defaultQuestion"]["masterVersion"]["body"]:
  120. # 套题处理
  121. mainquestionbody = questiondata["defaultQuestion"]["masterVersion"]["body"]
  122. mainbodyblocklist = splitQuestionBody(mainquestionbody)
  123. questionUnitList = questiondata["defaultQuestion"]["masterVersion"]["questionUnitList"]
  124. current_subjective_number = 1
  125. for questionUnit in questionUnitList:
  126. sub_ques_body = questionUnit["body"]
  127. if questionUnit["questionType"] == "FILL_UP" or questionUnit["questionType"] == "ESSAY":
  128. if current_subjective_number == question_unit_number:
  129. questionBean = {
  130. "mainNumber": main_number,
  131. "subNumber": sub_number,
  132. "studentAnswer": {
  133. "sections": []
  134. },
  135. "answer": {
  136. "sections": []
  137. },
  138. "body": {
  139. "sections": []
  140. }
  141. }
  142. quesbodyblocklist = splitQuestionBody(sub_ques_body)
  143. if mainbodyblocklist:
  144. questionBean["body"]["sections"] = mainbodyblocklist + quesbodyblocklist
  145. else:
  146. questionBean["body"]["sections"] = quesbodyblocklist
  147. questionBean["studentAnswer"]["sections"] = splitQuesitonStudentAnswer(studentanswer,
  148. questionUnit[
  149. "answerType"],
  150. questionUnit[
  151. "questionType"])
  152. questionBean["answer"]["sections"] = splitQuesitonAnswer(questionUnit["rightAnswer"][0])
  153. questionBeanList.append(questionBean)
  154. current_subjective_number = current_subjective_number + 1
  155. return questionBeanList
  156. def splittagElement(blocklist, childrenelement):
  157. if type(childrenelement) == element.NavigableString:
  158. block = {
  159. "type": "text",
  160. "value": childrenelement,
  161. "playTime": None,
  162. "param": None
  163. }
  164. blocklist.append(block)
  165. elif type(childrenelement) == element.Tag:
  166. for child in childrenelement.children:
  167. if child.name == "a":
  168. playTime = None
  169. if "playtime" in child.attrs:
  170. playTime = child.attrs["playtime"]
  171. block = {
  172. "type": "audio",
  173. "value": child.attrs["url"],
  174. "playTime": playTime,
  175. "param": None
  176. }
  177. blocklist.append(block)
  178. elif child.name == "img":
  179. width = None
  180. height = None
  181. if "width" in child.attrs and "height" in child.attrs:
  182. width = child.attrs["width"]
  183. height = child.attrs["height"]
  184. else:
  185. style = child.attrs["style"]
  186. width = re.search("width:([^;]*)", style).group(1)
  187. height = re.search("height:([^;]*)", style).group(1)
  188. block = {
  189. "type": "image",
  190. "value": child.attrs["src"],
  191. "playTime": None,
  192. "param": {
  193. "width": width,
  194. "height": height
  195. }
  196. }
  197. blocklist.append(block)
  198. else:
  199. splittagElement(blocklist, child)
  200. def splitQuestionBody(questionBody):
  201. """
  202. 切分quesitonBody
  203. """
  204. sectionlist = []
  205. bodyhtml = BeautifulSoup(questionBody, features="html.parser")
  206. plist = bodyhtml.find_all("p")
  207. for p in plist:
  208. # 遍历p标签
  209. section = {
  210. "blocks": []
  211. }
  212. splittagElement(section["blocks"], p)
  213. sectionlist.append(section)
  214. return sectionlist
  215. def splitQuesitonAnswer(quesitonanswer):
  216. """
  217. 切分问题标答
  218. """
  219. sectionlist = []
  220. # print(quesitonanswer)
  221. if quesitonanswer:
  222. bodyhtml = BeautifulSoup(quesitonanswer, features="html.parser")
  223. plist = bodyhtml.find_all("p")
  224. for p in plist:
  225. # 遍历p标签
  226. section = {
  227. "blocks": []
  228. }
  229. splittagElement(section["blocks"], p)
  230. sectionlist.append(section)
  231. else:
  232. sectionlist = None
  233. return sectionlist
  234. def splitQuesitonStudentAnswer(studentanswer, answerType, questionType):
  235. """
  236. 切分学生答案
  237. """
  238. print(answerType, questionType)
  239. if studentanswer:
  240. sectionlist = []
  241. if questionType == "ESSAY":
  242. if answerType == "SINGLE_AUDIO":
  243. answer = {
  244. "blocks": [{
  245. "type": "audio",
  246. "value": studentanswer,
  247. "playTime": None,
  248. "param": None
  249. }]}
  250. sectionlist.append(answer)
  251. else:
  252. # 取图片
  253. bodyhtml = BeautifulSoup(studentanswer, features="html.parser")
  254. blocks = {
  255. "blocks": []
  256. }
  257. for body in bodyhtml:
  258. if type(body) == element.NavigableString:
  259. textanswer = {
  260. "type": "text",
  261. "value": body,
  262. "playTime": None,
  263. "param": None
  264. }
  265. blocks["blocks"].append(textanswer)
  266. else:
  267. alist = body.find_all("a")
  268. if len(alist) > 0:
  269. for atag in alist:
  270. imageanswer = {
  271. "type": "image",
  272. "value": atag.attrs["href"],
  273. "playTime": None,
  274. "param": {
  275. "width": 200,
  276. "height": 200
  277. }
  278. }
  279. blocks["blocks"].append(imageanswer)
  280. else:
  281. textanswer = {
  282. "type": "text",
  283. "value": body.text,
  284. "playTime": None,
  285. "param": None
  286. }
  287. blocks["blocks"].append(textanswer)
  288. sectionlist.append(blocks)
  289. else:
  290. answer = {
  291. "blocks": [{
  292. "type": "text",
  293. "value": studentanswer,
  294. "playTime": None,
  295. "param": None
  296. }]
  297. }
  298. sectionlist.append(answer)
  299. print(sectionlist)
  300. else:
  301. sectionlist = None
  302. return sectionlist
  303. def getQuestion(questionId, courseCode, paperType):
  304. url = config.questiondomain + "api/core/questions/extract_config/getQuestion"
  305. headers = createRpcheader("3", "Q")
  306. data = {
  307. "examId": config.examId,
  308. "courseCode": courseCode,
  309. "groupCode": paperType,
  310. "questionId": questionId
  311. }
  312. result = requests.post(
  313. url, headers=headers,
  314. json=data)
  315. if result.status_code == 200:
  316. return result.json()
  317. def getCourse(courseId):
  318. url = config.basedomain + "api/core/basic/course/getCoursesByIdList"
  319. headers = createRpcheader("1", "B")
  320. data = {
  321. "courseIdList": [courseId]
  322. }
  323. result = requests.post(
  324. url, headers=headers, json=data)
  325. if result.status_code == 200:
  326. return result.json()["courseList"][0]
  327. def createRpcheader(appid, appcode):
  328. secretkey = "123456"
  329. t = time.time()
  330. secretstr = ''.join([appid, appcode, str(int(round(t * 1000))), secretkey])
  331. accssToken = hashlib.sha256(secretstr.encode("utf-8")).hexdigest()
  332. headers = {
  333. "App-Id": appid,
  334. "App-Code": appcode,
  335. "Trace-Id": "1222222",
  336. "Access-Token": accssToken,
  337. "timestamp": str(int(round(t * 1000)))
  338. }
  339. return headers
  340. if __name__ == "__main__":
  341. main()