sdpy-kit 0.4.4__tar.gz → 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/PKG-INFO +58 -18
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/README.md +52 -15
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/__init__.py +1 -1
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/config/kit_config.py +1 -1
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/docs/__init__.py +2 -1
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/docs/anydoc_kit.py +30 -22
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/docs/docx_kit.py +22 -23
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/docs/marker_kit.py +74 -51
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/docs/md2doc_kit.py +19 -14
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/docs/mineru_kit.py +21 -29
- sdpy_kit-0.5.0/kit/docs/rc_docparser_kit.py +546 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/pyproject.toml +7 -3
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/.gitignore +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/ai/__init__.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/ai/base_service.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/ai/chat_service.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/ai/embedding_service.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/ai/exceptions.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/ai/failover.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/ai/image_service.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/ai/model_builder.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/ai/model_client.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/ai/pool.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/ai/profiles.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/ai/rerank_service.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/ai/runner.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/ai/types.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/common_kit.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/config/__init__.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/config/log_config.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/crawl/__init__.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/crawl/article_models.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/crawl/web_article_kit.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/crawl/wx_article_kit.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/db/__init__.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/db/base_db_kit.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/db/crud.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/db/engine.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/db/exceptions.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/db/models/__init__.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/db/models/base.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/db/mysql_kit.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/db/pg_kit.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/db/query.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/db/session.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/db/sqlite_kit.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/db/transaction.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/file_kit.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/laya_kit.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/license_kit.py +0 -0
- {sdpy_kit-0.4.4 → sdpy_kit-0.5.0}/kit/redis_kit.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: sdpy-kit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: SDPY Kit——统一数据库访问层(PG/MySQL/SQLite)与 AI/Redis/文件/文档/向量工具集
|
|
5
5
|
Author-email: Clark <changhongyuan@126.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -32,13 +32,14 @@ Requires-Dist: httpx>=0.28.1; extra == 'all'
|
|
|
32
32
|
Requires-Dist: huggingface-hub<2,>=1.5; extra == 'all'
|
|
33
33
|
Requires-Dist: laya>=0.4.6; extra == 'all'
|
|
34
34
|
Requires-Dist: markdown-it-py>=4.2.0; extra == 'all'
|
|
35
|
-
Requires-Dist: marker-pdf
|
|
35
|
+
Requires-Dist: marker-pdf>=2.0.0; extra == 'all'
|
|
36
36
|
Requires-Dist: numpy>=2.5.4; extra == 'all'
|
|
37
37
|
Requires-Dist: pikepdf>=10.17.0; extra == 'all'
|
|
38
38
|
Requires-Dist: pimd[pdfa]>=2.2.5; extra == 'all'
|
|
39
39
|
Requires-Dist: psycopg2-binary>=2.9.13; extra == 'all'
|
|
40
40
|
Requires-Dist: pymysql>=1.2.3; extra == 'all'
|
|
41
41
|
Requires-Dist: python-dotenv>=1.2.4; extra == 'all'
|
|
42
|
+
Requires-Dist: rc-docparser>=0.2.2; extra == 'all'
|
|
42
43
|
Requires-Dist: redis>=8.1.0; extra == 'all'
|
|
43
44
|
Requires-Dist: requests>=2.34.2; extra == 'all'
|
|
44
45
|
Requires-Dist: sqliteai-vector>=1.1.2; extra == 'all'
|
|
@@ -48,11 +49,13 @@ Requires-Dist: firecrawl-anydoc>=0.2.4; extra == 'anydoc'
|
|
|
48
49
|
Requires-Dist: pikepdf>=10.17.0; extra == 'anydoc'
|
|
49
50
|
Provides-Extra: docx
|
|
50
51
|
Requires-Dist: docxtpl>=0.20.2; extra == 'docx'
|
|
52
|
+
Provides-Extra: docx-parse
|
|
53
|
+
Requires-Dist: rc-docparser>=0.2.2; extra == 'docx-parse'
|
|
51
54
|
Provides-Extra: laya
|
|
52
55
|
Requires-Dist: huggingface-hub<2,>=1.5; extra == 'laya'
|
|
53
56
|
Requires-Dist: laya>=0.4.6; extra == 'laya'
|
|
54
57
|
Provides-Extra: marker
|
|
55
|
-
Requires-Dist: marker-pdf
|
|
58
|
+
Requires-Dist: marker-pdf>=2.0.0; extra == 'marker'
|
|
56
59
|
Provides-Extra: md2doc
|
|
57
60
|
Requires-Dist: markdown-it-py>=4.2.0; extra == 'md2doc'
|
|
58
61
|
Requires-Dist: pimd[pdfa]>=2.2.5; extra == 'md2doc'
|
|
@@ -77,7 +80,7 @@ SDPY 统一工具集(Kit 体系),供 Python 项目开箱即用:
|
|
|
77
80
|
|
|
78
81
|
- **统一数据库访问层**:PostgreSQL / MySQL / SQLite,三个 Kit API 完全一致,切换数据库只改一行 import;
|
|
79
82
|
- **AI 多模型服务池**:chat / embedding / rerank / image 四类能力,多厂商候选链 + 故障自动转移;
|
|
80
|
-
- **工具集**:Redis / 文件 / 雪花 ID / 文档互转 / Word 模板填充 / MinerU 解析 / Marker 本地解析(md + images
|
|
83
|
+
- **工具集**:Redis / 文件 / 雪花 ID / 文档互转 / Word 模板填充 / MinerU 解析 / Marker 本地解析(PDF + 图片 → md + images/) / 离线 docx 解析(md + images/) / Laya 类型化决策 / 微信公众号文章抓取存储 / 通用网页文章抓取存储。
|
|
81
84
|
|
|
82
85
|
> 要求 Python 3.13+
|
|
83
86
|
|
|
@@ -93,9 +96,10 @@ SDPY 统一工具集(Kit 体系),供 Python 项目开箱即用:
|
|
|
93
96
|
| `kit.common_kit` | `CommonKit` | 雪花 ID、时间戳 ID、时间格式化 | 无 |
|
|
94
97
|
| `kit.docs.anydoc_kit` | `AnyDocKit` | docx / pdf / xlsx 等 → Markdown | `anydoc` |
|
|
95
98
|
| `kit.docs.docx_kit` | `DocxKit` | Word 模板动态填充(章节 / 列表 / 表格) | `docx` |
|
|
99
|
+
| `kit.docs.rc_docparser_kit` | `RcDocParserKit` | 离线 docx → Markdown + Images(无模型) | `docx-parse` |
|
|
96
100
|
| `kit.docs.md2doc_kit` | `Md2DocKit` | Markdown → Word / PDF / HTML | `md2doc` |
|
|
97
101
|
| `kit.docs.mineru_kit` | `MinerUKit` | MinerU 文档解析(精准 + Agent 轻量) | `mineru` |
|
|
98
|
-
| `kit.docs.marker_kit` | `MarkerKit` |
|
|
102
|
+
| `kit.docs.marker_kit` | `MarkerKit` | 本地解析(PDF / 图片 → Markdown + Images) | `marker` |
|
|
99
103
|
| `kit.laya_kit` | `LayaKit` | 类型化决策:choice / score / noul,返回判断结果 + 置信度 | `laya` |
|
|
100
104
|
| `kit.crawl.article_models` | `ArticleInfo` / `ArticleResult` / `SavedOutput` 等 | 文章抓取通用模型(两 `*ArticleKit` 共用,含 `reason` 分类与非致命 `warnings`) | 无 |
|
|
101
105
|
| `kit.crawl.wx_article_kit` | `WxArticleKit` | 微信公众号文章 → Markdown + 图片转存 | 无 |
|
|
@@ -121,8 +125,9 @@ uv add sdpy-kit
|
|
|
121
125
|
| `md2doc` | Md2DocKit:Markdown → Word / PDF / HTML(pimd / fpdf2) | `pip install "sdpy-kit[md2doc]"` |
|
|
122
126
|
| `anydoc` | AnyDocKit 文档转 Markdown(firecrawl-anydoc + pikepdf) | `pip install "sdpy-kit[anydoc]"` |
|
|
123
127
|
| `docx` | DocxKit 模板动态填充(docxtpl) | `pip install "sdpy-kit[docx]"` |
|
|
128
|
+
| `docx-parse` | RcDocParserKit 离线 docx 解析(rc-docparser → Markdown + images/) | `pip install "sdpy-kit[docx-parse]"` |
|
|
124
129
|
| `mineru` | MinerUKit 解析 API(精准解析 + Agent 轻量解析) | `pip install "sdpy-kit[mineru]"` |
|
|
125
|
-
| `marker` | MarkerKit
|
|
130
|
+
| `marker` | MarkerKit 本地解析(marker-pdf → Markdown + Images;PDF + 图片,依赖体积大) | `pip install "sdpy-kit[marker]"` |
|
|
126
131
|
| `laya` | LayaKit 类型化决策(laya + torch,本地小模型 choice / score / noul) | `pip install "sdpy-kit[laya]"` |
|
|
127
132
|
| `web-article` | WebArticleKit 通用网页文章抓取转存(trafilatura,纯 HTTP 无浏览器) | `pip install "sdpy-kit[web-article]"` |
|
|
128
133
|
| `all` | 全部能力 | `pip install "sdpy-kit[all]"` |
|
|
@@ -871,10 +876,10 @@ md = AnyDocKit.convert_to_md("scan.pdf", ocr="hosted") # 需 FIRECRAWL_API_KEY
|
|
|
871
876
|
| `detect_format(file_path) -> str \| None` | 由扩展名推断规范格式名 |
|
|
872
877
|
| `convert_to_md(file_path, *, ocr="reject", api_key=None, api_url=None) -> str` | 文件 → Markdown(非标 PDF 自动修复重试) |
|
|
873
878
|
| `convert_bytes_to_md(data, fmt=None, *, ocr="reject", api_key=None, api_url=None) -> str` | 字节内容 → Markdown |
|
|
874
|
-
| `convert(file_path, *, ocr="reject", api_key=None, api_url=None) ->
|
|
879
|
+
| `convert(file_path, *, ocr="reject", api_key=None, api_url=None) -> AnyDocResult` | 安全转换 |
|
|
875
880
|
| `convert_to_file(src_path, dest_path=None, *, ocr="reject", ...) -> str` | 转换并写入 `.md`,返回目标路径 |
|
|
876
881
|
|
|
877
|
-
`
|
|
882
|
+
`AnyDocResult(success, markdown, file_path, source_format, error)`
|
|
878
883
|
|
|
879
884
|
---
|
|
880
885
|
|
|
@@ -971,15 +976,18 @@ if r.state == "done":
|
|
|
971
976
|
|
|
972
977
|
---
|
|
973
978
|
|
|
974
|
-
## kit.docs.marker_kit ——
|
|
979
|
+
## kit.docs.marker_kit —— 本地解析:PDF + 图片 → Markdown + Images
|
|
975
980
|
|
|
976
|
-
安装:`pip install "sdpy-kit[marker]"`(依赖 `marker-pdf
|
|
981
|
+
安装:`pip install "sdpy-kit[marker]"`(依赖 `marker-pdf`,含 torch 等 80+ 包,体积较大;不含 `[full]`)
|
|
982
|
+
|
|
983
|
+
支持面:`.pdf`、`.png`、`.jpg`、`.jpeg`、`.webp`、`.gif`、`.bmp`。docx/pptx/xlsx/html/epub 不在支持面
|
|
984
|
+
(marker 侧实现依赖 weasyprint/GTK),传入会抛 `ValueError`。
|
|
977
985
|
|
|
978
986
|
```python
|
|
979
987
|
from kit.docs.marker_kit import MarkerKit
|
|
980
988
|
|
|
981
|
-
# 落盘 md + images
|
|
982
|
-
md_path = MarkerKit.convert_to_dir("report.pdf") # -> report/report.md +
|
|
989
|
+
# 落盘 md + images/(推荐):源文件同目录下建同名子目录
|
|
990
|
+
md_path = MarkerKit.convert_to_dir("report.pdf") # -> report/report.md + report/images/
|
|
983
991
|
md_path = MarkerKit.convert_to_dir("report.pdf", "out/doc") # 指定产物目录
|
|
984
992
|
|
|
985
993
|
# 只取 Markdown 文本(图片不落盘)
|
|
@@ -990,24 +998,56 @@ result = MarkerKit.convert("report.pdf", "out/doc")
|
|
|
990
998
|
if result.success:
|
|
991
999
|
print(result.md_path, len(result.image_paths), result.page_count)
|
|
992
1000
|
|
|
993
|
-
#
|
|
994
|
-
md = MarkerKit.convert_to_md("
|
|
1001
|
+
# 文本层 PDF 离线抽取(跳过 VLM/OCR,无需 llama-server)
|
|
1002
|
+
md = MarkerKit.convert_to_md("report.pdf", disable_ocr=True)
|
|
1003
|
+
|
|
1004
|
+
# 图片输入(无文本层,必须 OCR:仅 disable_ocr=True 时无文字内容)
|
|
1005
|
+
md = MarkerKit.convert_to_md("figure.png", disable_ocr=True)
|
|
995
1006
|
|
|
996
1007
|
MarkerKit.shutdown() # 释放模型与推理服务(幂等)
|
|
997
1008
|
```
|
|
998
1009
|
|
|
999
1010
|
| 方法 | 说明 |
|
|
1000
1011
|
|------|------|
|
|
1001
|
-
| `is_supported(file_path) -> bool` |
|
|
1012
|
+
| `is_supported(file_path) -> bool` | 白名单:`.pdf` + `.png/.jpg/.jpeg/.webp/.gif/.bmp` |
|
|
1002
1013
|
| `convert_to_md(file_path, *, mode=None, force_ocr=None, disable_ocr=None, page_range=None) -> str` | 解析并返回 Markdown 文本(图片不落盘) |
|
|
1003
|
-
| `convert_to_dir(src_path, output_dir=None, *, mode=None, force_ocr=None, disable_ocr=None, page_range=None, extract_images=True) -> str` | 解析并落盘 md + images
|
|
1014
|
+
| `convert_to_dir(src_path, output_dir=None, *, mode=None, force_ocr=None, disable_ocr=None, page_range=None, extract_images=True) -> str` | 解析并落盘 md + `images/`,返回 md 绝对路径 |
|
|
1004
1015
|
| `convert(src_path, output_dir=None, *, ...) -> MarkerResult` | 安全版:失败封装为 `MarkerResult`,不抛异常 |
|
|
1005
1016
|
| `shutdown() -> None` | 释放模型与共享推理服务(幂等) |
|
|
1006
1017
|
|
|
1007
|
-
> 产物:`<output_dir>/<源文件名>.md` +
|
|
1018
|
+
> 产物:`<output_dir>/<源文件名>.md` + `<output_dir>/images/`(md 内以 `images/<文件名>` 相对引用;无图片不建空目录),**不生成** `_meta.json`。
|
|
1008
1019
|
> 结果类型:`MarkerResult`(`success` / `markdown` / `file_path` / `output_dir` / `md_path` / `image_paths` / `page_count` / `error`);异常:`MarkerError`。
|
|
1009
1020
|
> `mode` 缺省时不写入配置,交由 marker 按设备自动选择;首次使用会下载模型权重(默认走 `MARKER_HF_ENDPOINT` 镜像)。
|
|
1010
|
-
>
|
|
1021
|
+
> **前提条件**:文本层 PDF 传 `disable_ocr=True` 即可完全离线(无需 llama-server);不传时 marker 默认启用 VLM/OCR,
|
|
1022
|
+
> 缺 `llama-server` 抛 `SpawnError`。扫描件 / 图片型 PDF / 图片输入要得到文字,必须有 llama.cpp 的 `llama-server`
|
|
1023
|
+
> (`MARKER_LLAMA_CPP_BINARY`),否则只得到空 md 或一条整图引用。PDF 内嵌图片抽取不需要 `llama-server`。
|
|
1024
|
+
|
|
1025
|
+
## kit.docs.rc_docparser_kit —— 离线 docx → Markdown + Images
|
|
1026
|
+
|
|
1027
|
+
安装:`pip install "sdpy-kit[docx-parse]"`(依赖 `rc-docparser`,纯 Python,无模型 / OCR / GTK)
|
|
1028
|
+
|
|
1029
|
+
支持面:仅 `.docx`。产物与 `MarkerKit` 同一契约:`<out>/<stem>.md` + `<out>/images/`。
|
|
1030
|
+
|
|
1031
|
+
```python
|
|
1032
|
+
from kit.docs.rc_docparser_kit import RcDocParserKit
|
|
1033
|
+
|
|
1034
|
+
md_path = RcDocParserKit.convert_to_dir("report.docx") # -> report/report.md + report/images/
|
|
1035
|
+
md = RcDocParserKit.convert_to_md("report.docx") # 只取文本(图片不落盘)
|
|
1036
|
+
result = RcDocParserKit.convert("report.docx", "out/doc")
|
|
1037
|
+
if result.success:
|
|
1038
|
+
print(result.md_path, len(result.image_paths))
|
|
1039
|
+
```
|
|
1040
|
+
|
|
1041
|
+
| 方法 | 说明 |
|
|
1042
|
+
|------|------|
|
|
1043
|
+
| `is_supported(file_path) -> bool` | 是否 `.docx` |
|
|
1044
|
+
| `convert_to_md(file_path) -> str` | 解析并返回 Markdown 文本 |
|
|
1045
|
+
| `convert_to_dir(src_path, output_dir=None, *, extract_images=True) -> str` | 落盘 md + `images/`,返回 md 绝对路径 |
|
|
1046
|
+
| `convert(src_path, output_dir=None, *, ...) -> RcDocParserResult` | 安全版:失败封装为结果对象 |
|
|
1047
|
+
|
|
1048
|
+
> 产物:`<out>/images/img-NNN-<sha1 前 10>.<ext>`(按出现顺序、内容哈希命名);无图不建空目录。
|
|
1049
|
+
> 前提:中文标题依赖 `w:outlineLvl` 或「标题 N」样式(都没有时退化为正文);合并单元格的复杂表格
|
|
1050
|
+
> 会退化为 GFM 表格;页眉页脚/脚注不提取。纯本地,无需模型或 GPU。
|
|
1011
1051
|
|
|
1012
1052
|
## kit.crawl.wx_article_kit —— 微信公众号文章抓取存储
|
|
1013
1053
|
|
|
@@ -4,7 +4,7 @@ SDPY 统一工具集(Kit 体系),供 Python 项目开箱即用:
|
|
|
4
4
|
|
|
5
5
|
- **统一数据库访问层**:PostgreSQL / MySQL / SQLite,三个 Kit API 完全一致,切换数据库只改一行 import;
|
|
6
6
|
- **AI 多模型服务池**:chat / embedding / rerank / image 四类能力,多厂商候选链 + 故障自动转移;
|
|
7
|
-
- **工具集**:Redis / 文件 / 雪花 ID / 文档互转 / Word 模板填充 / MinerU 解析 / Marker 本地解析(md + images
|
|
7
|
+
- **工具集**:Redis / 文件 / 雪花 ID / 文档互转 / Word 模板填充 / MinerU 解析 / Marker 本地解析(PDF + 图片 → md + images/) / 离线 docx 解析(md + images/) / Laya 类型化决策 / 微信公众号文章抓取存储 / 通用网页文章抓取存储。
|
|
8
8
|
|
|
9
9
|
> 要求 Python 3.13+
|
|
10
10
|
|
|
@@ -20,9 +20,10 @@ SDPY 统一工具集(Kit 体系),供 Python 项目开箱即用:
|
|
|
20
20
|
| `kit.common_kit` | `CommonKit` | 雪花 ID、时间戳 ID、时间格式化 | 无 |
|
|
21
21
|
| `kit.docs.anydoc_kit` | `AnyDocKit` | docx / pdf / xlsx 等 → Markdown | `anydoc` |
|
|
22
22
|
| `kit.docs.docx_kit` | `DocxKit` | Word 模板动态填充(章节 / 列表 / 表格) | `docx` |
|
|
23
|
+
| `kit.docs.rc_docparser_kit` | `RcDocParserKit` | 离线 docx → Markdown + Images(无模型) | `docx-parse` |
|
|
23
24
|
| `kit.docs.md2doc_kit` | `Md2DocKit` | Markdown → Word / PDF / HTML | `md2doc` |
|
|
24
25
|
| `kit.docs.mineru_kit` | `MinerUKit` | MinerU 文档解析(精准 + Agent 轻量) | `mineru` |
|
|
25
|
-
| `kit.docs.marker_kit` | `MarkerKit` |
|
|
26
|
+
| `kit.docs.marker_kit` | `MarkerKit` | 本地解析(PDF / 图片 → Markdown + Images) | `marker` |
|
|
26
27
|
| `kit.laya_kit` | `LayaKit` | 类型化决策:choice / score / noul,返回判断结果 + 置信度 | `laya` |
|
|
27
28
|
| `kit.crawl.article_models` | `ArticleInfo` / `ArticleResult` / `SavedOutput` 等 | 文章抓取通用模型(两 `*ArticleKit` 共用,含 `reason` 分类与非致命 `warnings`) | 无 |
|
|
28
29
|
| `kit.crawl.wx_article_kit` | `WxArticleKit` | 微信公众号文章 → Markdown + 图片转存 | 无 |
|
|
@@ -48,8 +49,9 @@ uv add sdpy-kit
|
|
|
48
49
|
| `md2doc` | Md2DocKit:Markdown → Word / PDF / HTML(pimd / fpdf2) | `pip install "sdpy-kit[md2doc]"` |
|
|
49
50
|
| `anydoc` | AnyDocKit 文档转 Markdown(firecrawl-anydoc + pikepdf) | `pip install "sdpy-kit[anydoc]"` |
|
|
50
51
|
| `docx` | DocxKit 模板动态填充(docxtpl) | `pip install "sdpy-kit[docx]"` |
|
|
52
|
+
| `docx-parse` | RcDocParserKit 离线 docx 解析(rc-docparser → Markdown + images/) | `pip install "sdpy-kit[docx-parse]"` |
|
|
51
53
|
| `mineru` | MinerUKit 解析 API(精准解析 + Agent 轻量解析) | `pip install "sdpy-kit[mineru]"` |
|
|
52
|
-
| `marker` | MarkerKit
|
|
54
|
+
| `marker` | MarkerKit 本地解析(marker-pdf → Markdown + Images;PDF + 图片,依赖体积大) | `pip install "sdpy-kit[marker]"` |
|
|
53
55
|
| `laya` | LayaKit 类型化决策(laya + torch,本地小模型 choice / score / noul) | `pip install "sdpy-kit[laya]"` |
|
|
54
56
|
| `web-article` | WebArticleKit 通用网页文章抓取转存(trafilatura,纯 HTTP 无浏览器) | `pip install "sdpy-kit[web-article]"` |
|
|
55
57
|
| `all` | 全部能力 | `pip install "sdpy-kit[all]"` |
|
|
@@ -798,10 +800,10 @@ md = AnyDocKit.convert_to_md("scan.pdf", ocr="hosted") # 需 FIRECRAWL_API_KEY
|
|
|
798
800
|
| `detect_format(file_path) -> str \| None` | 由扩展名推断规范格式名 |
|
|
799
801
|
| `convert_to_md(file_path, *, ocr="reject", api_key=None, api_url=None) -> str` | 文件 → Markdown(非标 PDF 自动修复重试) |
|
|
800
802
|
| `convert_bytes_to_md(data, fmt=None, *, ocr="reject", api_key=None, api_url=None) -> str` | 字节内容 → Markdown |
|
|
801
|
-
| `convert(file_path, *, ocr="reject", api_key=None, api_url=None) ->
|
|
803
|
+
| `convert(file_path, *, ocr="reject", api_key=None, api_url=None) -> AnyDocResult` | 安全转换 |
|
|
802
804
|
| `convert_to_file(src_path, dest_path=None, *, ocr="reject", ...) -> str` | 转换并写入 `.md`,返回目标路径 |
|
|
803
805
|
|
|
804
|
-
`
|
|
806
|
+
`AnyDocResult(success, markdown, file_path, source_format, error)`
|
|
805
807
|
|
|
806
808
|
---
|
|
807
809
|
|
|
@@ -898,15 +900,18 @@ if r.state == "done":
|
|
|
898
900
|
|
|
899
901
|
---
|
|
900
902
|
|
|
901
|
-
## kit.docs.marker_kit ——
|
|
903
|
+
## kit.docs.marker_kit —— 本地解析:PDF + 图片 → Markdown + Images
|
|
902
904
|
|
|
903
|
-
安装:`pip install "sdpy-kit[marker]"`(依赖 `marker-pdf
|
|
905
|
+
安装:`pip install "sdpy-kit[marker]"`(依赖 `marker-pdf`,含 torch 等 80+ 包,体积较大;不含 `[full]`)
|
|
906
|
+
|
|
907
|
+
支持面:`.pdf`、`.png`、`.jpg`、`.jpeg`、`.webp`、`.gif`、`.bmp`。docx/pptx/xlsx/html/epub 不在支持面
|
|
908
|
+
(marker 侧实现依赖 weasyprint/GTK),传入会抛 `ValueError`。
|
|
904
909
|
|
|
905
910
|
```python
|
|
906
911
|
from kit.docs.marker_kit import MarkerKit
|
|
907
912
|
|
|
908
|
-
# 落盘 md + images
|
|
909
|
-
md_path = MarkerKit.convert_to_dir("report.pdf") # -> report/report.md +
|
|
913
|
+
# 落盘 md + images/(推荐):源文件同目录下建同名子目录
|
|
914
|
+
md_path = MarkerKit.convert_to_dir("report.pdf") # -> report/report.md + report/images/
|
|
910
915
|
md_path = MarkerKit.convert_to_dir("report.pdf", "out/doc") # 指定产物目录
|
|
911
916
|
|
|
912
917
|
# 只取 Markdown 文本(图片不落盘)
|
|
@@ -917,24 +922,56 @@ result = MarkerKit.convert("report.pdf", "out/doc")
|
|
|
917
922
|
if result.success:
|
|
918
923
|
print(result.md_path, len(result.image_paths), result.page_count)
|
|
919
924
|
|
|
920
|
-
#
|
|
921
|
-
md = MarkerKit.convert_to_md("
|
|
925
|
+
# 文本层 PDF 离线抽取(跳过 VLM/OCR,无需 llama-server)
|
|
926
|
+
md = MarkerKit.convert_to_md("report.pdf", disable_ocr=True)
|
|
927
|
+
|
|
928
|
+
# 图片输入(无文本层,必须 OCR:仅 disable_ocr=True 时无文字内容)
|
|
929
|
+
md = MarkerKit.convert_to_md("figure.png", disable_ocr=True)
|
|
922
930
|
|
|
923
931
|
MarkerKit.shutdown() # 释放模型与推理服务(幂等)
|
|
924
932
|
```
|
|
925
933
|
|
|
926
934
|
| 方法 | 说明 |
|
|
927
935
|
|------|------|
|
|
928
|
-
| `is_supported(file_path) -> bool` |
|
|
936
|
+
| `is_supported(file_path) -> bool` | 白名单:`.pdf` + `.png/.jpg/.jpeg/.webp/.gif/.bmp` |
|
|
929
937
|
| `convert_to_md(file_path, *, mode=None, force_ocr=None, disable_ocr=None, page_range=None) -> str` | 解析并返回 Markdown 文本(图片不落盘) |
|
|
930
|
-
| `convert_to_dir(src_path, output_dir=None, *, mode=None, force_ocr=None, disable_ocr=None, page_range=None, extract_images=True) -> str` | 解析并落盘 md + images
|
|
938
|
+
| `convert_to_dir(src_path, output_dir=None, *, mode=None, force_ocr=None, disable_ocr=None, page_range=None, extract_images=True) -> str` | 解析并落盘 md + `images/`,返回 md 绝对路径 |
|
|
931
939
|
| `convert(src_path, output_dir=None, *, ...) -> MarkerResult` | 安全版:失败封装为 `MarkerResult`,不抛异常 |
|
|
932
940
|
| `shutdown() -> None` | 释放模型与共享推理服务(幂等) |
|
|
933
941
|
|
|
934
|
-
> 产物:`<output_dir>/<源文件名>.md` +
|
|
942
|
+
> 产物:`<output_dir>/<源文件名>.md` + `<output_dir>/images/`(md 内以 `images/<文件名>` 相对引用;无图片不建空目录),**不生成** `_meta.json`。
|
|
935
943
|
> 结果类型:`MarkerResult`(`success` / `markdown` / `file_path` / `output_dir` / `md_path` / `image_paths` / `page_count` / `error`);异常:`MarkerError`。
|
|
936
944
|
> `mode` 缺省时不写入配置,交由 marker 按设备自动选择;首次使用会下载模型权重(默认走 `MARKER_HF_ENDPOINT` 镜像)。
|
|
937
|
-
>
|
|
945
|
+
> **前提条件**:文本层 PDF 传 `disable_ocr=True` 即可完全离线(无需 llama-server);不传时 marker 默认启用 VLM/OCR,
|
|
946
|
+
> 缺 `llama-server` 抛 `SpawnError`。扫描件 / 图片型 PDF / 图片输入要得到文字,必须有 llama.cpp 的 `llama-server`
|
|
947
|
+
> (`MARKER_LLAMA_CPP_BINARY`),否则只得到空 md 或一条整图引用。PDF 内嵌图片抽取不需要 `llama-server`。
|
|
948
|
+
|
|
949
|
+
## kit.docs.rc_docparser_kit —— 离线 docx → Markdown + Images
|
|
950
|
+
|
|
951
|
+
安装:`pip install "sdpy-kit[docx-parse]"`(依赖 `rc-docparser`,纯 Python,无模型 / OCR / GTK)
|
|
952
|
+
|
|
953
|
+
支持面:仅 `.docx`。产物与 `MarkerKit` 同一契约:`<out>/<stem>.md` + `<out>/images/`。
|
|
954
|
+
|
|
955
|
+
```python
|
|
956
|
+
from kit.docs.rc_docparser_kit import RcDocParserKit
|
|
957
|
+
|
|
958
|
+
md_path = RcDocParserKit.convert_to_dir("report.docx") # -> report/report.md + report/images/
|
|
959
|
+
md = RcDocParserKit.convert_to_md("report.docx") # 只取文本(图片不落盘)
|
|
960
|
+
result = RcDocParserKit.convert("report.docx", "out/doc")
|
|
961
|
+
if result.success:
|
|
962
|
+
print(result.md_path, len(result.image_paths))
|
|
963
|
+
```
|
|
964
|
+
|
|
965
|
+
| 方法 | 说明 |
|
|
966
|
+
|------|------|
|
|
967
|
+
| `is_supported(file_path) -> bool` | 是否 `.docx` |
|
|
968
|
+
| `convert_to_md(file_path) -> str` | 解析并返回 Markdown 文本 |
|
|
969
|
+
| `convert_to_dir(src_path, output_dir=None, *, extract_images=True) -> str` | 落盘 md + `images/`,返回 md 绝对路径 |
|
|
970
|
+
| `convert(src_path, output_dir=None, *, ...) -> RcDocParserResult` | 安全版:失败封装为结果对象 |
|
|
971
|
+
|
|
972
|
+
> 产物:`<out>/images/img-NNN-<sha1 前 10>.<ext>`(按出现顺序、内容哈希命名);无图不建空目录。
|
|
973
|
+
> 前提:中文标题依赖 `w:outlineLvl` 或「标题 N」样式(都没有时退化为正文);合并单元格的复杂表格
|
|
974
|
+
> 会退化为 GFM 表格;页眉页脚/脚注不提取。纯本地,无需模型或 GPU。
|
|
938
975
|
|
|
939
976
|
## kit.crawl.wx_article_kit —— 微信公众号文章抓取存储
|
|
940
977
|
|
|
@@ -89,7 +89,7 @@ class Settings(BaseSettings):
|
|
|
89
89
|
default=600, ge=10, description="任务轮询总超时(秒),超时抛 MinerUError"
|
|
90
90
|
)
|
|
91
91
|
|
|
92
|
-
# Marker
|
|
92
|
+
# Marker 本地解析配置(marker-pdf,PDF/图片→Markdown+Images,模型本地运行)
|
|
93
93
|
MARKER_MODE: str | None = Field(
|
|
94
94
|
default=None,
|
|
95
95
|
description=(
|
|
@@ -25,7 +25,8 @@ Author: Clark Chang
|
|
|
25
25
|
- md2doc_kit: Md2DocKit Markdown 转 Word/PDF/HTML(pimd,extra: md2doc)
|
|
26
26
|
- docx_kit: DocxKit Word 模板动态填充(docxtpl,extra: docx)
|
|
27
27
|
- mineru_kit: MinerUKit MinerU 文档解析 API(requests,extra: mineru)
|
|
28
|
-
- marker_kit: MarkerKit
|
|
28
|
+
- marker_kit: MarkerKit PDF + 图片本地解析(marker-pdf,extra: marker)
|
|
29
|
+
- rc_docparser_kit: RcDocParserKit 离线 docx 解析(rc-docparser,extra: docx-parse)
|
|
29
30
|
|
|
30
31
|
本 __init__ 不导入任何成员:五个模块均携带重型可选依赖,保持
|
|
31
32
|
`import kit.docs` 在基础安装下零成本可用(对齐 kit.crawl 先例)。
|
|
@@ -18,21 +18,27 @@ Author: Clark Chang
|
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
20
|
# date: 2026-09-23
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
21
|
+
"""AnyDocKit —— 文档转 Markdown 工具类(基于 firecrawl-anydoc)
|
|
22
|
+
|
|
23
|
+
支持面:`.doc` / `.docx` / `.ppt` / `.pptx` / `.xls` / `.xlsx` / `.csv` / `.pdf`
|
|
24
|
+
(白名单为 anydoc 支持面的常用子集)。
|
|
25
|
+
|
|
26
|
+
实现内容:
|
|
27
|
+
- 全部静态方法、无内部状态;低层 `convert_to_md` 直接抛异常,高层 `convert`
|
|
28
|
+
返回 `AnyDocResult` 封装成功/失败,便于批量处理。
|
|
29
|
+
- PDF 结构非标(如知网件 `%%EOF` 后附加元数据)遇 `MalformedError` 时,用
|
|
30
|
+
pikepdf 重写为临时文件后重试一次;扫描页默认 reject,`ocr="hosted"` 走云端 OCR。
|
|
31
|
+
- 路径参数支持 `str` / `Path`;访问文件的方法内部 resolve 为绝对路径,
|
|
32
|
+
纯扩展名判断方法不做 resolve。
|
|
33
|
+
|
|
34
|
+
前提条件:
|
|
35
|
+
- 只产出 Markdown 文本,**不产出图片**(需要 `md + images/` 时用 `MarkerKit`
|
|
36
|
+
或 `RcDocParserKit`)。
|
|
37
|
+
- 云端 OCR 需 `FIRECRAWL_API_KEY`(或显式传 `api_key`)。
|
|
38
|
+
|
|
39
|
+
依赖:
|
|
40
|
+
- `firecrawl-anydoc`(extra `anydoc`,导入名 `anydoc`)+ `pikepdf`;
|
|
41
|
+
未安装时导入报错并提示安装命令。
|
|
36
42
|
"""
|
|
37
43
|
|
|
38
44
|
import io
|
|
@@ -44,7 +50,9 @@ try:
|
|
|
44
50
|
import anydoc
|
|
45
51
|
import pikepdf
|
|
46
52
|
except ImportError as e:
|
|
47
|
-
raise ImportError(
|
|
53
|
+
raise ImportError(
|
|
54
|
+
"anydoc_kit 需要可选依赖,请安装:pip install sdpy-kit[anydoc]"
|
|
55
|
+
) from e
|
|
48
56
|
|
|
49
57
|
from kit.config.log_config import get_default_logger
|
|
50
58
|
|
|
@@ -139,7 +147,7 @@ def _convert_with_repair(
|
|
|
139
147
|
|
|
140
148
|
|
|
141
149
|
@dataclass(frozen=True, slots=True)
|
|
142
|
-
class
|
|
150
|
+
class AnyDocResult:
|
|
143
151
|
"""文档转换结果对象
|
|
144
152
|
|
|
145
153
|
由 AnyDocKit.convert 返回,将成功与失败信息统一封装,调用方无需 try/except。
|
|
@@ -374,11 +382,11 @@ class AnyDocKit:
|
|
|
374
382
|
ocr: Literal["reject", "hosted"] = "reject",
|
|
375
383
|
api_key: str | None = None,
|
|
376
384
|
api_url: str | None = None,
|
|
377
|
-
) ->
|
|
385
|
+
) -> AnyDocResult:
|
|
378
386
|
"""安全转换文档为 Markdown,返回包含状态的结果对象
|
|
379
387
|
|
|
380
388
|
与 convert_to_md 不同,本方法不抛出转换异常,而是将成功/失败信息
|
|
381
|
-
封装到
|
|
389
|
+
封装到 AnyDocResult 中,便于批量处理或状态检查。
|
|
382
390
|
ocr/api_key/api_url 语义同 convert_to_md(PDF 自动修复对调用方
|
|
383
391
|
透明,失败信息封装在 result.error 中)。
|
|
384
392
|
边界:文件不存在 / 格式不支持 / 转换失败均封装为结果;若 file_path
|
|
@@ -391,7 +399,7 @@ class AnyDocKit:
|
|
|
391
399
|
api_url: 云端 OCR 服务地址;None 时回落 FIRECRAWL_API_URL
|
|
392
400
|
|
|
393
401
|
Returns:
|
|
394
|
-
|
|
402
|
+
AnyDocResult: 转换结果,包含 success/markdown/file_path/source_format/error
|
|
395
403
|
|
|
396
404
|
Example:
|
|
397
405
|
>>> result = AnyDocKit.convert("report.pdf")
|
|
@@ -410,7 +418,7 @@ class AnyDocKit:
|
|
|
410
418
|
except (ValueError, anydoc.ConvertError, OSError) as e:
|
|
411
419
|
# OSError 同时覆盖 FileNotFoundError(文件不存在)与文件读取失败
|
|
412
420
|
logger.warning(f"文档转换失败: {path.name}({type(e).__name__}): {e}")
|
|
413
|
-
return
|
|
421
|
+
return AnyDocResult(
|
|
414
422
|
success=False,
|
|
415
423
|
markdown="",
|
|
416
424
|
file_path=str(path),
|
|
@@ -418,7 +426,7 @@ class AnyDocKit:
|
|
|
418
426
|
error=f"{type(e).__name__}: {e}",
|
|
419
427
|
)
|
|
420
428
|
|
|
421
|
-
return
|
|
429
|
+
return AnyDocResult(
|
|
422
430
|
success=True,
|
|
423
431
|
markdown=markdown,
|
|
424
432
|
file_path=str(path),
|
|
@@ -18,29 +18,28 @@ Author: Clark Chang
|
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
20
|
# date: 2026-09-14
|
|
21
|
-
"""docx
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
``title`` 参数生成(居中、加粗)。
|
|
21
|
+
"""DocxKit —— docx 模板动态填充工具类(基于 docxtpl)
|
|
22
|
+
|
|
23
|
+
支持面:Word 模板(`.docx`)+ 结构化数据 → 成品 docx;章节数量、层级、标题、
|
|
24
|
+
正文段落、多级列表、表格均由运行时数据决定,模板只承载版式骨架。
|
|
25
|
+
|
|
26
|
+
实现内容:
|
|
27
|
+
- 章节循环由模板中的 ``{%p for %}`` 承载;列表/表格以私有使用区字符组成的 marker
|
|
28
|
+
段落承载「位置 + 载荷」,渲染后由 python-docx 原位转换,规避 docxtpl 无法表达
|
|
29
|
+
动态层级与富内容的限制。
|
|
30
|
+
- 章节标题段使用锚点样式(默认 ``DocxSectionTitle``),渲染后按 ``level`` 重设为
|
|
31
|
+
``Heading N``,使模板绑定的 Word 多级列表自动编号生效。
|
|
32
|
+
- 有序列表按「连续组」克隆独立编号定义,避免多个列表被 Word 串成一条编号序列。
|
|
33
|
+
- 渲染开启 ``autoescape``;变量值控制字符沿用 docxtpl 约定(``\\n`` 软换行、
|
|
34
|
+
``\\a`` 新段落)。
|
|
35
|
+
- 全静态方法、无模块级可变状态;路径参数支持 `str` / `Path`。
|
|
36
|
+
|
|
37
|
+
前提条件:
|
|
38
|
+
- 模板需保留样式与书签骨架;字体/标题颜色统一由 `unify_font` /
|
|
39
|
+
`unify_heading_color` 处理,产物继承模板样式。
|
|
40
|
+
|
|
41
|
+
依赖:
|
|
42
|
+
- `docxtpl` + `python-docx`(extra `docx`);未安装时导入报错并提示安装命令。
|
|
44
43
|
"""
|
|
45
44
|
|
|
46
45
|
import re
|