# -*- coding: utf-8 -*- """技术方案排版自检:导出 PDF、渲染指定页预览、报告版面留白过多的页。 用法:python doc/_bid_preview.py <文件名关键字> [页码 ...] [--export] 例: python doc/_bid_preview.py 第2章 1 5 9 """ import io import os import sys import time import fitz HERE = os.path.dirname(os.path.abspath(__file__)) PREV = os.path.join(HERE, "_bid_preview_pages") FILL_WARN = 0.62 sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8") def find_docx(keyword): hits = [n for n in os.listdir(HERE) if n.endswith(".docx") and not n.startswith("~$") and keyword in n] if not hits: raise SystemExit(f"未找到含「{keyword}」的 docx") if len(hits) > 1: print("匹配到多个,取第一个:", hits) return os.path.join(HERE, hits[0]) def export_pdf(src, pdf): import win32com.client as win32 for attempt in range(4): try: word = win32.gencache.EnsureDispatch("Word.Application") word.Visible = False d = word.Documents.Open(src, ReadOnly=True) d.ExportAsFixedFormat(pdf, 17) d.Close(False) word.Quit() return except Exception as e: # Word COM 偶发拒绝调用 print(f" 导出重试 {attempt + 1}/4:{e}") time.sleep(4) raise SystemExit("Word 导出 PDF 失败") def report_gaps(doc): print(f"版面留白检查(内容占比 < {FILL_WARN:.0%}):") hit = False for i, pg in enumerate(doc, 1): r = pg.rect bottoms = [b[3] for b in pg.get_text("blocks") if b[3] < r.height - 40] bottoms += [bb.y1 for bb in (pg.get_image_bbox(x) for x in pg.get_images(full=True)) if bb] if not bottoms: print(f" P{i:<3} 空白页") hit = True continue used = (max(bottoms) - 60) / (r.height - 120) if used < FILL_WARN: print(f" P{i:<3} 内容占比 {used * 100:5.1f}%") hit = True if not hit: print(" 无") def main(): args = sys.argv[1:] if not args: raise SystemExit(__doc__) keyword = args[0] pages = [int(a) for a in args[1:] if a.isdigit()] src = find_docx(keyword) # PDF 按源文档命名,避免不同章节复用同一个缓存文件 stem = os.path.splitext(os.path.basename(src))[0] pdf = os.path.join(HERE, "_bid_preview", stem + ".pdf") os.makedirs(os.path.dirname(pdf), exist_ok=True) os.makedirs(PREV, exist_ok=True) print("文档:", os.path.basename(src)) stale = (not os.path.exists(pdf) or os.path.getmtime(pdf) < os.path.getmtime(src)) if "--export" in args or stale: export_pdf(src, pdf) doc = fitz.open(pdf) print("PDF 页数:", doc.page_count) for p in pages: if 1 <= p <= doc.page_count: doc[p - 1].get_pixmap(dpi=110).save( os.path.join(PREV, f"p{p:02d}.png")) if pages: print("已渲染预览页:", pages) report_gaps(doc) if __name__ == "__main__": main()