#!/usr/bin/env/python # -*- coding:utf-8 -*- import re from structure.ans_structure import only_parse_split from structure.option import option_structure from structure.stems_to_groups import suojin def get_slave(one_item, con, parse, ans, parse_split=1): """ 带小问的大题 按小问切分 parse_split=1:解析拆 :return: """ # if re.search(r"[;;]", ans) and len(re.findall(r"[((]\s*\d\s*[))]", con)) > 1: # 模板要求老师小题题号(1)(2) con = re.sub("(<[/a-z]+>|[((]\s*\d+\s*分\s*[))])\s*([((]\s*\d\s*[))])", r"\1" + "\n" + r"\2", con) parse = re.sub("(<[/a-z]+>)\s*([((]\s*\d\s*[))])", r"\1" + "\n" + r"\2", parse) # kuo_num = len(re.findall(r"[((]\d[))]", con.replace(" ", ""))) # circle_num = len(re.findall(r"\n[((](i{1,3}|[ⅰⅱⅲⅳ①②③④⑤])[))]|\n[①②③④⑤]\s*(?![+-])", con.replace(" ", ""))) # 小题干按\n(\d)拆 if len(re.findall(r"\n[((]\d[))](?!小?题中)", con.replace(" ", ""))) > 1: # by_sub_item = True # 答案是按照小题获取 # -----------------------题干拆分----------------------------- con = re.sub(r"((?<=[\n::;;。求])|^)\s*([((]\s*[1-9]\s*[))])\s*(?!小?题中)|\n\s*[((]\s*\d{2}\s*[))]", "【ⅳ】", con) con_list = re.split(r"【ⅳ】", con) con_list = [con_list[0]] + [c for c in con_list[1:] if c.strip()] # ---------------答案和解析拆分--------------------------------------- # ans_list = [] if ans != "见解析" else "见解析" ans_list = [] parse_list = [] analy_comment = [] com_ans = "" if parse_split: # 解析需拆分 # 答案 if re.search(r"(\n|\s{2,})[((](\d)[))]", ans.replace(" ", "")): if len(re.findall(r"[((]\d[))]", ans.replace(" ", ""))) > 1: # 优先按(\d)拆分 ans = re.sub(r"((?<=[\n::;;。])\s*|\s{2,}|^\s*)([((]\s*\d\s*[))])", "【ⅳ】", ans) ans_list.extend(re.split(r"【ⅳ】", ans)) com_ans = ans_list[0] ans_list = ans_list[1:] while ans_list and not ans_list[0]: ans_list = ans_list[1:] elif ans.strip() == "见解析": ans_list = ["见解析"] * (len(con_list) - 1) # 解析 if parse: if re.search('【(详解|解析|解答|分析)】', parse): # 2020-6-10 temp_parse = re.split('【详解】|【解析】|【解答】', parse, maxsplit=1) if len(temp_parse) == 1: temp_parse = re.split('【分析】', parse, maxsplit=1) parse = temp_parse[1] analy_comment.append(temp_parse[0]) # 若分析也分小问来,则单独拆分 # if len(re.findall(r"[((]\d[))]", temp_parse[0].replace(" ", ""))) > 1: # syn = re.sub(r"((?<=[\n::;;。】])|^)\s*([((]\s*\d\s*[))])", "【ⅳ】", temp_parse[0]) # syn_list.extend(re.split(r"【ⅳ】", syn)) # syn_list.append(temp_parse[0]) # 【详解】|【解析】|【解答】 前面的部分 if re.search("【(点评|点睛)】", parse): comment = re.split('(【点评】|【点睛】)', parse, maxsplit=1) analy_comment.append(comment[-2] + comment[-1]) parse = comment[0] other_parse_info = re.search("\n\s*" + str(one_item["item_id"]) + "\s*[、..、]\s*[((]\s*1\s*[))]", "\n"+parse) # \d、(1)xxxx if other_parse_info: parse = "(1)" + parse[other_parse_info.end():] analy_comment.append(parse[:other_parse_info.start()]) # 解析拆分小问 if len(re.findall(r"[((]\d[))]", parse.replace(" ", ""))) > 1: parse = re.sub(r"((?<=[\n::;;。])|^)\s*([((]\s*\d\s*[))])", "【ⅳ】", parse) parse = re.sub(r"(/>)\s*([((]\s*\d\s*[))])", r"\1【ⅳ】", parse) # 将解析末尾出现的‘故答案为’在成功slave后删掉,还是容易出错 if re.search('(故|因[而此]|所以)\s*[::]?\s*答案分?别?([为是]|填)?\s*[::]\s*(.+?)(\n|$)', parse): ans_s = re.search('(\n.*?|^.*?|

)((故|因[而此]|所以)\s*[::]?\s*答案分?别?' '([为是]|填)?\s*[::]\s*(.+?))(\n|$)', parse) if ans_s.group(5) and ans_s.group(5).count("【ⅳ】") > 1: # 答案综述中(\d)出现多个时 ans_summarize = ans_s.group(2) ans_s_index = parse.index(ans_summarize) if ans_s.group(1) == '

' or not ans_s.group(1).strip() \ or ans_s.group(1).strip() is None else parse.index(ans_s.group(1)) # ans_summarize = [ans_s.group(2), ans_s_index] # parse = parse.replace(ans_summarize[0], "") parse = parse.replace(ans_summarize, "") elif ans_s.group(5) and "【ⅳ】" in ans_s.group(5): aa5 = ans_s.group(5).replace("【ⅳ】", "") parse = parse.replace(ans_s.group(5), aa5) # ----------------------------------------------- parse = re.sub("(【ⅳ】\s*解答?\s[::])\s*【ⅳ】", r"\1", parse) little_parse = re.split(r"【ⅳ】", parse) if len(little_parse) > 1: parse_list = little_parse[1:] if re.search("\n\s*(【参考译文】|参考译文\s*[::])", "\n"+little_parse[0]): analy_comment.append(little_parse[0]) # -----------------------------------拆分后组合---------------------------------------- one_item, yiwen = split2little_con(con_list, ans_list, parse_list, one_item) # 解析不拆分时,小问也要拆 if parse_split and "slave" in one_item: # 解析需拆分; # 小问解析个数与小问一致时才组合的 # 里层答案/解析存在时,外层就不需要了 if one_item["slave"][0]["parse"].strip(): one_item['parse'] = "\n".join(analy_comment) if one_item["slave"][0]["key"].strip(): # 里层答案存在时,外层就不需要了 one_item['key'] = com_ans.strip() if yiwen: one_item['parse'] += "\n" + yiwen else: # 题干不存在多个\n(\d),不存在多问 if re.findall(r"_{2,}", one_item["stem"]): one_item["blank_num"] = len(re.findall(r"_{2,}", one_item["stem"])) one_item["answer_type"] = "填空题" # if parse_split and re.search("^[A-Z]{2,}$", re.sub("\W", "", ans)): # one_item["type"] = "多选题" elif len(re.findall(r"[\n\s\u4e00-\u9fa5]\s*[A-D]\s*[..、、]", one_item["stem"])) >= 3: # 增加对选项的拆分处理 one_item = option_structure(one_item, con, ans, 1) one_item["answer_type"] = "选择题" if 'options' not in one_item: one_item["options"] = [] elif re.search("[((]\s+[))][\s\n]*$", one_item["stem"]) or one_item["type"] == "判断题": one_item["answer_type"] = "判断题" if re.match("【?(对的?|正确的?|[T√])】?$", one_item["key"].strip()): one_item["key"] = "正确" elif re.match("【?(错误?的?|不对的?|不正确的?|[F×])】?$", one_item["key"].strip()): one_item["key"] = "错误" elif re.search("[横划画]线处填写", one_item["stem"]) and "com_stem" in one_item: one_item["answer_type"] = "填空题" if "com_stem" in one_item: blank_num = len(re.findall(r"_{2,}", one_item["com_stem"])) if blank_num > 0: one_item["blank_num"] = blank_num else: one_item["answer_type"] = "解答题" else: one_item["answer_type"] = "解答题" return one_item def split2little_con(con_list, ans_list, parse_list, one_item): """ 将按小问切分开的题干、答案、解析 进行 【结构化组合】, 包含将小问题干继续按选项拆分的情况 :param con_list:切开了小问的题干 :param ans_list:切开了小问的答案 :param parse_list:切开了小问的解析 :param one_item: 初步切开的一道题目 :param is_sub_item: 答案是否按小题号获取(还是按照空的个数获取)的标志 :param ans_summarize: 解析中的综述 [内容,索引] :return: """ # print(con_list) # print(ans_list) # print(parse_list) # print('***********************') yiwen = "" if len(con_list) > 1: if con_list[0] == "": # 说明全是小题,没有总题文 one_item["stem"] = "" else: # one_item["stem"] = suojin(con_list[0]) # 公共题文缩进处理 one_item["stem"] = con_list[0] slave = [] for index, s in enumerate(con_list[1:]): # 以题干拆分为主 blank_num = len(re.findall(r"_{2,}", s)) s = re.sub(r"[((]\d+分[))]", "", s[:9]) + s[9:] # 格式行调整 if index > 0 and re.search('

\n+$', slave[index - 1]["stem"]): slave[index - 1]["stem"], b, _ = re.split('(

\n+)$', slave[index - 1]["stem"]) s = b + s elif re.search('

\n+$', one_item["stem"]): one_item["stem"], b, _ = re.split('(

\n+)$', one_item["stem"]) s = b + s one_slave = {"slave_no": "(%s)" % (index + 1), "stem": s, "key": "", "parse": "", "answer_type": "解答题", "errmsgs": [], } if len(con_list) - len(parse_list) == 1: one_slave["parse"] = parse_list[index] # 按索引取解析 if index == len(parse_list) - 1 and re.search("\n\s*(【参考译文】|参考译文\s*[::])", "\n"+parse_list[index]): one_slave["parse"], yiwen = re.split("\n\s*【参考译文】|\n\s*参考译文\s*[::]", "\n"+parse_list[index]) yiwen = "【参考译文】" + yiwen if isinstance(ans_list, list) and len(con_list) - len(ans_list) == 1: one_slave["key"] = ans_list[index] # 将小题干中的材料拿到公共题干中 # may_stem_info = re.search("\n材料[一二三四五六七八九十]\s", s) # if may_stem_info: # one_slave["stem"] = s[:may_stem_info.start()] # one_item["stem"] += s[may_stem_info.start()+1:] # 判断小题干是否可以是选择题 if len(re.findall(r"[\n\s\u4e00-\u9fa5]\s*[A-D]\s*[..、、]", s)) >= 3: raw_ans = one_slave["key"] raw_stem = one_slave["stem"] one_slave = option_structure(one_slave, s, one_slave["key"], 1) one_slave["answer_type"] = "选择题" if "options" not in one_slave or not one_slave["options"]: one_slave["key"] = raw_ans # 选择题解析不成功时,答案还原 elif blank_num > 1: one_slave["answer_type"] = "填空题" one_slave["key"] = raw_ans one_slave["stem"] = raw_stem del one_slave["options"], one_slave["options_rank"] if "options" not in one_slave or not one_slave["options"]: if blank_num > 0: one_slave["blank_num"] = blank_num one_slave["answer_type"] = "填空题" elif re.search("[((]\s+[))]\s*$|判断.*?正误", s): one_slave["answer_type"] = "判断题" elif re.search("[横划画]线处填写", s): one_slave["answer_type"] = "填空题" blank_num = len(re.findall(r"_{2,}", one_item["stem"])) if blank_num > 0: one_slave["blank_num"] = blank_num else: one_slave["answer_type"] = "解答题" if "errmsgs" in one_slave: del one_slave["errmsgs"] # 对带小题的大题,对每个小题的答案重新再提取一次 if one_slave["parse"].strip() and (not ans_list or "key" not in one_slave or not one_slave["key"] or one_slave["key"] == '见解析'): new_ans = only_parse_split(one_slave["parse"], one_item["type"], one_slave["stem"], reparse_n=2) # 再解析 if new_ans["key"]: one_slave["key"] = new_ans["key"] if not new_ans["parse"]: one_slave["parse"] = "" slave.append(one_slave) one_item["slave"] = slave one_item["slave_no"] = "1-{}".format(len(slave)) if len(slave) > 1 else "1" # if slave: # pass # else: # if ans_summarize: # one_item["parse"] = one_item["parse"][:ans_summarize[1]] + '\n' + ans_summarize[0] \ # + '\n' + one_item["parse"][ans_summarize[1]:] return one_item, yiwen