问题描述
提取word文档中的缩略语,并将文档内的缩略语替换为全称

解决方案
首先观察数据,缩小问题范围
发现文档内缩略语基本都以表格方式呈现,一般是两列,有时也有四列,所以只考虑解决缩略语为表格且为2、4列的情况,其他特殊情况(段落等非表格形式,列数不为2、4)不考虑
缩略语判断逻辑主要就是单元格内文本是大写字符串的比例
代码里我写了两种逻辑,V1是判断大写单元格占总的单元格比例,V2是,奇数列大写与偶数列非大写的比例
判断缩略语提取缩略语
def extract_abbreviation(file, cfd=0.1, judgement='V1'):
start_time = time.time()
all_abrvt = []
for table in file.tables:
try:
width, length = len(table.columns), len(table.rows)
if not (width == 2 or width ==4):
continue
if judgement == 'V1': # 判断英文大写占单元格文本比例
cell_text = [cell.text for row in table.rows for cell in row.cells if cell.text]
cell_upper = [i for i in cell_text if i.isupper()]
if 0.4 < (len(cell_upper)+1) / (len(cell_text)+1) < 0.6:
is_abrvt = True
else:
is_abrvt = False
elif judgement == 'V2': # 判断每列单元格文本类型比例
column_odd_text = [cell.text for i in range(0, width, 2) for cell in table.columns[i].cells if cell.text]
column_even_text = [cell.text for i in range(1, width, 2) for cell in table.columns[i].cells if cell.text]
column_odd_upper = [i for i in column_odd_text if i.isupper()]
column_even_upper = [i for i in column_even_text if not i.isupper()]
if 0.8 < (len(column_odd_upper)+1) / (len(column_even_upper)+1) < 1.2:
is_abrvt = True
else:
is_abrvt = False
if is_abrvt:
abrvt, cfd_num, confidence= [], 0, 0
for i in range(length):
for j in range(0, width, 2):
cell_1, cell_2 = table.rows[i].cells[j].text, table.rows[i].cells[j+1].text
if cell_1.isupper() and len(cell_1)>1 and len(cell_2)>2:
abrvt.append([cell_1, cell_2])
c_word = cell_2.split(' ')
c_head = ''.join([k[0] for k in c_word if k])
if c_head.lower() == cell_1.lower():
cfd_num += 1
if length == 2:
confidence = cfd_num / length
else:
confidence = cfd_num / (length * 2)
if confidence > cfd:
logging.info('***** 发现缩略语表,%s, confidence: %s' % (abrvt, confidence))
all_abrvt.extend(abrvt)
else:
continue
except Exception as e:
logging.error('Error: ' + str(e), exc_info=True)
print(e)
print(all_abrvt)
print('time: ', time.time()-start_time)
return all_abrvt
提取出来的缩略语事例:
文档内缩略语的替换
这里函数的输入是文本段落内容和抓取到的缩略语列表,
def abrvt_replace(file_text_total, abrvt):
try:
file_text = file_text_total.copy()
for i in range(len(file_text)):
abr_text = word_tokenize(file_text[i])
for j in abrvt:
if (file_text[i] != j[0]) and (j[0] in abr_text) and \
(j[1].lower() not in file_text[i].lower()):
for k in range(len(abr_text)):
if abr_text[k] == j[0]:
abr_text[k] = j[1] + "(" + j[0] + ")"
break
file_text[i] = ' '.join(abr_text)
return file_text
except Exception as e:
logging.info("***** 缩略语替换出错")
logging.error('Error: ' + str(e), exc_info=True)
return file_text_total
以上抓取和替换都不是很严谨,总能构造出反例,但实际效果以足够解决90%以上但问题了