| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- # -*- 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()
|