优化切片,增加章节图片信息
This commit is contained in:
parent
980abcfd75
commit
3ffa6704ad
936
chunk_text.py
936
chunk_text.py
File diff suppressed because it is too large
Load Diff
184
resetlevel.py
Normal file
184
resetlevel.py
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
import copy
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
CN_NUM = "\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u3007\u96f6\u4e24"
|
||||||
|
|
||||||
|
CHAPTER_PATTERN = re.compile(rf"^\s*\u7b2c\s*([{CN_NUM}\d]+)\s*\u7ae0")
|
||||||
|
CN_LEVEL1_PATTERN = re.compile(rf"^\s*([{CN_NUM}]+)(?=\s|[\u3001\u3002\uff0e.])")
|
||||||
|
|
||||||
|
CASE_LIKE_PATTERN = re.compile(r"^\s*\d+(?:\.|\uff0e)(?!\d|\s|$)")
|
||||||
|
ARABIC_PATTERN = re.compile(
|
||||||
|
r"^\s*(\d+(?:\.\d+)*)(?=\s|[\u4e00-\u9fff\u3001\u3002\uff0e]|$|\.(?:\s|$))"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def has_valid_text_level(item: dict) -> bool:
|
||||||
|
return "text_level" in item and item.get("text_level") not in (None, "")
|
||||||
|
|
||||||
|
|
||||||
|
def parse_heading(text: str):
|
||||||
|
text = text.strip()
|
||||||
|
if not text:
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
if CASE_LIKE_PATTERN.match(text):
|
||||||
|
return "case_like", None
|
||||||
|
|
||||||
|
if CHAPTER_PATTERN.match(text):
|
||||||
|
return "level1", None
|
||||||
|
|
||||||
|
if CN_LEVEL1_PATTERN.match(text):
|
||||||
|
return "level1", None
|
||||||
|
|
||||||
|
match = ARABIC_PATTERN.match(text)
|
||||||
|
if match:
|
||||||
|
return "arabic", match.group(1)
|
||||||
|
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
|
||||||
|
def arabic_depth(number: str) -> int:
|
||||||
|
return number.count(".") + 1
|
||||||
|
|
||||||
|
|
||||||
|
def parent_number(number: str) -> str | None:
|
||||||
|
parts = number.split(".")
|
||||||
|
if len(parts) <= 1:
|
||||||
|
return None
|
||||||
|
return ".".join(parts[:-1])
|
||||||
|
|
||||||
|
|
||||||
|
def collect_headings(data: list) -> list:
|
||||||
|
headings = []
|
||||||
|
|
||||||
|
for item in data:
|
||||||
|
if not isinstance(item, dict):
|
||||||
|
continue
|
||||||
|
if item.get("type") != "text":
|
||||||
|
continue
|
||||||
|
if not has_valid_text_level(item):
|
||||||
|
continue
|
||||||
|
|
||||||
|
kind, number = parse_heading(item.get("text", ""))
|
||||||
|
if kind in {"level1", "arabic", "case_like"}:
|
||||||
|
headings.append({"kind": kind, "number": number})
|
||||||
|
|
||||||
|
return headings
|
||||||
|
|
||||||
|
|
||||||
|
def is_valid_arabic_hierarchy(numbers: list[str], allow_missing_depth1_parent: bool) -> bool:
|
||||||
|
seen = set()
|
||||||
|
has_depth2 = False
|
||||||
|
has_depth3 = False
|
||||||
|
|
||||||
|
for number in numbers:
|
||||||
|
depth = arabic_depth(number)
|
||||||
|
if depth >= 2:
|
||||||
|
has_depth2 = True
|
||||||
|
if depth >= 3:
|
||||||
|
has_depth3 = True
|
||||||
|
|
||||||
|
parent = parent_number(number)
|
||||||
|
if parent is not None:
|
||||||
|
parent_depth = arabic_depth(parent)
|
||||||
|
parent_is_missing_depth1 = allow_missing_depth1_parent and parent_depth == 1
|
||||||
|
if parent not in seen and not parent_is_missing_depth1:
|
||||||
|
return False
|
||||||
|
|
||||||
|
seen.add(number)
|
||||||
|
|
||||||
|
return has_depth2 and has_depth3
|
||||||
|
|
||||||
|
|
||||||
|
def detect_valid_mode(headings: list):
|
||||||
|
if not headings:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if any(heading["kind"] == "case_like" for heading in headings):
|
||||||
|
return None
|
||||||
|
|
||||||
|
first = headings[0]
|
||||||
|
|
||||||
|
if first["kind"] == "arabic":
|
||||||
|
numbers = [heading["number"] for heading in headings if heading["kind"] == "arabic"]
|
||||||
|
if numbers and arabic_depth(numbers[0]) == 1:
|
||||||
|
if is_valid_arabic_hierarchy(numbers, allow_missing_depth1_parent=False):
|
||||||
|
return "A"
|
||||||
|
return None
|
||||||
|
|
||||||
|
if first["kind"] == "level1":
|
||||||
|
numbers = [heading["number"] for heading in headings[1:] if heading["kind"] == "arabic"]
|
||||||
|
if not numbers:
|
||||||
|
return None
|
||||||
|
|
||||||
|
first_depth = arabic_depth(numbers[0])
|
||||||
|
if first_depth == 2 and is_valid_arabic_hierarchy(numbers, allow_missing_depth1_parent=True):
|
||||||
|
return "B"
|
||||||
|
|
||||||
|
if first_depth == 1 and is_valid_arabic_hierarchy(numbers, allow_missing_depth1_parent=False):
|
||||||
|
return "C"
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
JsonContent = Any
|
||||||
|
|
||||||
|
|
||||||
|
def reset_textlevel(json_content: JsonContent) -> JsonContent:
|
||||||
|
"""
|
||||||
|
输入 JSON 内容,返回更新 text_level 后的新 JSON 内容。
|
||||||
|
|
||||||
|
json_content 可以是已经 json.load/json.loads 后的 Python 对象,
|
||||||
|
也可以是 JSON 字符串。函数不会修改原始入参。
|
||||||
|
"""
|
||||||
|
if isinstance(json_content, str):
|
||||||
|
data = json.loads(json_content)
|
||||||
|
else:
|
||||||
|
data = copy.deepcopy(json_content)
|
||||||
|
|
||||||
|
if not isinstance(data, list):
|
||||||
|
return data
|
||||||
|
|
||||||
|
headings = collect_headings(data)
|
||||||
|
mode = detect_valid_mode(headings)
|
||||||
|
|
||||||
|
if mode is None:
|
||||||
|
return data
|
||||||
|
|
||||||
|
for item in data:
|
||||||
|
if not isinstance(item, dict):
|
||||||
|
continue
|
||||||
|
if item.get("type") != "text":
|
||||||
|
continue
|
||||||
|
if not has_valid_text_level(item):
|
||||||
|
continue
|
||||||
|
|
||||||
|
kind, number = parse_heading(item.get("text", ""))
|
||||||
|
if kind == "level1":
|
||||||
|
item["text_level"] = 1
|
||||||
|
continue
|
||||||
|
if kind != "arabic":
|
||||||
|
continue
|
||||||
|
|
||||||
|
depth = arabic_depth(number)
|
||||||
|
item["text_level"] = depth if mode in {"A", "B"} else depth + 1
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
json_file_path = r'E:\ZKYNLP\Hjunproject\project0506\kgrag\163-06A0014-B01001_发动机-维修手册_content_list.json'
|
||||||
|
with open(json_file_path, "r", encoding="utf-8") as f:
|
||||||
|
json_content = json.load(f)
|
||||||
|
result= reset_textlevel(json_content)
|
||||||
|
|
||||||
|
for ins in result[:30]:
|
||||||
|
print(ins)
|
||||||
|
# print(json.dumps(result, ensure_ascii=False, indent=2))
|
||||||
Loading…
x
Reference in New Issue
Block a user