lyg
2 天以前 22f370322412074174cde20ecfd14ec03657ab63
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# -*- coding: utf-8 -*-
# doc_split.py
# @author: lyg
# @date: 2025-04-24
# @version: 0.0.1
# @description: 文档处理,按页切割文档并提取每一页的文本,提文档的章节信息,将章节信息和页码信息关联起来,提取每一页的实体词。
 
from dataclasses import dataclass, field
import docx
import pymupdf
 
import pymupdf4llm
 
from knowledgebase.doc.entity_recognition import EntityRecognition
 
 
@dataclass
class ChapterInfo:
    """
    表示章节信息的类,包含章节标题、起始页码、结束页码和层级。
    """
    title: str  # 章节标题
    start_page: int  # 起始页码
    end_page: int  # 结束页码
    level: int  # 章节层级
 
    def __post_init__(self):
        """
        在初始化后执行的钩子函数,用于验证输入参数的有效性。
        """
        # 验证标题是否为空
        if not self.title or not isinstance(self.title, str):
            raise ValueError("标题必须是非空字符串")
 
        # 验证页码是否为正整数
        if not isinstance(self.start_page, int) or self.start_page < 1:
            raise ValueError("起始页码必须是大于0的整数")
        if not isinstance(self.end_page, int) or self.end_page < 1:
            raise ValueError("结束页码必须是大于0的整数")
 
        # 验证起始页码是否小于等于结束页码
        if self.start_page > self.end_page:
            raise ValueError("起始页码不能大于结束页码")
 
        # 验证层级是否为正整数
        if not isinstance(self.level, int) or self.level < 1:
            raise ValueError("层级必须是大于0的整数")
 
 
@dataclass
class PageInfo:
    """
    页面信息类,用于存储页面的基本信息。
 
    参数:
    - page_num (int): 页面编号,必须为正整数。
    - chapter_info (str): 章节信息,描述当前页面所属章节。
    - text (str, optional): 页面文本内容,默认为空字符串。
    - entities (list[str]): 页面实体词列表。
 
    异常:
    - ValueError: 如果 `page_num` 不是正整数,或者 `chapter_info` 和 `text` 不是字符串。
    """
    page_num: int
    chapter_info: str
    text: str = ""
    entities: list[str] = field(default_factory=list)
 
    def __post_init__(self):
        """
        初始化后验证参数类型和值。
        """
        if not isinstance(self.page_num, int) or self.page_num < 0:
            raise ValueError("page_num 必须是正整数")
        if not isinstance(self.chapter_info, str):
            raise ValueError("chapter_info 必须是字符串")
        if not isinstance(self.text, str):
            raise ValueError("text 必须是字符串")
        if self.entities is None or not isinstance(self.entities, list):
            raise ValueError("entities 必须是列表")
 
 
class DocSplit:
    """
    文档处理
    按页切割文档并提取每一页都文本,使用
    """
    pdf_file: str
    page_infos: list[PageInfo]
    chapter_infos: list[ChapterInfo]
 
    def __init__(self, pdf_file):
        self.pdf_file = pdf_file
        self.page_infos = []
        self.chapter_infos = []
        self.doc = pymupdf.open(self.pdf_file)
        self.extract_chapter_info()
        self.extract_page_info()
 
    def extract_chapter_info(self):
        """
        提取章节信息
        """
        toc = self.doc.get_toc()
        for item in toc:
            idx = toc.index(item)
            end = len(self.doc)
            for i in range(idx + 1, len(toc)):
                if toc[i][0] >= item[0]:
                    end = toc[i][2]
                    break
            self.chapter_infos.append(ChapterInfo(title=item[1], start_page=item[2], end_page=end, level=item[0]))
 
    def extract_page_info(self):
        """
        提取页面信息
        """
        for page in self.doc:
            # 通过pymupdf4llm获取页面文本,markdown格式
            page_text = pymupdf4llm.to_markdown(self.doc, pages=[page.number])
            # 创建页面信息对象
            page_info = PageInfo(page_num=page.number, chapter_info="", text=page_text)
            self.page_infos.append(page_info)
 
    def get_page_info(self, page_num):
        """
        获取指定页码的页面信息
        """
        for page in self.page_infos:
            if page.page_num == page_num:
                return page
        return None
 
 
# if __name__ == '__main__':
#     ds = DocSplit("D:/workspace/PythonProjects/KnowledgeBase/doc/XA-5D无人机探测大纲(公开)111.pdf")
#     print()