# -*- coding: utf-8 -*- """自检:报价、业绩表、插入的图片数量与剩余占位项。""" import io import os import re import sys from docx import Document sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8") BID = r"C:\Users\skygu\OneDrive\Projects\AIDOP\项目\项目招投标" NAME = "响应文件(完整版)-2026年河南产互联制造业数据智能运营平台研发项目.docx" BLIP = ("{http://schemas.openxmlformats.org/drawingml/2006/main}blip") def check(path, label): d = Document(path) print(f"\n{'=' * 74}\n{label} {os.path.getsize(path) / 1024 / 1024:.1f}MB") print(f"段落 {len(d.paragraphs)} 表格 {len(d.tables)}") imgs = sum(len(p._p.findall(f".//{BLIP}")) for p in d.paragraphs) for t in d.tables: for row in t.rows: for c in row.cells: for p in c.paragraphs: imgs += len(p._p.findall(f".//{BLIP}")) print(f"图片 {imgs} 张") print("\n-- 报价 --") for i, p in enumerate(d.paragraphs): if re.search(r"5[68]6?,?000|伍拾陆万|伍拾捌万", p.text): m = re.findall(r"(?:伍拾[陆捌]万\S{0,6}|5[68]\d,000\.00)", p.text) print(f" 段P{i}: {' '.join(m)}") c = d.tables[0].rows[3].cells[1] print(f" 响应函附录: {c.text.replace(chr(10), ' / ')}") print("\n-- 业绩表 --") for i in range(2, 7): t = d.tables[i] print(f" [业绩{i - 1}]") for row in t.rows: k = row.cells[0].text.strip() v = row.cells[1].text.strip() flag = " ← 未填!" if "【待" in v else "" print(f" {k}:{v[:76]}{flag}") print("\n-- 剩余占位项 --") left = [(i, p.text.strip()) for i, p in enumerate(d.paragraphs) if "【待补" in p.text or "【待填" in p.text] for i, t in left: print(f" P{i}: {t[:96]}") for ti, t in enumerate(d.tables): for ri, row in enumerate(t.rows): for ci, cc in enumerate(row.cells): if "【待补" in cc.text or "【待填" in cc.text: print(f" 表{ti} 行{ri} 列{ci}: {cc.text.strip()[:80]}") print(f" 共 {len(left)} 处段落占位") check(os.path.join(BID, NAME), "响应文件(已改)") stale = os.path.join(BID, NAME[:-5] + "(已签章).docx") if os.path.exists(stale): d = Document(stale) shapes = len(d.element.body.findall( ".//{http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing}anchor")) print(f"\n{'=' * 74}\n遗留文件「(已签章)」:浮动图形 {shapes} 个," f"{os.path.getsize(stale) / 1024 / 1024:.1f}MB")