前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >python-mammoth - docx到 HTML 转换器

python-mammoth - docx到 HTML 转换器

原创
作者头像
1AI
发布2024-12-26 15:47:46
发布2024-12-26 15:47:46
12900
代码可运行
举报
文章被收录于专栏:PythonPython
运行总次数:0
代码可运行

python-mammoth - docx到 HTML 转换器

github : https://github.com/mwilliamson/python-mammoth

Mammoth旨在转换 .docx 文档,例如由Microsoft Word、Google Docs和LibreOffice创建的文档,并将其转换为 HTML 。Mammoth旨在通过使用文档中的语义信息来生成简单干净的 HTML ,而忽略其他细节。例如,Mammoth将任何样式为Heading 1的段落转换为h1元素,而不是试图完全复制标题的样式(字体、文本大小、颜色等)。

docx使用的结构和 HTML 的结构之间有很大的不匹配,这意味着转换不太可能完美地用于更复杂的文档。如果您只使用样式来语义标记文档,Mammoth效果最好。

目前支持以下功能:

  • 标题。undefined安装
  • 列表。
  • 从您自己的docx样式到 HTML 的可自定义映射。例如,您可以通过提供适当的样式映射将WarningHeading转换为h1.warning
  • 表格。当前忽略了表格本身的格式,例如边框,但文本的格式与文档的其余部分相同。
  • 脚注和尾注。
  • 图片。
  • 粗体、斜体、下划线、删除线、上标和下标。
  • 链接。
  • 换行符。
  • 文本框。输入框的内容被视为单独的段落,出现在包含输入框的段落之后。
  • 评论。
代码语言:shell
复制
pip install mammoth

其他支持的平台


CLI

您可以通过将路径传递给docx文件和输出文件来转换docx文件。例如:

代码语言:shell
复制
mammoth document.docx output.html

如果未指定输出文件,则将输出写入标准输出。

输出是使用UTF-8编码的 HTML 片段,而不是完整的 HTML 文档。由于片段中没有明确设置编码,如果浏览器不默认为UTF-8,在Web浏览器中打开输出文件可能会导致Unicode字符呈现不正确。


图片

默认情况下,图像包含在输出 HTML 中。如果输出目录由--output-dir指定,则图像将写入单独的文件。例如:

代码语言:shell
复制
mammoth document.docx --output-dir=output-dir

如果存在,现有文件将被覆盖。


风格

可以使用--style-map从文件中读取自定义样式映射。例如:

代码语言:shell
复制
mammoth document.docx output.html --style-map=custom-style-map

其中custom-style-map看起来像:

代码语言:shell
复制
p[style-name='Aside Heading'] => div.aside > h2:fresh
p[style-name='Aside Text'] => div.aside > p:fresh

样式映射的语法描述可以在“编写样式映射”部分找到。


Markdown

不推荐Markdown支持。建议生成 HTML 并使用单独的库将 HTML 转换为Markdown,并且可能会产生更好的结果。

使用--output-format=markdown将导致生成Markdown。例如:

代码语言:shell
复制
mammoth document.docx --output-format=markdown

Library


基本转换

要将现有的. docx文件转换为 HTML ,请将类似文件的对象传递给mammoth.convert_to_html。该文件应以二进制模式打开。例如:

代码语言:python
代码运行次数:0
复制
import mammoth

with open("document.docx", "rb") as docx_file:
    result = mammoth.convert_to_html(docx_file)
    html = result.value # The generated HTML
    messages = result.messages # Any messages, such as warnings during conversion

您还可以使用mammoth.extract_raw_text提取文档的原始文本。这将忽略文档中的所有格式。每个段落后面跟着两个换行符。

代码语言:python
代码运行次数:0
复制
with open("document.docx", "rb") as docx_file:
    result = mammoth.extract_raw_text(docx_file)
    text = result.value # The raw text
    messages = result.messages # Any messages

自定义样式图

默认情况下,Mammoth将一些常见的. docx样式映射到 HTML 元素。例如,样式名称为Heading 1的段落被转换为h1元素。您可以通过将带有style_map属性的选项对象作为第二个参数传递给convert_to_html来传递样式映射的自定义映射“编写样式映射”。例如,如果具有样式名称的段落Section Title应转换为h1元素,以及具有样式名称的段落Subsection Title应转换为h2元素:

代码语言:python
代码运行次数:0
复制
import mammoth

style_map = """
p[style-name='Section Title'] => h1:fresh
p[style-name='Subsection Title'] => h2:fresh
"""

with open("document.docx", "rb") as docx_file:
    result = mammoth.convert_to_html(docx_file, style_map=style_map)

用户定义的样式映射优先于默认样式映射使用。要完全停止使用默认样式映射,请传递include_default_style_map=False

代码语言:shell
复制
result = mammoth.convert_to_html(docx_file, style_map=style_map, include_default_style_map=False)

自定义图像处理程序

默认情况下,图像被转换为<img>元素,源包含在src属性中。可以通过将convert_image参数设置为图像转换器来更改此行为。

例如,以下将复制默认行为:

代码语言:python
代码运行次数:0
复制
def convert_image(image):
    with image.open() as image_bytes:
        encoded_src = base64.b64encode(image_bytes.read()).decode("ascii")

    return {
        "src": "data:{0};base64,{1}".format(image.content_type, encoded_src)
    }

mammoth.convert_to_html(docx_file, convert_image=mammoth.images.img_element(convert_image))

粗体

默认情况下,粗体文本包装在<strong>标签中。可以通过为b添加样式映射来更改此行为。例如,将粗体文本包装在<em>标签中:

代码语言:shell
复制
style_map = "b => em"

with open("document.docx", "rb") as docx_file:
    result = mammoth.convert_to_html(docx_file, style_map=style_map)

斜体

默认情况下,斜体字文本被包装在<em>标签中。可以通过为i添加样式映射来更改此行为。例如,将斜体字文本包装在<strong>标签中:

代码语言:shell
复制
style_map = "i => strong"

with open("document.docx", "rb") as docx_file:
    result = mammoth.convert_to_html(docx_file, style_map=style_map)

下划线

默认情况下,忽略任何文本的下划线,因为下划线可能会与 HTML 文档中的链接混淆。可以通过为u添加样式映射来更改此行为。例如,假设源文档使用下划线来强调。以下将在<em>标记中包装任何显式下划线的源文本:

代码语言:python
代码运行次数:0
复制
import mammoth

style_map = "u => em"

with open("document.docx", "rb") as docx_file:
    result = mammoth.convert_to_html(docx_file, style_map=style_map)

删除线

默认情况下,删除线文本被包装在<s>标签中。可以通过添加strike样式映射来更改此行为。例如,要将删除线文本包装在<del>标签中:

代码语言:shell
复制
style_map = "strike => del"

with open("document.docx", "rb") as docx_file:
    result = mammoth.convert_to_html(docx_file, style_map=style_map)

注释

默认情况下,注释将被忽略。要在生成的 HTML 中包含注释,请为comment-reference添加样式映射。例如:

代码语言:shell
复制
style_map = "comment-reference => sup"

with open("document.docx", "rb") as docx_file:
    result = mammoth.convert_to_html(docx_file, style_map=style_map)

注释将附加到文档的末尾,并使用指定的样式映射包装指向注释的链接。


API


mammoth.convert_to_html(fileobj, **kwargs)

将源文档转换为 HTML 。

  • fileobj:包含源文档的类似文件的对象。文件应该以二进制模式打开。undefinedmammoth.convert_to_markdown(fileobj, **kwargs)
  • style_map:用于指定Word样式到 HTML 的映射的字符串。有关语法的描述,请参阅“编写样式映射”部分。
  • include_embedded_style_map:默认情况下,如果文档包含嵌入的样式映射,则将其与默认样式映射组合。要忽略任何嵌入的样式映射,请传递include_embedded_style_map=False
  • include_default_style_map:默认情况下,传入style_map的样式映射与默认样式映射组合。要完全停止使用默认样式映射,请传递include_default_style_map=False
  • convert_image:默认情况下,图像被转换为<img>元素,源包含在src属性中。将此参数设置为图像转换器以覆盖默认行为。
  • ignore_empty_paragraphs:默认情况下,空段落被忽略。将此选项设置为False以保留输出中的空段落。
  • id_prefix:用于添加到任何生成的ID之前的字符串,例如书签、脚注和尾注使用的ID。默认为空字符串。
  • transform_document:如果设置,则此函数应用于转换为 HTML 之前从docx文件读取的文档。文档转换的API应该被认为是不稳定的。请参阅文档转换
  • 返回具有以下属性的结果:
    • value:生成的 HTML
    • messages:转换过程中生成的任何消息,如错误和警告

不推荐Markdown支持。建议生成 HTML 并使用单独的库将 HTML 转换为Markdown,并且可能会产生更好的结果。

将源文档转换为Markdown。这与convert_to_html的行为相同,只是结果的value属性包含Markdown而不是 HTML 。


mammoth.extract_raw_text(fileobj)

提取文档的原始文本。这将忽略文档中的所有格式。每个段落后面都有两个换行符。

  • fileobj:包含源文档的类似文件的对象。文件应该以二进制模式打开。undefinedmammoth.embed_style_map(fileobj, style_map)
  • 返回具有以下属性的结果:
    • value:原始文本
    • messages:任何消息,例如错误和警告

将样式映射style_map嵌入到fileobj中。当Mammoth读取文件对象时,它将使用嵌入的样式映射。

  • fileobj:包含源文件的类似文件的对象。应该以二进制模式打开文件进行读写。undefined留言
  • style_map:要嵌入的样式映射。
  • 返回None

每条消息具有以下属性:

  • type:表示消息类型的字符串,如"warning"undefined图像转换器
  • message:包含实际消息的字符串

可以通过调用mammoth.images.img_element(func)来创建图像转换器。这将为原始docx中的每个图像创建一个<img>元素。func应该是一个有一个参数image的函数。这个参数是正在转换的图像元素,并具有以下属性:

  • open():打开图像文件。返回一个类似文件的对象。
  • content_type:图像的内容类型,如image/png

func应该返回<img>元素的属性dict。至少,这应该包括src属性。如果找到图像的任何alt文本,这将自动添加到元素的属性中。

例如,以下复制默认图像转换:

代码语言:python
代码运行次数:0
复制
def convert_image(image):
    with image.open() as image_bytes:
        encoded_src = base64.b64encode(image_bytes.read()).decode("ascii")

    return {
        "src": "data:{0};base64,{1}".format(image.content_type, encoded_src)
    }

mammoth.images.img_element(convert_image)

mammoth.images.data_uri是默认的图像转换器。

Mammoth默认不处理WMF图像。食谱目录包含一个示例,说明如何使用LibreOffice转换它们,尽管转换的保真度完全取决于LibreOffice。


文档转换

文档转换的API应该被认为是不稳定的,并且可能在任何版本之间发生变化。如果您依赖此行为,您应该固定到特定版本的Mammoth,并在更新前仔细测试。

Mammoth允许在转换文档之前对其进行转换。例如,假设该文档没有进行语义标记,但您知道任何居中对齐的段落都应该是标题。您可以使用transform_document参数适当地修改文档:

代码语言:python
代码运行次数:0
复制
import mammoth.transforms

def transform_paragraph(element):
    if element.alignment == "center" and not element.style_id:
        return element.copy(style_id="Heading2")
    else:
        return element

transform_document = mammoth.transforms.paragraph(transform_paragraph)

mammoth.convert_to_html(fileobj, transform_document=transform_document)

或者,如果您希望已明确设置为使用等宽字体来表示代码的段落:

代码语言:python
代码运行次数:0
复制
import mammoth.documents
import mammoth.transforms

_monospace_fonts = set(["consolas", "courier", "courier new"])

def transform_paragraph(paragraph):
    runs = mammoth.transforms.get_descendants_of_type(paragraph, mammoth.documents.Run)
    if runs and all(run.font and run.font.lower() in _monospace_fonts for run in runs):
        return paragraph.copy(style_id="code", style_name="Code")
    else:
        return paragraph

convert_to_html(
    fileobj,
    transform_document=mammoth.transforms.paragraph(transform_paragraph),
    style_map="p[style-name='Code'] => pre:separator('\n')",
)

mammoth.transforms.paragraph(transform_paragraph)

返回一个可用作transform_document参数的函数。这将把函数transform_paragraph应用于每个段落元素。transform_paragraph应该返回新段落。


mammoth.transforms.run(transform_run)

返回一个可用作transform_document参数的函数。这将把函数transform_run应用于每个运行元素。transform_run应该返回新的运行。


mammoth.transforms.get_descendants(element)

获取元素的所有后代。


mammoth.transforms.get_descendants_of_type(element, type)

获取特定类型元素的所有后代。例如,要获取元素paragraph中的所有运行:

代码语言:python
代码运行次数:0
复制
import mammoth.documents
import mammoth.transforms

runs = mammoth.transforms.get_descendants_of_type(paragraph, documents.Run);

写作风格地图

样式映射由许多由新行分隔的样式映射组成。空行和以#开头的行将被忽略。

样式映射有两个部分:

  • 左侧箭头前是文档元素匹配器。
  • 右侧箭头后是 HTML 路径。

转换每个段落时,Mammoth会找到文档元素匹配器与当前段落匹配的第一个样式映射。然后,Mammoth确保满足 HTML 路径。


新鲜度

在编写样式映射时,理解Mammoth的新鲜概念很有帮助。在生成时,Mammoth只会在必要时关闭 HTML 元素。否则,元素会被重用。

例如,假设指定的样式映射之一是p[style-name='Heading 1'] => h1。如果Mammoth遇到样式名称为Heading 1的. docx段落,则.docx段落将转换为具有相同文本的h1元素。如果下一个.docx段落也具有样式名称Heading 1,则该段落的文本将附加到现有 h1元素,而不是创建新的h1元素。

在大多数情况下,您可能希望生成一个新的h1元素。您可以使用:fresh修饰符来指定这一点:

代码语言:shell
复制
p[style-name='Heading 1'] => h1:fresh

两个连续的Heading 1. docx段落将被转换为两个单独的h1元素。

重用元素对于生成更复杂的 HTML 结构很有用。例如,假设您的. docx包含旁白。每个旁白可能有一个标题和一些正文文本,它们应该包含在单个div.aside元素中。在这种情况下,样式映射类似于p[style-name='Aside Heading'] => div.aside > h2:freshp[style-name='Aside Text'] => div.aside > p:fresh可能会有所帮助。


文档元素匹配器


段落、运行和表格

匹配任何段落:

代码语言:shell
复制
p

匹配任何运行:

代码语言:shell
复制
r

匹配任何表格:

代码语言:shell
复制
table

要匹配具有特定样式的段落、运行或表格,您可以按名称引用样式。这是Microsoft Word或LibreOffice中显示的样式名称。例如,要匹配具有样式名称Heading 1的段落:

代码语言:shell
复制
p[style-name='Heading 1']

您还可以通过前缀匹配样式名称。例如,要匹配样式名称以Heading开头的段落:

代码语言:shell
复制
p[style-name^='Heading']

样式ID也可以引用样式。这是. docx文件内部使用的ID。要匹配段落或使用特定样式ID运行,请在样式ID后面附加一个点。例如,要匹配样式IDHeading1的段落:

代码语言:shell
复制
p.Heading1

粗体

匹配显式粗体文本:

代码语言:shell
复制
b

请注意,这匹配已显式应用粗体的文本。它不会匹配任何因其段落或运行样式而加粗的文本。


斜体的

显式匹配斜体字:

代码语言:shell
复制
i

请注意,这将匹配已显式应用斜体字的文本。它不会匹配任何因其段落或运行样式而成为斜体字的文本。


下划线

匹配显式下划线文本:

代码语言:shell
复制
u

请注意,这将匹配显式应用下划线的文本。它不会匹配任何因其段落或运行样式而带下划线的文本。


删除线

通过文本显式匹配结构:

代码语言:shell
复制
strike

请注意,这匹配已显式应用删除线的文本。它不会匹配任何因其段落或运行样式而被结构化的文本。


所有上限

显式匹配所有大写文本:

代码语言:shell
复制
all-caps

请注意,这匹配已显式应用所有大写的文本。由于其段落或运行样式,它不会匹配任何全部大写的文本。


小写

显式匹配小写文本:

代码语言:shell
复制
small-caps

请注意,这会匹配显式应用小写字母的文本。它不会匹配任何因其段落或运行样式而小写字母的文本。


高亮

匹配明确突出显示的文本:

代码语言:shell
复制
highlight

请注意,这匹配已显式应用突出显示的文本。它不会匹配任何因其段落或运行样式而突出显示的文本。

也可以匹配特定的颜色。例如,要匹配黄色高光:

代码语言:shell
复制
highlight[color='yellow']

通常使用的颜色集是:

  • blackundefined忽略文档元素
  • blue
  • cyan
  • green
  • magenta
  • red
  • yellow
  • white
  • darkBlue
  • darkCyan
  • darkGreen
  • darkMagenta
  • darkRed
  • darkYellow
  • darkGray
  • lightGray

使用!忽略文档元素。例如,忽略任何样式为Comment的段落:

代码语言:shell
复制
p[style-name='Comment'] => !

HTML 路径


单一元素

最简单的 HTML 路径是指定单个元素。例如,要指定一个h1元素:

代码语言:shell
复制
h1

要为元素提供CSS类,请附加一个点,后跟类名:

代码语言:shell
复制
h1.section-title

要添加属性,请使用类似于CSS属性选择器的方括号:

代码语言:shell
复制
p[lang='fr']

要要求元素是新鲜的,请使用:fresh

代码语言:shell
复制
h1:fresh

修饰符必须按正确的顺序使用:

代码语言:shell
复制
h1.section-title:fresh

隔板

要指定要放置在折叠在一起的段落内容之间的分隔符,请使用:separator('SEPARATOR STRING')

例如,假设一个文档包含一个代码块,其中每一行代码都是一个样式为Code Block的段落。我们可以编写一个样式映射来将这些段落映射到<pre>元素:

代码语言:shell
复制
p[style-name='Code Block'] => pre

由于pre没有被标记为:fresh,连续的pre元素将折叠在一起。但是,这会导致代码都在一行上。我们可以使用:separator在每一行代码之间插入一个换行符:

代码语言:shell
复制
p[style-name='Code Block'] => pre:separator('\n')

嵌套元素

使用>指定嵌套元素。例如,要在div.aside中指定h2

代码语言:shell
复制
div.aside > h2

您可以将元素嵌套到任何深度。


原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • python-mammoth - docx到 HTML 转换器
    • 其他支持的平台
      • CLI
      • Library
      • API
      • 文档转换
    • 写作风格地图
      • 新鲜度
      • 文档元素匹配器
      • HTML 路径
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档