_tmp_toc_verify.py 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. # -*- coding: utf-8 -*-
  2. """核对目录里的页码与正文标题实际所在页是否一致。"""
  3. import io
  4. import os
  5. import re
  6. import sys
  7. import fitz
  8. sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8")
  9. HERE = os.path.dirname(os.path.abspath(__file__))
  10. PDF = os.path.join(HERE, "_tmp_inspect", "current.pdf")
  11. d = fitz.open(PDF)
  12. print(f"PDF 共 {d.page_count} 页")
  13. # 目录只在正文开始前(响应函在第 9 页),限定在前 8 页里找
  14. HEAD = 8
  15. toc_pages = [i for i in range(1, HEAD + 1)
  16. if len(re.findall(r"[^\s]\s+\d{1,3}\s*$",
  17. d[i - 1].get_text(), re.M)) >= 5]
  18. print("目录所在页:", toc_pages)
  19. entries = []
  20. for i in toc_pages:
  21. for line in d[i - 1].get_text().split("\n"):
  22. m = re.match(r"^(.*?)[\s.\u2026]+(\d{1,3})$", line.strip())
  23. if m and len(m.group(1).strip()) >= 3:
  24. entries.append((m.group(1).strip(), int(m.group(2))))
  25. print(f"解析出目录条目 {len(entries)} 条\n")
  26. # 正文里每个标题实际出现的页(跳过目录页本身)
  27. body_text = {i: d[i - 1].get_text() for i in range(1, d.page_count + 1)}
  28. bad = 0
  29. for title, claim in entries:
  30. key = re.sub(r"\s+", "", title)
  31. hit = None
  32. for i in range(HEAD + 1, d.page_count + 1):
  33. if key and key in re.sub(r"\s+", "", body_text[i]):
  34. hit = i
  35. break
  36. if hit is None:
  37. print(f" ? 正文未找到:{title[:44]}(目录写 {claim})")
  38. bad += 1
  39. elif hit != claim:
  40. print(f" × {title[:44]} 目录 {claim} ≠ 实际 {hit}")
  41. bad += 1
  42. print(f"\n不一致 {bad} 条 / 共 {len(entries)} 条")
  43. d.close()