前言
Word 文档内容识别主要由两部分:doc、docx
docx 文档内容识别的难点在于:
- 格式不规范。
- 内容出现的规律
下面记录解析段落格式及内容。
一、docx内容提取
1、提取全文
提取全文内容相对简单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public class FileParsingService {
public String parsingWordContent(Resource file) { InputStream is = null; try { is = file.getInputStream(); XWPFDocument document = new XWPFDocument(is); return new XWPFWordExtractor(document).getText(); } catch (Exception e) { log.warn("解析 word 失败,fileName={}", file.getFilename(), e); } finally { if (is != null) { try { is.close(); } catch (IOException e) { log.warn("请关注输出入关闭失败", e); } } } return null; } }
|
2、提取有格式的内容
2.1、 基本原理
提取有格式的内容是按照段的方式提取的。
2.2、 获取所有段落
1 2 3 4 5 6 7 8 9
| public class FileParsingService { public List<String> parsingWordOpinion(Resource file) throws Exception{ InputStream is = file.getInputStream(); XWPFDocument document = new XWPFDocument(is); List<IBodyElement> bodyElements = document.getBodyElements(); } }
|
2.3、 处理段落
常用的几种段类型:
XWPFSDT 目录
XWPFParagraph 段落
XWPFTable 表格
2.3.1、XWPFSDT 目录
对于目录,直接获取目录内容就可以了
1
| ((XWPFSDT) bodyElement).getContent().getText()
|
2.3.2、XWPFParagraph 段落(重点)
作为段落的内容,又可以分为:
2.3.2.1、提取段落正文
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| public class FileParsingUtil { private final static boolean concatenatePhoneticRuns = true;
private final static boolean fetchHyperlinks = false;
public static String extractParagraphText(XWPFDocument document, XWPFParagraph paragraph) { StringBuilder text = new StringBuilder(); for (IRunElement run : paragraph.getIRuns()) { if (run instanceof XWPFSDT) { text.append(((XWPFSDT) run).getContent().getText()); } else if (!concatenatePhoneticRuns && run instanceof XWPFRun) { text.append(((XWPFRun) run).text()); } else { text.append(run); } if (run instanceof XWPFHyperlinkRun && fetchHyperlinks) { XWPFHyperlink link = ((XWPFHyperlinkRun) run).getHyperlink(document); if (link != null) text.append(" <").append(link.getURL()).append(">"); } } return text.toString(); } }
|
2.3.2.2、提取段落的格式
1 2
| XWPFParagraph paragraphTemp = (XWPFParagraph) bodyElement; paragraphTemp.getStyleID()
|
格式有很多,比如:
- 标题
Heading 1
Heading 2
RegHChG
RegH1G
RegH2G
- 序列的合适
ListParagraph
RegSingleTxtG
RegSingleTxtG2
备注:但是需要的判断方式不是序列的格式,因为格式是不固定的。
格式内容在 wps 的样式和格式中都能看到。
2.3.2.3、判断是否为序列
1 2 3 4
| XWPFParagraph paragraphTemp = (XWPFParagraph) bodyElement; if(paragraphTemp.getNumID()!=null){
}
|
需要有两个重要属性
NumLevelText 序列值的格式化方式
%1、,根据序列的类型,可以为 1、,一、,a、等
(%1),根据序列的类型,可以为 (1),(一),(a)等
- 暂未发现
%1与 %2 的区别——TODO
NumFmt 序列的类型
chineseCounting 中文
decimal 数字
decimalEnclosedCircleChinese 圆圈中的数字
upperLetter 大写字母
lowerLetter 小写字母
lowerRoman 小写罗马
upperRoman 大写罗马
bullet 无序(不用识别出方的、圆的和菱形的,没有意义)
- 其它
2.3.3、XWPFTable 表格
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public class FileParsingUtil {
public static String appendTableText(XWPFTable table) { StringBuilder text = new StringBuilder(); for (XWPFTableRow row : table.getRows()) { List<ICell> cells = row.getTableICells(); for (int i = 0; i < cells.size(); i++) { ICell cell = cells.get(i); if (cell instanceof XWPFTableCell) { text.append(((XWPFTableCell) cell).getTextRecursively()); } else if (cell instanceof XWPFSDTCell) { text.append(((XWPFSDTCell) cell).getContent().getText()); } if (i < cells.size() - 1) { text.append("\t"); } } text.append('\n'); } return text.toString(); } }
|
附
一段话:
在识别出内容出现的规律后,对于规范的格式,需要识别的内容也是多种多样的,需要打开 word (docx推荐用wps打开),然后打开样式和格式,对每个段落内容进行分析。
本文地址: https://github.com/maxzhao-it/blog/post/cb38f68c/