ans_structure1.py 76 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256
  1. #!/usr/bin/env/python
  2. # -*- coding:utf-8 -*-
  3. """
  4. """
  5. import re
  6. from utils.washutil import table_label_cleal, del_no
  7. from utils.topic_no import *
  8. def anss_structure_with_type(item_res, ans_str, all_type, all_type2,item_type_num,item_type_classify):
  9. """
  10. 针对含题型行的答案进行结构化
  11. :return:
  12. """
  13. rd1_is_fail = 0
  14. is_amount_wrong = 0
  15. if len(all_type2) == len(all_type):
  16. # try:
  17. if not all_type[0]: # 第一大题型不存在
  18. all_type[0] = all_type2[0]
  19. if all_type.count(all_type[0]) > 1:
  20. item_type_classify[all_type[0]] += item_type_num[0][1]
  21. if sorted(all_type) != sorted(all_type2): # !!!!!!还需细分
  22. print("题文和答案中的题型不一致,题文中的题型={},答案中的题型={}".format(str(all_type), str(all_type2)))
  23. ans22 = re.split(r"\n\s*[一二三四五六七八九十]\s*[、..、]\s*[^必考基础综合中等]{2,4}题.*?[分。.]?\s*(?=\n)", ans_str)
  24. while re.search(r"[A-H\u4e00-\u9fa5]", ans22[0]) is None:
  25. del ans22[0]
  26. ans_item_no_type = judge_ans_no_type(ans22, item_type_num) # 初步判断答案中的题号类型
  27. # print("tihao类型:", ans_item_no_type)
  28. # -----------------------------------------------------------------
  29. # 开始按题号切分题目!!!!!!!!!!!!!!!
  30. type_id = 0
  31. new_ans_no = []
  32. all_ans = []
  33. for num, one_type in enumerate(ans22):
  34. # 当前题型中的题目数量(以试题的题目个数为准)
  35. one_type_num = item_type_classify[all_type[num]]
  36. if len(all_type2) != len(item_type_classify): # 存在重复题型
  37. one_type_num = item_type_num[num][1]
  38. print("one_type_num :", one_type_num)
  39. # 1>> 先按题号都在行首的情况(一行不多于一个答案)
  40. item_id = 0
  41. one_type_ans = []
  42. one_type_no = []
  43. item_no_info = pre_get_item_no('\n'+one_type, ans_item_no_type) # 初步按非表格非排列的形式获取题号信息
  44. print("初步题号:", item_no_info)
  45. if not item_no_info:
  46. # 表格答案和排列型答案应该不同时存在!!!
  47. if "table" in one_type:
  48. # 存在表格答案
  49. ans_no, table_ans = get_table_ans(one_type)
  50. if table_ans:
  51. one_type_ans.extend(table_ans)
  52. one_type_no.extend(ans_no)
  53. else:
  54. one_type_no, one_type_ans = get_array_ans(one_type, new_ans_no, item_res[0]['item_id'],
  55. temp_type=all_type[num])
  56. # elif re.search("[1-9]\s*[-~]\s*1?[0-9]\s*([A-Z]\s*){2,}", one_type):
  57. # no_info = re.findall("([1-9])\s*[-~]\s*(1?[0-9])\s*([A-Z]\s*){2,}", one_type)
  58. # no_list = [list(range(int(i[0]), int(i[1])+1)) for i in no_info]
  59. # row_split = re.split("\n*[1-9]\s*[-~]\s*1?[0-9]", one_type)
  60. # if len(row_split) - len(no_list) == 1:
  61. # if not row_split[0].strip():
  62. # one_type_no.extend(sum(no_list, []))
  63. # for k, j in enumerate(row_split[1:]):
  64. # print(re.split("\s+",j.strip()))
  65. # if len(re.findall("[A-Z](?!\))", j)) == len(no_list[k]):
  66. # one_type_ans.extend(re.findall("[A-Z](?<!\))", j))
  67. # elif len(re.split("\s+",j.strip())) == len(no_list[k]):
  68. # one_type_ans.extend(re.split("\s+",j.strip()))
  69. # elif no_list[0][0]>1:
  70. # tt0 = re.split("\s+",row_split[0].strip())
  71. # if len(tt0) < no_list[0][0]-1:
  72. # tt0 = re.findall("[A-Z](?!\))", row_split[0])
  73. # if len(tt0) >= no_list[0][0]-1:
  74. # one_type_ans.extend(tt0[-(no_list[0][0]-1):])
  75. # one_type_no.extend(list(range(1,no_list[0][0]))[-(no_list[0][0]-1):])
  76. # one_type_no.extend(sum(no_list, []))
  77. # for k, j in enumerate(row_split[1:]):
  78. # print(re.split("\s+",j.strip()))
  79. # if len(re.findall("[A-Z](?!\))", j)) == len(no_list[k]):
  80. # one_type_ans.extend(re.findall("[A-Z](?<!\))", j))
  81. # elif len(re.split("\s+",j.strip())) == len(no_list[k]):
  82. # one_type_ans.extend(re.split("\s+",j.strip()))
  83. # elif re.search("([1-9]|[1-4][0-9])\s*[A-Z]", one_type) and \
  84. # all_type[num].replace("题", "") in ['选择','单选','多选', '不定选择']:
  85. # row_ans = re.split("[1-4][0-9]|[1-9]", one_type)
  86. # if not row_ans[0].strip():
  87. # row_ans = row_ans[1:]
  88. # one_type_ans.extend(row_ans)
  89. # if new_ans_no:
  90. # one_type_no.extend(list(range(new_ans_no[-1]+1,new_ans_no[-1]+1+len(row_ans))))
  91. # else:
  92. # one_type_no.extend(list(range(1, 1 + len(row_ans))))
  93. # else:
  94. # # row_ans = sum([re.findall("[A-Z](?<!\))", str(k.group())) for k in re.finditer("[A-Z]{4,}", one_type)],[])
  95. # row_ans = re.findall("[A-Z](?<!\))", one_type)
  96. # one_type_ans.extend(row_ans)
  97. # if new_ans_no and row_ans:
  98. # one_type_no.extend(list(range(new_ans_no[-1] + 1, new_ans_no[-1] + 1 + len(row_ans))))
  99. # else:
  100. # one_type_no.extend(list(range(1, 1 + len(row_ans))))
  101. else: # 一行多个时,可能初步提取的题号只有1-2个
  102. # 表格答案和1-10BCCDBB 答案类型 应该不同时存在吧
  103. local_ans_no1, items_no_idx = get_right_no(item_no_info)
  104. print("local_items_no:",local_ans_no1)
  105. print("local_items_no_idx:", items_no_idx)
  106. is_from_0 = 1 # shi
  107. if items_no_idx[0] != 0 and local_ans_no1[0] > 1:
  108. items_no_idx.insert(0, 0)
  109. is_from_0 = 0 # fei
  110. one_item_split = [del_no(("\n" + one_type)[i:j], ans_item_no_type) for i, j in zip(items_no_idx, items_no_idx[1:] + [None])]
  111. while "table" in one_item_split[0]:
  112. ans_no, table_ans = get_table_ans(one_item_split[0])
  113. one_type_ans.extend(table_ans)
  114. one_type_no.extend(ans_no)
  115. one_item_split[0] = re.sub("<table>(((?!(</?table>)).)*)</table>", "", one_item_split[0])
  116. if not is_from_0:
  117. if re.match('(\n|^)故[::]?选[::]|故[::]?答案分?别?[为是]?'
  118. '|【([解分][析答]|详解|点[评睛])】|(答案|解析|详解)[::]',
  119. one_item_split[0].replace(" ", "")) is None:
  120. one_item_split = one_item_split[1:]
  121. items_no_idx = items_no_idx[1:]
  122. else:
  123. local_ans_no1.insert(0, local_ans_no1[0]-1)
  124. # -------开始判断答案个数是否正确------------------------
  125. one_type_no1 = one_type_no.copy()
  126. one_type_no1.extend(local_ans_no1)
  127. print('开始:', one_type_no1, one_type_num)
  128. if len(one_type_no1) != one_type_num:
  129. # 存在一行多个的情况,题号前必须有空格
  130. one_type_str = '\n' + '\n'.join(one_item_split) # 本部分的str
  131. ans_no1, ans_no_idx1 = get_many_ans_no(one_type_str, ans_item_no_type)
  132. local_ans_no2, ans_no_idx2 = get_right_no((ans_no_idx1, ans_no1), 1)
  133. one_type_no2 = one_type_no.copy()
  134. one_type_no2.extend(local_ans_no2)
  135. # print('one_type_no2:', one_type_no2)
  136. if len(one_type_no2) != one_type_num:
  137. # 题号前不要求空格时,出错的概率大,最好限制下范围,在按换行获取的题号中对不连续的题号做这种操作!!!!
  138. # 有题型行的一般归类比较工整点
  139. ans_no21, ans_no_idx21,ans_no22, ans_no_idx22 = get_many_ans_no(one_type_str, ans_item_no_type, reget=1)
  140. local_ans_no3, ans_no_idx3 = get_right_no((ans_no_idx21, ans_no21), 1)
  141. one_type_no3 = one_type_no.copy()
  142. one_type_no3.extend(local_ans_no3)
  143. # print('one_type_no3:', one_type_no3)
  144. if len(one_type_no3) != one_type_num:
  145. local_ans_no4, ans_no_idx4 = get_right_no((ans_no_idx22, ans_no22), 1)
  146. one_type_no4 = one_type_no.copy()
  147. one_type_no4.extend(local_ans_no4)
  148. if len(one_type_no4) != one_type_num:
  149. print("第" + str(num + 1) + "大题(" + all_type[num], ")答案个数有问题!!!")
  150. is_amount_wrong = 1
  151. if 0<one_type_num-len(one_type_no1)<=2:
  152. one_type_ans.extend(one_item_split)
  153. one_type_no = one_type_no1
  154. elif 0<one_type_num-len(one_type_no2)<=2:
  155. new_item_split = [del_no(one_type_str[i:j], ans_item_no_type) for i, j in
  156. zip(ans_no_idx2, ans_no_idx2[1:] + [None])]
  157. one_type_ans.extend(new_item_split)
  158. one_type_no = one_type_no2
  159. else:
  160. print("第四种题号切分方案")
  161. new_item_split = [del_no(one_type_str[i:j], ans_item_no_type) for i, j in
  162. zip(ans_no_idx4, ans_no_idx4[1:] + [None])]
  163. one_type_ans.extend(new_item_split)
  164. one_type_no = one_type_no4
  165. else:
  166. print("第三种题号切分方案")
  167. new_item_split = [del_no(one_type_str[i:j], ans_item_no_type) for i, j in
  168. zip(ans_no_idx3, ans_no_idx3[1:] + [None])]
  169. one_type_ans.extend(new_item_split)
  170. one_type_no = one_type_no3
  171. else:
  172. print("第二种题号切分方案")
  173. new_item_split = [del_no(one_type_str[i:j], ans_item_no_type) for i, j in
  174. zip(ans_no_idx2, ans_no_idx2[1:] + [None])]
  175. one_type_ans.extend(new_item_split)
  176. one_type_no = one_type_no2
  177. else:
  178. print("第一种题号切分方案")
  179. one_type_ans.extend(one_item_split)
  180. one_type_no = one_type_no1
  181. # --------------------------------------------------------------------------------------------
  182. print("第" + str(num + 1) + "大题(" + all_type[num], ")答案题号:", one_type_no)
  183. # print('答案:', one_type_ans)
  184. # ------------------------------------题目和答案组合---------------------------------------------------
  185. # 按题号进行组合
  186. if not is_amount_wrong:
  187. # all_ans.extend(one_type_ans)
  188. # new_ans_no.extend(one_type_no)
  189. # try:
  190. if one_type_ans:
  191. # print('one_type_no:',one_type_no)
  192. # print('one_type_ans:', one_type_ans)
  193. for k, one_item in enumerate(one_type_ans):
  194. temp_id = item_id + type_id # 当前答案在整个答案中的序号
  195. # ----------当前答案序号与题号对不上时------
  196. if len(one_type_no) == len(one_type_ans) and item_res[temp_id]["item_id"] != one_type_no[k]:
  197. # 从试题的res寻找与当前答案题号相同的题目的位置
  198. temp_id_list = [i for i, v in enumerate(item_res) if v["item_id"] == one_type_no[k]]
  199. if len(temp_id_list) == 1:
  200. temp_id = temp_id_list[0]
  201. elif len(temp_id_list) > 1:
  202. for j in temp_id_list:
  203. if "key" not in item_res[j].keys():
  204. temp_id = j
  205. #--------------------end------------------
  206. res_con = item_res[temp_id]['stem']
  207. item_res[temp_id].update(
  208. only_parse_split(one_item, all_type[num], res_con)) # 单道答案的结构化
  209. item_id += 1
  210. else:
  211. for k, one_item in enumerate(one_type_ans):
  212. temp_id = "no"
  213. # 从试题的res寻找与当前答案题号相同的题目的位置
  214. temp_id_list = [i for i, v in enumerate(item_res) if v["item_id"] == one_type_no[k]]
  215. if len(temp_id_list) == 1:
  216. temp_id = temp_id_list[0]
  217. elif len(temp_id_list) > 1:
  218. for j in temp_id_list:
  219. if "key" not in item_res[j].keys():
  220. temp_id = j
  221. if temp_id != 'no': # 找到题目和答案相同的题目的序号时
  222. res_con = item_res[temp_id]['stem']
  223. item_res[temp_id].update(
  224. only_parse_split(one_item, all_type[num], res_con)) # 单道答案的结构化
  225. item_id += 1
  226. type_id += item_id
  227. # ---------------------------------------------------
  228. # except:
  229. # rd1_is_fail = 1
  230. else:
  231. rd1_is_fail = 1
  232. return item_res, rd1_is_fail
  233. def get_table_ans(ans_str):
  234. """
  235. 获取表格中的答案
  236. :return:
  237. """
  238. table_ans = []
  239. ans_no = []
  240. if ans_str and "table" in ans_str: # 答案以表格形式呈现, 表格应放在前两行位置,不要插在答案中间
  241. row_list = [] # 要求表格形式为 横纵分明 ,不存在合并
  242. for one_table in re.finditer('<table>(((?!(</?table>)).)*)</table>', ans_str, re.S):
  243. for tt in re.finditer(r'<tr>(((?!(</?tr>)).)*)</tr>', one_table.group(1), re.S):
  244. tt_list = re.split(r'</p></td>|<td><p>|</td><td>|</td>|<td>', tt.group(1))
  245. # row_list.append([col for col in tt_list if col.strip()]) # 也有可能答案为空
  246. row_list.append(tt_list)
  247. if row_list:
  248. print("^^^^^^存在答案放在表格里的情况!^^^^^^^")
  249. if len(row_list) % 2 != 0:
  250. print('有表格形式呈现的答案不是偶数行')
  251. else:
  252. for k, v in enumerate(row_list):
  253. if (k + 1) % 2 == 1: # 奇数行==》答案序号行
  254. item_no = [int(i) if re.sub(r"[^\d]", "", i) else -1 for i in v]
  255. item_no_st = [num for num, i in enumerate(item_no) if i != -1] # 可能开头是-1
  256. # print(item_no_st)
  257. ans_no.extend([i for i in item_no if i != -1]) # 表格序号
  258. table_ans.extend(row_list[k + 1][item_no_st[0]: item_no_st[-1] + 1]) # 表格答案
  259. return ans_no, table_ans
  260. def only_parse_split(one_item_ans, item_type, res_con, reparse_n=1):
  261. """
  262. 拆分出答案和解析,主要针对答案页中的每个题的答案进行拆分
  263. :one_item: 单道题的答案解析部分,
  264. :reparse_n == 1:表示再解析
  265. :return:{'key': ,"parse": }
  266. """
  267. one_item_ans = re.sub("\n\s*(化学|物理|生物|和|与)+\s*【答案】\s*$", '', one_item_ans)
  268. dd = {'parse': one_item_ans, 'key': ""}
  269. temp_ans = one_item_ans
  270. one_item_ans = one_item_ans.split("【答案】", maxsplit=1)[-1]
  271. simp_item = re.sub(r"(【([解分][析答]|详解|点[评睛])】|答案|解析|详解)\s*[::]?", "", one_item_ans)
  272. simp_item = re.sub("[^\u4e00-\u9fa5∵∴]", "", simp_item)
  273. deng_num = re.findall(r"((?!(src|width|height|style)).)+?([==]).+?", one_item_ans, re.S)
  274. huanheng_num = re.findall("\n+", one_item_ans, re.S)
  275. if len(simp_item) < 10 and re.search("因为?|因此|所以|根据|依据|若|假设", simp_item) is None and len(deng_num) < 2:
  276. dd['parse'] = ""
  277. if len(huanheng_num) > 1:
  278. dd['parse'] = one_item_ans
  279. sim_parse = dd['parse'] # 去掉点评后用于找答案
  280. if re.search(r"【(解析|解答|分析|详解|点评|点睛)】\n?|(解析|解答|分析|详?解|点评|点睛)\s*[::]", one_item_ans):
  281. dd1 = dict(zip(["key", "parse_title", "parse"],
  282. re.split(r"【(解析|解答|分析|详解|点评|点睛)】\n?", one_item_ans, maxsplit=1)))
  283. if len(dd1)==1:
  284. dd1 = dict(zip(["key", "parse_title", "parse"],
  285. re.split(r"(解)\s*[::]", one_item_ans, maxsplit=1)))
  286. if "【答案】" in temp_ans:
  287. dd["key"] = dd1["key"]
  288. if len(dd1) >= 3:
  289. dd["parse"] = "【" + dd1["parse_title"] + "】" + dd1["parse"]
  290. del dd1["parse_title"]
  291. sim_parse = re.split("【点评】|【点睛】", dd["parse"])[0].strip()
  292. # 将解析中末尾出现的图片去掉
  293. while re.search('\n\s*<imgsrc\d+\sw_h=(\d+\*\d{3})/>\s*$', sim_parse):
  294. sim_parse = re.sub('\n\s*<imgsrc\d+\sw_h=(\d+\*\d{3})/>\s*$', "", sim_parse)
  295. if item_type.replace("题", "") in ["单选", "多选", "选择", "不定选择"]:
  296. ans = re.search(r'故选\s*[::]?\s*<imgsrc\d+\sdata-latex="([A-Z;;和与、、\s]+)"/>'
  297. r'|故选\s*[::]?\s*([A-Z;;和与、、\s]+)', dd["parse"].replace("$", ""))
  298. ans1 = re.search(r'故答案[为是有]\s*[::]\s*<imgsrc\d+\sdata-latex="([A-Z;;和与、、\s]+)"/>'
  299. r'|故答案[为是有]\s*[::]?\s*([A-Z;;和与、、\s]+)', dd["parse"].replace("$", ""))
  300. if ans:
  301. dd["key"] = ans.group(1) if ans.group(1) is not None else ans.group(2)
  302. if ans1:
  303. dd["key"] = ans1.group(1) if ans1.group(1) is not None else ans1.group(2)
  304. elif not dd['key']:
  305. dd['key'] = one_item_ans.strip()
  306. dd['key'] = re.sub(r"[.;;.]\s*$", "", dd['key'])
  307. elif item_type: # 把所有的图片能先提前替换比较好,后面匹配的话会容易些
  308. ans0 = re.search(r'故选\s*[::]?\s*([A-Z;;和与、、\s]+)[..;;。]?$', sim_parse) # 试验题中可能还有选择题
  309. ans01 = re.search(r'故选\s*[::]\s*<imgsrc\d+\sdata-latex="([A-Z;;和与、、\s]+)"/>', sim_parse.replace("$", "")) # 可能开始题型写错
  310. ans1 = re.search(r'(故|因[而此]|所以)\s*[::]?\s*(答案分?别?[为是填]?|填)\s*[::]?\s*(((?!(<img)).)+?)[..]?\s*(\n|$)', sim_parse)
  311. ans11 = re.search(r'((?<!解)答\s*[::]|整理得\s*[::]?)\s*(.+?)([..;;]?\s*$|[..]\s*\n)', sim_parse)
  312. ans2 = re.search(r'(故|因[而此]|所以)\s*[::]?\s*(答案分?别?[为是填]?|填)\s*[::]?\s*(<imgsrc.+?/>)[..]?\s*(\n|$)', sim_parse, re.S)
  313. ans22 = re.search(r'(故|因[而此]|所以)\s*[::]?\s*(答案分?别?[为是填]?|填)\s*[::]?\s*([^∴∵故因所即【】]+?)([..]\s*(\n|$)|$)', sim_parse)
  314. ans21 = re.search(r'综上所述\s*[::]\s*([^∴∵故因所即【】]+?)[..;;]\s*$', sim_parse)
  315. ans3 = re.search(r'(故|因[而此]|所以|∴)\s*[::]?.+?[为是填]\s*[::]?\s*([^∴∵故因所即则【】]+?)([..;;,,]\s*$|[..]\s*\n)', sim_parse) # 改添
  316. ans31 = re.search(r'(故|因[而此]|所以|∴)\s*([^当为是填∴∵因所故即则【】]+?)[..;;]\s*$', sim_parse) # 改添
  317. ans32 = re.search(r'(故|因[而此]|所以)\s*[::]?[^当为是填∴∵因所故即【】]+?[为是填]\s*[::]?\s*(<imgsrc.+?/>)[..]?\s*(\n|$)', sim_parse, re.S)
  318. ans4 = re.search(r'\n\s*[==]([^=\n]+?)[..]?\s*$', sim_parse)
  319. # ans42 = re.search(r'[==](?!")(((?!([故=∴即]|原式|因[而此]|所以|\n|=[^"])).)+?)[..]?\s*$', sim_parse)
  320. ans41 = re.search(r'原式\s*[==].+?[==](?!")(((?!(=|=[^"])).)+?|\s*<imgsrc.+?/>)([..]?\s*$|[..]\s*\n)', sim_parse)
  321. if reparse_n != 2 and "【答案】" not in one_item_ans and dd['parse'] and \
  322. len(re.findall(r"[((]\d[))]|[\n::;;。】]([((](i{1,3}|[ⅰⅱⅲⅳⅠⅡⅢIV①②③④])[))]|[①②③④]\s*(?![+-]))",
  323. sim_parse.replace(" ", ""))) > 1 and not (item_type == '填空题' and len(re.findall(r"_{2,}|_+([^_]*?)_+", res_con)) == 1):
  324. dd["key"] = "见解析"
  325. elif ans0:
  326. dd["key"] = ans0.group(1)
  327. elif ans01:
  328. dd["key"] = ans01.group(1)
  329. elif ans1 or ans11:
  330. dd["key"] = ans1.group(3) if ans1 else ans11.group(2)
  331. elif ans2:
  332. dd["key"] = ans2.group(3)
  333. elif ans22:
  334. dd["key"] = ans22.group(3)
  335. elif ans21:
  336. dd["key"] = ans21.group(1)
  337. elif (ans3 or ans31 or ans32) and '证明' not in one_item_ans:
  338. if ans3:
  339. dd["key"] = ans3.group(2)
  340. if ans31:
  341. dd["key"] = ans31.group(2)
  342. if ans32:
  343. dd["key"] = ans32.group(2)
  344. elif (ans4 or ans41) and '证明' not in one_item_ans:
  345. if ans4:
  346. dd["key"] = ans4.group(1)
  347. if ans41:
  348. dd["key"] = ans41.group(1)
  349. # if ans42:
  350. # dd["key"] = ans42.group(1)
  351. elif not dd['parse']:
  352. dd['key'] = one_item_ans.strip()
  353. else:
  354. dd["key"] = "见解析"
  355. else: # 题型未知
  356. if len(simp_item) < 10:
  357. dd["key"] = re.sub(r"【答案】|答案\s*[::]", "", one_item_ans.strip())
  358. else:
  359. ans1 = re.search(
  360. r'故选\s*[::]\s*<imgsrc\d+\sdata-latex="([A-Z;;和与、、\s]+)"/>|故选\s*[::]?\s*([A-Z;;和与、、\s]+)',
  361. dd["parse"].replace("$", ""))
  362. ans2 = re.search(r'故\s*[::]?\s*答案分?别?[为是]?\s*[::]?\s*(.+?)[..]\s*(\n|$)', dd["parse"])
  363. ans3 = re.search(r'(【答案】|答案)\s*[::]?(.+?)(\n|$)', dd["parse"])
  364. if ans1:
  365. dd["key"] = ans1.group(1) if ans1.group(1) is not None else ans1.group(2)
  366. elif ans2:
  367. dd["key"] = ans2.group(1)
  368. elif ans3:
  369. dd["key"] = ans3.group(2)
  370. dd["parse"] = dd["parse"].replace(ans3.group(0), "")
  371. elif not dd['key']:
  372. dd['key'] = "见解析"
  373. # print('最后:',dd)
  374. return dd
  375. def ans_structure_step1(anss, item_type_classify, item_res):
  376. """
  377. 针对答案部分解析结构化汇总
  378. anss : 整个答案部分
  379. :return: dd = {'parse': , 'key': }
  380. """
  381. anss = [k for k in anss if k.strip()]
  382. ans_label = [k for k, a in enumerate(anss) if re.match("【答案】", a.strip())]
  383. parse_label = [k for k, a in enumerate(anss) if re.match("【解析】", a.strip())]
  384. if len(ans_label) == 1 and len(parse_label) == 1:
  385. ans1 = anss[ans_label[0] + 1: parse_label[0]]
  386. parse1 = anss[parse_label[0]+1:]
  387. item_res = ans_structure_step2(ans1, item_type_classify, item_res,'group_ans')
  388. item_res = ans_structure_step2(parse1, item_type_classify, item_res, 'group_parse')
  389. else:
  390. item_res = ans_structure_step2(anss, item_type_classify, item_res)
  391. return item_res
  392. def ans_structure_step2(anss, item_type_classify, item_res, *group):
  393. """
  394. 拆分答案,并根据已拆分好的题目item_res 补上答案和解析
  395. 有的答案放在表格里,如选择题、填空题、判断题,有的一行多个答案
  396. 思路:1.先按一行没有多个题答案的情况取答案,数量与题干不同 时 >>>> 2.再按一行多个答案的情况取答案:
  397. 1)先判断表格,拿到表格的答案;2)一行多个答案
  398. anss: 一组按所有不重复题号的答案
  399. item_type_classify: 题目中对各题型的统计
  400. :return: [{'parse': , 'key': },{},{}]
  401. """
  402. while not anss[0]:
  403. anss = anss[1:]
  404. if re.match(".+?省.+?试[卷题]|[^a-zA-Z]*?【专题】", anss[0]):
  405. anss = anss[1:]
  406. # --------- 答案整体解析----存在一行中有选择题和填空题答案,填空题答案尽量每题占一行----------
  407. item_type_num = sum(list(item_type_classify.values()))
  408. all_item_ans = [] # 前期只记录表格答案和排列型答案
  409. table_ans = []
  410. ans_no = [] # 只记录表格答案和排列型答案的id
  411. # 默认表格答案放在最前面 !!!
  412. while anss and "table" in anss[0]: # 答案以表格形式呈现, 表格应放在前两行位置,不要插在答案中间
  413. row_list = [] # 要求表格形式为 横纵分明 ,不存在合并
  414. for tt in re.finditer('<tr>(((?!(</?tr>)).)*)</tr>', anss[0], re.S): # 先划分每行
  415. tt_list = re.split(r'</p></td>|<td><p>|</td><td>|</td>|<td>', tt.group(1)) # 再划分每列
  416. # row_list.append([col for col in tt_list if col.strip()]) # 也有可能答案为空
  417. row_list.append(tt_list)
  418. if row_list:
  419. print("^^^^^^存在答案放在表格里的情况!^^^^^^^")
  420. if len(row_list) % 2 != 0:
  421. print('表格形式呈现的答案不是偶数行')
  422. else:
  423. print("row_list:", row_list)
  424. for k, v in enumerate(row_list):
  425. # print('-----',v)
  426. if (k + 1) % 2 == 1: # 奇数行==》答案序号行
  427. item_no = [int(i) if re.sub(r"[^\d]", "", i) else -1 for i in v]
  428. item_no_st = [num for num, i in enumerate(item_no) if i != -1] # 可能开头是-1
  429. ans_no.extend([i for i in item_no if i != -1]) # 表格序号
  430. table_ans.extend(row_list[k + 1][item_no_st[0]: item_no_st[-1] + 1]) # 表格答案
  431. anss = anss[1:]
  432. print("表格答案:", table_ans)
  433. all_item_ans.extend(table_ans)
  434. if re.search("<table>.*?</table>", anss[0], re.S) is None:
  435. anss[0] = anss[0].split("</table>")[-1].replace("</div>", "")
  436. # 先按一行没有多个题答案的情况取答案
  437. anss_str = table_label_cleal("\n" + "\n".join(anss))
  438. # print(anss_str)
  439. # if re.search("<table>.+?</table>", anss_str,, re.S) is None: # 放在前面判断比较合适些
  440. # anss_str = anss_str.split("</table>")[-1].replace("</div>", "")
  441. ans_item_no_type = 1 # 初步定义答案的题号就是第一种类型!!!
  442. # 将序号前面是大写字母或分号的情况,加空
  443. anss_str = re.sub(r"([A-H])\s*[..](\s*([1-9][0-9]|[1-9])\s*[..、、])", r"\1 \2", anss_str)
  444. while re.search(r"([A-E])(([1-9][0-9]|[1-9])\s*[..、、]\s*[A-E])", anss_str):
  445. anss_str = re.sub(r"([A-E])(([1-9][0-9]|[1-9])\s*[..、、]\s*[A-E])", r"\1 \2", anss_str)
  446. def sub1(ss):
  447. if int(ss.group(3)) - int(ss.group(1)) == 1:
  448. return ss.group(1)+ss.group(2)+' '+ss.group(3)+'、'+ss.group(4)
  449. anss_str = re.sub(r"([1-9][0-9]|[1-9])\s*([..、、]\s*[A-E])\s*([1-9][0-9]|[1-9])\s*([A-E]\s*([1-9][0-9]|[1-9])\s*[..、、])", sub1, anss_str)
  450. anss_str = re.sub(r"([;;])(\s*([1-9][0-9]|[1-9])\s*[.、、])", r"\1 \2", anss_str)
  451. item_no_info = pre_get_item_no('\n' + anss_str, ans_item_no_type) # 按\n\d、
  452. print("初步题号:", item_no_info) # 初步按非表格非排列的形式获取题号信息
  453. if not item_no_info and len(anss_str.replace(" ", "")) < 50:
  454. item_0 = re.split(r"[1-9]\s*[..、、::]|[1-9][0-9]\s*[..、、::]", anss_str)
  455. if len(item_0) > 1:
  456. anss_str = item_0[0]
  457. array_ans_no, array_ans = get_array_ans(anss_str, ans_no, item_res[0]['item_id'])
  458. all_item_ans.extend(array_ans)
  459. ans_no.extend(array_ans_no)
  460. if len(item_0) > 1:
  461. all_item_ans.extend(item_0[1:])
  462. ans_no.extend(re.findall(r"([1-9]|[1-9][0-9])\s*[..、、::]", anss_str))
  463. # if re.search("[A-Z]{4,}", anss_str):
  464. # new_ans = []
  465. # rest_item0 = re.split(r"[1-9]\s*[..、、::]|[1-9][0-9]\s*[..、、::]", anss_str)
  466. # if len(rest_item0) > 1:
  467. # new_ans = re.findall("[A-Z](?<!\))", rest_item0[0])
  468. # new_ans.extend(rest_item0[1:])
  469. # else:
  470. # rest_item1 = re.split(r"[、、]", anss_str)
  471. # if len(rest_item1) > 1:
  472. # new_ans = re.findall("[A-Z](?<!\))", rest_item1[0])
  473. # new_ans.extend(rest_item1[1:])
  474. # if len(all_item_ans) + len(new_ans) < len(item_res):
  475. # new_ans = []
  476. # for k in re.finditer("[A-Z]{4,}", anss_str):
  477. # row_ans = re.findall("[A-Z](?<!\))", str(k.group()))
  478. # new_ans.append(row_ans)
  479. # all_item_ans.extend(new_ans)
  480. # if ans_no:
  481. # ans_no.extend(list(range(ans_no[-1] + 1, ans_no[-1] + 1 + len(new_ans))))
  482. # else:
  483. # ans_no.extend(list(range(item_res[0]['item_id'], 1 + len(new_ans))))
  484. # elif re.search("^[\d\sA-Z]+$", anss_str):
  485. # new_ans = []
  486. # rest_item0 = re.split(r"[1-9][0-9]|[1-9]", anss_str)
  487. # if len(rest_item0) > 1:
  488. # new_ans = re.findall("[A-Z](?<!\))", rest_item0[0])
  489. # if ans_no:
  490. # ans_no.extend(list(range(ans_no[-1] + 1, ans_no[-1] + 1 + len(new_ans))))
  491. # else:
  492. # ans_no.extend(list(range(item_res[0]['item_id'], 1 + len(new_ans))))
  493. # new_ans.extend(rest_item0[1:])
  494. # ans_no.extend([int(i) for i in re.findall(r"[1-4][0-9]|[1-9]", anss_str)])
  495. # all_item_ans.extend(new_ans)
  496. if len(ans_no) == item_type_num or len(ans_no) == len(item_res): # 只有表格答案或排列答案的情况
  497. print('答案第1种切分方案:只有表格答案或排列答案的情况!')
  498. item_res = get_ans_match(item_res, all_item_ans, ans_no, group)
  499. else:
  500. ans_no0, ans_no_idx0 = get_right_no(item_no_info) # 初始题号纠正,第一个不换行的题号可能被剔除
  501. print("ans_no0:", ans_no0)
  502. print("ans_no_idx0:", ans_no_idx0)
  503. is_from_0 = 1 # shi
  504. if ans_no_idx0[0] != 0 and ans_no0[0] > 1:
  505. ans_no_idx0.insert(0, 0)
  506. is_from_0 = 0 # fei
  507. # 除表格、排列型之外的答案
  508. rest_item_split = [('\n' + anss_str)[i:j] for i, j in zip(ans_no_idx0, ans_no_idx0[1:] + [None])]
  509. if not is_from_0: # 不是从0开始, 从0开始的话就不用判断
  510. if re.match('(\n|^)故[::]?选[::]|故[::]?答案分?别?[为是]?'
  511. '|【([解分][析答]|详解|点[评睛])】|(答案|解析|详解)[::]',
  512. rest_item_split[0].replace(" ", "")) is None:
  513. if item_no_info[0][0]==0 or item_no_info[0][1]=='1':
  514. # 说明rest_item_split[0] 是一行多个排列的答案
  515. array_ans_no, array_ans = get_array_ans(rest_item_split[0], ans_no, item_res[0]['item_id'])
  516. if array_ans:
  517. ans_no.extend(array_ans_no)
  518. all_item_ans.extend(array_ans)
  519. # rest_item_split = sum([array_ans.copy(), rest_item_split[1:]], [])
  520. rest_item_split = rest_item_split[1:]
  521. ans_no_idx0 = ans_no_idx0[1:]
  522. else:
  523. print("rest_item_split[0]:", rest_item_split[0])
  524. item_0 = re.split(r"([1-9]\s*[..、、::]\s*(?![A-F])|[1-4][0-9]\s*[..、、::]\s*(?![A-F]))", rest_item_split[0], maxsplit=1)
  525. if len(item_0) > 1:
  526. rest_item_split[0] = item_0[0]
  527. # print(item_0[0])
  528. rest_item_split.insert(1, "\n" + "".join(item_0[1:]))
  529. ans_no0.insert(0, int(re.findall("[1-9]|[1-9][0-9]", item_0[1])[0])) # 这时补充的肯定与后面序号差别比较大
  530. ans_no_idx0[0] = re.search(r"([1-9]|[1-9][0-9])\s*[..、、::]\s*(?![A-F])", rest_item_split[0]).start()
  531. array_ans_no, array_ans = get_array_ans(rest_item_split[0], ans_no, item_res[0]['item_id'])
  532. if array_ans:
  533. ans_no.extend(array_ans_no)
  534. all_item_ans.extend(array_ans)
  535. # rest_item_split = sum([array_ans.copy(), rest_item_split[1:]], [])
  536. else:
  537. ans_no_idx0 = ans_no_idx0[1:]
  538. if 'imgsrc' in rest_item_split[0]: # 针对答案前面存在图的情况,图暂时不管(不清楚是什么图)
  539. temp_str0 = re.sub('<imgsrc.*?/>', "", rest_item_split[0]).replace(" ", "")
  540. if len(temp_str0) < 3 and ans_no0 and ans_no0[0] > 9:
  541. is_from_0 = 1
  542. rest_item_split = rest_item_split[1:]
  543. anss_str = "\n" + "\n".join(rest_item_split[1:]) # 更新anss_str
  544. # if re.search("[1-9]\s*[-~~]\s*([1-9]|1[0-9]).+?", rest_item_split[0]):
  545. # new_ans = re.findall("[A-Z](?<!\))", rest_item_split[0])
  546. # if len(new_ans) == ans_no0[0]-1:
  547. # if ans_no:
  548. # ans_no.extend(list(range(ans_no[-1] + 1, ans_no[-1] + 1 + len(new_ans))))
  549. # else:
  550. # ans_no.extend(list(range(item_res[0]['item_id'], 1 + len(new_ans))))
  551. # new_ans.extend(rest_item_split[1:])
  552. # rest_item_split = new_ans.copy()
  553. # if re.search("[A-Z]{4,}", rest_item_split[0]): # 一般是单选题,多选题答案放在一起的情况暂不考虑,还没遇到
  554. # # 存在排列型答案
  555. # rest_item0 = re.split(r"([1-9]\s*[..、、::]|[1-4][0-9]\s*[..、、::])", rest_item_split[0])
  556. # if len(rest_item0) > 1:
  557. # rest_item_split[0] = rest_item0[0]
  558. # # rest_item_split[1] = "\n"+" ".join(rest_item0[1:]) + rest_item_split[1]
  559. # rest_item_split.insert(1, "\n"+" ".join(rest_item0[1:]))
  560. # ans_no0.insert(0, int(re.findall("[1-9]|[1-4][0-9]", rest_item0[1])[0])) # 这时补充的肯定与后面序号差别比较大
  561. # # print('rest_item0:',rest_item0)
  562. # new_ans = []
  563. # for k in re.finditer("[A-Z]{4,}", rest_item_split[0]):
  564. # row_ans = re.findall("[A-Z](?<!\))", str(k.group()))
  565. # new_ans.append(row_ans)
  566. # if len(new_ans) != ans_no0[0]-1:
  567. # new_ans = re.findall("[A-Z](?<!\))", rest_item_split[0])
  568. # if ans_no:
  569. # ans_no.extend(list(range(ans_no[-1] + 1, ans_no[-1] + 1 + len(new_ans))))
  570. # else:
  571. # ans_no.extend(list(range(item_res[0]['item_id'], 1 + len(new_ans)))) # 默认从1开始,严谨的话,应按题目中第一题的题号开始计
  572. # # 更新anss_str,all_item_ans,rest_item_split!!!!!!
  573. # # anss_str = re.sub("^.+?"+"".join(new_ans[-4:]), "", anss_str)
  574. # anss_str = "\n".join(rest_item_split[1:])
  575. # all_item_ans.extend(new_ans)
  576. # new_ans.extend(rest_item_split[1:])
  577. # rest_item_split = new_ans.copy()
  578. # elif re.search("^[\d\sA-Z]+$", rest_item_split[0]):
  579. # new_ans = []
  580. # rest_item0 = re.split(r"[1-4][0-9]|[1-9]", rest_item_split[0])
  581. # if len(rest_item0) > 1:
  582. # new_ans = re.findall("[A-Z](?<!\))", rest_item0[0])
  583. # if ans_no:
  584. # ans_no.extend(list(range(ans_no[-1] + 1, ans_no[-1] + 1 + len(new_ans))))
  585. # else:
  586. # ans_no.extend(list(range(item_res[0]['item_id'], 1 + len(new_ans))))
  587. # new_ans.extend(rest_item0[1:])
  588. # ans_no.extend([int(i) for i in re.findall(r"[1-4][0-9]|[1-9]", rest_item_split[0])])
  589. # rest_item_split = rest_item_split[1:]
  590. # anss_str = "\n"+"\n".join(rest_item_split)
  591. # all_item_ans.extend(new_ans)
  592. # else:
  593. # ans_no_idx0 = ans_no_idx0[1:]
  594. # if 'imgsrc' in rest_item_split[0]: # 针对答案前面存在图的情况
  595. # temp_str0 = re.sub('<imgsrc.*?/>', "", rest_item_split[0]).replace(" ", "")
  596. # if len(temp_str0)<3 and ans_no0 and ans_no0[0]>9:
  597. # is_from_0 = 1
  598. # rest_item_split = rest_item_split[1:]
  599. else:
  600. ans_no0.insert(0, ans_no0[0] - 1)
  601. # 没有一行多个答案的情况
  602. print("ans_no:",ans_no) # ans_no只记录表格答案和排列型答案
  603. pre_split_ansinfo_list = all_item_ans, ans_no, ans_no0, ans_no_idx0, anss_str, is_from_0, ans_item_no_type
  604. all_item_ans, ans_no = ans_select(item_res, item_type_num, rest_item_split, pre_split_ansinfo_list)
  605. # ans_no1 = ans_no.copy()
  606. # ans_no1.extend(ans_no0) # ans_no0 按换行切分的答案
  607. # print("ans_no0:", ans_no0, len(ans_no0), len(ans_no1))
  608. # # print("ans_no_idx0:", ans_no_idx0, )
  609. # # print("rest_item_split:", rest_item_split,len(rest_item_split))
  610. # if len(ans_no1) != item_type_num and len(ans_no1) != len(item_res):
  611. # if is_from_0: # 答案确实只有部分或前面答案是图片形式
  612. # print('答案第6种切分方案:答案确实只有部分或前面答案是图片形式!')
  613. # rest_item_split = [del_no(k) for k in rest_item_split]
  614. # all_item_ans.extend(rest_item_split)
  615. # ans_no = ans_no1
  616. # item_res = get_ans_match(item_res, all_item_ans, ans_no1, group)
  617. # else:
  618. # # 存在一行多个的情况,题号前必须有空格
  619. # temp_ans_no1, ans_no_idx1 = get_many_ans_no("\n"+anss_str, ans_item_no_type) # 初步获取
  620. # temp_ans_no1, ans_no_idx1 = get_right_no((ans_no_idx1, temp_ans_no1), 1) # 筛选
  621. # ans_no2 = ans_no.copy()
  622. # ans_no2.extend(temp_ans_no1)
  623. # if len(ans_no2) != item_type_num and len(ans_no2) != len(item_res): # 一行多个,题号前可有可无空格
  624. # # 题号前不要求空格时,出错的概率大,最好限制下范围,在按换行获取的题号中对不连续的题号做这种操作!!!!
  625. # new_anss_str = "\n"+anss_str
  626. # seq_no = find_seq_num(ans_no1)
  627. # ans_no_after = []
  628. # no_idx_after = []
  629. # if seq_no:
  630. # ans_no_after.extend(ans_no0[ans_no0.index(seq_no[-1][0]):])
  631. # no_idx_after.extend(ans_no_idx0[ans_no0.index(seq_no[-1][0]):])
  632. # breakp = ans_no_idx0[ans_no0.index(seq_no[-1][0])]
  633. # new_anss_str = ("\n"+anss_str)[:breakp]
  634. # temp_ans_no21, ans_no_idx21, temp_ans_no22, ans_no_idx22 = get_many_ans_no(new_anss_str, ans_item_no_type, reget=1)
  635. # temp_ans_no21.extend(ans_no_after)
  636. # ans_no_idx21.extend(no_idx_after)
  637. # temp_ans_no21, ans_no_idx21 = get_right_no((ans_no_idx21, temp_ans_no21), 1) # 筛选
  638. # ans_no3 = ans_no.copy()
  639. # ans_no3.extend(temp_ans_no21)
  640. # if len(ans_no3) != item_type_num and len(ans_no3) != len(item_res): # 无空格情况下,遇到两位数先取2位
  641. # temp_ans_no22.extend(ans_no_after)
  642. # ans_no_idx22.extend(no_idx_after)
  643. # temp_ans_no22, ans_no_idx22 = get_right_no((ans_no_idx22, temp_ans_no22), 1) # 筛选
  644. # ans_no4 = ans_no.copy()
  645. # ans_no4.extend(temp_ans_no22)
  646. # if len(ans_no4) != item_type_num and len(ans_no4) != len(item_res):
  647. # print('答案格式(无序号)影响答案个数有问题!!!', )
  648. # # 也有可能题目比答案多,如理综题目不全
  649. # if abs(len(item_res) - len(ans_no1)) <= 2 or (len(ans_no1) > len(item_res) and ans_no1[0]==1):
  650. # print('1111111111111111111111')
  651. # rest_item_split = [del_no(k) for k in rest_item_split]
  652. # all_item_ans.extend(rest_item_split)
  653. # ans_no = ans_no1
  654. # # item_res = get_ans_match(item_res, all_item_ans, ans_no1, group)
  655. # elif abs(len(item_res) - len(ans_no2)) <= 2 or (len(ans_no2) > len(item_res) and ans_no2[0]==1):
  656. # print('2222222222222222222222',ans_no2)
  657. # rest_item_split = [del_no(("\n" + anss_str)[i:j]) for i, j in
  658. # zip(ans_no_idx1, ans_no_idx1[1:] + [None])]
  659. # all_item_ans.extend(rest_item_split)
  660. # ans_no = ans_no2
  661. # # item_res = get_ans_match(item_res, all_item_ans, ans_no2, group)
  662. # # elif all_item_ans: # 最后起码把表格答案、排列型答案先填上
  663. # # item_res = get_ans_match(item_res, all_item_ans, ans_no, group)
  664. # else:
  665. # print('答案第5种切分方案:存在一行多个答案,每个答案题号前可以没有空格2')
  666. # rest_item_split = [del_no(("\n" + anss_str)[i:j]) for i, j in
  667. # zip(ans_no_idx22, ans_no_idx22[1:] + [None])]
  668. # all_item_ans.extend(rest_item_split)
  669. # ans_no = ans_no4
  670. # # item_res = get_ans_match(item_res, all_item_ans, ans_no4, group)
  671. # else:
  672. # print('答案第4种切分方案:存在一行多个答案,每个答案题号前可以没有空格1')
  673. # rest_item_split = [del_no(("\n" + anss_str)[i:j]) for i, j in
  674. # zip(ans_no_idx21, ans_no_idx21[1:] + [None])]
  675. # all_item_ans.extend(rest_item_split)
  676. # ans_no = ans_no3
  677. # # item_res = get_ans_match(item_res, all_item_ans, ans_no3, group)
  678. # else:
  679. # print('答案第3种切分方案:存在一行多个答案,且每个答案题号前必须有空格或顶格')
  680. # rest_item_split = [del_no(("\n"+anss_str)[i:j]) for i, j in zip(ans_no_idx1, ans_no_idx1[1:] + [None])]
  681. # all_item_ans.extend(rest_item_split)
  682. # ans_no = ans_no2
  683. # # item_res = get_ans_match(item_res, all_item_ans, ans_no2, group)
  684. #
  685. # else:
  686. # print('答案第2种切分方案:没有一行多个答案的情况!')
  687. # rest_item_split = [del_no(k) for k in rest_item_split]
  688. # all_item_ans.extend(rest_item_split)
  689. # ans_no = ans_no1
  690. item_res = get_ans_match(item_res, all_item_ans, ans_no, group)
  691. return item_res
  692. def get_array_ans(one_item, raw_ans_no, st_no, temp_type=""):
  693. """
  694. 获取排列型的答案
  695. :param one_item: 获取排列型的答案的文本
  696. :param raw_ans_no: 已有的答案id
  697. :param st_no: 题文中的初始题号
  698. :param temp_type: 题型
  699. :return:
  700. """
  701. one_item_no, one_item_ans = [], []
  702. if re.search("([1-9]|1[0-9])\s*[-~-~~]\s*1?[0-9]\s*([A-Z]\s*){2,}", one_item):
  703. no_info = re.findall("([1-9]|1[0-9])\s*[-~]\s*(1?[0-9])\s*([A-Z]\s*){2,}", one_item)
  704. no_list = [list(range(int(i[0]), int(i[1]) + 1)) for i in no_info]
  705. row_split = re.split("\n*[1-9]\s*[-~-~~]\s*1?[0-9]|\n*1[0-9]\s*[-~-~~]\s*1?[0-9]", one_item)
  706. if len(row_split) - len(no_list) == 1:
  707. if not row_split[0].strip():
  708. one_item_no.extend(sum(no_list, []))
  709. for k, j in enumerate(row_split[1:]):
  710. if len(re.findall("[A-Z](?!\))", j)) == len(no_list[k]):
  711. one_item_ans.extend(re.findall("[A-Z](?<!\))", j))
  712. elif len(re.split("\s+", j.strip())) == len(no_list[k]):
  713. one_item_ans.extend(re.split("\s+", j.strip()))
  714. elif len(re.split("[、、]+", j.strip())) == len(no_list[k]):
  715. one_item_ans.extend(re.split("[、、]+", j.strip()))
  716. elif no_list[0][0] > 1:
  717. tt0 = re.split("\s+", row_split[0].strip())
  718. if len(tt0) < no_list[0][0] - 1:
  719. tt0 = re.findall("[A-Z](?!\))", row_split[0])
  720. if len(tt0) >= no_list[0][0] - 1:
  721. one_item_ans.extend(tt0[-(no_list[0][0] - 1):])
  722. one_item_no.extend(list(range(1, no_list[0][0]))[-(no_list[0][0] - 1):])
  723. one_item_no.extend(sum(no_list, []))
  724. for k, j in enumerate(row_split[1:]):
  725. print(re.split("\s+", j.strip()))
  726. if len(re.findall("[A-Z](?!\))", j)) == len(no_list[k]):
  727. one_item_ans.extend(re.findall("[A-Z](?<!\))", j))
  728. elif len(re.split("\s+", j.strip())) == len(no_list[k]):
  729. one_item_ans.extend(re.split("\s+", j.strip()))
  730. elif len(re.split("[、、]+", j.strip())) == len(no_list[k]):
  731. one_item_ans.extend(re.split("[、、]+", j.strip()))
  732. elif (re.search("([1-9]|1[0-9])\s*[A-Z]", one_item) and temp_type.replace("题", "")
  733. in ['选择', '单选', '多选', '不定选择']) or re.search("^[\d\sA-Z..、、\n]+$", one_item): # 1A 2B 3C 4D
  734. row_ans = re.split("[1-9][0-9]|[1-9]", one_item)
  735. if re.search("[A-F]", row_ans[0].strip()):
  736. new_ans = re.findall("[A-Z](?<!\))", row_ans[0])
  737. one_item_ans.extend(new_ans)
  738. if raw_ans_no:
  739. one_item_no.extend(list(range(raw_ans_no[-1] + 1, raw_ans_no[-1] + 1 + len(new_ans))))
  740. else:
  741. one_item_no.extend(list(range(st_no, 1 + len(new_ans))))
  742. else:
  743. row_ans = row_ans[1:]
  744. one_item_ans.extend(row_ans)
  745. one_item_no.extend([int(i) for i in re.findall(r"1[0-9]|[1-9]", one_item)])
  746. else:
  747. # row_ans = sum([re.findall("[A-Z](?<!\))", str(k.group())) for k in re.finditer("[A-Z]{4,}", one_type)],[])
  748. row_ans = re.findall("[A-Z](?<!\))", one_item)
  749. one_item_ans.extend(row_ans)
  750. if raw_ans_no and row_ans:
  751. one_item_no.extend(list(range(raw_ans_no[-1] + 1, raw_ans_no[-1] + 1 + len(row_ans))))
  752. else:
  753. one_item_no.extend(list(range(1, 1 + len(row_ans))))
  754. return one_item_no, one_item_ans
  755. def ans_select(item_res, item_type_num, rest_item_split, pre_split_ansinfo_list):
  756. """
  757. 按换行切分答案、按一行多个答案(含答案序号前有空格或非空格两种情况),
  758. 按此三种方法,与题文试题的切分结构进行对比而选取答案
  759. :param item_type_num:
  760. :param ans_no:
  761. :param ans_str:
  762. :return:
  763. """
  764. all_item_ans, ans_no, ans_no0, ans_no_idx0, anss_str, is_from_0, ans_item_no_type = pre_split_ansinfo_list
  765. ans_no1 = ans_no.copy()
  766. ans_no1.extend(ans_no0)
  767. if len(ans_no1) != item_type_num and len(ans_no1) != len(item_res):
  768. if is_from_0: # 答案确实只有部分或前面答案是图片形式
  769. print('答案第6种切分方案:答案确实只有部分或前面答案是图片形式!')
  770. rest_item_split = [del_no(k) for k in rest_item_split]
  771. all_item_ans.extend(rest_item_split)
  772. ans_no = ans_no1
  773. # item_res = get_ans_match(item_res, all_item_ans, ans_no1, group)
  774. else:
  775. # 存在一行多个的情况,题号前必须有空格
  776. temp_ans_no1, ans_no_idx1 = get_many_ans_no("\n" + anss_str, ans_item_no_type) # 初步获取
  777. temp_ans_no1, ans_no_idx1 = get_right_no((ans_no_idx1, temp_ans_no1), 1) # 筛选
  778. ans_no2 = ans_no.copy()
  779. ans_no2.extend(temp_ans_no1)
  780. if len(ans_no2) != item_type_num and len(ans_no2) != len(item_res): # 一行多个,题号前可有可无空格
  781. # 题号前不要求空格时,出错的概率大,最好限制下范围,在按换行获取的题号中对不连续的题号做这种操作!!!!
  782. new_anss_str = "\n" + anss_str
  783. seq_no = find_seq_num(ans_no1)
  784. ans_no_after = []
  785. no_idx_after = []
  786. if seq_no:
  787. ans_no_after.extend(ans_no0[ans_no0.index(seq_no[-1][0]):])
  788. no_idx_after.extend(ans_no_idx0[ans_no0.index(seq_no[-1][0]):])
  789. breakp = ans_no_idx0[ans_no0.index(seq_no[-1][0])]
  790. new_anss_str = ("\n" + anss_str)[:breakp]
  791. temp_ans_no21, ans_no_idx21, temp_ans_no22, ans_no_idx22 = get_many_ans_no(new_anss_str,
  792. ans_item_no_type, reget=1)
  793. temp_ans_no21.extend(ans_no_after)
  794. ans_no_idx21.extend(no_idx_after)
  795. temp_ans_no21, ans_no_idx21 = get_right_no((ans_no_idx21, temp_ans_no21), 1) # 筛选
  796. ans_no3 = ans_no.copy()
  797. ans_no3.extend(temp_ans_no21)
  798. if len(ans_no3) != item_type_num and len(ans_no3) != len(item_res): # 无空格情况下,遇到两位数先取2位
  799. temp_ans_no22.extend(ans_no_after)
  800. ans_no_idx22.extend(no_idx_after)
  801. temp_ans_no22, ans_no_idx22 = get_right_no((ans_no_idx22, temp_ans_no22), 1) # 筛选
  802. ans_no4 = ans_no.copy()
  803. ans_no4.extend(temp_ans_no22)
  804. if len(ans_no4) != item_type_num and len(ans_no4) != len(item_res):
  805. print('答案格式(无序号)影响答案个数有问题!!!', )
  806. # 也有可能题目比答案多,如理综题目不全
  807. if abs(len(item_res) - len(ans_no1)) <= 2 or (len(ans_no1) > len(item_res) and ans_no1[0] == 1):
  808. print('1111111111111111111111')
  809. rest_item_split = [del_no(k) for k in rest_item_split]
  810. all_item_ans.extend(rest_item_split)
  811. ans_no = ans_no1
  812. # item_res = get_ans_match(item_res, all_item_ans, ans_no1, group)
  813. elif abs(len(item_res) - len(ans_no2)) <= 2 or (
  814. len(ans_no2) > len(item_res) and ans_no2[0] == 1):
  815. print('2222222222222222222222', ans_no2)
  816. rest_item_split = [del_no(("\n" + anss_str)[i:j]) for i, j in
  817. zip(ans_no_idx1, ans_no_idx1[1:] + [None])]
  818. all_item_ans.extend(rest_item_split)
  819. ans_no = ans_no2
  820. # item_res = get_ans_match(item_res, all_item_ans, ans_no2, group)
  821. # elif all_item_ans: # 最后起码把表格答案、排列型答案先填上
  822. # item_res = get_ans_match(item_res, all_item_ans, ans_no, group)
  823. else:
  824. print('答案第5种切分方案:存在一行多个答案,每个答案题号前可以没有空格2')
  825. rest_item_split = [del_no(("\n" + anss_str)[i:j]) for i, j in
  826. zip(ans_no_idx22, ans_no_idx22[1:] + [None])]
  827. all_item_ans.extend(rest_item_split)
  828. ans_no = ans_no4
  829. # item_res = get_ans_match(item_res, all_item_ans, ans_no4, group)
  830. else:
  831. print('答案第4种切分方案:存在一行多个答案,每个答案题号前可以没有空格1')
  832. rest_item_split = [del_no(("\n" + anss_str)[i:j]) for i, j in
  833. zip(ans_no_idx21, ans_no_idx21[1:] + [None])]
  834. all_item_ans.extend(rest_item_split)
  835. ans_no = ans_no3
  836. # item_res = get_ans_match(item_res, all_item_ans, ans_no3, group)
  837. else:
  838. print('答案第3种切分方案:存在一行多个答案,且每个答案题号前必须有空格或顶格')
  839. rest_item_split = [del_no(("\n" + anss_str)[i:j]) for i, j in
  840. zip(ans_no_idx1, ans_no_idx1[1:] + [None])]
  841. all_item_ans.extend(rest_item_split)
  842. ans_no = ans_no2
  843. # item_res = get_ans_match(item_res, all_item_ans, ans_no2, group)
  844. else:
  845. print('答案第2种切分方案:没有一行多个答案的情况!')
  846. rest_item_split = [del_no(k) for k in rest_item_split]
  847. all_item_ans.extend(rest_item_split)
  848. ans_no = ans_no1
  849. return all_item_ans, ans_no
  850. # item_res = get_ans_match(item_res, all_item_ans, ans_no, group)
  851. def get_ans_match(item_res, all_ans, ans_no, *group):
  852. """
  853. 根据切分后的答案及其题号,与前面试题进行匹配更新
  854. :param item_res:
  855. :param all_ans:
  856. :param ans_no:
  857. :return:
  858. """
  859. for k, one_ans in enumerate(all_ans):
  860. temp_id = "no"
  861. # 从试题的res寻找与当前答案题号相同的题目的位置
  862. temp_id_list = [i for i, v in enumerate(item_res) if v["item_id"] == ans_no[k]]
  863. if len(temp_id_list) == 1:
  864. temp_id = temp_id_list[0]
  865. elif len(temp_id_list) > 1:
  866. for j in temp_id_list:
  867. if "key" not in item_res[j].keys():
  868. temp_id = j
  869. if temp_id != 'no': # 找到题目和答案相同的题目的序号时,没找到就先不要答案了
  870. res_con = item_res[temp_id]['stem']
  871. if group==((),) or not group: # 这里group参数是双层嵌套不定参数,if not group[0]
  872. simp_res = only_parse_split(one_ans, item_res[k]["type"], res_con)
  873. item_res[temp_id].update(simp_res)
  874. else:
  875. if group == 'group_ans':
  876. item_res[temp_id]['key'] = one_ans
  877. item_res[temp_id]['parse'] = ""
  878. if group == 'group_parse':
  879. item_res[temp_id]['parse'] = one_ans
  880. if not item_res[temp_id]['key']:
  881. item_res[temp_id]['key'] = '见解析'
  882. return item_res
  883. # def stem_ans_struc_combine(item_type_classify, item_res, all_item_ans, ans_no, group):
  884. # """
  885. # 题干结构化与答案结构化的合并
  886. # :return:
  887. # """
  888. # print("item_type_classify:", item_type_classify)
  889. # print("题干中的题目数量:", len(item_res))
  890. # print("答案中的题目数量:", len(all_item_ans))
  891. # if item_type_classify and len(all_item_ans) == sum(list(item_type_classify.values())):
  892. # res1 = []
  893. # for num1, one_ans in enumerate(all_item_ans):
  894. # parse = only_parse_split(one_ans, item_res[num1]["type"], item_res[num1]['stem'])
  895. # res1.append(parse)
  896. # return res1, 1
  897. # elif not item_type_classify and len(all_item_ans) == len(item_res):
  898. # res1 = []
  899. # for num1, one_ans in enumerate(all_item_ans):
  900. # parse = only_parse_split(one_ans, item_res[num1]["type"], item_res[num1]['stem'])
  901. # res1.append(parse)
  902. # return res1, 1
  903. # else:
  904. # print('答案数量与题干数量不一致,请检查题干和答案中的题号,是否有遗漏答案或答案格式不对;',
  905. # '答案中若存在一行多个答案时,保证每个题的答案间要留有多个空格!', 2)
  906. # print("试题个数:", len(item_res))
  907. # print("答案中的题号:", ans_no)
  908. # # ----------------------是否正确对上序号还需进一步验证!!!!!!!!!!-------------------------------
  909. # res1 = []; simp_res = []
  910. # err_n = 0 # 与题目id没对上号的个数, 默认答案一般也是从前往后排序
  911. # for k, one_item in enumerate(item_res): # 以题目为主
  912. # search_range = ans_no
  913. # if k+3-err_n <= len(ans_no):
  914. # search_range = ans_no[k-err_n:k+3-err_n]
  915. # elif k-err_n < len(ans_no):
  916. # search_range = ans_no[k-err_n:]
  917. # # print("答案的搜索范围search_range:",search_range)
  918. # if one_item['item_id'] in search_range: # 在对应位置前
  919. # ans_no_st = [k1+k-err_n for k1, v1 in enumerate(search_range) if v1 == one_item['item_id']] # 默认取第一个作为对应答案
  920. # # print("答案的位置{0}:{1}, ----对应题目id:{2}".format(ans_no_st, all_item_ans[ans_no_st[0]],one_item['item_id']))
  921. # parse = only_parse_split(all_item_ans[ans_no_st[0]], one_item["type"], one_item['stem'])
  922. # one_item['key'] = parse['key']
  923. # one_item['parse'] = parse['parse']
  924. # res1.append(one_item)
  925. # if group == 'group_ans':
  926. # simp_res.append({'parse': "", 'key': parse['key'],'item_id':one_item['item_id']})
  927. # if group == 'group_parse':
  928. # simp_res.append({'parse': parse['parse'], 'key': parse['key'],'item_id':one_item['item_id']})
  929. # else:
  930. # err_n += 1
  931. # one_item.update({'parse': "", 'key': ""})
  932. # res1.append(one_item)
  933. # if group:
  934. # simp_res.append({'parse': '', 'key': '', 'item_id': one_item['item_id']})
  935. # if simp_res:
  936. # return simp_res, 1
  937. #
  938. # return res1, 2
  939. # def ans_structure_step1(anss, item_type_classify, item_res):
  940. # """
  941. # 针对答案部分解析结构化汇总
  942. # anss : 整个答案部分
  943. # :return: dd = {'parse': , 'key': }
  944. # """
  945. # anss = [k for k in anss if k.strip()]
  946. # ans_label = [k for k, a in enumerate(anss) if re.match("【答案】", a.strip())]
  947. # parse_label = [k for k, a in enumerate(anss) if re.match("【解析】", a.strip())]
  948. # if len(ans_label) == 1 and len(parse_label) == 1:
  949. # ans1 = anss[ans_label[0] + 1: parse_label[0]]
  950. # parse1 = anss[parse_label[0]+1:]
  951. # res_ans, flag1 = ans_structure_step2(ans1, item_type_classify, item_res,'group_ans')
  952. # res_parse, flag2 = ans_structure_step2(parse1, item_type_classify, item_res, 'group_parse')
  953. # if flag1 == flag2 == 1:
  954. # for idx, item_r in enumerate(item_res):
  955. # if not res_ans[idx]['key']:
  956. # if not res_parse[idx]['key']:
  957. # item_res[idx]['key'] = "见解析"
  958. # else:
  959. # item_res[idx]['key'] = res_parse[idx]['key']
  960. # else:
  961. # item_res[idx]['key'] = res_ans[idx]['key']
  962. #
  963. # if not res_ans[idx]['parse']:
  964. # item_res[idx]['parse'] = res_parse[idx]['parse']
  965. # else: # 解析中的parse肯定有
  966. # item_res[idx]['parse'] = res_ans[idx]['parse']+"<br/>【解析】"+res_parse[idx]['parse']
  967. # return item_res
  968. # elif flag1 == 2:
  969. # return "【答案】组中题型数量与题目中不一致,请重点检查题目序号,重新手输题目序号"
  970. # elif flag2 == 2:
  971. # return "【解析】组中题型数量与题目中不一致,请重点检查题目序号,重新手输题目序号"
  972. # else:
  973. # return '【答案】组和【解析】组中题型数量与题目中均不一致,请重点检查题目序号,重新手输题目序号'
  974. # else:
  975. # res_ans, flag1 = ans_structure_step2(anss, item_type_classify, item_res)
  976. # if flag1 == 1:
  977. # for idx, item_r in enumerate(item_res):
  978. # item_res[idx]['key'] = res_ans[idx]['key']
  979. # item_res[idx]['parse'] = res_ans[idx]['parse']
  980. # else:
  981. # # return "答案中题目数量与题目中不一致,①请重点检查题目序号,重新手输题目序号;②将参考答案开头没用的信息去掉;" \
  982. # # "③是否有遗漏答案或答案格式不对;④答案中若存在一行多个答案时,保证每个题的答案间要留有多个空格!"
  983. # return res_ans
  984. # return item_res
  985. #
  986. #
  987. # def ans_structure_step2(anss, item_type_classify, item_res, *group):
  988. # """
  989. # 拆分答案,并根据已拆分好的题目item_res 补上答案和解析
  990. # 有的答案放在表格里,如选择题、填空题、判断题,有的一行多个答案
  991. # 思路:1.先按一行没有多个题答案的情况取答案,数量与题干不同 时 >>>> 2.再按一行多个答案的情况取答案:
  992. # 1)先判断表格,拿到表格的答案;2)一行多个答案
  993. # anss: 一组按所有不重复题号的答案
  994. # item_type_classify: 题目中对各题型的统计
  995. # :return: [{'parse': , 'key': },{},{}]
  996. # """
  997. # while not anss[0]:
  998. # anss = anss[1:]
  999. # if re.match(".+?省.+?试[卷题]|[^a-zA-Z]*?【专题】", anss[0]):
  1000. # anss = anss[1:]
  1001. #
  1002. # # # 预处理: 对答案部分的题号进行处理, 将(\d)类型的题号改为\d、类型
  1003. # # sub_item_no = [int(no[0]+no[2]) for no in
  1004. # # re.findall(r'\n\s*([1-9]|[1-4][0-9])\s*[..、、]|\n\s*([1-9]|[1-4][0-9])\s*[..、、].+?\s+([1-9]|[1-4][0-9])\s*[..、、].+?',
  1005. # # "\n" + "\n".join(anss))]
  1006. # # if len(sub_item_no) <= 2:
  1007. # # sub_item_no = [int(no[0]+no[2]) for no in re.findall(r'\n\s*\(([1-9]|[1-4][0-9])\)\s*[..、、]?'
  1008. # # r'|\n\s*\(([1-9]|[1-4][0-9])\)\s*[..、、]?.+?\s+\(([1-9]|[1-4][0-9])\)\s*[..、、]?.+?',
  1009. # # "\n" + "\n".join(anss))]
  1010. # # if len(sub_item_no) > 3:
  1011. # # anss = re.sub(r'\n\s*\(([1-9]|[1-4][0-9])\)\s*[..、、]?', "\n" + r"【@\1、", "\n" + "\n".join(anss))
  1012. # # anss = re.sub(r'(\n【@([1-9]|[1-4][0-9])、.+?\s+)\(([1-9]|[1-4][0-9])\)\s*[..、、]?', r"\1【@\3、", anss)
  1013. # # anss = anss.replace("【@", "").split("\n")[1:]
  1014. #
  1015. # # --------- 答案整体解析----存在一行中有选择题和填空题答案,填空题答案尽量每题占一行----------
  1016. # item_type_num = sum(list(item_type_classify.values()))
  1017. # all_item_ans = []
  1018. # table_ans = []
  1019. # ans_no = []
  1020. # # 默认表格答案放在最前面 !!!
  1021. # while anss and "table" in anss[0]: # 答案以表格形式呈现, 表格应放在前两行位置,不要插在答案中间
  1022. # row_list = [] # 要求表格形式为 横纵分明 ,不存在合并
  1023. # for tt in re.finditer('<tr>(((?!(</?tr>)).)*)</tr>', anss[0], re.S): # 先划分每行
  1024. # tt_list = re.split(r'</p></td>|<td><p>|</td><td>|</td>|<td>', tt.group(1)) # 再划分每列
  1025. # # row_list.append([col for col in tt_list if col.strip()]) # 也有可能答案为空
  1026. # row_list.append(tt_list)
  1027. # if row_list:
  1028. # print("^^^^^^存在答案放在表格里的情况!^^^^^^^")
  1029. # if len(row_list) % 2 != 0:
  1030. # print('表格形式呈现的答案不是偶数行')
  1031. # else:
  1032. # # print("row_list:", row_list)
  1033. # for k, v in enumerate(row_list):
  1034. # # print('-----',v)
  1035. # if (k + 1) % 2 == 1: # 奇数行==》答案序号行
  1036. # item_no = [int(i) if re.sub(r"[^\d]", "", i) else -1 for i in v]
  1037. # item_no_st = [num for num, i in enumerate(item_no) if i != -1] # 可能开头是-1
  1038. # ans_no.extend([i for i in item_no if i != -1]) # 表格序号
  1039. # table_ans.extend(row_list[k + 1][item_no_st[0]: item_no_st[-1] + 1]) # 表格答案
  1040. # anss = anss[1:]
  1041. #
  1042. # # 先按一行没有多个题答案的情况取答案
  1043. # anss_str = table_label_cleal("\n" + "\n".join(anss))
  1044. # if re.search("<table>.+?</table>", anss_str) is None:
  1045. # anss_str = anss_str.split("</table>")[-1].replace("</div>", "")
  1046. #
  1047. # ans_item_no_type = 1 # 初步定义答案的题号就是第一种类型
  1048. # # 将序号前面是大写字母或分号的情况,加空
  1049. # anss_str = re.sub(r"([A-H])\s*[..](\s*([1-4][0-9]|[1-9])\s*[..、、])", r"\1 \2", anss_str)
  1050. # anss_str = re.sub(r"([;;])(\s*([1-4][0-9]|[1-9])\s*[.、、])", r"\1 \2", anss_str)
  1051. #
  1052. # rest_item_split = re.split(r'\n+\s*[1-4][0-9]\s*[..、、]|\n+\s*[1-9]\s*[..、、]', anss_str)
  1053. # if not rest_item_split[0]:
  1054. # rest_item_split = rest_item_split[1:]
  1055. #
  1056. # all_item_ans.extend(table_ans)
  1057. # all_item_ans.extend(rest_item_split)
  1058. # print("表格答案:", table_ans)
  1059. # # pprint(all_item_ans)
  1060. # # ------------先按没有一行多个答案的情况-------------------
  1061. # if item_type_classify and len(all_item_ans) == sum(list(item_type_classify.values())):
  1062. # res1 = []
  1063. # for num1, one_ans in enumerate(all_item_ans):
  1064. # parse = only_parse_split(one_ans, item_res[num1]["type"], item_res[num1]['stem'])
  1065. # res1.append(parse)
  1066. # return res1, 1
  1067. # elif not item_type_classify and len(all_item_ans) == len(item_res):
  1068. # res1 = []
  1069. # for num1, one_ans in enumerate(all_item_ans):
  1070. # parse = only_parse_split(one_ans, item_res[num1]["type"], item_res[num1]['stem'])
  1071. # res1.append(parse)
  1072. # return res1, 1
  1073. # else: # 答案个数与题目不一致时,再按一行多个答案处理(题目个数正常,答案个数比题目少时)
  1074. # print('-----存在一行多个答案的情况-----')
  1075. # all_item_ans = []
  1076. # all_item_ans.extend(table_ans)
  1077. # # 再按一行多个答案的情况取答案
  1078. # manyans_oneline_split = re.split(r'\n\s*[1-4][0-9]\s*[..、、]|\n\s*[1-9]\s*[..、、]'
  1079. # r'|(?<![::..、、+\-*/=])\s[1-4][0-9]\s*[..、、]|(?<![::..、、+\-*/=])\s[1-9]\s*[..、、]'
  1080. # r'|\s{2,}[1-4][0-9]\s*[..、、]|\s{2,}[1-9]\s*[..、、]', anss_str)
  1081. #
  1082. # temp_no = re.findall(r'\n\s*([1-4][0-9]|[1-9])\s*[..、、]'
  1083. # r'|(?<![::..、、+\-*/=])\s([1-4][0-9]|[1-9])\s*[..、、]|\s{2,}([1-4][0-9]|[1-9])\s*[..、、]', anss_str)
  1084. # temp_no = [int("".join(i)) for i in temp_no]
  1085. # # print("temp_no:",temp_no)
  1086. # # print('manyans_oneline_split:', manyans_oneline_split, len(manyans_oneline_split))
  1087. # if not temp_no and not all_item_ans: # 没有表格答案的情况,如1~10 ACBBD...
  1088. # row_ans = re.findall("[A-Z](?<!\))", manyans_oneline_split[0].strip())
  1089. # all_item_ans.extend(row_ans)
  1090. # temp_no = re.findall("(\d)-(\d{1,2})", manyans_oneline_split[0])
  1091. # for t in temp_no:
  1092. # ans_no.extend(list(range(int(t[0]), int(t[1])+1)))
  1093. # if row_ans:
  1094. # manyans_oneline_split = []
  1095. # elif temp_no and not manyans_oneline_split[0]:
  1096. # manyans_oneline_split = manyans_oneline_split[1:]
  1097. # ans_no.extend(temp_no)
  1098. # elif re.match("A-Z", manyans_oneline_split[1].strip()) is None and \
  1099. # len(re.findall("[A-Z](?<!\))", manyans_oneline_split[0].strip())) == len(item_res) - (len(manyans_oneline_split)-1):
  1100. # print('第一行答案不是以题号形式一个个给出')
  1101. # row_ans = re.findall("[A-Z](?<!\))", manyans_oneline_split[0].strip())
  1102. # all_item_ans.extend(row_ans)
  1103. # manyans_oneline_split = manyans_oneline_split[1:]
  1104. # if temp_no and temp_no[0] > len(row_ans):
  1105. # ans_no.extend(list(range(temp_no[0]-len(row_ans), temp_no[0])))
  1106. # ans_no.extend(temp_no)
  1107. # else:
  1108. # print("答案序号有问题!!")
  1109. # ans_no.extend(['']*len(row_ans))
  1110. # ans_no.extend(temp_no)
  1111. # # print("manyans_oneline_split:************")
  1112. # # pprint(manyans_oneline_split)
  1113. # print("ans_no:", ans_no)
  1114. # all_item_ans.extend(manyans_oneline_split)
  1115. # combine_res = stem_ans_struc_combine(item_type_classify, item_res, all_item_ans, ans_no, group)
  1116. # # if not combine_res:
  1117. # # return '答案数量与题干数量不一致,请检查题干和答案中的题号,是否有遗漏答案或答案格式不对;' \
  1118. # # '答案中若存在一行多个答案时,保证每个题的答案间要留有多个空格!', 2
  1119. #
  1120. # return combine_res
  1121. # def manyans_oneline_split(item_str, one_type_num):
  1122. # """
  1123. # 对一行多个答案的情况进行拆分,包含表格形式表示的答案,表格要求放在前面
  1124. # :param item_str:
  1125. # :param one_type_num:
  1126. # :return:
  1127. # """
  1128. # all_item_ans = []
  1129. # table_ans = []
  1130. # ans_no = []
  1131. # if item_str and "table" in item_str: # 答案以表格形式呈现, 表格应放在前两行位置,不要插在答案中间
  1132. # row_list = [] # 要求表格形式为 横纵分明 ,不存在合并
  1133. # for one_table in re.finditer('<table>(((?!(</?table>)).)*)</table>', item_str, re.S):
  1134. # for tt in re.finditer(r'<tr>(((?!(</?tr>)).)*)</tr>', one_table.group(1), re.S):
  1135. # tt_list = re.split(r'</p></td>|<td><p>|</td><td>|</td>|<td>', tt.group(1))
  1136. # # row_list.append([col for col in tt_list if col.strip()]) # 也有可能答案为空
  1137. # row_list.append(tt_list)
  1138. # if row_list:
  1139. # print("^^^^^^存在答案放在表格里的情况!^^^^^^^")
  1140. # if len(row_list) % 2 != 0:
  1141. # print('有表格形式呈现的答案不是偶数行')
  1142. # else:
  1143. # for k, v in enumerate(row_list):
  1144. # if (k + 1) % 2 == 1: # 奇数行==》答案序号行
  1145. # item_no = [int(i) if re.sub(r"[^\d]", "", i) else -1 for i in v]
  1146. # item_no_st = [num for num, i in enumerate(item_no) if i != -1] # 可能开头是-1
  1147. # # print(item_no_st)
  1148. # ans_no.extend([i for i in item_no if i != -1]) # 表格序号
  1149. # table_ans.extend(row_list[k + 1][item_no_st[0]: item_no_st[-1] + 1]) # 表格答案
  1150. #
  1151. # all_item_ans.extend(table_ans)
  1152. # rest_item_str = item_str.split("</table>")[-1].replace("</div>", "").strip()
  1153. # rest_item_split = re.split(r'\n+\s*\([1-9]\)\s*[..、、]?|\n+\s*\([1-9][0-9]\)\s*[..、、]?', rest_item_str) # (\d)形式
  1154. # if len(rest_item_split) > 1:
  1155. # if not rest_item_split[0]:
  1156. # rest_item_split = rest_item_split[1:]
  1157. # all_item_ans.extend(rest_item_split)
  1158. # # print("初步all_item_ans:", all_item_ans) # 初步答案
  1159. # print("table_ans:",table_ans)
  1160. # if len(all_item_ans) == one_type_num:
  1161. # ans_no.extend([int(no) for no in re.findall(r'\n+\s*\(([1-9]|[1-9][0-9])\)\s*[..、、]?', rest_item_str)])
  1162. # return all_item_ans, ans_no
  1163. # else:
  1164. # all_item_ans = []
  1165. # all_item_ans.extend(table_ans)
  1166. # # 再按一行多个答案的情况取答案
  1167. # manyans_oneline_split = re.split(r'\n\s*[1-9][0-9]\s*[..、、]|\n\s*[1-9]\s*[..、、]'
  1168. # r'|(?<![::..、、])\s+[1-9][0-9]\s*[..、、](?!png)|(?<![::..、、])\s+[1-9]\s*[..、、](?!png)',
  1169. # rest_item_str)
  1170. # temp_no = re.findall(r'\n\s*([1-9][0-9]|[1-9])\s*[..、、]|(?<![::..、、])\s+([1-4][0-9]|[1-9])\s*[..、、](?!png)', rest_item_str)
  1171. # temp_no = [int("".join(i)) for i in temp_no]
  1172. # if not temp_no and not all_item_ans: # 没有表格答案的情况,如1~10 ACBBD...
  1173. # row_ans = re.findall("[A-Z](?<!\))", manyans_oneline_split[0].strip())
  1174. # all_item_ans.extend(row_ans)
  1175. # temp_no = re.findall("(\d)-(\d{1,2})", manyans_oneline_split[0])
  1176. # for t in temp_no:
  1177. # ans_no.extend(list(range(int(t[0]), int(t[1])+1)))
  1178. # if row_ans:
  1179. # manyans_oneline_split = []
  1180. # elif temp_no and not manyans_oneline_split[0]:
  1181. # manyans_oneline_split = manyans_oneline_split[1:]
  1182. # ans_no.extend(temp_no)
  1183. # elif re.match("A-Z", manyans_oneline_split[1].strip()) is None and \
  1184. # len(re.findall("[A-Z](?<!\))", manyans_oneline_split[0].strip())) == one_type_num - (
  1185. # len(manyans_oneline_split) - 1): # 没有表格答案的情况,如1~10 ACBBD...
  1186. # row_ans = re.findall("[A-Z](?<!\))", manyans_oneline_split[0].strip())
  1187. # all_item_ans.extend(row_ans)
  1188. # manyans_oneline_split = manyans_oneline_split[1:]
  1189. # if temp_no and temp_no[0] > len(row_ans):
  1190. # ans_no.extend(list(range(temp_no[0]-len(row_ans), temp_no[0])))
  1191. # ans_no.extend(temp_no)
  1192. # else:
  1193. # print("答案序号有问题!!")
  1194. # ans_no.extend(['']*len(row_ans))
  1195. # ans_no.extend(temp_no)
  1196. # # print("manyans_oneline_split:", manyans_oneline_split)
  1197. # all_item_ans.extend(manyans_oneline_split)
  1198. # # print("all_item_ans:", all_item_ans)
  1199. # if len(all_item_ans) == one_type_num:
  1200. # return all_item_ans, ans_no