common.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. import copy
  2. import json as json_parse
  3. import os
  4. import click
  5. from loguru import logger
  6. import magic_pdf.model as model_config
  7. from magic_pdf.libs.draw_bbox import (draw_layout_bbox, draw_line_sort_bbox,
  8. draw_model_bbox, draw_span_bbox)
  9. from magic_pdf.libs.MakeContentConfig import DropMode, MakeMode
  10. from magic_pdf.pipe.OCRPipe import OCRPipe
  11. from magic_pdf.pipe.TXTPipe import TXTPipe
  12. from magic_pdf.pipe.UNIPipe import UNIPipe
  13. from magic_pdf.rw.AbsReaderWriter import AbsReaderWriter
  14. from magic_pdf.rw.DiskReaderWriter import DiskReaderWriter
  15. import fitz
  16. # from io import BytesIO
  17. # from pypdf import PdfReader, PdfWriter
  18. def prepare_env(output_dir, pdf_file_name, method):
  19. local_parent_dir = os.path.join(output_dir, pdf_file_name, method)
  20. local_image_dir = os.path.join(str(local_parent_dir), 'images')
  21. local_md_dir = local_parent_dir
  22. os.makedirs(local_image_dir, exist_ok=True)
  23. os.makedirs(local_md_dir, exist_ok=True)
  24. return local_image_dir, local_md_dir
  25. # def convert_pdf_bytes_to_bytes_by_pypdf(pdf_bytes, start_page_id=0, end_page_id=None):
  26. # # 将字节数据包装在 BytesIO 对象中
  27. # pdf_file = BytesIO(pdf_bytes)
  28. # # 读取 PDF 的字节数据
  29. # reader = PdfReader(pdf_file)
  30. # # 创建一个新的 PDF 写入器
  31. # writer = PdfWriter()
  32. # # 将所有页面添加到新的 PDF 写入器中
  33. # end_page_id = end_page_id if end_page_id is not None and end_page_id >= 0 else len(reader.pages) - 1
  34. # if end_page_id > len(reader.pages) - 1:
  35. # logger.warning("end_page_id is out of range, use pdf_docs length")
  36. # end_page_id = len(reader.pages) - 1
  37. # for i, page in enumerate(reader.pages):
  38. # if start_page_id <= i <= end_page_id:
  39. # writer.add_page(page)
  40. # # 创建一个字节缓冲区来存储输出的 PDF 数据
  41. # output_buffer = BytesIO()
  42. # # 将 PDF 写入字节缓冲区
  43. # writer.write(output_buffer)
  44. # # 获取字节缓冲区的内容
  45. # converted_pdf_bytes = output_buffer.getvalue()
  46. # return converted_pdf_bytes
  47. def convert_pdf_bytes_to_bytes_by_pymupdf(pdf_bytes, start_page_id=0, end_page_id=None):
  48. document = fitz.open("pdf", pdf_bytes)
  49. output_document = fitz.open()
  50. end_page_id = end_page_id if end_page_id is not None and end_page_id >= 0 else len(document) - 1
  51. if end_page_id > len(document) - 1:
  52. logger.warning("end_page_id is out of range, use pdf_docs length")
  53. end_page_id = len(document) - 1
  54. output_document.insert_pdf(document, from_page=start_page_id, to_page=end_page_id)
  55. output_bytes = output_document.tobytes()
  56. return output_bytes
  57. def do_parse(
  58. output_dir,
  59. pdf_file_name,
  60. pdf_bytes,
  61. model_list,
  62. parse_method,
  63. debug_able,
  64. f_draw_span_bbox=True,
  65. f_draw_layout_bbox=True,
  66. f_dump_md=True,
  67. f_dump_middle_json=True,
  68. f_dump_model_json=True,
  69. f_dump_orig_pdf=True,
  70. f_dump_content_list=True,
  71. f_make_md_mode=MakeMode.MM_MD,
  72. f_draw_model_bbox=False,
  73. f_draw_line_sort_bbox=False,
  74. start_page_id=0,
  75. end_page_id=None,
  76. lang=None,
  77. layout_model=None,
  78. formula_enable=None,
  79. table_enable=None,
  80. ):
  81. if debug_able:
  82. logger.warning('debug mode is on')
  83. f_draw_model_bbox = True
  84. f_draw_line_sort_bbox = True
  85. if lang == "":
  86. lang = None
  87. pdf_bytes = convert_pdf_bytes_to_bytes_by_pymupdf(pdf_bytes, start_page_id, end_page_id)
  88. orig_model_list = copy.deepcopy(model_list)
  89. local_image_dir, local_md_dir = prepare_env(output_dir, pdf_file_name,
  90. parse_method)
  91. image_writer, md_writer = DiskReaderWriter(
  92. local_image_dir), DiskReaderWriter(local_md_dir)
  93. image_dir = str(os.path.basename(local_image_dir))
  94. if parse_method == 'auto':
  95. jso_useful_key = {'_pdf_type': '', 'model_list': model_list}
  96. pipe = UNIPipe(pdf_bytes, jso_useful_key, image_writer, is_debug=True,
  97. # start_page_id=start_page_id, end_page_id=end_page_id,
  98. lang=lang,
  99. layout_model=layout_model, formula_enable=formula_enable, table_enable=table_enable)
  100. elif parse_method == 'txt':
  101. pipe = TXTPipe(pdf_bytes, model_list, image_writer, is_debug=True,
  102. # start_page_id=start_page_id, end_page_id=end_page_id,
  103. lang=lang,
  104. layout_model=layout_model, formula_enable=formula_enable, table_enable=table_enable)
  105. elif parse_method == 'ocr':
  106. pipe = OCRPipe(pdf_bytes, model_list, image_writer, is_debug=True,
  107. # start_page_id=start_page_id, end_page_id=end_page_id,
  108. lang=lang,
  109. layout_model=layout_model, formula_enable=formula_enable, table_enable=table_enable)
  110. else:
  111. logger.error('unknown parse method')
  112. exit(1)
  113. pipe.pipe_classify()
  114. if len(model_list) == 0:
  115. if model_config.__use_inside_model__:
  116. pipe.pipe_analyze()
  117. orig_model_list = copy.deepcopy(pipe.model_list)
  118. else:
  119. logger.error('need model list input')
  120. exit(2)
  121. pipe.pipe_parse()
  122. pdf_info = pipe.pdf_mid_data['pdf_info']
  123. if f_draw_layout_bbox:
  124. draw_layout_bbox(pdf_info, pdf_bytes, local_md_dir, pdf_file_name)
  125. if f_draw_span_bbox:
  126. draw_span_bbox(pdf_info, pdf_bytes, local_md_dir, pdf_file_name)
  127. if f_draw_model_bbox:
  128. draw_model_bbox(copy.deepcopy(orig_model_list), pdf_bytes, local_md_dir, pdf_file_name)
  129. if f_draw_line_sort_bbox:
  130. draw_line_sort_bbox(pdf_info, pdf_bytes, local_md_dir, pdf_file_name)
  131. md_content = pipe.pipe_mk_markdown(image_dir,
  132. drop_mode=DropMode.NONE,
  133. md_make_mode=f_make_md_mode)
  134. if f_dump_md:
  135. md_writer.write(
  136. content=md_content,
  137. path=f'{pdf_file_name}.md',
  138. mode=AbsReaderWriter.MODE_TXT,
  139. )
  140. if f_dump_middle_json:
  141. md_writer.write(
  142. content=json_parse.dumps(pipe.pdf_mid_data,
  143. ensure_ascii=False,
  144. indent=4),
  145. path=f'{pdf_file_name}_middle.json',
  146. mode=AbsReaderWriter.MODE_TXT,
  147. )
  148. if f_dump_model_json:
  149. md_writer.write(
  150. content=json_parse.dumps(orig_model_list,
  151. ensure_ascii=False,
  152. indent=4),
  153. path=f'{pdf_file_name}_model.json',
  154. mode=AbsReaderWriter.MODE_TXT,
  155. )
  156. if f_dump_orig_pdf:
  157. md_writer.write(
  158. content=pdf_bytes,
  159. path=f'{pdf_file_name}_origin.pdf',
  160. mode=AbsReaderWriter.MODE_BIN,
  161. )
  162. content_list = pipe.pipe_mk_uni_format(image_dir, drop_mode=DropMode.NONE)
  163. if f_dump_content_list:
  164. md_writer.write(
  165. content=json_parse.dumps(content_list,
  166. ensure_ascii=False,
  167. indent=4),
  168. path=f'{pdf_file_name}_content_list.json',
  169. mode=AbsReaderWriter.MODE_TXT,
  170. )
  171. logger.info(f'local output dir is {local_md_dir}')
  172. parse_pdf_methods = click.Choice(['ocr', 'txt', 'auto'])