Mammoth 旨在转换 .docx 文档(例如由 Microsoft Word、Google Docs 和 LibreOffice 创建的文档)并将其转换为 HTML。Mammoth 旨在通过使用文档中的语义信息并忽略其他细节来生成简单干净的 HTML。例如,Mammoth 将任何具有样式的段落转换Heading 1
为h1
元素,而不是尝试完全复制标题的样式(字体、文本大小、颜色等)。
.docx 使用的结构与 HTML 的结构有很大的不匹配,这意味着对于更复杂的文档来说,转换不太可能完美。如果您仅使用样式对文档进行语义标记,Mammoth 效果最佳。
目前支持以下功能:
-
标题。
-
列表。
-
可自定义从您自己的 docx 样式到 HTML 的映射。例如,您可以通过提供适当的样式映射
WarningHeading
来转换为。h1.warning
-
表格。表格本身的格式(如边框)目前被忽略,但文本的格式与文档其余部分的格式相同。
-
脚注和尾注。
-
图片。
-
粗体、斜体、下划线、删除线、上标和下标。
-
链接。
-
换行。
-
文本框。文本框的内容将被视为单独的段落,该段落出现在包含文本框的段落之后。
-
评论。
安装
pip install mammoth
其他支持的平台
-
JavaScript,包括浏览器和 node.js。可在 npm 上使用。
用法
命令行界面
您可以通过传递 docx 文件和输出文件的路径来转换 docx 文件。例如:
mammoth document.docx output.html
如果没有指定输出文件,则输出将写入标准输出。
输出是使用 UTF-8 编码的 HTML 片段,而不是完整的 HTML 文档。由于片段中未明确设置编码,如果浏览器未默认使用 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)
自定义图像处理器
默认情况下,图像将转换为<img>
元素,其源包含在属性中。可以通过将参数设置为图像转换器src
来更改此行为。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
:默认情况下,图像将转换为<img>
元素,其源包含在src
属性中。将此参数设置为图像转换器可覆盖默认行为。 -
ignore_empty_paragraphs
:默认情况下,空段落会被忽略。将此选项设置为False
可在输出中保留空段落。 -
id_prefix
:添加到任何生成的 ID 前面的字符串,例如书签、脚注和尾注使用的 ID。默认为空字符串。 -
transform_document
:如果设置,则此功能将应用于从 docx 文件读取的文档,然后再转换为 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)
。这<img>
将为原始 docx 中的每个图像创建一个元素。 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 图像。配方目录包含如何使用 LibreOffice 转换 WMF 图像的示例,尽管转换的保真度完全取决于 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 遇到样式名称为 的 .docx 段落Heading 1
,则该 .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:fresh
和的 样式映射p[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
请注意,此匹配项匹配已明确应用小型大写字母的文本。它不会匹配任何因段落或运行样式而采用小型大写字母的文本。
忽略文档元素
用于!
忽略文档元素。例如,忽略具有以下样式的任何段落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 STRING')
。
例如,假设文档包含一个代码块,其中每行代码都是一个具有样式的段落Code Block
。我们可以编写样式映射将这些段落映射到<pre>
元素:
p[style-name='Code Block'] => pre
由于pre
未标记为:fresh
,连续pre
元素将折叠在一起。但是,这会导致代码全部位于一行上。我们可以使用:separator
在每行代码之间插入换行符:
p[style-name='Code Block'] => pre:separator('\n')
嵌套元素
用于>
指定嵌套元素。例如,h2
在 内指定div.aside
:
div.aside > h2
您可以将元素嵌套到任意深度。