Files
OnebotCatalog/onebot-data/tools/gen-clamp-manual.py
wangruiguo 0584ba67b4 v1.0: 夹紧缸模块真实数据替换 + 仓库瘦身
数据 (CLM 气动夹紧缸分类):
- 1 系列 demo -> 11 个官方系列, 6 型号 -> 859 个真实型号
- 参数化升级: 仅缸径 -> 最多 5 维 (缸径/臂位置/臂类型/臂样式/传感器)
- 11 系列各含官方图册附图 (84 张) + datasheet PDF
- 修复: 枚举维度空串必须为合法值 (否则级联过滤后下拉全空)
- 修复: catalog.json 分类 series 数组未更新导致新系列不进包
- 修复: _step 副本后缀归一化错误 (产生假型号)

工具:
- gen-clamp-series.py     数据清洗 (X盘数模 -> CSV/meta/STEP)
- copy-clamp-step.py      8线程并行复制 (网络盘 I/O 优化)
- gen-clamp-manual.py     官方图册 PDF -> 附图
- update-clamp-meta-attach.py / fix-clamp-meta-empty-enum.py

仓库瘦身:
- .gitignore 排除数模(5GB)/.opc(1.2GB)/编译产物/发布产物
- 移出索引: release/ bin产物 STEP数模 .opc 大型PDF 等
- 提交体积 17MB (原 15.97GB)

其他: SelfTest.cs 可解析选型逻辑放宽 (稀疏数据用真实变体回验)

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-14 15:24:16 +08:00

129 lines
4.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
"""
为夹紧缸 11 个系列生成附图(多页尺寸图 + 裁剪版数据表 PDF)。
来源:Univer 官方图册 PDF(X 盘)。
用法: PYTHONUTF8=1 python gen-clamp-manual.py [--clean]
--clean 先清空各系列 manual 目录再生成(避免旧页残留)
输出: manual/<系列>/p<NN>.png + <系列>_manual.pdf(裁成该系列的页)
"""
import fitz, os, shutil, sys
SRC = r'X:/新开发产品-Research and Development/2_产品资料/Univer资料/官方图册'
DST = r'D:/开发/OnebotCatalog/onebot-data/catalog/manual'
DPI = 110
CLEAN = '--clean' in sys.argv
MAIN_CATALOG = 'katalog-pneumatische-spanner-univer-13032019-en.pdf'
# 系列 -> 官方 PDF 列表(多缸径系列合并成一个系列的图,按缸径顺序)
SERIES_PDFS = {
'UCBP': ['ucbp25cten_en380', 'ucbp40en_en382', 'ucbp50cten_en391', 'ucbp63cten_en401', 'ucbp80cten_en392'],
'UCBM': ['ucbm32cten_en432', 'ucbm50cten_en394', 'ucbm63cten_en395', 'ucbm80cten_en414'],
'UCBH': ['ucbh63cten_en393'],
'UCBQ': ['ucbq63cten_en397'],
'UCDP': ['ucdp40cten_en417', 'ucdp63cten_en418'],
'UCIM': ['ucim40cten_en415'],
'UCIP': ['ucip40cten_en402'],
'UCNM': ['ucnm50cten_en387', 'ucnm63cten_en389', 'ucnm80cten_en429'],
'UCNP': ['ucnp50cten_en385', 'ucnp63cten_en403', 'ucnp80cten_en388'],
# UFL450/UHL463 实为官方 UCBL(Manual power clamps Ø50/Ø63)
'UFL': ['ucbl450cten_en398', 'ucbl463cten_en478'],
}
UCBT_FROM_MAIN = True # UCBT 无独立图册,从主目录提取
def classify(page):
"""按内容标记归类页面: char(特性) / dim(尺寸) / arm(夹臂配件) / other"""
t = page.get_text().upper()
if 'CLAMPING ARMS' in t or 'ACCESSORIES' in t:
return 'arm'
if 'DIMENSIONS' in t:
return 'dim'
if 'CHARACTERISTICS' in t or 'CODIFICATION' in t:
return 'char'
return 'other'
def render(pages, out_dir, start_no):
"""pages = [(doc, page_idx), ...] 渲染为 p<NN>.png,返回下一个编号"""
n = start_no
for doc, i in pages:
pix = doc[i].get_pixmap(dpi=DPI, colorspace=fitz.csGRAY)
pix.save(os.path.join(out_dir, f'p{n:02d}.png'))
n += 1
return n
def main():
os.makedirs(DST, exist_ok=True)
for series, pdfs in SERIES_PDFS.items():
d = os.path.join(DST, series)
if CLEAN and os.path.isdir(d):
shutil.rmtree(d)
os.makedirs(d, exist_ok=True)
all_pages = [] # (doc, page_idx, kind)
src_docs = []
for name in pdfs:
p = os.path.join(SRC, name + '.pdf')
if not os.path.exists(p):
print(f'[{series}] 源缺失: {name}')
continue
doc = fitz.open(p)
src_docs.append((name, doc))
for i in range(doc.page_count):
all_pages.append((doc, i, classify(doc[i])))
if not all_pages:
print(f'[{series}] 无可用源 PDF')
continue
# 渲染顺序: 特性页 -> 尺寸页 -> 夹臂页(稳定顺序,便于对照)
order = {'char': 0, 'dim': 1, 'arm': 2, 'other': 3}
all_pages.sort(key=lambda x: order[x[2]])
n = render([(doc, i) for doc, i, k in all_pages], d, 1)
kinds = [k for _, _, k in all_pages]
print(f'[{series}] {len(all_pages)} 页 -> {kinds}')
# 数据表 PDF: 只保留该系列的页(合并多缸径 PDF)
out_pdf = fitz.open()
for name, doc in src_docs:
out_pdf.insert_pdf(doc)
out_path = os.path.join(d, series + '_manual.pdf')
out_pdf.save(out_path, garbage=3, deflate=True)
out_pdf.close()
print(f'[{series}] datasheet <- {len(pdfs)} 个PDF合并 ({os.path.getsize(out_path)/1024:.0f}KB)')
# UCBT: 从主目录提取
if UCBT_FROM_MAIN:
d = os.path.join(DST, 'UCBT')
if CLEAN and os.path.isdir(d):
shutil.rmtree(d)
os.makedirs(d, exist_ok=True)
main_pdf = os.path.join(SRC, MAIN_CATALOG)
doc = fitz.open(main_pdf)
# 找 UCBT40 相关页(数据页)
idxs = []
for i in range(doc.page_count):
t = doc[i].get_text().upper()
if 'UCBT40' in t and any(m in t for m in ('DIMENSIONS', 'CODIFICATION', 'CHARACTERISTICS')):
idxs.append(i)
if idxs:
n = render([(doc, i) for i in idxs], d, 1)
print(f'[UCBT] {len(idxs)} 页 <- 主目录 idx={idxs}')
# datasheet: 只裁 UCBT 那几页
out_pdf = fitz.open()
for i in idxs:
out_pdf.insert_pdf(doc, from_page=i, to_page=i)
out_path = os.path.join(d, 'UCBT_manual.pdf')
out_pdf.save(out_path, garbage=3, deflate=True)
out_pdf.close()
print(f'[UCBT] datasheet <- 裁剪 {len(idxs)} 页 ({os.path.getsize(out_path)/1024:.0f}KB)')
else:
print('[UCBT] 未找到数据页')
print('完成')
if __name__ == '__main__':
main()