赞
踩
本文基于上篇代码抽取功能优化(一)进行了一些优化,增加了对python多行注释、C++多行注释以及markdown的处理,修复了一些小bug,将抽取准确率提升至92%。
思路:
1、判断```是否在该行中,在的话count+1,并取出该行行号
2、得到行号后,从原list中取出行号之间的内容
整体还需看代码才能更好的理解
def extract_markdown(data_list): """提取markdown中的代码,即"```"中的内容 Args: data_list: 文本列表 Returns: codes: 提取出来的代码段(list) texts: 提取出的文本(string类型) """ idxs = [] count = 0 for idx, line in enumerate(data_list): if "```" in line: idxs.append(idx) count += 1 if count < 2: return [], data_list else: try: assert (len(idxs) % 2) == 0 codes = [] texts = [] for idx, val in enumerate(idxs): if idx % 2 == 0: if idx == 0: text = data_list[:idxs[idx]] else: text = data_list[idxs[idx - 1] + 1: idxs[idx]] code = data_list[idxs[idx] + 1: idxs[idx + 1]] code = '\n'.join(code) text = '\n'.join(text) codes.append(code) texts.append(text) if idx == len(idxs) - 1: text = data_list[idxs[idx] + 1:] text = '\n'.join(text) texts.append(text) texts = ''.join(texts) except: return [], data_list return codes, texts
整体思路与提取markdown中的code类似,这里不再赘述,直接看代码:
def extract_py_annotation_idx(data_list, annotation= "'''"): """提取python多行注释内容 Args: data_list: 文本列表 Returns: idx: 返回的索引 """ idxs = [] count = 0 for idx, line in enumerate(data_list): if annotation in line: idxs.append(idx) count += 1 if (count % 2) == 1: return [] else: assert (len(idxs) % 2) == 0 return idxs
这里与前面两个稍有不同,但整体思路也是一样
def extract_cpp_annotation_idx(data_list): """提取/* */中的多行注释行索引 Args: data_list: 文本列表 Returns: idx: 注释索引列表 """ idxs = [] count = 0 for idx, line in enumerate(data_list): if line.find('/*') != -1 and line.find('*/') != -1: continue elif line.find('/*') != -1: count += 1 idxs.append(idx) elif line.find('*/') != -1: count += 1 idxs.append(idx) if (count % 2) == 1: return [] else: return idxs
不管是哪种代码的多行注释,都需要注意一点:这些注释符一定是成对存在的!
1、输入为line,对每一行代码进行判定,是代码返回True,否则返回False。
2、对传入的line,先直接判定为False,满足一定的条件后,再置为True。
def is_code_new(self, line, feature_list, annotation_list, text_keywords_list, code_print_list): code_flag = False #先置为False,满足一定条件后再判定为True # count = 0 # cn_num = getnum_of_cn(line) # en_num = getnum_of_en(line) cn_and_symbol_num = getnum_of_cn_and_symbol(line) # 计算中文字符及中文标点符号的个数 for symbol in feature_list: # 遍历代码关键字 if is_sub_string(line, symbol): # 判断该行是否包含代码关键字 code_flag = True #包含的话,置为True for annotation in annotation_list: #遍历各种代码的注释符 if is_sub_string(line, annotation): #判定是否包含注释符 code_flag = True #包含注释符,置为True,跳出注释遍历 break else: #不包含注释符 for text_keyword in text_keywords_list: #遍历文本关键词,如果包含文本关键词,置为False if is_sub_string(line, text_keyword): code_flag = False break if cn_and_symbol_num > 30: # 如果不包含注释,且中文字符数大于30,则置为False # 考虑到大于30个中文字符,也有可能是print的情况,因此该段代码必须放在判断print条件之前 code_flag = False # 如果不包含注释,且中文字符数大于0,便考虑是否是print输出的情况 # 如果确实是print的输出,则置为True if cn_and_symbol_num > 0: for print_keyword in code_print_list: if is_sub_string(line, print_keyword): code_flag = True break else: #如果不是print的情况,则考虑到是否是定义的字典 # 如python定义字典,里面存在这种情况: # dict = { # 'name' : '张三', # '性别': '男' # } #如果是上述类似情况,则置为True if re.search(r'[\=\:]\s*?[\'\"].*?[\'\"]', line): code_flag = True else: code_flag = False # 考虑到有些报错也会被误判为代码,这里排除类似以下情况的报错 # Trace back in line xxx # 其中xxx可以是任意数字 # 只要该行包含line xxx,则置为False if is_line_num(line): code_flag = False return code_flag
1、虽然准确率已经有90+%,但测试数据仅有400条,可能漏掉了一些情况,比如SQL代码,51汇编代码,以及一些其他的关键字段,后续会围绕这几个点去优化,争取将效果提升至95+%。
2、考虑过将所有语言的保留字加入code_feature_list中,但这样的话,准确率虽然有所提升,但代码执行效率将下降很多,由于代码提取服务作为一个基础模块,必须要兼顾效率及准确率,因此,两者需有个平衡。
1、经过20多天的努力,终于将代码提取服务的效果提升至90+%,也算是个不错的开始。
2、一个人或许可以走得很快,但一群人却能够走的更远
3、感恩遇见这么好的一个团队
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。