8

我必须从 PDF 页面中提取文本,就像缩进到 CSV 文件中一样。

PDF教科书的索引页:

我应该将文本与页码一起拆分为类和子类类型层次结构。例如在图像中, Application server是类,Apache Tomcat是页码275中的子类

这是 CSV 的预期输出:

我已经使用 Tika 解析器来解析 PDF,但是在解析的内容中没有正确维护缩进(不是唯一的),以便将文本拆分为类和子类。

解析后的文本如下所示:

谁能建议我针对此要求的正确方法?

4

2 回答 2

4

尽管我不了解 pdf 提取,但可以从“解析的文本”重建层次结构,因为“子类”部分总是以额外的换行符开始和结束。

带有以下测试文本:

app architect . 50
app logic . 357
app server . 275

tomcat . 275
websphere . 275
jboss . 164

architect

acceptance . 303
development path . 304

architecting . 48
architectural activity . 25, 320

以下代码:

import csv
import sys
import re


def gen():
    is_subclass = False
    p_class = None

    with open('test.data') as f:
        s = f.read()
    lines = re.findall(r'[^\n]+\n+', s)
    for line in lines:
        if ' . ' in line:
            class_name, page_no = map(lambda s: s.strip(), line.split('.'))
        else:
            class_name, page_no = line.strip(), ''

        if line.endswith('\n\n'):
            if not is_subclass:
                p_class = class_name
                is_subclass = True
                continue

        if is_subclass:
            yield (p_class, class_name, page_no)
        else:
            yield (class_name, '', page_no)

        if line.endswith('\n\n'):
            is_subclass = False


writer = csv.writer(sys.stdout)
writer.writerows(gen())

产量:

app architect,,50
app logic,,357
app server,tomcat,275
app server,websphere,275
app server,jboss,164
architect,acceptance,303
architect,development path,304
architecting,,48
architectural activity,,"25, 320"

希望这可以帮助。

于 2018-09-25T12:27:24.287 回答
2

所以这里是解决方案:

  1. 安装 Fitz(PyMuPDF) https://github.com/rk700/PyMuPDF
  2. 使用 Python 2.7 在与 PDF 文件相同的文件夹中运行以下代码
  3. 比较结果

代码:

import fitz
import json
import re
import csv

class MyClass:
    def __init__(self, text, main_class):
        my_arr = re.split("[.]*", text)
        if main_class != my_arr[0].strip():
            main_class = my_arr[0].strip()
        self.main_class = main_class
        self.sub_class = my_arr[0].strip()
        try:
            self.page = my_arr[1].strip()
        except:
            self.page = ""

def add_line(text, is_recording, main_class):
    if(is_recording):
        obj = MyClass(text, main_class)
        if obj.sub_class == "Glossary":
            return False, main_class
        table.append(obj)
        return True, obj.main_class
    elif text == "Contents":
        return True, main_class
    return False, main_class

last_text = ""
is_recording = False
main_class = ""
table = []

doc = fitz.open("TCS_1.pdf")
page = doc.getPageText(2, output="json")
blocks = json.loads(page)["blocks"]
for block in blocks:
    if "lines" in block:
        for line in block["lines"]:
            line_text = ""
            for span in block["lines"]:
                line_text += span["spans"][0]["text"].encode("utf-8")
            if last_text != line_text:
                is_recording, main_class = add_line(line_text, is_recording, main_class)
                last_text = line_text

writer = csv.writer(open("output.csv", 'w'), delimiter=',', lineterminator='\n')
for my_class in table:
    writer.writerow([my_class.main_class, my_class.sub_class, my_class.page])
    # print(my_class.main_class, my_class.sub_class, my_class.page)

这是所提供文件的 CSV 输出: 在此处输入图像描述

于 2018-10-01T15:36:50.067 回答