cli.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. """
  2. cli.py - 命令行入口
  3. 用法:
  4. # 单文件模式(所有表格放入一个 DOCX)
  5. python -m pdf_table_to_docx <pdf_path>
  6. # 目录模式(JSON 元数据 + 每个表格独立 DOCX)
  7. python -m pdf_table_to_docx <pdf_path> --dir
  8. 示例:
  9. python -m pdf_table_to_docx data/sample.pdf
  10. python -m pdf_table_to_docx data/sample.pdf -o output.docx
  11. python -m pdf_table_to_docx data/sample.pdf --dir -o output_dir/
  12. python -m pdf_table_to_docx data/sample.pdf --dir --verbose
  13. """
  14. import argparse
  15. import logging
  16. import sys
  17. from .extractor import PDFTableExtractor
  18. def setup_logging(verbose: bool = False):
  19. """配置日志输出。"""
  20. level = logging.DEBUG if verbose else logging.INFO
  21. fmt = "%(asctime)s [%(levelname)s] %(message)s"
  22. datefmt = "%H:%M:%S"
  23. logging.basicConfig(
  24. level=level,
  25. format=fmt,
  26. datefmt=datefmt,
  27. stream=sys.stderr,
  28. )
  29. def main():
  30. parser = argparse.ArgumentParser(
  31. description="从 PDF 中提取表格并生成 DOCX 文件",
  32. formatter_class=argparse.RawDescriptionHelpFormatter,
  33. epilog="""
  34. 使用示例:
  35. %(prog)s document.pdf # 单 DOCX 模式
  36. %(prog)s document.pdf --dir # 目录模式(JSON + 每表独立 DOCX)
  37. %(prog)s document.pdf -o result.docx # 指定输出文件
  38. %(prog)s document.pdf --dir -o output_dir/ # 指定输出目录
  39. %(prog)s document.pdf --verbose # 详细日志
  40. %(prog)s document.pdf --page-width 42 --page-height 29.7 # A3 横版
  41. """,
  42. )
  43. parser.add_argument(
  44. "pdf_path",
  45. help="输入的 PDF 文件路径",
  46. )
  47. parser.add_argument(
  48. "-o", "--output",
  49. help="输出路径(单文件模式时是 .docx,目录模式时是文件夹路径)",
  50. )
  51. parser.add_argument(
  52. "--dir", "--directory",
  53. action="store_true",
  54. dest="dir_mode",
  55. help="目录模式:输出 JSON 元数据 + 每个表格独立的 DOCX 文件",
  56. )
  57. parser.add_argument(
  58. "--verbose", "-v",
  59. action="store_true",
  60. help="输出详细日志",
  61. )
  62. parser.add_argument(
  63. "--page-width",
  64. type=float,
  65. default=21.0,
  66. help="页面宽度,单位厘米(默认 21.0,即 A4)",
  67. )
  68. parser.add_argument(
  69. "--page-height",
  70. type=float,
  71. default=29.7,
  72. help="页面高度,单位厘米(默认 29.7,即 A4)",
  73. )
  74. parser.add_argument(
  75. "--margin",
  76. type=float,
  77. default=2.0,
  78. help="页边距,单位厘米(默认 2.0)",
  79. )
  80. args = parser.parse_args()
  81. setup_logging(verbose=args.verbose)
  82. logger = logging.getLogger(__name__)
  83. try:
  84. extractor = PDFTableExtractor(args.pdf_path)
  85. if args.dir_mode:
  86. # ---- 目录模式 ----
  87. output_dir = extractor.to_docx_directory(
  88. output_dir=args.output,
  89. page_width_cm=args.page_width,
  90. page_height_cm=args.page_height,
  91. margin_cm=args.margin,
  92. )
  93. if output_dir:
  94. print(f"\n✅ 表格已提取至目录: {output_dir}", file=sys.stderr)
  95. print(f" 元数据: {output_dir}/tables.json", file=sys.stderr)
  96. print(f" 表格: {output_dir}/tables/", file=sys.stderr)
  97. else:
  98. print("\n⚠️ 未检测到表格或处理失败", file=sys.stderr)
  99. sys.exit(1)
  100. else:
  101. # ---- 单文件模式(默认) ----
  102. output = extractor.to_docx(
  103. output_path=args.output,
  104. page_width_cm=args.page_width,
  105. page_height_cm=args.page_height,
  106. margin_cm=args.margin,
  107. )
  108. if output:
  109. print(f"\n✅ 表格已提取并保存至: {output}", file=sys.stderr)
  110. else:
  111. print("\n⚠️ 未检测到表格或处理失败", file=sys.stderr)
  112. sys.exit(1)
  113. except FileNotFoundError as e:
  114. logger.error(e)
  115. sys.exit(1)
  116. except Exception as e:
  117. logger.exception(f"处理失败: {e}")
  118. sys.exit(1)
  119. if __name__ == "__main__":
  120. main()