| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 |
- # -*- 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]}")
|