#!/usr/bin/env/python # -*- coding:utf-8 -*- # paper3_process: 第三类word试卷模式, 题目和答案分开的情况 # split2one_item:将所有行文本 按题型分大类,再在每个大类中切分每个题目 # split2one_item_by_topicno:将所有行文本 按题型分大类,再在每个大类中按题号切分每个题目 """ 总共3种方案:1、教师用卷;2、按题号切分;3、划分试题和答案,再按题号切分 """ from structure.ans_structure import * from utils.insert_keywords import get_con from utils.item_resplit import resplit from utils.washutil import table_label_cleal from structure.stems_structure import stems_structure_byno from utils.item_type_line import get_item_head_info, get_item_head_info_cn from utils.topic_no import judge_item_no_type, get_right_no from utils.stem_ans_split import stem_ans_split from collections import Counter from pprint import pprint def items_ans_reform(items_list, ans_list, subject): """ 第三种word试卷格式, 题目和答案分开的情况 答案也有几种类型:带题型? :param items_list: :param ans_list: :param subject: :return: """ con1 = list(filter(lambda x: x.strip() != "", items_list)) # 题目 anss1 = list(filter(lambda x: x.strip() != "", ans_list)) # 答案,list中的每个元素为一行 if re.match(".+?省.+?试[卷题]", con1[-1]): con1 = con1[:-1] if re.match(".+?省.+?试[卷题]|.*?答题?[卷卡页]", anss1[0]): anss1 = anss1[1:] # --------------答案页也包含题目的情况----------但可能题目不存在----------------------- ans_n = re.findall("【答案】", "\n".join(anss1)) if subject not in ["地理", "语文"] and ans_n and len(ans_n) == len(re.findall("【解析】", "\n".join(anss1))) > 2: # 带相同个数的答案和解析 print("答案页中有相同个数的答案和解析,可以答案中也带题干") item_res = split_by_keywords(anss1, subject) print("item_res:", item_res) if type(item_res) != str: # 还要判断题目是否为空 if len(item_res[0]) > 10 and len([i["item_id"] for i in item_res[0] if len(i["stem"].strip()) < 5]) < 2: return item_res # ----------------- 【解析 题目】---------------------------- print('---------------解析 题目-------------------') ress = stems_structure_byno(con1, subject) if type(ress) == str: return ress else: item_res, all_type, item_type_classify, item_no_type, \ item_type_num, new_item_no, item_groups = ress # 全题目(不含解析)的结构化 print("item_groups:",item_groups) # pprint(item_groups) # 将空题目去掉 new_res = [] for k, sub_res in enumerate(item_res): if sub_res['stem'].strip(): sub_res['stem'] = del_no(sub_res['stem']) new_res.append(sub_res) item_res = new_res # 先对题目的切分结果进行纠正!!!!! item_res = resplit(item_res) print("item_type_classify:", item_type_classify) print("item_type_num:", item_type_num) print('----------解析 答案---------------') # -------------解析 答案--------------------------- # 分两种情况:1>>答案中又按题型排列, 如一、选择题 1.答案 2.答案 # 2>>答案中不含题型关键字,只按序号排列 # 3>>答案中不含题型关键字,且题目中也没有,all_type, item_type_classify为空 rd1_is_fail = 0 have_type_line = re.search(r"[一二三四五六七八九十]\s*[、..、]\s*[^必考基础综合中等((\[]{2,5}题", "\n".join(anss1)) anss1_cy = anss1.copy() # 复制一份,保证不能影响后面 if have_type_line and subject != "语文": # 这里的anss1的清洗不应该影响rd2_is_fail中的原始文本!!先不修改看看再说 while re.search(r"
[A-F]
)?"
r"(\s*(.{2,5}题|.{,4}(运用|阅读|写作|选择|单选|默写|语言表达|作文|综合|诗歌鉴赏)).+?分\s*[.。]?\s*$"
r"|.*?[((].+?[得共]\d+分.*?[))].*?$"
r"|\s*(.{2,5}题|.{,4}(运用|阅读|写作|选择|单选|默写|语言表达|作文|综合|诗歌鉴赏))\s*([((].+?[))])?).*?$"
r"|(\n|^)\s*([^\d]{2,5}题|.{,4}(运用|阅读|写作|选择|单选|默写|语言表达|作文|综合|诗歌鉴赏))(.+?分\s*[))])?\s*$", "", x), anss1))
# print("anss1:", anss1)
raw_item_res = item_res
# try:
item_res = ans_structure_step1(anss1, item_type_classify, item_res) # 答案整体结构化
if str(raw_item_res) != str(item_res):
rd2_is_fail = 1
# except:
# rd2_is_fail = 1
# for i, one_item in enumerate(item_res):
# item_res[i].update({'key': "", 'parse': ""})
# return item_res, item_no_type, rd2_is_fail
for i, one_item in enumerate(item_res):
if 'key' not in one_item:
item_res[i]['key'] = ""
if 'parse' not in one_item:
item_res[i]['parse'] = ""
return item_res, item_no_type, rd2_is_fail, item_groups
def split_by_keywords(con_list, subject):
"""
第一种试卷格式:教师用卷,含答案和解析关键字
切分思路:
1.根据大题型分,再按【答案|解析】初步拆分题目,再在‘解析’和‘答案’间细分‘题干’和‘解析’
:param con_list:
:return: 每个切分后的题目组成的dict
"""
# items_con = "\n" + "\n".join(con_list)
# judge_item_no_type(items_con)
# item_no_type = 1
# all_con = table_label_cleal()
# item_no = [int(no) for no in re.findall(r'\n+\s*([1-9][0-9]?)\s*[..、、]', all_con)]
# if len(item_no) <= 2:
# item_no_type = 2
# item_no = [int(no) for no in re.findall(r'\n+\s*[((]\s*([1-9][0-9]?)\s*[))]\s*[..、、]?', all_con)]
# if len(item_no) > 3:
# 去掉多余空格,作用不大
con2 = ["【delete】" if (k < len(con_list) - 1 and v.strip() == "" and (
re.match(r"【(答案|解析)】|(答案|解析)\s*[::]| \n+$', one_i["com_stem"]):
one_i["com_stem"], b, _ = re.split('( \n+)$', one_i["com_stem"])
one_i["stem"] = b + one_i["stem"]
if nn > 0 and re.search(' \n+$', res[nn-1]["stem"]):
res[nn - 1]["stem"], b, _ = re.split('( \n+)$', res[nn-1]["stem"])
if "com_stem" not in one_i:
one_i["stem"] = b + one_i["stem"]
# 可能存在有的题目有解析,有的没有
last_comstem_id = 0
ans_groups = {}
no_ans_n = 0
for k, one_res in enumerate(res):
if item_groups["is_groups"]:
if "com_stem" in one_res:
last_comstem_id = k
if re.search('\n【(答案|[解分][析答]|详解|点[评睛]|考点|专题)】', one_res["stem"]):
case = "case1" # 默认有“答案”关键字
if re.search(r'\n【答案】|[\n】]\s*答案\s*[::]', one_res["stem"]) is None:
# 没“答案”关键字
case = "case0"
dd1 = stem_ans_split(one_res, case) # 对切分后的每道题再细分
one_res["stem"] = dd1["stem"]
del dd1["stem"]
if not dd1["key"] and not dd1["parse"]:
no_ans_n += 1
else:
if subject in ["地理", "语文"] and no_ans_n == k-last_comstem_id > 0:
if (k+1 < len(res) and ("com_stem" in res[k+1] or k+1 in item_groups["groups_data"])) or len(re.findall("【\d?题?详解】", dd1["parse"])) > 1\
or len(re.findall(r"(?<=[】\s\n])\d{1,2}\s*[、..、]|^\d{1,2}\s*[、..、]", dd1["key"])) > 1:
# 默认是前后都是题组的情况
if is_dati:
ans_groups["{}-{}".format(last_comstem_id + res[0]["item_id"], k + res[0]["item_id"])] = dd1
else:
ans_groups["{}-{}".format(last_comstem_id + 1, k + 1)] = dd1
dd1 = {"key": "", "parse": ""}
no_ans_n = 0
one_res.update(dd1)
else: # 没有解析的情况
one_res.update({"key": "", "parse": ""})
no_ans_n += 1
one_res["stem"] = del_no(one_res["stem"], item_no_type)
if 'pic' in one_res:
one_res["stem"] += "\n" + "\n".join(one_res["pic"])
del one_res["pic"]
# 先对题目的切分结果进行纠正!!!!!
res = resplit(res)
# pprint(res)
# 对最后一个题后面带个别答案(无答案页)
# if res:
# pattern1 = re.search('\n\s*([1-9]|[1-9][0-9])\s*[..、、]\s*(解\s*[::]|【解析|【答案)', res[-1]["stem"])
# if pattern1:
# breakp = pattern1.start()
# ans_str = res[-1]["stem"][breakp:]
# ans_no_info = pre_get_item_no(ans_str, item_no_type)
# ans_no, ans_no_idx = get_right_no(ans_no_info)
# all_ans = [del_no(ans_str[i:j]) for i, j in zip(ans_no_idx, ans_no_idx[1:] + [None])]
# res[-1]["stem"] = res[-1]["stem"][:breakp]
# res = get_ans_match(res, all_ans, ans_no)
# else:
# ans_str = res[-1]["stem"] + res[-1]["parse"]
# ans_no_info = pre_get_item_no(ans_str, item_no_type)
# ans_no, ans_no_idx = get_right_no(ans_no_info)
# if len(ans_no) == len(res):
# all_ans = [del_no(ans_str[i:j]) for i, j in zip(ans_no_idx, ans_no_idx[1:] + [None])]
# res[-1]["stem"] = res[-1]["stem"][:ans_no_idx[0]]
# res = get_ans_match(res, all_ans, ans_no)
# elif ans_no_idx:
# try:
# ans_no1, table_ans, st = get_table_ans(res[-1]["stem"][:ans_no_idx[0]], [], flag=1)
# if table_ans and 0 < ans_no[0] - ans_no1[-1] < 3:
# all_ans = table_ans
# all_ans.extend([del_no(ans_str[i:j]) for i, j in zip(ans_no_idx, ans_no_idx[1:] + [None])])
# new_ans_no = ans_no1
# new_ans_no.extend(ans_no)
# if st >= 0:
# res[-1]["stem"] = res[-1]["stem"][:st]
# else:
# res[-1]["stem"] = res[-1]["stem"][:ans_no_idx[0]]
# res = get_ans_match(res, all_ans, new_ans_no)
# except:
# if len(ans_no) > 4 and all([True if not one_res["key"] and not one_res["parse"]
# else False for one_res in res[:-1]]):
# all_ans = [del_no(ans_str[i:j]) for i, j in zip(ans_no_idx, ans_no_idx[1:] + [None])]
# res[-1]["stem"] = res[-1]["stem"][:ans_no_idx[0]]
# res = get_ans_match(res, all_ans, ans_no)
# 没有识别出答案切分点的情况,很可能答案里的部分也当成题文进行拆分,所以先判断下是否有相同的id
all_no = [one_res['item_id'] for one_res in res]
if len(list(set(all_no))) - len(all_no) < -2:
Count_no = sorted(dict(Counter(all_no)).items(), key=lambda d: d[1], reverse=True)
if Count_no[0][1] > 1:
split_idx = [i for i, no in enumerate(all_no) if no == Count_no[0][0]][1]
for one_res in res[split_idx:]:
if re.search("[((]\s+[))]|(等于|存在|[是有为])多少|求.*?[??]",
one_res["stem"] + "\n" + one_res["parse"]) is None:
bef_no = [k for k, j in enumerate(res[:split_idx]) if j["item_id"]==one_res["item_id"]]
if bef_no and not res[:split_idx][bef_no[0]]["parse"]:
res[:split_idx][bef_no[0]]["parse"] = one_res["stem"] + "\n" + one_res["parse"]
return res[:split_idx], item_no_type
return res, item_no_type, item_groups, ans_groups