doc-parser 0.1.2.6
基于深度学习的文档结构解析库
License: Apache-2.0

# doc_parser

基于Pytorch神经网络模型的跨平台Docx及PDF文档解析库

## 原理

我们可以通过制定一个通用的文档层级规范，将Word中每段都对应到规范中某一类别，从而将文档解析任务建模为段落分类问题。

关于特征选择，通过前期的手工规则处理经验以及大致观察统计，确定了包含`text_feature`、`is_center`、`is_bold`、`is_list_item`、`name`、`text_indent`、`size`、`font_size`等8类特征，具体细节参见[html.py](./doc_parser/utils/html.py)与[text_feature.py](./doc_parser/utils/text_feature.py)。经验上感觉前述特征对于判别段落类别有帮助。同时由于相邻段落间存在一定的依赖约束关系，所以理论上我们可以把以上的文档解析问题建模为多特征（同时包含离散字符和连续数字）序列标注任务。

### doc解析具体实现

实际实现中，通过`LibreOffice`工具将word转为html文件，然后通过BeautifulSoup库提取文档样式，并使用序列标注（Bi-LSTM-CRF）模型预测各段类别从而构建文档树。

### pdf解析具体实现

基于`pdf2docx`库实现将pdf文件转换为docx文件，然后同上。然而pdf解析得到的word段落之间并不是连续的，而是一行一行的分隔开的。所以具体实现与doc解析大体一致，但细节略有不同，比如pdf标注文件是以BIO的格式用以约束多个节点同为一个段落而word标注文档则每个节点单独一种类别（段落）。

## 依赖库

除了[requirements.txt](./requirements.txt)中列举的库以外，还需要额外安装一些库，如下：

### pdf2docx

> **注意**:此处用的并非Github官方的[dothinking/pdf2docx](https://github.com/dothinking/pdf2docx)，而是使用的魔改版：[pdf2docx: pdf转docx](https://gitee.com/intelligent_learning/pdf2docx)。具体变动和原因参见前述链接。

安装方式：

```shell script
pip install -U git+https://github.com/smilelight/pdf2docx.git@master
```

### LibreOffice

用户需要自行安装LibreOffice并且配置环境变量。

## 安装

### 在线安装

```shell script
pip install -U git+https://gitee.com/intelligent_learning/doc_parser.git@master
```

### 离线安装

在[doc_parser 发行版 - Gitee.com](https://gitee.com/intelligent_learning/doc_parser/releases)页面下载最新版本的whl文件然后安装。

## 使用示例

**说明**：
1. 为了便于调试，可以直接传入中间文件html作为输入文件（避免重复的文件转换过程，由pdf转换至docx再转换至html比较耗时）。
2. 为了给甲方看到更满意的结果，可以直接输入标记结果作为神经网络模型预测结果（作弊），从而得到更准确的结果。

### 1.解析docx文档：

将doc/docx文档中的层级信息提出来，并且解析出表格和图片以及其对应的标题。

```python
# -*- coding: utf-8 -*-
from doc_parser.parser import Parser

file_path = r"D:\Documents\科东\冀北电网\word文档\模板-张家口电网2022年调控系统冬奥电力保障应急处置预案-20200902.doc"

save_dir = r"saves"
model_path = r"E:\Projects\GiteeProjects\doc_parser\models"

if __name__ == '__main__':
    parser = Parser(model_path)
    parser.parse(file_path, output_dir=save_dir)

```

输出结果：

```text
[2020-09-23 17:31:33] [INFO] [MainThread] [config.py:6] using device: cuda
[2020-09-23 17:31:36] [INFO] [MainThread] [base.py:47] loading config from E:\Projects\GiteeProjects\doc_parser\models\doc_model\config.pkl
[2020-09-23 17:31:53] [INFO] [MainThread] [base.py:77] loading model from E:\Projects\GiteeProjects\doc_parser\models\doc_model\model.pkl
[2020-09-23 17:31:53] [INFO] [MainThread] [base.py:23] loading preprocessor from E:\Projects\GiteeProjects\doc_parser\models\doc_model\data_processor.pkl
[2020-09-23 17:31:53] [INFO] [MainThread] [predict_nodes.py:46] 成功加载doc预测模型
[2020-09-23 17:31:53] [INFO] [MainThread] [base.py:47] loading config from E:\Projects\GiteeProjects\doc_parser\models\pdf_model\config.pkl
[2020-09-23 17:31:53] [INFO] [MainThread] [base.py:77] loading model from E:\Projects\GiteeProjects\doc_parser\models\pdf_model\model.pkl
[2020-09-23 17:31:53] [INFO] [MainThread] [base.py:23] loading preprocessor from E:\Projects\GiteeProjects\doc_parser\models\pdf_model\data_processor.pkl
[2020-09-23 17:31:53] [INFO] [MainThread] [predict_nodes.py:46] 成功加载pdf预测模型
[2020-09-23 17:31:53] [INFO] [MainThread] [doc.py:24] 开始进行文件预处理
[2020-09-23 17:31:53] [INFO] [MainThread] [libre_office.py:54] 待转换文件路径为：D:\Documents\科东\冀北电网\word文档\模板-张家口电网2022年调控系统冬奥电力保障应急处置预案-20200902.doc
[2020-09-23 17:31:53] [INFO] [MainThread] [libre_office.py:55] 文档转换(doc -> docx)中，请稍等。。。
[2020-09-23 17:32:10] [INFO] [MainThread] [libre_office.py:84] 待转换文件路径为：D:\Documents\科东\冀北电网\word文档\模板-张家口电网2022年调控系统冬奥电力保障应急处置预案-20200902.docx
[2020-09-23 17:32:10] [INFO] [MainThread] [libre_office.py:85] 文档转换(doc/docx -> txt)中，请稍等。。。
[2020-09-23 17:32:13] [INFO] [MainThread] [libre_office.py:145] 待转换文件路径为：D:\Documents\科东\冀北电网\word文档\模板-张家口电网2022年调控系统冬奥电力保障应急处置预案-20200902.docx
[2020-09-23 17:32:13] [INFO] [MainThread] [libre_office.py:146] 文档转换(doc/docx -> html)中，请稍等。。。
0it [00:00, ?it/s]
[2020-09-23 17:32:15] [INFO] [MainThread] [rectify_html.py:80] 通过txt文档，生成待处理的规则配置
[2020-09-23 17:32:15] [INFO] [MainThread] [rectify_html.py:48] 开始填充
100%|██████████| 59/59 [00:00<00:00, 19718.24it/s]
[2020-09-23 17:32:16] [INFO] [MainThread] [rectify_html.py:66] 修改后进行保存
[2020-09-23 17:32:16] [INFO] [MainThread] [libre_office.py:209] 文件清理成功！
[2020-09-23 17:32:16] [INFO] [MainThread] [doc.py:30] 文件预处理结束
[2020-09-23 17:32:16] [INFO] [MainThread] [html.py:194] 开始抽取文档节点
100%|██████████| 67/67 [00:00<00:00, 6716.82it/s]
[2020-09-23 17:32:16] [INFO] [MainThread] [html.py:202] 文档节点抽取完成
[2020-09-23 17:32:16] [INFO] [MainThread] [html.py:215] 文档节点特征抽取中
100%|██████████| 54/54 [00:00<00:00, 126.80it/s]
100%|██████████| 1/1 [00:02<00:00,  2.82s/it]
[2020-09-23 17:32:19] [INFO] [MainThread] [doc.py:52] 文件结构树构建中
54it [00:00, 3384.53it/s]
[2020-09-23 17:32:19] [INFO] [MainThread] [doc.py:68] 文件结构树构建结束
[2020-09-23 17:32:19] [INFO] [MainThread] [document.py:141] 文档内容成功写入到：saves\模板-张家口电网2022年调控系统冬奥电力保障应急处置预案-20200902-contents.json中！
[2020-09-23 17:32:19] [INFO] [MainThread] [document.py:87] 文档信息成功写入到：saves\模板-张家口电网2022年调控系统冬奥电力保障应急处置预案-20200902-infos.json中！
```

### 2.解析pdf文档

将pdf文档中的层级信息提出来，并且解析出表格和图片以及其对应的标题。

```python
# -*- coding: utf-8 -*-
from doc_parser.parser import Parser

file_path = r"D:\Documents\科东\冀北电网\pdf测试\缺陷定级-国网公司输变电一次设备缺陷分类标准.pdf"
file_html_path = r"D:\Documents\科东\冀北电网\pdf文档\缺陷定级-国网公司输变电一次设备缺陷分类标准.html"
labeled_path = r"D:\Documents\科东\冀北电网\pdf文档\缺陷定级-国网公司输变电一次设备缺陷分类标准-labeled.xlsx"
save_dir = r"pdf_saves"

model_path = r"E:\Projects\GiteeProjects\doc_parser\models"

if __name__ == '__main__':
    parser = Parser(model_path)
    parser.parse(file_html_path, output_dir=save_dir, label_path=labeled_path, parser_type='pdf')
```

输出结果与解析结果与doc解析结果类似，略。

## 参考