# -*- coding: utf-8 -*- """合并成册后的自检:目录条目、页码连续性、并入完整性、占位项清单。""" import io import os import re import sys import fitz sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8") HERE = os.path.dirname(os.path.abspath(__file__)) PDF = os.path.join(HERE, "_bid_preview", "响应文件(完整版)-2026年河南产互联制造业数据智能运营平台研发项目.pdf") d = fitz.open(PDF) pages = [d[i].get_text() for i in range(d.page_count)] print(f"总页数 {d.page_count}") # ---------------- 目录:条目、层级、页码 toc_pages = [i for i, t in enumerate(pages[:8]) if "目 录" in t or "目 录" in t] toc_txt = "".join(pages[i] for i in range(toc_pages[0], toc_pages[0] + 4)) \ if toc_pages else "" ENTRY = re.compile(r"^(.*?)\s\.{3,}\s*(\d+)\s*$", re.M) entries = ENTRY.findall(toc_txt) print(f"目录页 P{toc_pages[0] + 1} 起,抓到条目 {len(entries)} 条") bad = [e for e in entries if re.search(r"(四、\s*四、|(三)\s*(三))", e[0])] print(" 重复编号:", bad or "无") nums = [int(n) for _, n in entries] print(" 页码是否单调不减:", all(b >= a for a, b in zip(nums, nums[1:]))) print(" 目录首条 / 末条:", entries[0][0].strip()[:30] if entries else "-", "/", entries[-1][0].strip()[:30] if entries else "-") # ---------------- 页脚页码连续性:每页末尾的独立数字 foot = [] for i, t in enumerate(pages): m = re.match(r"\s*(\d+)\s", t) # 页码在页面文本流最前(页脚被前置) foot.append(int(m.group(1)) if m else None) miss = [i + 1 for i, v in enumerate(foot) if v is None] jump = [(i + 1, foot[i], foot[i + 1]) for i in range(len(foot) - 1) if foot[i] is not None and foot[i + 1] is not None and foot[i + 1] != foot[i] + 1] print(f"\n页脚页码:缺失 {len(miss)} 页 {miss[:8]} 断号 {len(jump)} 处 {jump[:6]}") # ---------------- 并入完整性:各部分标志性文字 MARKS = { "增值税专票承诺书": "关于能够提供增值税专用发票的承诺书", "不组联合体承诺书": "关于不组成联合体及中选后不转包的承诺书", "资格及信用承诺书": "关于资格条件及信用状况的承诺书", "软著一览表": "计算机软件著作权登记证书一览表", "项目团队表": "项目团队岗位职责与人员配备表", "4 项目需求理解": "4、项目需求理解及综合分析", "5 系统功能展示": "5、系统功能展示", "6 系统建设方案": "6、系统建设方案", "7 智能诊断": "7、智能诊断与分析方案", "8 UAT 测试": "8、UAT 测试与质量保障", "9 质量与工期": "9、质量与工期保障", "10 应急支撑": "10、应急支撑方案", "11 售后服务": "11、售后服务方案", "12 项目培训": "12、项目培训方案", } print("\n并入完整性:") for label, key in MARKS.items(): hit = next((i + 1 for i, t in enumerate(pages) if key.replace(" ", "") in t.replace(" ", "").replace("\n", "")), None) print(f" {'○' if hit else '×'} {label:<18} {('P' + str(hit)) if hit else '未找到'}") # ---------------- 残留占位与标记 print("\n残留检查:") for tok, name in (("@@MERGE", "合并标记"), ("【待填", "待填占位"), ("【待补", "待补占位")): hits = [i + 1 for i, t in enumerate(pages) if tok in t] print(f" {name}:{len(hits)} 页 {hits[:12]}")