开发者

Python使用pypandoc将markdown文件和LaTex公式转为word

目录
  • 一 pypandoc 介绍
    • 1. 项目介绍
    • 2. 安装
  • 二、使用python 将markdown转Word
    • 三、直接指定Word格式
      • 四、将LaTex公式转为Word
        • 四、将LaTex公式转为Word,追加写入Word

          通义千问等大模型生成的回答多数是markdown类型的,需要将他们转为Word文件

          一 pypandoc 介绍

          1. 项目介绍

          pypandoc 是一个用于 pandoc 的轻量级 Python 包装器。pandoc 是一个通用的文档转换工具,支持多种格式的文档转换,如 Markdown、html、LaTeX、DocBook 等。pypandoc 通过提供一个简单的 Python 接口,使得在 Python 脚本中调用 pandoc 变得更加方便。

          2. 安装

          使用pip安装

          pip install pypandoc_binary
          

          自动下载 Pandoc并安装

          注意:pypandoc 提供了两个包:

          pypandoc:需要用户自行安装 pandoc软件才能使用。

          pypandoc_binary:包含了预编译的 pandoc 二进制文件,方便用户快速上手。

          手动安装

          可以手动安装pandoc再安装pypandoc库

          pip install pypandoc
          

          也可以先安装pypandoc然后再在pyhon中运行 pypandoc.download_pandoc()函数自动下载并安装 Pandoc,将其存放在 pypandoc 可以访问的目录中。

          二、使用Python 将markdown转Word

          本脚本实现了三类功能

          1、将markdown文件转为word文件

          2、将 markdown中段落开头的“-“转为回车,避免渲染成黑点或者空心圆等Word中不常见的符号

          3、自定义了模板,格式化输出。

          import pypandoc
          import time
          import re
          
          # 定义路径
          path1 = r"md.md"
          path2 = r".docx"
          template_path = r"D:\aTools\ytemplates\templates_s.docx"
          
          # 读取原始Markdown文件内容
          with open(path1, 'r', encoding='utf-8') as file:
              content = file.read()
          
          # 使用正则表达式将以'- '开头的部分替换为换行符
          processed_content = re.sub(r'- ', '\n', content)
          
          # 记录开始时间
          t1 = time.time()
          
          # 将处理后的内容转换为编程客栈Word文档
          pypandoc.convert_text(
              processed_content,
              'docx',
              format='md',
              outputfile=path2,
              extra_args=['--reference-doc', template_path]
          )
          
          # 打印耗时
          print(time.time() - t1)
          print("转换完成!")
          

          三、直接指定Word格式

          直接读取文件(可以为txt或者md)转为指定格式的word。

          这里格式是:

          1、将 markdown中段落开头的“-“转为回车,避免渲染成黑点或者空心圆等Word中不常见的符号

          2、将原来加粗部分继续加粗和左对齐

          3、字体为黑色GB2312

          注意:代码用正则替换####这些时需要先从4级标题开始替换否则会有逻辑错误,导致奇数个#无法替换。

          设置中文字体不能用run.font.name = '仿宋_GB2312’而是用style._element.rPr.rFonts.set(qn(‘w:eastAsia’), ‘仿宋_GB2312’) 设置中文字体。

          import re
          from docx import Document
          from docx.shared import Pt, RGBColor
          from docx.enum.text import WD_ALIGN_PARAGRAPH
          from docx.oXML.ns import qn
          
          def set_font_color(run):
              run.font.name = 'Times New Roman'
              run._element.rPr.rFonts.set(qn('w:eastAsia'), '仿宋_GB2312')
              run.font.size = Pt(12)
              run.font.color.rgb = RGBColor(0, 0, 0)
              run.italijsc = False
          
          def process_content(line, paragraph):
              """通用内容处理函数"""
              bold_pattern = re.compile(r'\*\*(.*?)\*\*')
              matches = list(bold_pattern.finditer(line))
              
              if not matches:
                  run = paragraph.add_run(line)
                  set_font_color(run)
              else:
                  start = 0
                  for match in matches:
                      if match.start() > start:
                          run = paragraph.add_run(line[start:match.start()])
                          set_font_color(run)
                      run = paragraph.add_run(match.group(1))
                      run.bold = True
                      set_font_color(run)
                      start = match.end()
                  if start < len(line):
                      run = paragraph.add_run(line[start:])
                      set_font_color(run)
          
          def mdtxt2word(txt_path, docx_path):
              with open(txt_path, 'r', encoding='utf-8') as file:
                  content = re.sub(r'- ', '\n', file.read())
          
              doc = Document()
              style = doc.styles['Normal']
              style.font.name = 'Times New Roman'
              style._element.rPr.rFonts.set(qn('w:eastAsia'), '仿宋_GB2312')
              style.font.size = Pt(12)
              style.font.color.rgb = RGBColor(0, 0, 0)
          
              # 合并标题正则表达式
              heading_pattern = re.compile(
                  r'^\s*(#{1,4})\s*(javascript.*?)\s*$'  # 匹配1-4个#开头的标题
              )
          
              for line in content.split('\n'):
                  # 处理所有标题类型
                  heading_match = heading_pattern.match(line)
                  if heading_match:
                      level = len(heading_match.group(1))  # 根据#数量确定级别
                      title_text = heading_match.group(2).strip()
                      
                      if not title_text:
                          continue  # 跳过空标题
          
                      # 创建对应级别的标题
                      heading = doc.add_heading(level=min(level, 4))  # 限制最大4级
                      heading.alignment = WD_ALIGN_PARAGRAPH.LEFT
                      
                      # 处理标题内容中的加粗标记
                      process_content(titwww.devze.comle_text, heading)
                      continue
          
                  # 处理普通段落
                  paragraph = doc.add_paragraph()
                  paragraph.alignment = WD_ALIGN_PARAGRAPH.LEFT
                  process_content(line, paragraph)
          
              doc.save(docx_path)
              print("转换完成!")
          
          if __name__ == "__main__":
              txt_path = r"C:\Users\xueshifeng\Desktop\11.txt"
              docx_path = r"C:\Users\xueshifeng\Desktop\11.docx"
              mdtxt2word(txt_path, docx_path)
          

          四、将LaTex公式转为Word

          将 latex_content字符串$ $ 中间的位置替换为公式,或者直接复制代码到GPT,让GPT修改代码

          import pypandoc
          
          # 定义包含特定公式的LaTeX字符串
          #$ $ 中间的位置替换为公式,或者直接复制代码到GPT,让GPT生成最终代码
          latex_content = r"""
          \documentclass{article}
          \usepackage{amsmath} % 确保包含用于数学排版的包
          \begin{document}
          
          $ L(y_i, f(x_i)) = \max(0, 1 - y_if(x_i)) $
          
          
          \end{document}
          """
          
          # 将LaTeX内容转换为Word文档
          output_file = r"xx14.docx"
          
          output = pypandoc.convert_text(
              latex_content,  # 输入的字符串
              'docx',         # 输出格式
              format='latex', # 输入格式(LaTeX)
              outputfile=output_file,  # 输出文件路径
              extra_args=['--mathml']  # 额外参数,确保公式渲染为MathML格式
          )
          
          # 检查转换是否成功
          if output != '':
              print(f"转换过程中出现错误: {output}")
          else:
              print(f"Word 文档已生成: {output_file}")
          

          四、将LaTex公式转为Word,追加写入Word

          难点在于如何管理文件句柄,没有找到好方法,采用对已打开的文档,先关闭再打开的方法。

          import os
          import pypandoc
          from docx import Document
          import tempfile
          import time
          import pythoncom
          www.devze.comfrom win32com.client import Dispatch  # 需要安装pywin32库
          
          def is_file_locked(filepath):
              try:
                  with open(filepath, 'a'):
                      return False
              except PermissionError:
                  return True
              except FileNotFoundError:
                  return False
          
          def close_word_document(filepath):
              try:
                  word = Dispatch("Word.Application")
                  for doc in word.Documents:
                      if doc.FullName.lower() == os.path.abspath(filepath).lower():
                          doc.Save()
                          doc.Close()
                          print("已保存并关闭Word文档")
                          return True
                  word.Quit()
              except Exception as e:
                  print(f"关闭Word文档失败:{str(e)}")
              return False
          
          def generate_latex_content(formula):
              """生成完整的LaTeX文档内容"""
              return fr"""
              \documentclass{{article}}
              \usepackage{{amsmath}}
              \begin{{document}}
          
              开始:
          
              ${formula}$
          
              结束。
              \end{{document}}
              
              """
              
          def doc_creat(user_formula, output_file):
          
          
              # 检查文件是否存在
              if not os.path.exists(output_file):
                  # 创建新文档对象
                  doc = Document()
                  # 保存文档
                  doc.save(output_file)
                  print(f"文件已创建:{output_file}")
                  document = Document(output_file)
              else:
                  print("文件已打开")
                  
              
              
              retry_count = 3
              for _ in range(retry_count):
                  if is_file_locked(output_file):
                      print("检测到文件被占用,尝试关闭Word文档...")
                      if close_word_document(output_file):
                          time.sleep(0.5)  # 等待系统释放文件
                          continue
                      else:
                          print("错误:文件被其他程序占用,请手动关闭后重试!")
                          break
          
                  try:
                      with tempfile.NamedTemporaryFile(delete=False, suffix=".tex") as temp_tex_file:
                          latex_content = generate_latex_content(user_formula)
                          temp_tex_file.write(latex_content.encode('utf-8'))
                          temp_tex_file_name = temp_tex_file.name
          
                      with tempfile.NamedTemporaryFile(delete=False, suffix=".docx") as temp_docx_file:
                          temp_docx_file_name = temp_docx_file.name
          
                      # 转换LaTeX到Word
                      pypandoc.convert_file(
                          temp_tex_file_name, 'docx', 
                          outputfile=temp_docx_file_name, extra_args=['--mathjax']
                      )
          
                      # 创建或打开目标文档
                      target_doc = Document(output_file) if os.path.exists(output_file) else Document()
                      temp_doc = Document(temp_docx_file_name)
                      
                      # 复制所有元素
                      for element in temp_doc.element.body:
                          target_doc.element.body.append(element)
                      
                      # 保存目标文档
                      target_doc.save(output_file)
                      print(f"内容已成功追加至:{output_file}")
                      
                      # 自动用Word打开文档
                      os.startfile(output_file)
                      break
          
                  except PermissionError:
                      print("文件权限错误,请检查文件是否被其他程序占用")
                      break
                  except Exception as e:
                      print(f"操作失败:{str(e)}")
                      break
                  finally:
                      if 'temp_tex_file_name' in locals() and os.path.exists(temp_tex_file_name):
                          os.unlink(temp_tex_file_name)
                      if 'temp_docx_file_name' in locals() and os.path.exists(temp_docx_file_name):
                          os.unlink(temp_docx_file_name)
              else:
                  print("重试次数已达上限,请检查文件状态")
          
          if __name__ == '__main__':
              # 用户输入公式(示例)
              user_formula = r"\frac{\sqrt{x^2 + y^2}}{z}"   
              # 输出文件路径
              output_file = r"C:\Users\xueshifeng\Desktop\18.docx"
              
              doc_creat(user_formula, output_file)
          

          以上就是Python使用pypandoc将markdown文件和LaTex公式转为word的详细内容,更多关于Python pypandoc格式转换的资料请关注编程客栈(www.devze.com)其它相关文章!

          0

          上一篇:

          下一篇:

          精彩评论

          暂无评论...
          验证码 换一张
          取 消

          最新开发

          开发排行榜