跳转到主要内容

将Word文档从docx转换为简单且干净的HTML和Markdown

项目描述

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

.docx使用的结构与HTML的结构之间存在很大的不匹配,这意味着对于更复杂的文档,转换可能不会完美。如果仅使用样式来语义化文档,Mammoth将工作得最好。

目前支持以下功能

  • 标题。

  • 列表。

  • 自定义将您的docx样式映射到HTML的映射。例如,您可以通过提供适当的样式映射将WarningHeading转换为h1.warning

  • 表格。当前忽略表格本身的格式,如边框,但文本的格式与文档其他部分的处理方式相同。

  • 脚注和尾注。

  • 图片。

  • 粗体、斜体、下划线、删除线、上标和下标。

  • 链接。

  • 换行。

  • 文本框。文本框的内容被视为一个独立的段落,出现在包含文本框的段落之后。

  • 注释。

安装

pip install mammoth

其他支持的平台

用法

命令行界面

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

mammoth document.docx output.html

如果没有指定输出文件,输出将写入stdout。

输出是一个HTML片段,而不是完整的HTML文档,并使用UTF-8编码。由于片段中未明确设置编码,如果在浏览器中默认不使用UTF-8打开输出文件,可能会导致Unicode字符渲染错误。

图片

默认情况下,图片会内联包含在输出HTML中。如果通过--output-dir指定了输出目录,则图片将写入单独的文件。例如:

mammoth document.docx --output-dir=output-dir

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

样式

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

mammoth document.docx output.html --style-map=custom-style-map

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

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。例如:

mammoth document.docx --output-format=markdown

基本转换

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

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提取文档的原始文本。这将忽略文档中的所有格式。每个段落后面跟有两个换行符。

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元素

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

result = mammoth.convert_to_html(docx_file, style_map=style_map, include_default_style_map=False)

自定义图片处理程序

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

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

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> 标签中

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> 标签中

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> 标签中

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> 标签中

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 的样式映射。例如

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: 包含源文档的文件类似对象。文件应以二进制模式打开。

  • 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: 默认情况下,图像被转换为包含源内联在 src 属性中的 <img> 元素。设置此参数为一个 图像转换器 以覆盖默认行为。

  • ignore_empty_paragraphs: 默认情况下,忽略空段落。将此选项设置为 False 以保留输出中的空段落。

  • id_prefix: 一个字符串,用于在生成的任何 ID 前添加,例如书签、脚注和尾注使用的 ID。默认为空字符串。

  • transform_document: 如果设置,则在此将文档转换为 HTML 之前应用此函数。文档转换的 API 应被视为不稳定。有关文档转换的更多信息,请参阅文档转换

  • 返回的结果具有以下属性

    • value: 生成的 HTML

    • messages: 在转换过程中生成的任何消息,例如错误和警告

mammoth.convert_to_markdown(fileobj, **kwargs)

Markdown支持已被弃用。建议生成HTML并使用单独的库将HTML转换为Markdown,这可能会产生更好的结果。

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

mammoth.extract_raw_text(fileobj)

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

  • fileobj: 包含源文档的文件类似对象。文件应以二进制模式打开。

  • 返回的结果具有以下属性

    • value: 原始文本

    • messages:任何消息,例如错误和警告

mammoth.embed_style_map(fileobj, style_map)

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

  • fileobj:包含源文档的文件类似对象。文件应以二进制模式打开以供读写。

  • style_map:要嵌入的样式映射。

  • 返回 None

消息

每条消息都具有以下属性

  • type:表示消息类型的字符串,例如 "warning"

  • message:包含实际消息的字符串

图像转换器

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

  • open():打开图像文件。返回一个文件类似对象。

  • content_type:图像的内容类型,例如 image/png

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

例如,以下代码复制了默认图像转换

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 图像。recipes 目录包含 一个使用 LibreOffice 转换它们的示例,尽管转换的保真度完全取决于 LibreOffice。

文档转换

应将文档转换 API 视为不稳定的,并且可能在不同版本之间更改。如果您依赖于此行为,您应将 Mammoth 锁定到特定版本,并在更新之前仔细测试。

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

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)

或者如果您想将显式设置为使用等宽字体表示代码的段落

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 中的所有运行

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 修饰符来指定此操作

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 的样式映射可能很有帮助。

文档元素匹配器

段落、运行和表格

匹配任何段落

p

匹配任何运行

r

匹配任何表格

table

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

p[style-name='Heading 1']

您也可以通过前缀匹配样式名称。例如,为了匹配样式名称以 Heading 开头的段落

p[style-name^='Heading']

样式还可以通过样式ID进行引用。这是在.docx文件中内部使用的ID。为了匹配具有特定样式ID的段落或运行,请附加一个点后跟样式ID。例如,为了匹配具有样式ID Heading1 的段落

p.Heading1

粗体

显式匹配粗体文本

b

请注意,这匹配了已经明确应用了粗体的文本。它不会匹配任何因为其段落或运行样式而呈现为粗体的文本。

斜体

显式匹配斜体文本

i

请注意,这匹配了已经明确应用了斜体的文本。它不会匹配任何因为其段落或运行样式而呈现为斜体的文本。

下划线

显式匹配下划线文本

u

请注意,这匹配了已经明确应用了下划线的文本。它不会匹配任何因为其段落或运行样式而呈现为下划线的文本。

删除线

显式匹配删除线文本

strike

请注意,这匹配了已经明确应用了删除线的文本。它不会匹配任何因为其段落或运行样式而呈现为删除线的文本。

全部大写

显式匹配全部大写文本

all-caps

请注意,这匹配了已经明确应用了全部大写的文本。它不会匹配任何因为其段落或运行样式而呈现为全部大写的文本。

小写字母

显式匹配小写字母文本

small-caps

请注意,这匹配了已经明确应用了小写字母的文本。它不会匹配任何因为其段落或运行样式而呈现为小写字母的文本。

突出显示

显式匹配突出显示的文本

highlight

请注意,这会匹配已明确应用高亮的文本。它不会匹配任何由于段落或运行样式而高亮的文本。

还可以匹配特定颜色。例如,要匹配黄色高亮

highlight[color='yellow']

通常使用的颜色集包括

  • 黑色

  • 蓝色

  • 青色

  • 绿色

  • 品红色

  • 红色

  • 黄色

  • 白色

  • 深蓝色

  • 深青色

  • 深绿色

  • 深品红色

  • 深红色

  • 深黄色

  • 深灰色

  • 浅灰色

忽略文档元素

使用 ! 来忽略文档元素。例如,要忽略任何具有 Comment 样式的段落

p[style-name='Comment'] => !

HTML 路径

单个元素

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

h1

要给元素添加 CSS 类,请在类名前添加一个点

h1.section-title

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

p[lang='fr']

要指定元素是新的,请使用 :fresh

h1:fresh

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

h1.section-title:fresh

分隔符

要指定在合并的段落内容之间放置的分隔符,请使用 :separator('SEPARATOR 字符串')

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

p[style-name='Code Block'] => pre

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

p[style-name='Code Block'] => pre:separator('\n')

嵌套元素

使用 > 来指定嵌套元素。例如,要指定 h2div.aside

div.aside > h2

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

捐赠

如果您想表示感谢,请随时通过 Ko-fi 进行捐赠

如果您在您的业务中使用 Mammoth,请考虑通过 Liberapay 进行每周捐赠 以支持 Mammoth 的持续维护。

项目详情


发布历史 发布通知 | RSS 源

下载文件

下载适用于您的平台的文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。

源代码分布

mammoth-1.8.0.tar.gz (50.3 kB 查看哈希值)

上传时间 源代码

构建分布

mammoth-1.8.0-py2.py3-none-any.whl (52.3 kB 查看哈希值)

上传时间 Python 2 Python 3