Files
mdpolish/cleaner/cli.py
T
Bepr4 c19e9fcebf govdoc-md-cleaner v0.1.0: 政务文档 Markdown 清洗工具(规则引擎 + CLI + 测试)
- 8 条 YAML 声明规则:页码/页眉页脚/目录点线/图片/HTML表格/散落标签/行尾空白/空行
- 防误伤设计:protect 正则 + 内容形态豁免 + OCR burst 检测
- md-clean single/batch CLI,JSON 清洗报告
- 18 个单元测试

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-20 17:04:10 +08:00

90 lines
3.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""命令行入口。
用法:
md-clean single <input.md> [-o output.md] [--diff] [--rules rules.yaml]
md-clean batch <dir> [-o outdir] [--pattern "*.md"] [--report report.json]
"""
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
from typing import List, Optional
from cleaner.cleaner import MarkdownCleaner
from cleaner.rules import load_rules
def _build(path: Optional[Path]) -> MarkdownCleaner:
return MarkdownCleaner(rules=load_rules(path))
def cmd_single(args: argparse.Namespace) -> int:
cleaner = _build(args.rules)
src = Path(args.input)
raw = src.read_text(encoding="utf-8")
result = cleaner.clean_text(raw)
if args.output:
Path(args.output).parent.mkdir(parents=True, exist_ok=True)
Path(args.output).write_text(result.text, encoding="utf-8")
print(f"已写入 {args.output}")
if args.diff:
print(MarkdownCleaner.diff(raw, result.text))
print(json.dumps(result.stats, ensure_ascii=False, indent=2))
return 0
def cmd_batch(args: argparse.Namespace) -> int:
cleaner = _build(args.rules)
src_dir = Path(args.directory)
files = sorted(p for p in src_dir.rglob(args.pattern) if p.is_file())
if not files:
print(f"在 {src_dir} 下未找到匹配 {args.pattern} 的文件", file=sys.stderr)
return 1
out_dir = Path(args.output) if args.output else src_dir.parent / (src_dir.name + "_cleaned")
report = []
for f in files:
rel = f.relative_to(src_dir)
dst = out_dir / rel
result = cleaner.clean_file(f, dst)
report.append({"file": str(rel), "stats": result.stats})
hits = result.total_hits
print(f"[ok] {rel} 命中 {hits} 处")
if args.report:
Path(args.report).parent.mkdir(parents=True, exist_ok=True)
Path(args.report).write_text(
json.dumps({"files": report}, ensure_ascii=False, indent=2), encoding="utf-8"
)
print(f"报告已写入 {args.report}")
print(f"共清洗 {len(files)} 个文件 → {out_dir}")
return 0
def main(argv: Optional[List[str]] = None) -> int:
parser = argparse.ArgumentParser(prog="md-clean", description="政务文档 Markdown 清洗工具")
sub = parser.add_subparsers(dest="command", required=True)
p1 = sub.add_parser("single", help="清洗单个文件")
p1.add_argument("input", help="输入 .md 文件")
p1.add_argument("-o", "--output", help="输出路径(缺省打印统计不写文件)")
p1.add_argument("--diff", action="store_true", help="打印 unified diff")
p1.add_argument("--rules", type=Path, help="规则 YAML 路径")
p2 = sub.add_parser("batch", help="批量清洗目录(递归)")
p2.add_argument("directory", help="输入目录")
p2.add_argument("-o", "--output", help="输出目录(缺省 <dir>_cleaned")
p2.add_argument("--pattern", default="*.md", help="文件 glob(默认 *.md")
p2.add_argument("--report", help="清洗报告 JSON 输出路径")
p2.add_argument("--rules", type=Path, help="规则 YAML 路径")
args = parser.parse_args(argv)
if args.command == "single":
return cmd_single(args)
return cmd_batch(args)
if __name__ == "__main__":
sys.exit(main())