Compare commits

..

No commits in common. "44050b239156d479aab8079a0907973eedc36f43" and "532eb2857c490a519b62c021f70eacbe56f1137b" have entirely different histories.

16 changed files with 4514 additions and 3551 deletions

377
README.md
View File

@ -48,108 +48,6 @@ pip install -r requirements.txt
## 最近更新 ## 最近更新
### 2024年6月2日
- 改进Markdown表格转换功能
- 修复了合并单元格内容重复显示的问题
- 修复了空单元格自动填充相邻值的问题
- 优化表格处理逻辑,正确处理多级表头和复杂表格结构
- 确保合并单元格的内容仅在原始单元格位置显示,被合并的单元格保持为空
### 2024年6月1日
- **修复服务端文件处理过程中的类型错误**
- 解决文件处理后删除临时文件时出现的`'dict' object has no attribute 'strip'`错误
- 增强了`main.py`中处理文本内容时的类型安全性,确保只对字符串类型调用字符串方法
- 添加了对处理文件时`all_content`合并时的严格类型检查,实现对混合内容类型(字符串、字典等)的安全处理
- 优化了临时文件和目录清理过程,增加类型检查以避免对非字符串类型执行路径操作
- 改进临时文件删除的安全性,使用`safe_delete_file`函数确保字符串类型参数
- 提高了文件处理后清理逻辑的健壮性,避免因类型不匹配导致的处理中断
- 完善错误处理机制,提供更详细的日志信息,便于快速定位问题
### 2024年5月31日
- **修复表格文本提取过程中的类型错误**
- 解决了在无效表格转换为文本时出现的`'dict' object has no attribute 'strip'`错误
- 增强了`save_as_docx`方法中对`_extract_table_text`返回值的类型安全检查
- 确保只有在返回值是字符串类型时才调用`strip()`方法
- 优化了表格文本提取的错误处理流程,提高系统处理复杂表格的稳健性
- 完善了不同表格类型的处理逻辑,确保各种特殊结构表格都能被正确处理
- 修复了在表格无效时可能触发的类型错误,保证表格处理流程不会因类型不匹配而中断
### 2024年5月30日
- **修复文本清理过程中的类型错误**
- 解决了在文本清理过程中出现的`'dict' object has no attribute 'strip'`错误
- 增强了`_clean_text`方法中的类型检查,确保只对字符串类型对象调用字符串方法
- 改进了文本文件生成逻辑,添加针对不同数据类型的处理策略
- 优化了元数据字典的内容提取方式,确保其正文内容能够被包含在文本输出中
- 提高了代码的健壮性,可以正确处理混合类型的内容列表
- 完善了错误处理机制,避免因类型不匹配导致的处理中断
### 2024年5月29日
- **修复文档去重处理异常**
- 解决了处理带元数据的文档时出现的`'dict' object has no attribute 'startswith'`错误
- 增强了_remove_duplicates方法使其能够正确处理字典类型的元数据结构
- 改进了内部类型检查,区分处理字符串、字典、元组和列表等不同数据类型
- 优化了去重机制,保证包含元数据的文档正常处理不会中断
- 更新了相关方法的类型提示,明确方法可以处理任何类型的元素
- 完善对特殊数据类型的保留逻辑,确保元数据不会在去重过程中丢失
### 2024年5月28日
- **增强复杂表格结构处理能力**
- 实现多级表头表格的自动识别与处理支持最多4级嵌套表头
- 完善对复杂表头结构的分析,正确处理跨行跨列的表头单元格
- 针对多级表头表格优化Markdown输出格式保持原始表格的层次结构
- 改进表格预处理流程,添加表格结构类型自动检测功能
- 优化合并单元格处理逻辑,确保复杂表格数据的完整性和准确性
- 引入表格元数据记录机制,保存表格结构特征以便后续处理
- 完善复杂表格的调试日志,便于排查处理过程中的问题
### 2024年5月27日
- **修复表格处理异常错误**
- 解决了处理特殊表格时出现的`'dict' object has no attribute 'strip'`类型错误
- 增强了内容过滤函数的类型安全检查,避免对非字符串类型应用字符串方法
- 改进了对多种数据类型(字典、元组、列表等)的兼容性处理
- 确保在处理表格时不会因类型错误而导致文档处理中断
- 优化了错误处理机制,提供更详细的错误信息以便于调试
- 提高了代码的健壮性,能更好地处理各种格式和结构的输入数据
### 2024年5月26日
- **增强特殊结构表格处理能力**
- 优化对特殊格式表格的识别能力,特别是键值对形式的表格(如账号、订单号等信息表)
- 新增键值对表格专用渲染模式,确保所有键值对数据都被正确提取
- 改进单元格内容提取逻辑,避免遗漏特殊格式的单元格内容
- 引入表格结构智能分析,自动识别不同类型的表格并应用最合适的处理方法
- 完善对"PO-Number"、"Account No."等业务类信息字段的特殊处理
- 添加了多种关键字模式匹配,提高对各类业务表格的兼容性
- 优化文本提取过程,确保每个文本片段都能被完整保留
### 2024年5月25日
- **优化Markdown表格格式输出**
- 严格按照原文档中的表格格式输出Markdown表格保留空单元格
- 去除过度智能填充功能,避免自动填充空单元格导致的格式不一致
- 保留完整表格结构,包括所有的空行
- 只处理显式标记的合并单元格,不进行推断性的内容填充
- 确保表格的每个单元格精确反映原始文档中的内容
- 简化表格处理逻辑,提高处理速度和准确性
### 2024年5月24日
- **优化Markdown输出格式**
- 移除Markdown输出中的文档元数据信息如创建时间、作者、备注等
- 保留DOCX和TXT输出中的文档元信息不影响其完整性
- 重构元数据处理逻辑,使用类型标记区分不同内容类型
- 提高代码的可维护性和扩展性
- 优化内部数据结构,便于后续自定义输出格式
- 改进文本处理流程,统一处理文本和结构化内容
### 2024年5月23日
- **修复PDF转Word时图片丢失的问题**
- 增加了多种图片提取方法确保即使在PDF转DOCX过程中丢失图片也能正确保留
- 直接从PDF源文件提取图片不再完全依赖转换后的DOCX文档
- 改进图片处理流程确保OCR结果被正确保存到最终输出
- 增强Markdown图片处理逻辑优化图片路径管理和文件复制过程
- 添加详细日志和错误诊断信息,便于问题排查
- 优化图片文件存储结构,避免图片重复处理
- 增加图片处理失败时的备选方案,提高系统鲁棒性
- 解决Markdown文档中图片无法显示的问题
### 2024年5月21日 ### 2024年5月21日
- **增强复杂表格处理的安全性和稳定性** - **增强复杂表格处理的安全性和稳定性**
- 全面优化索引安全处理,解决表格解析中的索引越界问题 - 全面优化索引安全处理,解决表格解析中的索引越界问题
@ -321,16 +219,6 @@ pip install -r requirements.txt
- 优化文件处理逻辑 - 优化文件处理逻辑
- 改进错误处理 - 改进错误处理
### 2024年6月3日
- 优化表格数据处理逻辑:
- 重构format_group_to_text函数采用更通用的处理方式
- 移除对特定字段名的依赖,提高代码灵活性
- 自动清理和格式化字段名中的特殊字符
- 统一的文本格式化逻辑,适应不同数据结构
- 改进键值对处理方式,支持更多数据格式
- 自动清理"表格无有效数据"等无效提示信息
- 优化文本拼接逻辑,确保输出格式的一致性
## 安装说明 ## 安装说明
1. 克隆项目代码 1. 克隆项目代码
@ -471,268 +359,3 @@ python fix_tesseract_path.py
1. 将Tesseract安装目录(通常是`C:\Program Files\Tesseract-OCR`)添加到系统PATH环境变量 1. 将Tesseract安装目录(通常是`C:\Program Files\Tesseract-OCR`)添加到系统PATH环境变量
2. 设置环境变量`TESSERACT_CMD`为Tesseract可执行文件的完整路径 2. 设置环境变量`TESSERACT_CMD`为Tesseract可执行文件的完整路径
# 文档表格处理工具
本工具提供了强大的表格数据处理功能,可以处理文档中的各种类型表格。
## 主要功能
### 1. 表格数据处理
- 表格数据验证和清理
- 表格结构规范化
- 表格数据增强
- 表格布局优化
### 2. 数据转换和分析
- 表格转换为字典格式
- 表格内容分析
- 基本统计信息
- 列数据分析
- 数据模式检测
- 结构特征分析
- 内容质量评估
- 重复值检测
- 值分布分析
- 列相关性分析
- 数据一致性检查
- 潜在问题检测
### 3. 格式转换
- 转换为CSV格式
- 转换为Excel格式
- 转换为Markdown格式
- 转换为HTML格式
### 4. 高级功能
- 多级表头处理
- 合并单元格处理
- 键值对表格处理
- 数据类型自动识别
- 表格结构优化
## 使用示例
```python
from cxs.cxs_table_processor import TableProcessor
# 创建处理器实例
processor = TableProcessor()
# 处理表格数据
table_data = {
'rows': [...],
'header_rows': 1
}
# 数据转换
dict_data = processor._convert_table_to_dict(table_data)
# 内容分析
analysis = processor._analyze_table_content(table_data)
# 检测数据模式
patterns = processor._detect_table_patterns(table_data)
# 导出为不同格式
csv_data = processor._convert_table_to_csv(table_data)
excel_data = processor._convert_table_to_excel(table_data)
```
## 数据转换能力
支持以下数据转换:
1. 表格 -> 字典
- 支持键值对表格
- 支持普通表格结构
- 支持多级表头
2. 表格 -> CSV
- 自动处理表头
- 处理合并单元格
- 支持自定义分隔符
3. 表格 -> Excel
- 保留表格结构
- 处理合并单元格
- 自动调整列宽
- 设置表头样式
4. 表格 -> Markdown/HTML
- 格式化输出
- 保持表格结构
- 支持样式设置
## 开发要求
- Python 3.7+
- 依赖包:
- openpyxl
- pandas
- numpy
## 安装说明
```bash
pip install -r requirements.txt
```
## 更新日志
### v1.0.0
- 初始版本发布
- 基本的表格处理功能
### v1.1.0
- 添加数据验证和清理功能
- 增加表格结构规范化
### v1.2.0
- 添加数据转换功能
- 支持多种输出格式
### v1.3.0
- 添加内容分析功能
- 增加数据模式检测
- 优化表格处理性能
### 2024-03-xx
- 优化了表格处理器的稳定性和错误处理
- 增加了严格的索引检查和边界处理
- 改进了单元格和行级别的错误处理机制
- 增强了对大型表格和复杂表头的支持
- 优化了表格规范化处理
- 提高了处理不规则表格的兼容性
- 改进了内存使用效率
## 注意事项
1. 大文件处理
- 建议分批处理大型表格
- 注意内存使用
2. 数据验证
- 建议在处理前进行数据验证
- 检查表格结构完整性
3. 错误处理
- 所有方法都包含错误处理
- 详细的错误信息输出
## 贡献指南
1. Fork 项目
2. 创建特性分支
3. 提交变更
4. 发起 Pull Request
## 许可证
MIT License
## 更新日志
### 2024-03-21
- 修复了文本分段工具的命令行参数问题
- 现在支持使用相对路径处理文件
- 新增txt格式输出支持默认输出格式改为txt
- 优化了段落分隔显示,使用空行分隔各段落
- 全新的智能语义分段功能:
- 支持基于章节标题的主要分段
- 支持基于语义转折词的次要分段
- 智能识别特殊段落(如摘要、引言等)
- 自动合并过短段落,保持语义完整性
- 优化的中文标点符号处理
- 添加token长度控制
- 确保每个段落不超过512个token
- 智能估算中英文混合文本的token数量
- 对超长句子进行智能拆分
- 在保持语义完整性的同时控制token数量
- 优化表格内容处理:
- 自动移除表格标记(如"表格1开始"、"表格1结束"
- 智能分割长表格内容确保每段不超过token限制
- 保持表格行的语义完整性
- 使用逗号和分号作为表格内容的分割点
- 优化表格段落的可读性
## 使用方法
### 文本分段工具
基本用法输出txt格式
```bash
python text_paragraph_splitter.py sample_continuous_text.txt
```
指定输出文件:
```bash
python text_paragraph_splitter.py sample_continuous_text.txt -o output.txt
```
输出JSON格式
```bash
python text_paragraph_splitter.py sample_continuous_text.txt -f json -o output.json
```
参数说明:
- input_file输入文件路径例如sample_continuous_text.txt
- --output/-o输出文件路径默认为当前目录下的 paragraphs.txt
- --format/-f输出格式支持txt和json默认为txt
分段规则说明:
1. Token长度控制
- 每个段落严格控制在512个token以内
- 中文字符按1.5个token计算
- 英文单词按1个token计算
- 标点符号按1个token计算
- 超长句子会按逗号智能拆分
2. 表格处理:
- 自动识别并移除表格标记
- 按行处理表格内容
- 智能合并短行不超过token限制
- 对超长行进行分割处理
- 保持表格内容的语义连贯性
3. 主要分段标记:
- 章节标题(如"第一章"、"第1节"等)
- 序号标记(如"一、"、"1."、"1"等)
- 罗马数字标记(如"I."、"II."等)
4. 次要分段标记:
- 语义转折词(如"然而"、"但是"、"因此"等)
- 总结性词语(如"总的来说"、"综上所述"等)
- 举例词语(如"例如"、"比如"等)
5. 特殊段落:
- 自动识别摘要、引言、结论等特殊段落
- 保持这些段落的独立性
6. 智能合并:
- 合并过短的段落小于50字
- 确保合并后不超过token限制
- 保持标题等特殊标记的独立性
- 确保段落语义的完整性
### 2024-03-xx
- 重写了表格处理逻辑,增强了对复杂表格的处理能力
- 使用@dataclass重新设计了表格数据结构Cell、Row、Table类
- 支持多级表头和合并单元格的识别
- 自动识别表格类型(标准表格、键值对、矩阵等)
- 支持特殊格式(货币、百分比、日期等)的识别和转换
- 增加了表格处理的错误处理和容错机制
- 优化了表格输出格式支持Markdown、HTML和字典格式
- 添加了表格处理的调试信息输出
- 更新了导入路径使用新的table_processor模块
### 2024年3月
- 优化表格处理逻辑:
- 修复复杂表头和矩阵类型表格的索引越界问题
- 增强表格行和单元格的错误处理机制
- 改进表头结构分析,支持多级表头识别
- 优化矩阵类型表格的检测算法
- 增加数字单元格识别功能
- 完善表格转文本的格式化处理
- 增加边界检查和异常处理机制
- 优化内存使用和处理效率

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -464,12 +464,7 @@ async def process_single_file(file_path: str, cleaner: DocCleaner) -> tuple[str,
# 合并正文和附录内容用于返回 # 合并正文和附录内容用于返回
all_content = main_content + ["附录"] + appendix if appendix else main_content all_content = main_content + ["附录"] + appendix if appendix else main_content
# 增加类型检查确保只对字符串类型调用strip()方法 text_content = " ".join([t.replace("\n", " ").strip() for t in all_content if t.strip()])
text_content = " ".join([
t.replace("\n", " ").strip() if isinstance(t, str) else str(t)
for t in all_content
if (isinstance(t, str) and t.strip()) or not isinstance(t, str)
])
# 验证所有文件是否成功创建 # 验证所有文件是否成功创建
if not output_file.exists(): if not output_file.exists():
@ -492,11 +487,10 @@ async def process_single_file(file_path: str, cleaner: DocCleaner) -> tuple[str,
print(f"清理图片目录时出错: {str(cleanup_error)}") print(f"清理图片目录时出错: {str(cleanup_error)}")
try: try:
# 添加类型检查确保temp_docx是字符串类型 if temp_docx and os.path.exists(temp_docx):
if temp_docx and isinstance(temp_docx, (str, Path)) and os.path.exists(str(temp_docx)):
print(f"清理临时DOCX文件: {temp_docx}") print(f"清理临时DOCX文件: {temp_docx}")
safe_delete_file(str(temp_docx)) # 确保传递字符串参 safe_delete_file(temp_docx) # 使用安全删除函
temp_dir = os.path.dirname(str(temp_docx)) temp_dir = os.path.dirname(temp_docx)
if os.path.exists(temp_dir): if os.path.exists(temp_dir):
try: try:
os.rmdir(temp_dir) os.rmdir(temp_dir)

View File

@ -1,705 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import List, Dict, Any, Optional, Tuple, Union
from dataclasses import dataclass, field
from datetime import datetime
import re
import json
from copy import deepcopy
@dataclass
class Cell:
"""单元格数据结构"""
text: str = "" # 单元格文本内容
row_span: int = 1 # 垂直合并行数
col_span: int = 1 # 水平合并列数
is_header: bool = False # 是否是表头单元格
data_type: str = "text" # 数据类型text, number, date, currency等
original_value: Any = None # 原始值
formatted_value: str = "" # 格式化后的值
position: Dict[str, int] = field(default_factory=lambda: {"row": 0, "col": 0}) # 单元格位置
metadata: Dict[str, Any] = field(default_factory=dict) # 元数据
@dataclass
class Row:
"""行数据结构"""
cells: List[Cell] = field(default_factory=list) # 单元格列表
is_header: bool = False # 是否是表头行
row_index: int = 0 # 行索引
metadata: Dict[str, Any] = field(default_factory=dict) # 元数据
@dataclass
class Table:
"""表格数据结构"""
rows: List[Row] = field(default_factory=list) # 行列表
header_rows: int = 0 # 表头行数
total_rows: int = 0 # 总行数
total_cols: int = 0 # 总列数
has_complex_header: bool = False # 是否有复杂表头
table_type: str = "normal" # 表格类型normal, key_value, matrix等
metadata: Dict[str, Any] = field(default_factory=dict) # 元数据
@dataclass
class TableData:
"""表格数据结构"""
rows: List[List[Dict[str, Any]]] = field(default_factory=list) # 存储表格行数据
style: Optional[str] = None # 表格样式
columns: List[Dict[str, Any]] = field(default_factory=list) # 列属性
has_multi_level_header: bool = False # 是否有多级表头
has_key_value_pairs: bool = False # 是否包含键值对结构
header_rows: int = 1 # 表头行数默认为1
table_type: str = "normal" # 表格类型normal, key_value, matrix等
def add_row(self, row_data: List[Dict[str, Any]]):
"""添加一行数据到表格"""
self.rows.append(row_data)
def get_row_count(self) -> int:
"""获取表格行数"""
return len(self.rows)
def get_column_count(self) -> int:
"""获取表格列数"""
return len(self.columns) if self.columns else (
max((len(row) for row in self.rows), default=0)
)
def is_empty(self) -> bool:
"""检查表格是否为空"""
return len(self.rows) == 0
def get_cell_text(self, row_idx: int, col_idx: int) -> str:
"""获取单元格文本内容"""
try:
if 0 <= row_idx < len(self.rows) and 0 <= col_idx < len(self.rows[row_idx]):
cell = self.rows[row_idx][col_idx]
return cell.get('text', '').strip()
except Exception as e:
print(f"获取单元格文本时出错 [{row_idx},{col_idx}]: {str(e)}")
return ''
def set_cell_text(self, row_idx: int, col_idx: int, text: str):
"""设置单元格文本内容"""
try:
if row_idx < len(self.rows) and col_idx < len(self.rows[row_idx]):
self.rows[row_idx][col_idx]['text'] = text
except Exception as e:
print(f"设置单元格文本时出错 [{row_idx},{col_idx}]: {str(e)}")
def get_cell_merge_info(self, row_idx: int, col_idx: int) -> Dict[str, Any]:
"""获取单元格合并信息"""
try:
if row_idx < len(self.rows) and col_idx < len(self.rows[row_idx]):
cell = self.rows[row_idx][col_idx]
return {
'gridspan': cell.get('gridspan', 1),
'vmerge': cell.get('vmerge', None)
}
except Exception as e:
print(f"获取单元格合并信息时出错 [{row_idx},{col_idx}]: {str(e)}")
return {'gridspan': 1, 'vmerge': None}
def set_cell_merge_info(self, row_idx: int, col_idx: int, gridspan: int = 1, vmerge: Optional[str] = None):
"""设置单元格合并信息"""
try:
if row_idx < len(self.rows) and col_idx < len(self.rows[row_idx]):
cell = self.rows[row_idx][col_idx]
cell['gridspan'] = gridspan
if vmerge is not None:
cell['vmerge'] = vmerge
except Exception as e:
print(f"设置单元格合并信息时出错 [{row_idx},{col_idx}]: {str(e)}")
def is_merged_cell(self, row_idx: int, col_idx: int) -> bool:
"""检查单元格是否是合并单元格"""
try:
if row_idx < len(self.rows) and col_idx < len(self.rows[row_idx]):
cell = self.rows[row_idx][col_idx]
return cell.get('gridspan', 1) > 1 or cell.get('vmerge') is not None
except Exception as e:
print(f"检查单元格合并状态时出错 [{row_idx},{col_idx}]: {str(e)}")
return False
def get_header_rows(self) -> List[List[Dict[str, Any]]]:
"""获取表头行数据"""
return self.rows[:self.header_rows]
def get_data_rows(self) -> List[List[Dict[str, Any]]]:
"""获取数据行数据"""
return self.rows[self.header_rows:]
class TableProcessor:
"""增强的表格处理器"""
def __init__(self):
# 数据类型识别模式
self.patterns = {
'currency': r'^\s*¥?\s*\d+(\.\d{2})?\s*$', # 货币金额
'percentage': r'^\s*\d+(\.\d+)?%\s*$', # 百分比
'date': r'^\d{4}[-/年]\d{1,2}[-/月]\d{1,2}日?$', # 日期
'number': r'^\s*\d+(\.\d+)?\s*$', # 数字
'time': r'^\d{1,2}:\d{2}(:\d{2})?$' # 时间
}
# 表头关键词
self.header_keywords = [
'序号', '编号', '项目', '名称', '类型', '说明', '备注',
'金额', '时间', '日期', '地区', '部门', '人员'
]
def process_table(self, raw_table: Any) -> Table:
"""处理表格,返回标准化的表格对象"""
try:
# 1. 初始化表格对象
table = Table()
# 2. 分析表格结构
self._analyze_table_structure(raw_table, table)
# 3. 处理表头
self._process_headers(raw_table, table)
# 4. 处理数据行
self._process_data_rows(raw_table, table)
# 5. 规范化表格
self._normalize_table(table)
# 6. 识别表格类型
self._identify_table_type(table)
return table
except Exception as e:
print(f"处理表格时出错: {str(e)}")
return Table()
def _analyze_table_structure(self, raw_table: Any, table: Table):
"""分析表格结构,包括行数、列数、合并单元格等"""
try:
# 获取基本维度信息
rows = raw_table.rows
table.total_rows = len(rows)
table.total_cols = len(raw_table.columns)
# 分析表头结构
header_info = self._analyze_header_structure(raw_table)
table.header_rows = header_info['header_rows']
table.has_complex_header = header_info['is_complex']
# 记录结构信息到元数据
table.metadata['structure_info'] = {
'total_rows': table.total_rows,
'total_cols': table.total_cols,
'header_rows': table.header_rows,
'has_complex_header': table.has_complex_header,
'analyzed_at': datetime.now().isoformat()
}
except Exception as e:
print(f"分析表格结构时出错: {str(e)}")
def _analyze_header_structure(self, raw_table: Any) -> Dict[str, Any]:
"""分析表头结构,返回表头信息"""
header_info = {
'header_rows': 1,
'is_complex': False
}
try:
# 检查前三行
for i in range(min(3, len(raw_table.rows))):
row = raw_table.rows[i]
# 检查是否有合并单元格
has_merged_cells = any(
cell._element.find('.//{*}vMerge') is not None or
cell._element.find('.//{*}gridSpan') is not None
for cell in row.cells
)
# 检查是否包含表头关键词
has_header_keywords = any(
any(keyword in cell.text for keyword in self.header_keywords)
for cell in row.cells
)
if has_merged_cells or has_header_keywords:
header_info['header_rows'] = max(header_info['header_rows'], i + 1)
if has_merged_cells:
header_info['is_complex'] = True
# 检查单元格格式是否符合表头特征
cell_formats = [self._analyze_cell_format(cell) for cell in row.cells]
if any(fmt == 'header' for fmt in cell_formats):
header_info['header_rows'] = max(header_info['header_rows'], i + 1)
except Exception as e:
print(f"分析表头结构时出错: {str(e)}")
return header_info
def _analyze_cell_format(self, cell: Any) -> str:
"""分析单元格格式特征"""
try:
# 获取单元格文本
text = cell.text.strip()
# 检查是否是表头格式
if text and any(char.isupper() for char in text): # 包含大写字母
return 'header'
if text and any(keyword in text for keyword in self.header_keywords):
return 'header'
# 检查数据类型
for data_type, pattern in self.patterns.items():
if re.match(pattern, text):
return data_type
return 'text'
except Exception as e:
print(f"分析单元格格式时出错: {str(e)}")
return 'text'
def _process_headers(self, raw_table: Any, table: Table):
"""处理表头,包括多级表头的处理"""
try:
for i in range(min(table.header_rows, len(raw_table.rows))):
try:
row = raw_table.rows[i]
header_row = Row(is_header=True, row_index=i)
# 处理每个表头单元格
col_index = 0
max_cols = len(row.cells) # 获取实际的列数
for cell_idx in range(max_cols):
try:
cell = row.cells[cell_idx]
header_cell = self._process_header_cell(cell, i, col_index)
header_row.cells.append(header_cell)
col_index += header_cell.col_span
except Exception as cell_error:
print(f"处理表头单元格时出错 [行={i}, 列={cell_idx}]: {str(cell_error)}")
# 添加一个空单元格
header_cell = Cell(text="", is_header=True, position={'row': i, 'col': col_index})
header_row.cells.append(header_cell)
col_index += 1
# 如果单元格数量不足,补充空单元格
while len(header_row.cells) < table.total_cols:
header_cell = Cell(text="", is_header=True, position={'row': i, 'col': col_index})
header_row.cells.append(header_cell)
col_index += 1
table.rows.append(header_row)
except Exception as row_error:
print(f"处理表头行时出错 [行={i}]: {str(row_error)}")
# 创建一个空行
empty_row = Row(is_header=True, row_index=i)
for col in range(table.total_cols):
empty_row.cells.append(Cell(text="", is_header=True, position={'row': i, 'col': col}))
table.rows.append(empty_row)
except Exception as e:
print(f"处理表头时出错: {str(e)}")
def _process_header_cell(self, cell: Any, row_index: int, col_index: int) -> Cell:
"""处理表头单元格"""
try:
# 创建表头单元格
header_cell = Cell(
text=cell.text.strip(),
is_header=True,
position={'row': row_index, 'col': col_index}
)
# 处理合并单元格
vmerge = cell._element.find('.//{*}vMerge')
gridspan = cell._element.find('.//{*}gridSpan')
if vmerge is not None:
val = vmerge.get('{http://schemas.openxmlformats.org/wordprocessingml/2006/main}val', 'continue')
header_cell.row_span = 2 if val == 'restart' else 1
if gridspan is not None:
try:
header_cell.col_span = int(gridspan.get('{http://schemas.openxmlformats.org/wordprocessingml/2006/main}val', '1'))
except ValueError:
header_cell.col_span = 1
return header_cell
except Exception as e:
print(f"处理表头单元格时出错: {str(e)}")
return Cell(text="", is_header=True, position={'row': row_index, 'col': col_index})
def _process_data_rows(self, raw_table: Any, table: Table):
"""处理数据行"""
try:
for i in range(table.header_rows, table.total_rows):
try:
row = raw_table.rows[i]
data_row = Row(is_header=False, row_index=i)
# 处理每个数据单元格
col_index = 0
max_cols = len(row.cells) # 获取实际的列数
for cell_idx in range(max_cols):
try:
cell = row.cells[cell_idx]
data_cell = self._process_data_cell(cell, i, col_index)
data_row.cells.append(data_cell)
col_index += data_cell.col_span
except Exception as cell_error:
print(f"处理单元格时出错 [行={i}, 列={cell_idx}]: {str(cell_error)}")
# 添加一个空单元格
data_cell = Cell(text="", position={'row': i, 'col': col_index})
data_row.cells.append(data_cell)
col_index += 1
# 如果单元格数量不足,补充空单元格
while len(data_row.cells) < table.total_cols:
data_cell = Cell(text="", position={'row': i, 'col': col_index})
data_row.cells.append(data_cell)
col_index += 1
table.rows.append(data_row)
except Exception as row_error:
print(f"处理数据行时出错 [行={i}]: {str(row_error)}")
# 创建一个空行
empty_row = Row(is_header=False, row_index=i)
for col in range(table.total_cols):
empty_row.cells.append(Cell(text="", position={'row': i, 'col': col}))
table.rows.append(empty_row)
except Exception as e:
print(f"处理数据行时出错: {str(e)}")
def _process_data_cell(self, cell: Any, row_index: int, col_index: int) -> Cell:
"""处理数据单元格"""
try:
# 获取单元格文本
text = cell.text.strip()
# 创建数据单元格
data_cell = Cell(
text=text,
position={'row': row_index, 'col': col_index}
)
# 识别数据类型
data_type = 'text'
original_value = text
formatted_value = text
# 尝试识别数据类型和格式化值
for type_name, pattern in self.patterns.items():
if re.match(pattern, text):
data_type = type_name
if type_name == 'currency':
# 处理货币金额
try:
value = float(re.sub(r'[¥,\s]', '', text))
original_value = value
formatted_value = f"¥{value:.2f}"
except ValueError:
pass
elif type_name == 'percentage':
# 处理百分比
try:
value = float(text.rstrip('%')) / 100
original_value = value
formatted_value = f"{value:.2%}"
except ValueError:
pass
elif type_name == 'date':
# 处理日期
try:
# 统一日期格式
date_text = re.sub(r'[年月日]', '-', text).rstrip('-')
date_obj = datetime.strptime(date_text, '%Y-%m-%d')
original_value = date_obj
formatted_value = date_obj.strftime('%Y-%m-%d')
except ValueError:
pass
break
data_cell.data_type = data_type
data_cell.original_value = original_value
data_cell.formatted_value = formatted_value
# 处理合并单元格
vmerge = cell._element.find('.//{*}vMerge')
gridspan = cell._element.find('.//{*}gridSpan')
if vmerge is not None:
val = vmerge.get('{http://schemas.openxmlformats.org/wordprocessingml/2006/main}val', 'continue')
data_cell.row_span = 2 if val == 'restart' else 1
if gridspan is not None:
try:
data_cell.col_span = int(gridspan.get('{http://schemas.openxmlformats.org/wordprocessingml/2006/main}val', '1'))
except ValueError:
data_cell.col_span = 1
return data_cell
except Exception as e:
print(f"处理数据单元格时出错: {str(e)}")
return Cell(text="", position={'row': row_index, 'col': col_index})
def _normalize_table(self, table: Table):
"""规范化表格,确保所有行都有相同的列数"""
try:
max_cols = table.total_cols
# 确保每行都有正确的列数
for row in table.rows:
current_cols = len(row.cells)
if current_cols < max_cols:
# 添加空单元格
for col in range(current_cols, max_cols):
empty_cell = Cell(
text="",
is_header=row.is_header,
position={'row': row.row_index, 'col': col}
)
row.cells.append(empty_cell)
elif current_cols > max_cols:
# 移除多余的单元格
row.cells = row.cells[:max_cols]
# 更新表格的总列数
table.total_cols = max_cols
except Exception as e:
print(f"规范化表格时出错: {str(e)}")
def _identify_table_type(self, table: Table):
"""识别表格类型"""
try:
# 检查是否是键值对表格
if table.total_cols == 2:
key_col_pattern = all(
cell.text.strip() != "" for row in table.rows
if not row.is_header for cell in row.cells[:1]
)
if key_col_pattern:
table.table_type = "key_value"
return
# 检查是否是矩阵表格
if table.has_complex_header and table.total_cols > 2:
table.table_type = "matrix"
return
# 默认为普通表格
table.table_type = "normal"
except Exception as e:
print(f"识别表格类型时出错: {str(e)}")
table.table_type = "normal"
def convert_to_markdown(self, table: Table) -> str:
"""将表格转换为Markdown格式"""
try:
markdown_lines = []
# 处理表头
for i in range(table.header_rows):
row = table.rows[i]
header_cells = [cell.text for cell in row.cells]
markdown_lines.append("| " + " | ".join(header_cells) + " |")
# 添加分隔行
if i == table.header_rows - 1:
separator = "|" + "|".join(["---" for _ in range(table.total_cols)]) + "|"
markdown_lines.append(separator)
# 处理数据行
for row in table.rows[table.header_rows:]:
data_cells = [
cell.formatted_value if cell.formatted_value
else cell.text for cell in row.cells
]
markdown_lines.append("| " + " | ".join(data_cells) + " |")
return "\n".join(markdown_lines)
except Exception as e:
print(f"转换为Markdown格式时出错: {str(e)}")
return ""
def convert_to_html(self, table: Table) -> str:
"""将表格转换为HTML格式"""
try:
html_lines = ['<table border="1">']
# 处理表头
if table.header_rows > 0:
html_lines.append("<thead>")
for i in range(table.header_rows):
row = table.rows[i]
html_lines.append("<tr>")
for cell in row.cells:
span_attrs = []
if cell.row_span > 1:
span_attrs.append(f'rowspan="{cell.row_span}"')
if cell.col_span > 1:
span_attrs.append(f'colspan="{cell.col_span}"')
attrs = " ".join(span_attrs)
html_lines.append(f"<th {attrs}>{cell.text}</th>")
html_lines.append("</tr>")
html_lines.append("</thead>")
# 处理数据行
html_lines.append("<tbody>")
for row in table.rows[table.header_rows:]:
html_lines.append("<tr>")
for cell in row.cells:
span_attrs = []
if cell.row_span > 1:
span_attrs.append(f'rowspan="{cell.row_span}"')
if cell.col_span > 1:
span_attrs.append(f'colspan="{cell.col_span}"')
attrs = " ".join(span_attrs)
# 使用格式化值或原始文本
display_value = cell.formatted_value if cell.formatted_value else cell.text
html_lines.append(f"<td {attrs}>{display_value}</td>")
html_lines.append("</tr>")
html_lines.append("</tbody>")
html_lines.append("</table>")
return "\n".join(html_lines)
except Exception as e:
print(f"转换为HTML格式时出错: {str(e)}")
return ""
def convert_to_dict(self, table: Table) -> Dict[str, Any]:
"""将表格转换为字典格式"""
try:
result = {
'metadata': table.metadata,
'structure': {
'total_rows': table.total_rows,
'total_cols': table.total_cols,
'header_rows': table.header_rows,
'has_complex_header': table.has_complex_header,
'table_type': table.table_type
},
'headers': [],
'data': []
}
# 处理表头
for i in range(table.header_rows):
header_row = []
for cell in table.rows[i].cells:
header_row.append({
'text': cell.text,
'row_span': cell.row_span,
'col_span': cell.col_span,
'position': cell.position
})
result['headers'].append(header_row)
# 处理数据行
for row in table.rows[table.header_rows:]:
data_row = []
for cell in row.cells:
data_row.append({
'text': cell.text,
'data_type': cell.data_type,
'original_value': cell.original_value,
'formatted_value': cell.formatted_value,
'position': cell.position
})
result['data'].append(data_row)
return result
except Exception as e:
print(f"转换为字典格式时出错: {str(e)}")
return {}
def convert_to_text(self, table: Table) -> str:
"""
将表格转换为文本格式"标题:内容"的形式显示多级表头用下划线连接
Args:
table: Table对象
Returns:
str: 表格的文本表示
"""
if not table or not table.rows:
return "【空表格】"
try:
# 存储处理后的文本行
text_parts = []
# 存储处理后的表头文本
header_texts = {}
# 处理表头
if table.header_rows > 0:
# 对于多级表头,需要合并处理
for row_idx in range(table.header_rows):
row = table.rows[row_idx]
for col_idx, cell in enumerate(row.cells):
# 获取当前列的已有表头文本
current_header = header_texts.get(col_idx, [])
if cell.text.strip():
current_header.append(cell.text.strip())
header_texts[col_idx] = current_header
# 合并多级表头
final_headers = {}
for col_idx, headers in header_texts.items():
final_headers[col_idx] = "_".join(headers) if headers else ""
# 处理数据行
data_rows = []
for row in table.rows[table.header_rows:]:
row_data = {}
for col_idx, cell in enumerate(row.cells):
if cell.text.strip():
row_data[col_idx] = cell.text.strip()
if row_data:
data_rows.append(row_data)
# 生成"标题:内容"格式输出
for row_idx, row_data in enumerate(data_rows):
row_parts = []
for col_idx, content in row_data.items():
if col_idx in final_headers and final_headers[col_idx]:
row_parts.append(f"{final_headers[col_idx]}:{content}")
if row_parts:
text_parts.append("".join(row_parts))
return "\n".join(text_parts)
except Exception as e:
print(f"转换表格为文本时出错: {str(e)}")
return "【表格处理失败】"
def _convert_table_to_text(self, table: Table) -> str:
"""
转换表格为文本格式兼容方法
Args:
table: Table对象
Returns:
str: 表格的文本表示
"""
return self.convert_to_text(table)

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,14 @@
# 文档内容
【文档信息】
作者: Lenovo
创建时间: 2025-05-15 08:30:10
修改时间: 2025-05-15 08:30:25
1111 1111
【图片识别文本】 【图片识别文本】
@ -22,3 +33,37 @@
以 上 优 化 星 觞 失 了 临 时 文 伟 删 除 问 题 , 又 保 持 了 系 统 的 以 上 优 化 星 觞 失 了 临 时 文 伟 删 除 问 题 , 又 保 持 了 系 统 的
稳 定 性 , 让 您 能 雪 顺 畅 地 处 理 Bxcel 文 件 。 稳 定 性 , 让 您 能 雪 顺 畅 地 处 理 Bxcel 文 件 。
## 图片内容
### 图片 1
![图片 1](images/image_1.png)
**OCR文本内容:**
“ 完 善 了 异 常 处 理 , 防 止 惑 时 目 录 券 除 失 败 导 致 程 序 崖
4. 更 新 README.md
* 在 暨 近 更 新 部 分 记 录 了 临 时 文 件 处 理 机 制 的 改 进
。 添 加 了 Excel 文 件 句 柄 管 理
使 用 说 明
这 东 改 进 不 需 要 您 做 任 何 额 外 操 作 , 系 统 会 自 动 -
1. 在 处 理 Excel 文 件 时 正 球 关 闭 文 件 句 柄
2 当 尝 试 删 除 文 件 通 刨 “ 文 件 被 占 用 “ 错 误 时 , 自 动 等 待
并 重 试
3 即 使 无 法 券 除 临 时 文 件 , 也 不 影 响 处 #
如 果 仍 然 通 到 惧 时 文 件 问 题 , 系 统 会 在 下 次 启 动 时 自 动
清 理 所 有 临 时 文 件 , 不 会 影 响 系 统 功 能 。
以 上 优 化 星 觞 失 了 临 时 文 伟 删 除 问 题 , 又 保 持 了 系 统 的
稳 定 性 , 让 您 能 雪 顺 畅 地 处 理 Bxcel 文 件 。

View File

@ -1 +1 @@
1111 【图片识别文本】 “ 完 善 了 异 常 处 理 , 防 止 惑 时 目 录 券 除 失 败 导 致 程 序 崖 澎 澎 4. 更 新 README.md * 在 暨 近 更 新 部 分 记 录 了 临 时 文 件 处 理 机 制 的 改 进 。 添 加 了 Excel 文 件 句 柄 管 理 使 用 说 明 这 东 改 进 不 需 要 您 做 任 何 额 外 操 作 , 系 统 会 自 动 - 1. 在 处 理 Excel 文 件 时 正 球 关 闭 文 件 句 柄 2 当 尝 试 删 除 文 件 通 刨 “ 文 件 被 占 用 “ 错 误 时 , 自 动 等 待 并 重 试 3 即 使 无 法 券 除 临 时 文 件 , 也 不 影 响 处 # 如 果 仍 然 通 到 惧 时 文 件 问 题 , 系 统 会 在 下 次 启 动 时 自 动 清 理 所 有 临 时 文 件 , 不 会 影 响 系 统 功 能 。 以 上 优 化 星 觞 失 了 临 时 文 伟 删 除 问 题 , 又 保 持 了 系 统 的 稳 定 性 , 让 您 能 雪 顺 畅 地 处 理 Bxcel 文 件 。 【文档信息】 作者: Lenovo 创建时间: 2025-05-15 08:30:10 修改时间: 2025-05-15 08:30:25 1111 【图片识别文本】 “ 完 善 了 异 常 处 理 , 防 止 惑 时 目 录 券 除 失 败 导 致 程 序 崖 澎 澎 4. 更 新 README.md * 在 暨 近 更 新 部 分 记 录 了 临 时 文 件 处 理 机 制 的 改 进 。 添 加 了 Excel 文 件 句 柄 管 理 使 用 说 明 这 东 改 进 不 需 要 您 做 任 何 额 外 操 作 , 系 统 会 自 动 - 1. 在 处 理 Excel 文 件 时 正 球 关 闭 文 件 句 柄 2 当 尝 试 删 除 文 件 通 刨 “ 文 件 被 占 用 “ 错 误 时 , 自 动 等 待 并 重 试 3 即 使 无 法 券 除 临 时 文 件 , 也 不 影 响 处 # 如 果 仍 然 通 到 惧 时 文 件 问 题 , 系 统 会 在 下 次 启 动 时 自 动 清 理 所 有 临 时 文 件 , 不 会 影 响 系 统 功 能 。 以 上 优 化 星 觞 失 了 临 时 文 伟 删 除 问 题 , 又 保 持 了 系 统 的 稳 定 性 , 让 您 能 雪 顺 畅 地 处 理 Bxcel 文 件 。

View File

@ -0,0 +1,359 @@
表格 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
【文档信息】
作者: 王兴龙
创建时间: 2017-09-04 06:43:00
修改时间: 2022-10-25 03:31:00
附件
医疗器械分类目录
2017年8月目 录
01有源手术器械1
02无源手术器械6
03神经和心血管手术器械16
04骨科手术器械23
05放射治疗器械33
06医用成像器械37
07医用诊察和监护器械48
08呼吸、麻醉和急救器械56
09物理治疗器械62
10输血、透析和体外循环器械69
11医疗器械消毒灭菌器械75
12有源植入器械78
13无源植入器械81
14注输、护理和防护器械88
15患者承载器械102
16眼科器械105
17口腔科器械116
18妇产科、辅助生殖和避孕器械128
19医用康复器械136
20中医器械139
21医用软件143
22临床检验器械147
编制说明155
01 有源手术器械说明
一、范围
本子目录包括以手术治疗为目的与有源相关的医疗器械,包括超声、激光、高频/射频、微波、冷冻、冲击波、手术导航及控制系统、手术照明设备、内窥镜手术用有源设备等医疗器械。
二、框架结构
本子目录按照产品预期用途和专业技术及功能特点进行层级排序共划分为10个一级产品类别在一级产品类别的基础上根据先设备后附件的形式设立二级产品类别共25个列举120个品名举例。
本子目录包括2002版医疗器械分类目录中《6821医用电子仪器设备》《6822医用光学器具仪器及内窥镜设备》《6824医用激光仪器设备》《6825医用高频仪器设备》《6854手术室急救室诊疗室设备及器具》《6858医用冷疗低温冷藏设备及器具》和《〈6816烧伤整形科手术器械〉部分还包括了2012版医疗器械分类目录中《〈6823医用超声仪器及有关设备〉部分》。
该子目录中一级产品类别与2002/2012版分类目录产品类别的对应关系如下
与2002/2012版分类目录对应关系
三、其他说明
医用激光光纤与激光治疗仪配套应用传输激光器产生的能量用于激光手术治疗。依据《关于一次性前列腺治疗套件等产品分类界定的通知》国食药监械2008587号和《国家食品药品监督管理局关于超声肿瘤治疗系统等17个产品分类界定的通知》国食药监械201236号分类界定文件规定管理类别为二类分类编码6824。因此将医用激光光纤纳入《01有源手术器械》目录中。
(二)射频消融设备用灌注泵,管理类别由第三类降为第二类。
发光二极管LED手术照明灯管理类别由第二类降为第一类。
本子目录包括通用刀、剪、钳等各类无源手术医疗器械,不包括神经和心血管手术器械、骨科手术器械、眼科器械、口腔科器械、妇产科、辅助生殖和避孕器械。
02无源手术器械说明
本子目录按照无源手术器械的功能用途及产品特性分为15个一级产品类别。根据产品的具体用途的不同分为83个二级产品类别列举597个品名举例。
本子目录是将各种通用无源手术器械、内窥镜下用无源手术器械和医用缝合材料及粘合剂归类整合,将共同功能用途的产品,如,刀、剪、钳等,归在同一个一级产品类别,同时根据产品的具体用途或结构特征,细化成二级产品类别。
本子目录包括2002版分类目录的《6801基础外科手术器械》《6802显微外科手术器械》《6805耳鼻喉科手术器械》《6808腹部外科手术器械》《6809泌尿肛肠外科手术器械》《6816烧伤整形科手术器械》《〈6822医用光学器具仪器及内窥镜设备〉内窥镜无源手术器械部分》和《6865医用缝合材料及粘合剂产品》。子目录中第一类产品主要参考2014年《第一类医疗器械产品目录》。
将内窥镜下用无源手术器械在02无源手术器械目录中以二级产品类别单独列出。
02无源手术器械
本子目录包括神经外科手术器械、胸腔心血管手术器械和心血管介入器械。
本子目录按照神经、胸腔心血管和心血管介入器械的功能用途及产品特性分为14个一级产品类别。在一级产品类别下根据产品的具体用途的不同细分为60个二级产品类别列举224个品名举例。
本子目录包括2002版分类目录的《6803神经外科手术器械》《6807胸腔心血管外科手术器械》《6877介入器材》4个子目录中大部分产品。子目录中第一类产品主要参考2014年《第一类医疗器械产品目录》。
03神经和心血管手术器械说明
本子目录是将神经外科手术器械、胸腔心血管手术器械和心血管介入器械归类整合,将共同功能用途的产品,比如刀、剪、钳等,归在同一个一级产品类别,同时根据产品的具体用途或结构特征,细化成二级产品类别。
(一)接触血液循环系统的心脏拉钩、心房拉钩、心室拉钩、房室拉钩、二尖瓣膜拉钩、凹凸齿止血夹,根据分类规则应按照第二类医疗器械管理,但鉴于相关产品一直按照第一类医疗器械管理,因此继续按照第一类医疗器械管理。
(二)心血管手术或脑外科手术冲吸器,规范为第二类管理。
(三)根据新版医疗器械分类规则将脑压板管理类别调整为第二类。
导管消毒连接器由外接头、70%异丙醇或乙醇水溶液等组成,用于对输液(注射)器具无针接头进行消毒,按第三类医疗器械管理。
本子目录框架是在2014年《第一类医疗器械产品目录》中《6810骨科手术器械》框架的基础上综合考虑2002版分类目录中的第二类、第三类产品及近年来的新产品而设置。本子目录将2014年《第一类医疗器械产品目录》中的"骨科用其他器械"进行了拆分一级产品类别由13个增至18个。本子目录包括2002版分类目录的《〈6810矫形外科骨科手术器械〉全部》、《〈6826物理治疗及康复设备〉部分》。
03神经和心血管手术器械
(二)与有源设备(如电动骨钻、电动骨锯、气动骨钻)连接使用的钻头、刀头、锯片、扩髓器、刨刀、磨头等配套工具,规范为第一类管理。
髌骨爪尖端侵入人体且滞留时间大于30天规范为第三类管理。
04骨科手术器械说明
(五)开口用锥(如手锥),管理类别由第二类降为第一类。
本子目录包括在骨科手术术中、术后及与临床骨科相关的各类手术器械及相关辅助器械,不包括在骨科手术后以康复为目的的康复器具,也不包括用于颈椎、腰椎患者减压牵引治疗及缓解椎间压力的牵引床(椅)、牵引治疗仪、颈部牵引器、腰部牵引器等类器械。
本子目录按照临床骨科手术器械的功能不同或产品特性分为18个一级产品类别包括11个骨科常用手术器械类别、1个骨科用有源器械类别、1个外固定及牵引器械类别、4个骨科手术用辅助器械类别和1个骨科其它手术器械类别依据其功能或用途的不同细分为96个二级产品类别并列举605个品名举例。
(一)骨髓抽吸和活检系统电钻,规范为第二类管理。
(四)接触椎间隙的非无菌提供的骨科重复使用手术器械,管理类别由第二类降为第一类。
(六)对于在手术操作过程中本子目录可能接触中枢神经系统的非无菌提供的骨科用凿、骨科用锉、骨科用铲、脊柱外科定位/导向/测量器械、脊柱外科开孔扩孔器械、脊柱外科神经根探子、脊柱外科植骨块嵌入器、脊柱外科椎弓根钉尾部切断器、脊柱手术通道器械、脊柱外科椎体复位器、骨科剥离保护器、骨科组织保护器具,管理类别由第二类降为第一类。
本子目录根据放射治疗领域特点、预期用途和产品特性分为4个一级产品类别22个二级产品类别共列举90个品名举例。本子目录包括2012年发布的《〈6830医用X射线设备〉部分》、2002版《6832医用高能射线治疗设备》和《〈6833放射性核素治疗设备〉部分》。
04骨科手术器械
(一)光学定位引导系统,配合外照射设备,用于患者在放射治疗中的定位、追踪和监测。此类产品验证放射治疗计划中定位的准确性,进而影响放射治疗剂量的准确性,预期用途和风险程度类似,对于放射治疗定位精准度影响较大,风险等级相对较高,该子目录中将光学定位引导系统统一规范为第三类医疗器械管理。
(三)放射治疗患者床板,用于放射治疗过程中对患者的支撑。该产品作为加速器附件,随整机注册,不单独按医疗器械管理,本目录不单独列出。
05放射治疗器械说明
本子目录包括放射治疗类医疗器械。
(二)主动呼吸控制系统,用于控制患者呼吸,最大程度的减少患者呼吸所引起的胸部和腹部器官运动的影响,提高治疗过程中的靶区定位的准确性。目前该产品在临床中使用率不是很高,由于患者在定位和治疗时,呼吸运动引起胸腹部器官位置变化不可预知性很大,各个患者的情况也千差万别,一旦该产品定位出现失误,患者的肿瘤部位和正常器官接受不正确的放射剂量,可能出现很大的风险。因此该子目录中将主动呼吸控制系统调整为第三类医疗器械进行管理。
(一)本子目录的名称,原有"医用成像器械"和"医用影像器械"两种意见。经讨论认为"成像"能包括"无影"的光学类器械,因此,选用"医用成像器械"的名称。
胃肠X射线检查用品中的胃肠道造影显像剂管理类别由第三类降为第二类。
(五)内窥镜气囊控制器,管理类别由第三类降为第二类。
带有LED光源的医用光学放大器具管理类别由第二类降为第一类。
单光子发射及X射线计算机断层成像系统SPECT/CT、正电子发射及X射线计算机断层成像系统PET/CT、正电子发射及磁共振成像系统PET/MR、超声电子内窥镜等产品具备一种以上的成像功能并进行图像融合。经过研讨设置一级产品类别"06-17组合功能融合成像器械"。
6831-3图像打印及后处理产品在《6831医用X射线附属设备及部件》子目录下。该子目录中设置一级产品类别"06-18图像显示、处理、传输及打印设备",适用于所有医用成像器械。
06医用成像器械
本子目录包括医用成像类医疗器械主要有X射线、超声、放射性核素、核磁共振和光学等成像医疗器械不包括眼科、妇产科等临床专科中的成像医疗器械。
本子目录根据成像原理划分为18个一级产品类别根据预期临床用途、产品组成划分为93个二级产品类别列举了360个品名举例。
本子目录主要对应2012版分类目录中的《〈6830医用X射线设备〉X射线成像器械》《6831医用X射线附属设备及部件》《6834医用射线防护用品、装置》《〈6823医用超声仪器及有关设备〉超声成像器械2002版《〈6828医用磁共振设备〉核磁共振成像器械》《〈6833医用核素设备〉放射性核素成像器械》《6821医用电子仪器设备》《〈6822医用光学器具、仪器及内窥镜设备〉光学成像器械》和《〈6824医用激光仪器设备〉激光诊断仪器、干色激光打印机》。
(三)胃肠超声显像粉,管理类别由第三类降为第二类。
(四)放射性核素扫描装置,管理类别由第三类降为第二类。
本子目录主要包括呼吸、麻醉和急救以及相关辅助器械。
本子目录根据呼吸、麻醉和急救器械产品功能特点,按照由主机到辅助器械的顺序分为"呼吸设备"、"麻醉器械"、"急救设备"等7个一级产品类别。根据预期用途分为55个二级产品类别并按管理类别由高到低的顺序排列。列举188个品名举例。
07 医用诊察和监护器械说明
08呼吸、麻醉和急救器械
本子目录包括医用诊察和监护器械及诊察和监护过程中配套使用的医疗器械,不包括眼科器械、口腔科器械等临床专科使用的诊察器械和医用成像器械。
本子目录分为10个一级产品类别。根据工作原理和应用类别将医用诊察设备分为"呼吸功能及气体分析测定装置"等10个一级产品类别。将多原理组合但预期用途成熟明确的医用诊察设备划分到"其他测量、分析设备"一级产品类别,将各类监护设备归入"监护设备"一级产品类别。将各附件耗材合并,归入"附件、耗材"一级产品类别。根据预期用途不同分为58个二级产品类别列举153个品名举例。
本子目录主要由2002版《6820普通诊察器械》《〈6821医用电子仪器设备〉部分》和本子目录2012版《〈6823医用超声仪器及有关设备〉部分》整合而来并根据近年来产品本子目录的发展新增了部分内容。相对2002/2012版整合了有创式电生理仪器及创新电生理仪器产品呼吸功能及气体分析测定装置等6个一级产品类别由2002/2012版的子目录整合形成同时根据注册产品情况和目录设计新增了"遥测和中央监护设备"、"其他测量、分析设备"这两个一级产品类别适应产业发展需要。
体表电极种类众多,但其预期用途类似,风险程度相近。因此在该子目录中,统一描述为"体表电极"。
本子目录按照物理治疗器械的原理或产品特性分为8个一级产品类别主要根据电疗、温热疗、光疗、力疗、磁疗、超声治疗、高频治疗等类别来划分。本子目录包括2012版分类目录中的《6823医用超声仪器及有关设备部分和2002版分类目录中的《6824医用激光仪器设备部分》《6825医用高频仪器设备部分》《6826物理治疗及康复设备物理治疗部分》以及《6821医用电子仪器设备》《6854手术室、急救室、诊疗室设备及器具》《6858医用冷疗、低温、冷藏设备及器具》3个子目录中的个别产品。不包括《6821医用电子仪器设备》《6823医用超声仪器及有关设备》《6824医用激光仪器设备》《6825医用高频仪器设备》《6854手术室、急救室、诊疗室设备及器具》《6858医用冷疗、低温、冷藏设备及器具》6个目录中的手术类产品。同时由于氧治疗设备、生物反馈治疗设备、肠道水疗机、药物导入设备等和上述的几类产品分类的技术依据、作用原理明显不同所以列入了"08-其他物理治疗设备"中。根据本次目录修订的专科优先的总体原则属于手术类的产品放入01有源手术器械属于妇产科类的产品放入18妇产科、辅助生殖和避孕器械中。在一级产品类别下依据其功能或用途的不同细分为37个二级目录并列举165个品名举例。
2002版分类目录中"电疗设备"名称改为"电疗设备/器具"。
肠道水疗机、灌肠机归入08"其他物理治疗设备"中,名称确定为"肠道水疗机"。
08"其他物理治疗设备"中的04 "病人浸浴装置"的二级产品类别名称确定为"烧烫伤浸浴装置"。
09物理治疗器械
10输血、透析和体外循环器械说明
本子目录包括临床用于输血、透析和心肺转流领域的医疗器械。
本子目录按照输血、透析、心肺转流和体液处理等产品应用领域和有源属性、无源属性分为7个一级产品类别按照产品具体用途分为41个二级产品类别并列举139个品名举例。
本子目录主要涉及与血液处理相关的器械包括2002版分类目录中《6845体外循环及血液处理设备》同时补充入原《〈6866医用高分子材料及制品〉与输血器械相关》。
(一)血液透析导管套件,通常由导管、导管导引器、注射帽、扩张器、推进器、引导针、导丝、导管鞘组成,临床上须由以上附件组合才能正常使用,鉴于其临床使用的特殊性,建议按套件注册,因此纳入该子目录中。
(二)碘液保护帽,管理类别由第三类降为第二类。
09物理治疗器械说明
本子目录包括采用电、热、光、力、磁、声以及不能归入以上范畴的其他物理治疗器械。不包括手术类的器械;不包括属于其他专科专用的物理治疗器械。
一级目录08"其他物理治疗设备"里面增加二级目录"药物导入设备"合并了2012版分类目录中03"超声治疗设备"中的二级目录04"非理疗超声治疗设备"中的"超声导入设备"及现有的 "(药物传递)离子导入治疗设备"。
(四)"排痰设备"归入04"力疗设备"中。
11医疗器械消毒灭菌器械
12有源植入器械说明
本子目录按照临床使用领域的不同分为4个一级产品类别分别是"心脏节律管理设备"、"神经调控设备"、"辅助位听觉设备"和"其他"。进一步根据不同临床用途、风险类别划分为27个二级产品类别列举76个品名举例。
2002版分类目录中未见单独的有源植入器械系统子目录所涉及的有源植入物器械较少仅包括《〈6821医用电子仪器设备〉植入式心脏起搏器》和《〈6846植入材料和人工器官〉人工耳蜗并结合梳理的注册产品信息增补近年来上市的新产品形成独立的子目录。
11医疗器械消毒灭菌器械说明
本子目录包括非接触人体的、用于医疗器械消毒灭菌的医疗器械,不包括以"无源医疗器械或部件+化学消毒剂"组合形式的专用消毒器械。
本子目录按照消毒和灭菌的原理、方式即根据消毒技术特点建立框架。按照消毒和灭菌的原理、方式分为5个一级产品类别按照产品特性分为15个二级产品类别并列举30个品名举例。
在本子目录的一级、二级产品类别中采用狭义的消毒和灭菌概念从而把消毒器和灭菌器区别开来。按照先消毒器、后灭菌器的顺序排序。该子目录中包括2002版分类目录中的《6857消毒和灭菌设备及器具》。
医用伽玛射线灭菌器不用于医疗环境,且无注册产品,不列入目录。
(二)足部隔离用品、隔离护罩:在医疗机构中使用,阻隔体液、血液飞溅或泼溅,管理类别由第二类降为第一类。
(三)注射器用活塞:为一次性使用无菌注射器的配套用组件,不具有医疗器械的功能和目的,不按照医疗器械管理。
(六)接触胸腔、腹腔、脑室、腰椎、体内创面或体表真皮深层及其以下组织创面的引流导管:管理类别由第三类降为第二类。
(七)造口袋(含造口底盘)、造口护理用品、造口底盘、造口栓、防漏膏、造口护肤粉、造口皮肤保护剂等造口护理产品:管理类别由第二类降为第一类。
(八)髂骨穿刺针:管理类别由第三类降为第二类。
(九)用于非慢性创面、接触真皮深层及其以下组织且所含成分不可被人体吸收的的医用敷料:管理类别由第三类降为第二类。
本子目录包括由植入体和配合使用的体外部分组成的有源植入器械。
本子目录与2002版分类目录的对应关系不大大部分领域为新增。本子目录框架包括2002版医疗器械分类目录中《6821医用电子仪器设备》和《6846植入材料和人工器官》的个别产品。
15患者承载器械说明
12有源植入器械
本子目录包括具有患者承载和转运等功能的器械,不包括具有承载功能的专科器械,例如口腔科、妇产科、骨科、医用康复器械中的承载器械。
13无源植入器械说明
本子目录包括2002版分类目录中的《〈6854手术室、急救室、诊疗室设备及器具〉部分》和《〈6856病房护理设备及器具〉部分》。
本子目录包括无源植入类医疗器械,不包括眼科器械、口腔科器械和妇产科、辅助生育和避孕器械中的无源植入器械,不包括可吸收缝合线。
本子目录主要根据植入部位和植入器械特点分为11个一级产品类别依据功能、用途或者结构特点进一步细化为66个二级产品类别并列举191个品名举例。
本子目录包括2002版分类目录的《〈6846植入材料和人工器官〉无源部分》和《〈6877介入器材〉部分整合后将无源植入器械产品分别按照植入部位和植入器械特点进行分类。此外针对组织工程类新兴医疗器械产品组织工程化同种异体皮肤、脱细胞异种神经修复材料、脱细胞异种神经修复材料等本次修订将其设置为独立的一级产品类别名为"组织工程支架材料"(其中不包含活细胞成分)。
13无源植入器械
16眼科器械说明
14注输、护理和防护器械说明
本子目录包括注射器械、穿刺器械、输液器械、止血器具、非血管内导(插)管与配套用体外器械、清洗、灌洗、吸引、给药器械、外科敷料(材料)、创面敷料、包扎敷料、造口器械、疤痕护理用品等以护理为主要目的器械(主要在医院普通病房内使用),还包括医护人员防护用品、手术室感染控制用品等控制病毒传播的医疗器械。
本子目录不包括输血器、血袋等输血器械归入10子目录和血样采集器械归入22子目录也不包括石膏绷带等骨科病房固定肢体的器械归入04子目录、妇产科护理如阴道护理用品归入18子目录等只在专科病房中使用的护理器械还不包括医用弹力袜等物理治疗器械归入09子目录和防压疮垫等患者承载器械归入15子目录
本子目录总体上主要依据用途即注射、输液、护理和防护功能特点并结合与血管是否接触、管理类别高低等因素设置16个一级产品类别。其中注输功能器械类设置了"注射、穿刺器械"、"血管内输液器械"、"非血管内输液器械"、"止血器具"、"非血管内导(插)管"、"与非血管内导管配套用体外器械"、"清洗、灌洗、吸引、给药器械"等7个一级产品类别护理功能器械类设置了"可吸收外科敷料(材料)"、"不可吸收外科敷料"、"创面敷料"、"包扎敷料"、"造口、疤痕护理用品"等5个一级产品类别防护功能器械类设置了"手术室感染控制用品"、"医护人员防护用品"等2个一级产品类别另外还设置了"病人护理防护用品"、"其他器械"2个一级产品类别。结合编制过程中对有效注册证的梳理情况依据相关器械的组成、用途的特点及差异对上述16个一级产品类别细化设置了110个二级产品类别列举了827个品名举例。
本子目录所包含器械主要对应2002版分类目录中的《6815注射穿刺器械》《6854手术室、急救室、诊疗室设备及器具》《6856病房护理设备及器具》《6864医用卫生材料及敷料》《6866医用高分子材料及制品》等子目录中的相关产品。
(一)一次性使用活检针:用于从人体组织获取标本进行活检,一次性使用,其管理类别由第三类降为第二类。
(四)输液瓶贴:用于封存开启后的静脉输瓶口,防止输液污染,不符合医疗器械定义,不按照医疗器械管理。
(五)输注工作站:仅提供空间和电源功能的,不具有报警等功能,不符合医疗器械定义,不按照医疗器械管理。
(十)含有酒精、碘酊或碘伏,且仅用于临床上对完整皮肤消毒的涂抹及吸液材料:按第二类医疗器械管理。
本子目录按照口腔科设备、口腔科器具和口腔科材料的预期用途分为10个一级产品类别按照产品组成成分和产品用途分为93个二级产品类别并列举585个品名举例。
(二)咬合关系记录/检查材料,通常由双组份糊剂或粉液剂或片,一般由硅橡胶、蜡或软质塑料等材料组成;所含成分不具有药理学作用,所含成分不可被人体吸收;仅用于牙面接触点及义齿修复体关系的检查如硅橡胶咬合检查材料,按第一类管理。
(四)银汞合金,管理类别由第三类降为第二类。
与有源器械如牙科手机连接使用的牙科锉、口腔车针、牙科钻等产品的分类原则用于切削、锉、钻操作的口腔车针、钻、锉仍按照第二类管理用于打磨、研磨、抛光操作的口腔抛光刷、研磨头、车针按第一类管理。按照此原则原2002版分类目录中有明确分类的洁牙工作尖和仅用于打磨、抛光的车针管理类别由第二类降为第一类。
(八)种植体密封材料,管理类别由第三类降为第二类。
(十)替代体,作为医疗器械管理,管理类别为一类。
(十二)洁牙粉,管理类别由第三类降为第二类。
(十四)临时冠桥树脂,管理类别由第三类降为第二类。
本子目录分为6个一级产品类别其中3个为床类承载器械1个为转运器械2个为固定和承载器械附件。在一级产品类别下根据有源、无源、电动和手动等原则分为17个二级产品类别列举101个品名举例。
(一)考虑到液压传送装置有一定风险和不良事件报告,含液压功能的承载器械按照第二类医疗器械管理,不含液压功能按照第一类医疗器械管理。
轮椅车、助行器、医用拐杖等设备归属于19医用康复器械。
18妇产科、辅助生殖和避孕器械说明
本子目录包括专用于妇产科、计划生育和辅助生殖的医疗器械。
本子目录按照妇产科、辅助生殖和避孕器械的临床特点分为"手术器械"等7个一级产品类别。按照临床预期用途细分为37个二级产品类别列举238个品名举例。
本子目录将妇产科手术器械、妇产科设备、计划生育手术器械、计划生育设备、辅助生殖器械、医用超声仪器及有关设备产品归类整合于本目录。对于既可以用于妇产科、妊娠控制和辅助生殖也可以用于其他科室的器械则不归入本子目录中。本子目录包括2002版分类目录中的《6812妇产科用手术器械》《6813计划生育手术器械》《〈6822医用光学器具、仪器及内窥镜设备〉妇产科部分》《〈6826物理治疗及康复设备〉妇产科部分》《〈6846植入材料和人工器官〉妇产科部分》《〈6854手术室、急救室、诊疗室设备及器具〉妇产科部分》、《〈6865医用缝合材料及粘合剂〉妇产科部分》《〈6866医用缝合材料及粘合剂〉妇产科部分》和2012版分类目录中的《〈6823医用超声仪器及有关设备〉妇产科部分》。
本子目录主要包括眼科诊察、手术、治疗、防护所使用的各类眼科器械及相关辅助器械不包括眼科康复训练类器械归入19子目录
本子目录按照眼科器械的功能不同或产品特性分为7个一级产品类别根据具体产品特性的不同细分为82个二级产品类别按照品名举例原则列举513个品名举例。按照眼科无源手术器械及辅助器械、眼科诊察设备及器具包括视光设备和眼科测量诊断设备、眼科治疗和手术设备及辅助器具、眼科矫治和防护器具、眼科植入物及辅助器械的顺序形成基本框架。
眼科用激光光纤。根据《国家食品药品监督管理局关于吸入笑气镇痛装置等76个产品医疗器械分类界定的通知》国食药监械2012271号明确"眼内照明光纤探头"分类界定为三类。从光辐射角度上说,激光比其他非激光的危害更大,本子目录将进入眼内进行治疗的眼科用激光光纤的管理类别规范为第三类。
(二)试镜架通常由鼻托支架、左右镜框、左右耳挂组成,用于视力检查时安装验光镜片。试镜架不符合医疗器械定义,不作为医疗器械管理。
本子目录包括医用康复器械类医疗器械,主要有认知言语视听障碍康复设备、运动康复训练器械、助行器械、矫形固定器械,不包括骨科用器械。
16眼科器械
肢体矫形器:依据《医疗器械分类规则》和分类界定文件,本子目录对具有矫形功能产品的管理类别规范为第二类,仅具有固定支撑功能产品的管理类别规范为第一类。
20中医器械说明
17 口腔科器械说明
本子目录包括口腔科用设备、器具、口腔科材料等医疗器械。不包括口腔科治疗用激光、内窥镜、显微镜、射线类医疗器械。
本子目录包括2002版分类目录中的《6806口腔科手术器械》《6855口腔科设备及器具》和《6863口腔科材料》2012版分类目录中的《〈6823医用超声仪器及有关设备〉超声治疗设备中的超声洁牙设备》及2014年发布的《第一类医疗器械产品目录》。
(一)脱敏剂类产品,管理类别由第三类降为第二类。
(三)义齿试用材料,如试色糊剂产品,管理类别规范为第一类。
(五)金属、陶瓷材料制成的固位桩,管理类别规范为第二类。
(七)正畸弹簧,管理类别由第二类降为第一类。
(九)牙周塞治剂,管理类别由第三类降为第二类。
(十一)研磨材料,用于口内按第二类管理,用于口外按第一类管理。
(十三)根管扩大液、根管清洗剂,管理类别由第三类降为第二类。
(十五)牙托梗,管理类别由第二类降为第一类。
医学影像处理软件用于对来源于单模式或多模式的医学影像进行处理。如果影像处理软件没有辅助诊断功能因此统一将2002版分类目录的"6870-2诊断图象处理软件"中的X射线影像处理系统、核医学成像、医用磁共振成像系统等管理类别降为第二类。
2002版分类目录中的"6870-5人体解剖学测量软件"。现有效注册证信息中无此类产品,且其预期用途不完全符合医疗器械定义,因此,未将此产品纳入本子目录。
十一如果IVD软件中包含计算机辅助诊断功能应归入决策支持软件。
17口腔科器械
22临床检验器械说明
本子目录包括2002版分类目录中《6840临床检验分析仪器》和《6841医用化验和基础设备器具》还包括《〈6822医用光学器具〉生物显微镜》《〈6833医用核素设备〉核素标本测定装置》《〈6815注射穿刺器械〉动静脉采血针》和《〈6858医用冷疗、低温、冷藏设备及器具〉医用低温设备、医用冷藏设备、医用冷冻设备》。
根据学科发展和产品现状,本子目录的二级产品类别中新增了如下内容:基因测序仪、质谱仪、生物安全柜和洁净工作台。
(一)免疫分析设备中"全自动免疫分析仪",包括"全自动酶联免疫分析仪"、"全自动化学发光免疫分析仪"、"全自动荧光免疫分析仪"管理类别由第三类降为第二类。
(一)含消毒剂(抗菌剂)阴道填塞产品,不按照医疗器械管理。
一、修订背景
2014年发布实施的《条例》对医疗器械分类工作提出更高要求为解决2002版目录与产业发展和监管要求不适应的问题在全面归纳分析历年发布医疗器械分类界定文件、梳理有效医疗器械注册产品信息并对国外同类医疗器械产品管理情况进行研究的基础上为进一步落实《国务院关于改革药品医疗器械审评审批制度的意见》国发201544号推进医疗器械分类管理改革的要求总局根据医疗器械分类管理改革工作部署决定于2015年7月启动《医疗器械分类目录》修订工作优化、调整医疗器械分类目录框架、结构和内容。
按照《医疗器械分类管理改革工作方案》部署总局成立了推进医疗器械分类管理改革联合工作组统筹《医疗器械分类目录》修订有关工作。总局印发《医疗器械分类目录修订工作方案》根据职责分工总局器械注册司负责总体规划和工作协调总局医疗器械标准管理中心以下简称标管中心牵头会同总局医疗器械技术审评中心组织各有关省局、全国24个医疗器械标准化技术委员会及承担《医疗器械分类目录》修订任务的11个医疗器械检验单位具体负责修订技术工作。
2016年9月总局对《医疗器械分类目录征求意见稿》面向社会公开征求意见并致函工业和信息化部、民政部、卫生计生委等相关部委中国生物医学工程学会、中国生物材料学会、中国医疗器械行业协会等学术团体和协会组织征求意见同期总局组织召开面向监管、审评、检验卫生、科研、工程专家以及代表性企业的面对面征求意见会议。与此同时总局同步开展了《医疗器械分类目录征求意见稿》的WTO/TBT通报。根据各方反馈的意见经认真研究讨论后进一步对目录进行修改完善形成了《医疗器械分类目录送审稿》。经总局医疗器械分类技术委员会专业组会议审议进一步修改完善形成《医疗器械分类目录报批稿以下简称新《分类目录》
三、主要修订内容
19 医用康复器械说明
(一)总体情况
本子目录包含2002版分类目录的《〈6826物理治疗及康复设备〉部分》和《〈6846植入材料和人工器官〉助听器、外挂式人工喉》。
7.《22临床检验器械》子目录放置在最后为后续体外诊断试剂修订预留空间。
(三)目录内容
19医用康复器械
表1 新《分类目录》结构
本子目录包括基于中医医理的医疗器械,不包括中医独立软件。
本子目录按照临床用途的不同分为中医诊断设备、中医治疗设备和中医器具3个一级产品类别根据产品原理的不同形成24个二级产品类别并列举60个品名举例。本子目录包括2002版分类目录的《6827中医器械》。
20中医器械
21医用软件说明
本子目录包括医用独立软件医疗器械。
本子目录仅列出了独立软件,不包含软件组件。医用软件按照预期用途分为辅助诊断类和治疗类,按照处理对象,可以分为"影像"、"数据"、"影像和数据"三种情况。本子目录分为6个一级产品类别13个二级产品类别列举51个品名举例。
(一)目前现有注册产品名称使用"图像"或"影像"进行命名。影像既包含图像,又包含视频等内容,由于"影像处理"比"图像处理"包含的范围大,考虑到未来产品发展,本子目录将所有"图像"和"影像"表述统一成"影像"。
(二)由于翻译和中文用语等习惯问题,有些产品名称包含"**system系统"使得判定产品是否为独立软件产生歧义。由于《21医用软件》的特殊性若存在行业特殊用语TPS、PACS等行业内达成共识的产品名称则保留"**系统软件"的命名方法,否则删除产品名称中的"系统"字样。
诊断功能软件风险程度按照其采用算法的风险程度、成熟程度、公开程度等为判定依据不仅仅依据处理对象癌症、恶性肿瘤等疾病的影像为判定依据。若诊断软件通过其算法提供诊断建议仅具有辅助诊断功能不直接给出诊断结论本子目录中相关产品按照第二类医疗器械管理。若诊断软件通过其算法例如CAD骨密度除外对病变部位进行自动识别并提供明确的诊断提示则其风险级别相对较高本子目录中相关产品按照第三类医疗器械管理。
(四)导航软件与导航设备关系密切,没有导航设备的参与,导航软件无法实现预期用途。目前注册产品"手术导航软件"中多数包含硬件。本子目录修订过程中确定原则手术导航包含硬件的产品规范到01有源手术器械。无硬件参与的"手术计划软件"可以作为医用软件纳入本子目录。同时对品名举例进行规范,删除"导航"字样,以避免混淆。
(五)医疗信息管理软件属性界定原则,如果医疗信息管理软件仅仅是医院管理工具,管理内容是患者信息等非医疗诊断和/或治疗内容,不按照医疗器械管理。如果医疗信息管理软件包含患者诊断、治疗数据和影像,则按照软件处理对象(影像、数据)的不同,将软件产品规范到"21-2影像处理软件"或者"21-3数据处理软件"。
(六)远程医疗会诊系统软件用于在不同医疗机构之间实现医学信息传输和会诊平台功能。本子目录将包含影像或者数据传输的远程医疗软件规范到"21-02-01医学影像存储与传输系统软件"或者"21-03-02医学影像处理软件"中,如果不包含医学图像或者数据,则不按照医疗器械管理。
(七)移动医疗软件运行平台不同,其他的影像处理功能,数据处理功能等与运行在通用平台上的软件风险程度相当。本子目录不体现"移动医疗软件",依据软件处理对象(影像、数据)的不同,将软件产品规范到"21-2影像处理软件"或者"21-3数据处理软件"。
(八)由于图像处理软件为约定俗成的名称,因此"21-02 图像处理软件"二级产品类别名称不采用"图像后处理软件"。由于CT等设备上自带的处理软件不作为独立软件进行规范不存在混淆的风险。
21 医用软件
本子目录包括用于临床检验实验室的设备、仪器、辅助设备和器具及医用低温存贮设备,不包括体外诊断试剂。
本子目录主要以检验学科和设备性能为依据分为16个一级产品类别其中临床检验分析设备10个采样设备1个样本处理设备3个检验及其他辅助设备和医用生物防护设备各1个。按照学科内仪器类别细分为86个二级产品类别列出411个品名举例。本子目录按照临床检验用分析设备、采样设备、样本处理设备、检验及其他辅助设备和医用生物防护设备的顺序排列。
(二)微生物鉴定药敏分析仪器、微生物药敏培养监测仪器用于临床培养血液和体液等标本中需氧菌、厌氧菌、真菌和分枝杆菌等,同时用于细菌、真菌和分枝杆菌的药敏检测,管理类别由第三类降为第二类。
(三)洗板机,管理类别由第二类降为第一类。
(四)与临床检验有关,但产品自身不具有医疗器械功能的产品,不按照医疗器械管理,如:移液器、移液管,普通反应杯、反应管、反应板,普通采样杯、采样管、样本收集器,在临床实验室用于检测前/后样本传输、加/去盖、条形码识别等功能的样本管理系统等。
(五)全自动血库系统,规范为第三类管理。
《医疗器械分类目录》编制说明
2002年原国家食品药品监督管理局发布实施《医疗器械分类目录》国药监械2002302号以下简称2002版目录对医疗器械监管和行业发展起到了积极的推动作用。医疗器械行业经过10余年的高速发展产品种类增长迅速技术复杂的产品不断涌现2002版分类目录已经不能适应形势发展的要求主要体现在以下几个方面一是2002版目录仅提供产品类别和品名举例信息缺乏产品描述和预期用途等界定产品的关键信息容易导致分类管理工作中理解不一致影响注册审批的统一性和规范性二是技术发展新形势下2002版目录的整体设计和层级设置显现出一定的不合理性产品归类存在交叉。三是2002版目录已不能完全覆盖近年出现的新产品虽然多次以分类界定文件的形式明确有关产品的管理类别部分弥补2002版目录的不足但因缺乏整体性和系统性仍不能满足需要。为解决以上问题原国家药品监督管理局自2009年开始组织开展了2002版目录修订工作于2012年8月28日发布修订完成的《6823 医用超声仪器及有关设备》等4个子目录并开展了其他子目录修订的研究工作。
二、修订过程
借鉴国际医疗器械分类管理思路研究分析欧盟、美国、日本等国家和地区的分类管理模式、分类管理文件在对2002版目录、2012年发布6823等4个子目录、第一类医疗器械产品目录等分类界定文件及已获准注册的医疗器械产品注册信息梳理的基础上经归纳总结并多次易稿于2016年8月形成了《医疗器械分类目录征求意见稿》。
新《分类目录》符合《医疗器械分类规则》国家食品药品监督管理总局令第15号以下简称《分类规则》目录不包括《6840体外诊断试剂分类子目录2013版》内容和组合包类产品。主要修订内容如下
新《分类目录》将2002版目录的43个子目录整合精简为22个子目录将260个产品类别细化扩充为206个一级产品类别和1157个二级产品类别增加了产品预期用途和产品描述在原1008个产品名称举例的基础上扩充到6609个典型产品名称举例。
(二)子目录设置
因2002版目录从多角度划分子目录子目录的数量较多容易因缺乏统一的划分原则而造成目录之间交叉。新《分类目录》主要以技术领域为主线更侧重从医疗器械的功能和临床使用的角度划分产品归属经总局分类技术委员会审议通过子目录数量由43个减少为22个。相比2002版目录目录修订稿框架设置更合理、层级结构更清晰。
新版目录修订稿中22个子目录设置情况如下
1.手术类器械设置4个子目录分别是通用手术器械分设《01有源手术器械》和《02无源手术器械》因分类规则中对接触神经和血管的器械有特殊要求单独设置《03神经和血管手术器械》骨科手术相关器械量大面广产品种类繁杂单独设置《04骨科手术器械》。
2.有源器械为主的器械设置8个子目录分别是《05放射治疗器械》《06医用成像器械》《07医用诊察和监护器械》《08呼吸、麻醉和急救器械》《09物理治疗器械》《10输血、透析和体外循环器械》《11医疗器械消毒灭菌器械》《12有源植入器械》。
3.无源器械为主的器械设置3个子目录分别是《13无源植入器械》《14注输、护理和防护器械》《15患者承载器械》。
4.按照临床科室划分3个子目录分别是《16眼科器械》《17口腔科器械》《18妇产科、生殖和避孕器械》。
5.《19医用康复器械》和《20中医器械》是根据《医疗器械监督管理条例》中对医用康复器械和中医器械两大类产品特殊管理规定而单独设置的子目录。
6.《21医用软件》是收录医用独立软件产品的子目录。
1.新《分类目录》与2002版目录相比较内容上更为丰富和完善产品覆盖更全面目录的科学性和指导性明显提升。
参考2012年发布4个子目录内容设置新《分类目录》修订稿中设置子目录、类别序号、一级产品类别、二级产品类别、产品描述、预期用途、品名举例、管理类别8项内容见表1。2002版目录为5项内容分别是子目录、类别序号、产品类别、品名举例、管理类别见表2。
表2 2002版目录结构
2.目录中增加的"产品描述"和"预期用途",是对一类产品共性内容的基本描述,用于指导具体产品所属类别的综合判定;列举的品名举例为符合《医疗器械通用名称命名规则》的规范性、代表性名称。
3.本次目录修订过程中,根据医疗器械生产、经营、使用情况的收集,对医疗器械风险变化的评估,经总局医疗器械分类技术委员会专业组审核,降低了上市时间长、产品成熟度高的部分医疗器械产品的管理类别,对于既往不规范审批的产品管理类别进行了统一。
四、其他问题说明
(一)医疗器械产品归类的优先原则
鉴于医疗器械产品的复杂性,对技术交叉或学科交叉的产品,按以下优先顺序确定归属:第一,按照临床专科优先顺序;第二,多功能产品依次按照主要功能、高风险功能、新功能优先顺序;第三,按照医疗器械管理的附件类产品,优先归属整机所在子目录或者产品类别。
(二)药械组合产品的标示
2009年11月12日原国家食品药品监督管理局发布《关于药械组合产品注册有关事宜的通告》2009年第16号以下简称16号公告规定以医疗器械作用为主的药械组合产品需申报医疗器械注册申请人根据产品属性审定意见向国家食品药品监督管理局申报药品或医疗器械注册申请并在申请表中注明"药械组合产品"。为和16号公告中的保持一致在新目录中按照医疗器械管理的药械组合产品除列出管理类别外另标注了"药械组合产品"。

View File

@ -0,0 +1,27 @@
【文档信息】
作者: Lenovo
创建时间: 2025-05-15 08:30:10
修改时间: 2025-05-15 08:30:25
1111
【图片识别文本】
" 完 善 了 异 常 处 理 , 防 止 惑 时 目 录 券 除 失 败 导 致 程 序 崖
4. 更 新 README.md
* 在 暨 近 更 新 部 分 记 录 了 临 时 文 件 处 理 机 制 的 改 进
。 添 加 了 Excel 文 件 句 柄 管 理
使 用 说 明
这 东 改 进 不 需 要 您 做 任 何 额 外 操 作 , 系 统 会 自 动 -
1. 在 处 理 Excel 文 件 时 正 球 关 闭 文 件 句 柄
2 当 尝 试 删 除 文 件 通 刨 " 文 件 被 占 用 " 错 误 时 , 自 动 等 待
并 重 试
3 即 使 无 法 券 除 临 时 文 件 , 也 不 影 响 处 #
如 果 仍 然 通 到 惧 时 文 件 问 题 , 系 统 会 在 下 次 启 动 时 自 动
清 理 所 有 临 时 文 件 , 不 会 影 响 系 统 功 能 。
以 上 优 化 星 觞 失 了 临 时 文 伟 删 除 问 题 , 又 保 持 了 系 统 的
稳 定 性 , 让 您 能 雪 顺 畅 地 处 理 Bxcel 文 件 。

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View File

@ -1,6 +1,6 @@
fastapi>=0.68.0 fastapi>=0.100.0
python-multipart>=0.0.5 python-multipart>=0.0.6
uvicorn>=0.15.0 uvicorn>=0.23.0
python-docx>=0.8.11 python-docx>=0.8.11
numpy>=1.24.0 numpy>=1.24.0
scikit-learn>=1.0.2 scikit-learn>=1.0.2
@ -18,4 +18,3 @@ pandas>=2.0.0
aiofiles>=23.1.0 aiofiles>=23.1.0
openpyxl>=3.1.2 openpyxl>=3.1.2
uuid>=1.30 uuid>=1.30
pydantic>=1.8.2

View File

@ -5,198 +5,22 @@ import re
import json import json
import argparse import argparse
def count_chinese_tokens(text):
"""
估算中文文本的token数量
1个汉字约等于1.5个token
1个英文单词约等于1个token
1个标点符号约等于1个token
"""
# 匹配中文字符
chinese_chars = len(re.findall(r'[\u4e00-\u9fff]', text))
# 匹配英文单词
english_words = len(re.findall(r'[a-zA-Z]+', text))
# 匹配标点符号
punctuations = len(re.findall(r'[^\w\s]', text))
# 计算总token数粗略估算
total_tokens = chinese_chars * 1.5 + english_words + punctuations
return int(total_tokens)
def process_table_content(table_content):
"""
处理表格内容移除表格标记并进行智能分段
处理策略
1. 清理无效内容
2. 智能分段
3. 保持语义完整性
4. 控制token长度
"""
# 移除表格标记和多余空白
content = re.sub(r'表格\s*\d+\s*(?:开始|结束)', '', table_content)
content = re.sub(r'\s+', ' ', content).strip()
# 分段处理
paragraphs = []
current_para = []
# 按句子分割
sentences = re.split(r'([。!?\n])', content)
for i in range(0, len(sentences), 2):
sentence = sentences[i].strip()
if not sentence:
continue
# 添加标点符号(如果存在)
if i + 1 < len(sentences):
sentence += sentences[i + 1]
# 检查是否是新段落的开始
if (re.match(r'^[的]', sentence) or # 以"的"开头
re.match(r'^[在]', sentence) or # 以"在"开头
re.match(r'^[\w()]+[:]', sentence)): # 以键值对形式开头
# 保存当前段落
if current_para:
full_para = ''.join(current_para).strip()
if full_para:
# 控制token长度
if count_chinese_tokens(full_para) > 512:
split_paras = split_long_paragraph(full_para)
paragraphs.extend(split_paras)
else:
paragraphs.append(full_para)
current_para = []
current_para.append(sentence)
# 处理最后一个段落
if current_para:
full_para = ''.join(current_para).strip()
if full_para:
if count_chinese_tokens(full_para) > 512:
split_paras = split_long_paragraph(full_para)
paragraphs.extend(split_paras)
else:
paragraphs.append(full_para)
return paragraphs
def split_long_paragraph(paragraph):
"""智能分割长段落,保持语义完整性"""
result = []
# 首先尝试按逗号分割
parts = re.split(r'([,。!?])', paragraph)
current_part = ""
current_tokens = 0
for i in range(0, len(parts), 2):
part = parts[i].strip()
if not part:
continue
# 添加标点符号(如果存在)
if i + 1 < len(parts):
part += parts[i + 1]
part_tokens = count_chinese_tokens(part)
if current_tokens + part_tokens > 512:
if current_part:
result.append(current_part)
current_part = part
current_tokens = part_tokens
else:
current_part += part
current_tokens += part_tokens
if current_part:
result.append(current_part)
return result
def format_group_to_text(group):
"""将分组数据格式化为易读的文本,采用通用的处理方式"""
if not group:
return ""
parts = []
# 通用处理:遍历所有键值对,构建文本
for key, value in group.items():
# 跳过空值
if not value:
continue
# 清理和格式化键名
clean_key = re.sub(r'[_\(\)]', ' ', key).strip()
# 清理值中的"表格无有效数据"字眼
if isinstance(value, str):
value = re.sub(r'[【\[]*表格无[有效]*数据[】\]]*', '', value)
if not value.strip(): # 如果清理后为空,则跳过
continue
# 构建文本片段
text = f"{clean_key}{value}"
parts.append(text)
# 使用逗号连接所有部分,并确保结果中没有"表格无有效数据"字眼
result = "".join(parts)
result = re.sub(r'[【\[]*表格无[有效]*数据[】\]]*', '', result)
return result.strip("") + "" if result.strip("") else ""
def split_long_text(text):
"""将长文本按token限制分割"""
if count_chinese_tokens(text) <= 512:
return [text]
result = []
parts = re.split(r'([。])', text)
current_part = ""
current_tokens = 0
for i in range(0, len(parts), 2):
sentence = parts[i]
if i + 1 < len(parts):
sentence += parts[i + 1] # 添加句号
sentence_tokens = count_chinese_tokens(sentence)
if current_tokens + sentence_tokens > 512:
if current_part:
result.append(current_part)
current_part = sentence
current_tokens = sentence_tokens
else:
current_part += sentence
current_tokens += sentence_tokens
if current_part:
result.append(current_part)
return result
def split_text_into_paragraphs(text): def split_text_into_paragraphs(text):
""" """
将连续文本智能分段 将连续文本智能分段
策略: 策略:
1. 基于标题和章节标记进行主要分段 1. 识别表格标记将表格内容作为独立段落处理
2. 基于段落语义标记进行次要分段 2. 对普通文本按照语义和长度适当分段约500字/
3. 基于句子关联度进行内容分段 3. 确保分段不破坏语义完整性
4. 基于token长度进行辅助分段确保每段不超过512个token
5. 保持段落的语义完整性
6. 智能处理表格内容
""" """
# 清理文本中可能存在的多余空格和换行 # 清理文本中可能存在的多余空格
text = re.sub(r'\s+', ' ', text).strip() text = re.sub(r'\s+', ' ', text).strip()
# 首先处理表格内容 # 识别表格范围,表格以"表格 N 开始"和"表格 N 结束"标记
table_pattern = re.compile(r'(表格\s*\d+\s*开始.*?表格\s*\d+\s*结束)', re.DOTALL) table_pattern = re.compile(r'表格\s*\d+\s*开始(.*?)表格\s*\d+\s*结束', re.DOTALL)
# 使用表格标记分割文本
parts = [] parts = []
last_end = 0 last_end = 0
@ -205,14 +29,9 @@ def split_text_into_paragraphs(text):
if match.start() > last_end: if match.start() > last_end:
parts.append(("text", text[last_end:match.start()])) parts.append(("text", text[last_end:match.start()]))
# 处理表格内容 # 获取表格内容(去掉表格标记)
table_content = match.group(1) table_content = match.group(1).strip()
table_paragraphs = process_table_content(table_content) parts.append(("table", table_content))
for para in table_paragraphs:
# 确保表格段落没有冒号开头
para = re.sub(r'^[:]+\s*', '', para.strip())
if para: # 只添加非空段落
parts.append(("table", para))
last_end = match.end() last_end = match.end()
@ -220,132 +39,112 @@ def split_text_into_paragraphs(text):
if last_end < len(text): if last_end < len(text):
parts.append(("text", text[last_end:])) parts.append(("text", text[last_end:]))
# 如果没有找到表格,将整个文本作为一个文本部分 # 如果没有找到表格,则整个文本作为一个文本片段
if not parts: if not parts:
parts = [("text", text)] parts = [("text", text)]
# 主要分段标记(标题、章节等) # 对文本段落进行处理
major_markers = [ final_paragraphs = []
r'^第[一二三四五六七八九十百千]+[章节篇]', # 中文数字章节
r'^第\d+[章节篇]', # 阿拉伯数字章节
r'^[一二三四五六七八九十][、.]', # 中文数字序号
r'^\d+[、.]', # 阿拉伯数字序号
r'^[(][一二三四五六七八九十][)]', # 带括号的中文数字
r'^[(]\d+[)]', # 带括号的阿拉伯数字
r'^[IVX]+[、.]', # 罗马数字序号
]
# 次要分段标记(语义转折等) # 可能表示段落边界或重要语义分割点的标记
minor_markers = [ paragraph_markers = [
r'然而[,]', r'^第.{1,3}章',
r'但是[,]', r'^第.{1,3}节',
r'不过[,]', r'^[一二三四五六七八九十][、.\s]',
r'相反[,]', r'^\d+[、.\s]',
r'因此[,]', r'^[IVX]+[、.\s]',
r'所以[,]', r'^附录',
r'总的来说', r'^前言',
r'综上所述', r'^目录',
r'总而言之',
r'例如[,]',
r'比如[,]',
r'首先[,]',
r'其次[,]',
r'最后[,]',
r'另外[,]',
]
# 特殊段落标记
special_markers = [
r'^摘要', r'^摘要',
r'^引言', r'^引言',
r'^前言',
r'^结论', r'^结论',
r'^致谢', r'^参考文献'
r'^参考文献',
r'^注释',
r'^附录',
] ]
marker_pattern = re.compile('|'.join(paragraph_markers))
# 合并所有标记模式
all_markers = major_markers + special_markers
marker_pattern = '|'.join(all_markers)
minor_marker_pattern = '|'.join(minor_markers)
# 按句子分割的分隔符 # 按句子分割的分隔符
sentence_separators = r'([。!?\!\?])' sentence_separators = r'([。!?\!\?])'
# 分段处理 # 目标段落长度(字符数)
paragraphs = [] target_length = 500
# 最小段落长度阈值
min_length = 100
# 最大段落长度阈值
max_length = 800
for part_type, content in parts: for part_type, content in parts:
# 如果是表格内容,直接添加为独立段落
if part_type == "table": if part_type == "table":
# 表格内容已经过处理,直接添加 final_paragraphs.append(content)
paragraphs.append(content)
continue continue
# 处理普通文本 # 处理普通文本
# 按句子分割文本
sentences = re.split(sentence_separators, content)
# 将分割后的句子和标点符号重新组合
sentence_list = []
for i in range(0, len(sentences)-1, 2):
if i+1 < len(sentences):
sentence_list.append(sentences[i] + sentences[i+1])
else:
sentence_list.append(sentences[i])
# 如果最后一个元素不是句子结束符,添加它
if len(sentences) % 2 == 1:
if sentences[-1]:
sentence_list.append(sentences[-1])
# 构建段落
current_para = "" current_para = ""
current_tokens = 0 for sentence in sentence_list:
# 检查是否是段落标记的开始
is_marker = marker_pattern.search(sentence)
# 按主要标记分段 # 如果当前段落已经足够长,或者遇到段落标记,则开始新段落
text_parts = re.split(f'({marker_pattern})', content) if ((len(current_para) >= target_length and len(current_para) + len(sentence) > max_length) or
for i, part in enumerate(text_parts): (is_marker and current_para)):
if not part.strip(): # 跳过空部分 if current_para.strip():
continue final_paragraphs.append(current_para.strip())
# 去除冒号开头
part = re.sub(r'^[:]+\s*', '', part.strip())
if not part: # 跳过清理后为空的部分
continue
if i % 2 == 1: # 是标记
if current_para:
paragraphs.append(current_para)
current_para = part
current_tokens = count_chinese_tokens(part)
else: # 是内容
sentences = re.split(sentence_separators, part)
for j, sentence in enumerate(sentences):
if not sentence.strip():
continue
# 去除句子开头的冒号
sentence = re.sub(r'^[:]+\s*', '', sentence.strip())
if not sentence:
continue
sentence_tokens = count_chinese_tokens(sentence)
# 检查是否有次要分段标记
has_minor_marker = bool(re.search(minor_marker_pattern, sentence))
if has_minor_marker and current_para:
paragraphs.append(current_para)
current_para = sentence current_para = sentence
current_tokens = sentence_tokens
elif current_tokens + sentence_tokens > 512:
if current_para:
paragraphs.append(current_para)
current_para = sentence
current_tokens = sentence_tokens
else: else:
if current_para:
current_para += sentence current_para += sentence
# 添加最后一个段落
if current_para.strip():
final_paragraphs.append(current_para.strip())
# 对段落进行后处理,合并过短的段落
processed_paragraphs = []
temp_para = ""
for para in final_paragraphs:
if len(para) < min_length:
# 如果段落太短,尝试与临时段落合并
if temp_para:
temp_para += " " + para
else: else:
current_para = sentence temp_para = para
current_tokens += sentence_tokens else:
# 如果有临时段落,先处理它
if temp_para:
# 如果临时段落也很短,合并到当前段落
if len(temp_para) < min_length:
para = temp_para + " " + para
else:
processed_paragraphs.append(temp_para)
temp_para = ""
if current_para: processed_paragraphs.append(para)
paragraphs.append(current_para)
# 最后一次清理所有段落,确保没有冒号开头 # 处理最后可能剩余的临时段落
cleaned_paragraphs = [] if temp_para:
for para in paragraphs: if processed_paragraphs and len(temp_para) < min_length:
para = re.sub(r'^[:]+\s*', '', para.strip()) processed_paragraphs[-1] += " " + temp_para
if para: # 只添加非空段落 else:
cleaned_paragraphs.append(para) processed_paragraphs.append(temp_para)
return cleaned_paragraphs return processed_paragraphs
def save_to_json(paragraphs, output_file): def save_to_json(paragraphs, output_file):
"""将段落保存为JSON格式""" """将段落保存为JSON格式"""
@ -359,19 +158,10 @@ def save_to_json(paragraphs, output_file):
print(f"成功将文本分成 {len(paragraphs)} 个段落并保存到 {output_file}") print(f"成功将文本分成 {len(paragraphs)} 个段落并保存到 {output_file}")
def save_to_txt(paragraphs, output_file):
"""将段落保存为TXT格式每段用换行符分隔"""
with open(output_file, 'w', encoding='utf-8') as f:
for paragraph in paragraphs:
f.write(paragraph + '\n\n') # 使用两个换行符使段落分隔更清晰
print(f"成功将文本分成 {len(paragraphs)} 个段落并保存到 {output_file}")
def main(): def main():
parser = argparse.ArgumentParser(description="将连续文本智能分段并保存为TXT或JSON") parser = argparse.ArgumentParser(description="将连续文本智能分段并保存为JSON")
parser.add_argument("input_file", help="输入文件路径例如sample_continuous_text.txt") parser.add_argument("input_file", help="输入文本文件路径")
parser.add_argument("--output", "-o", default="paragraphs.txt", help="输出文件路径,默认为当前目录下的 paragraphs.txt") parser.add_argument("--output", "-o", default="paragraphs.json", help="输出JSON文件路径")
parser.add_argument("--format", "-f", choices=['txt', 'json'], default='txt', help="输出文件格式支持txt和json默认为txt")
args = parser.parse_args() args = parser.parse_args()
@ -386,11 +176,8 @@ def main():
# 分段 # 分段
paragraphs = split_text_into_paragraphs(text) paragraphs = split_text_into_paragraphs(text)
# 根据指定格式保存 # 保存为JSON
if args.format == 'json':
save_to_json(paragraphs, args.output) save_to_json(paragraphs, args.output)
else:
save_to_txt(paragraphs, args.output)
if __name__ == "__main__": if __name__ == "__main__":
main() main()