前言
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/