Cómo convertir DOCX a Html con Python Mammoth

Mammoth es una herramienta que puede convertir archivos docx a HTML. Aprendamos a usar Mammoth con Python para convertir archivos DOCX a HTML manteniendo su formato.

Introducción

En algún momento de su ruta de desarrollo de software, tendrá que convertir archivos de un formato a otro.

DOCX (usado por Microsoft Word) es un formato de archivo bastante común para que lo use mucha gente. Y a veces, nos gustaría convertir documentos de Word en HTML.

Esto se puede lograr fácilmente a través del paquete Mammoth. Es una biblioteca fácil, eficiente y rápida que se utiliza para convertir archivos DOCX a HTML. En este artículo, aprenderemos cómo usar Mammoth en Python para convertir DOCX a HTML.

Instalación de Mammoth {#instalación de Mammoth}

Como buena práctica, recuerda tener tu ambiente virtual listo y activado antes de la instalación:

1
2
$ python3 -m venv myenv
$ . myenv/bin/activate

Entonces instalemos Mammoth con pip:

1
$ pip3 install mammoth

Este tutorial utiliza la versión 1.4.15 de Mammoth. Aquí hay un documento de muestra que puede usar en todo este tutorial. Si tiene un documento para convertir, ¡asegúrese de que sea un archivo .docx!

Ahora que está listo para comenzar, comencemos a extraer el texto y escribirlo como HTML.

Extraiga el texto sin procesar de un archivo DOCX

Preservar el formato mientras se convierte a HTML es una de las mejores características de Mammoth. Sin embargo, si solo necesita el texto del archivo DOCX, se sorprenderá gratamente de las pocas líneas de código que se necesitan.

Puedes usar el método extract_raw_text() para recuperarlo:

1
2
3
4
5
6
7
import mammoth

with open(input_filename, "rb") as docx_file:
    result = mammoth.extract_raw_text(docx_file)
    text = result.value # The raw text
    with open('output.txt', 'w') as text_file:
        text_file.write(text)

Tenga en cuenta que este método no devuelve un documento HTML válido. Solo devuelve el texto de la página, por eso lo guardamos con la extensión .txt. Si necesita mantener el diseño y/o el formato, querrá extraer el contenido HTML.

Convierta Docx a HTML con asignación de estilo personalizado

De forma predeterminada, Mammoth convierte su documento a HTML, pero no le proporciona una página HTML válida. Si bien los navegadores web pueden mostrar el contenido, falta una etiqueta <html> para encapsular el documento y una etiqueta <cuerpo> para contener el documento. La forma en que elija integrar su salida depende de usted. Digamos que está utilizando un marco web que tiene plantillas. Es probable que defina una plantilla para mostrar un documento de Word y cargue la salida de Mammoth dentro del cuerpo de la plantilla.

Mammoth no solo es flexible con la forma en que puede usar su salida, sino también con la forma en que puede crearla. Particularmente, tenemos muchas opciones cuando queremos diseñar el HTML que producimos. Asignamos estilos haciendo coincidir cada regla de formato DOCX con la regla CSS equivalente (o lo más cerca posible).

Para ver qué estilos tiene tu archivo DOCX, tienes dos opciones:

  1. Puede abrir su archivo docx con MS Word y verificar la barra de herramientas Estilos.
  2. Puede profundizar en los archivos XML abriendo su archivo DOCX con un administrador de archivos y luego navegar a /word/styles.xml y ubicar sus estilos.

La segunda opción puede ser utilizada por aquellos que no tienen acceso a MS Word oa un procesador de texto alternativo que pueda interpretar y mostrar los estilos.

Mammoth ya tiene algunos de los mapas de estilo más comunes cubiertos de forma predeterminada. Por ejemplo, el estilo docx Heading1 se asigna al elemento HTML <h1>, negrita se asigna al elemento HTML <strong>, etc.

También podemos usar Mammoth para personalizar los estilos del documento mientras los mapeamos. Por ejemplo, si desea cambiar todas las apariciones en negrita en el archivo DOCX a cursiva en el HTML, puede hacer esto:

1
2
3
4
5
6
7
8
9
import mammoth

custom_styles = "b => i"

with open(input_filename, "rb") as docx_file:
    result = mammoth.convert_to_html(docx_file, style_map = custom_styles)
    text = result.value
    with open('output.html', 'w') as html_file:
        html_file.write(text)

Con la variable custom_styles, el estilo de la izquierda es del archivo DOCX, mientras que el de la derecha es el CSS correspondiente.

Digamos que queremos omitir las ocurrencias en negrita por completo, podemos dejar el objetivo de mapeo en blanco:

1
custom_styles = "b => "

A veces, el documento que estamos portando tiene muchos estilos para conservar. Rápidamente se vuelve poco práctico crear una variable para cada estilo que queremos mapear. Afortunadamente, podemos usar docstrings para mapear tantos estilos como queramos de una sola vez:

1
2
3
custom_styles = """ b => del
                    u => em
                    p[style-name='Heading 1'] => i"""

Es posible que haya notado que el último mapeo fue un poco diferente de los demás. Al mapear estilos, podemos usar corchetes [] con una condición dentro de ellos para que solo un subconjunto de elementos tenga ese estilo.

En nuestro ejemplo, p[style-name='Título 1'] selecciona párrafos que tienen un nombre de estilo Título 1. También podemos usar p[style-name^='Heading'] para seleccionar cada párrafo que tenga un nombre de estilo que comience con Título.

El mapeo de estilos también nos permite mapear estilos a clases CSS personalizadas. Al hacerlo, podemos dar forma al estilo de HTML como queramos. Hagamos un ejemplo en el que definimos nuestro CSS personalizado básico en una cadena de documentación como esta:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
custom_css ="""
    <style>
    .red{
        color: red;
    }
    .underline{
        text-decoration: underline;
    }
    .ul.li{
        list-style-type: circle;
    }
    table, th, td {
    border: 1px solid black;
    }
    </style>
    """

Ahora podemos actualizar nuestro mapeo para hacer referencia a las clases CSS que hemos definido en el bloque <estilo>:

1
2
3
custom_styles = """ b => b.red
                    u => em.red
                    p[style-name='Heading 1'] => h1.red.underline"""

Ahora todo lo que tenemos que hacer es fusionar el CSS y el HTML juntos:

1
edited_html = custom_css + html

Si su archivo DOCX tiene alguno de esos elementos, podrá ver los resultados.

Ahora que sabemos cómo mapear estilos, usemos un marco CSS más conocido (junto con el JS) para darle a nuestro HTML una mejor apariencia y practicar un escenario de la vida real más probable.

Asignación de estilos con Bootstrap (o cualquier otro marco de interfaz de usuario)

Al igual que hicimos con custom_css, debemos asegurarnos de que el CSS esté cargado con el HTML. Necesitamos agregar el archivo URI o CDN de Bootstrap a nuestro HTML:

1
2
bootstrap_css = '<link href="https://cdn.jsdelivr.net/npm/[correo electrónico protegido]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">'
bootstrap_js = '<script src="https://cdn.jsdelivr.net/npm/[correo electrónico protegido]/dist/js/bootstrap.bundle.min.js" integrity="sha384-b5kHyXgcpbZJO/tY9Ul7kGkf1S0CWuKcCD38l8YkeH8z8QjE0GmW1gYU5S9FOnJ0" crossorigin="anonymous"></script>'

También modificaremos ligeramente nuestros custom_styles para que coincidan con nuestras nuevas clases de CSS:

1
2
3
4
5
custom_styles = """ b => b.mark
                    u => u.initialism
                    p[style-name='Heading 1'] => h1.card
                    table => table.table.table-hover
                    """

En la primera línea, estamos asignando el estilo DOCX en negrita al elemento HTML b con una clase marca, que es una clase de Bootstrap equivalente a la etiqueta HTML <marca>, utilizada para resaltar parte del texto .

En la segunda línea, agregamos la clase inicialismo al elemento HTML u, disminuyendo ligeramente el tamaño de fuente y transformando el texto en mayúsculas.

En la tercera línea, seleccionamos todos los párrafos que tienen el nombre de estilo Título 1 y los convertimos en elementos HTML h1 con la clase Bootstrap de card, que establece varias propiedades de estilo, como el color de fondo, la posición y borde para el elemento.

En la última línea, estamos convirtiendo todas las tablas en nuestro archivo docx al elemento HTML tabla, con la clase tabla de Bootstrap para darle una nueva apariencia, también estamos resaltando cuando se desplaza , agregando la clase Bootstrap de table-hover.

Como antes, usamos la notación de puntos para asignar varias clases al mismo elemento HTML, aunque los estilos provengan de otra fuente.

Finalmente, agregue los CDN de Bootstrap a nuestro HTML:

1
edited_html = bootstrap_css + html + bootstrap_js

¡Nuestro HTML ahora está listo para ser compartido, con un aspecto y una sensación pulidos! Aquí está el código completo para referencia:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import mammoth

input_filename = "file-sample_100kB.docx"

custom_styles = """ b => b.mark
                    u => u.initialism
                    p[style-name='Heading 1'] => h1.card
                    table => table.table.table-hover
                    """


bootstrap_css = '<link href="https://cdn.jsdelivr.net/npm/[correo electrónico protegido]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">'
bootstrap_js = '<script src="https://cdn.jsdelivr.net/npm/[correo electrónico protegido]/dist/js/bootstrap.bundle.min.js" integrity="sha384-b5kHyXgcpbZJO/tY9Ul7kGkf1S0CWuKcCD38l8YkeH8z8QjE0GmW1gYU5S9FOnJ0" crossorigin="anonymous"></script>'


with open(input_filename, "rb") as docx_file:
    result = mammoth.convert_to_html(docx_file, style_map = custom_styles)
    html = result.value 

edited_html = bootstrap_css + html + bootstrap_js

output_filename = "output.html"
with open(output_filename, "w") as f: 
    f.writelines(edited_html)

Además, otro punto a tener en cuenta aquí es que, en un escenario de la vida real, probablemente no agregará Bootstrap CSS directamente al contenido HTML como lo hicimos aquí. En su lugar, cargaría/inyectaría el contenido HTML en una página HTML preempaquetada, que ya tendría los paquetes CSS y JS necesarios.

Hasta ahora, ha visto cuánta flexibilidad tenemos para diseñar nuestra salida. Mammoth también nos permite modificar el contenido que estamos convirtiendo. Echemos un vistazo a eso ahora.

Tratar con imágenes que no queremos compartir {#tratar con imágenes que no queremos compartir}

Digamos que nos gustaría omitir la conversión de imágenes de nuestro archivo DOCX. convert_to_html() acepta un argumento convert_image, que es una función de manejo de imágenes. Devuelve una lista de imágenes que deben convertirse y agregarse al documento HTML.

Naturalmente, si lo anulamos y devolvemos una lista vacía, se omitirán de la página convertida:

1
2
def ignore_image(image):
    return []

Ahora, pasemos esa función como parámetro al método convert_to_html():

1
2
3
4
5
with open(input_filename, "rb") as docx_file:
    result = mammoth.convert_to_html(docx_file, style_map = custom_styles, convert_image=ignore_image)
    html = result.value
    with open('output.html', 'w') as html_file:
        html_file.write(text)

¡Eso es todo! Mammoth ignorará todas las imágenes al generar un archivo HTML.

Hasta ahora hemos estado usando Mammoth con Python mediante programación. Mammoth también es una herramienta CLI, por lo tanto, tenemos otra interfaz para hacer conversaciones de DOCX a HTML. Veamos cómo funciona eso en la siguiente sección.

Convertir DOCX a HTML mediante la herramienta de línea de comandos

La conversión de archivos con Mammoth, utilizando la CLI, generalmente se ve así:

1
$ mammoth path/to/input_filename.docx path/to/output.html

Si desea separar las imágenes del HTML, puede especificar una carpeta de salida:

1
$ mammoth file-sample_100kB.docx --output-dir=imgs

También podemos agregar estilos personalizados como lo hicimos en Python. Primero debe crear un archivo de estilo personalizado:

1
$ touch my-custom-styles

Luego agregaremos nuestros estilos personalizados en él, la sintaxis es la misma que antes:

1
2
3
b => b.red
u => em.red
p[style-name='Heading 1'] => h1.red.underline

Ahora podemos generar nuestro archivo HTML con estilo personalizado:

1
$ mammoth file-sample_100kB.docx output.html --style-map=my-custom-styles

¡Y tu estas listo! Su documento se habría convertido con los estilos personalizados definidos.

Conclusión

El encasillamiento de archivos es una situación común cuando se trabaja en tecnologías web. Convertir archivos DOCX en HTML conocido y fácil de manipular nos permite reconstruir los datos tanto como necesitemos. Con Mammoth, hemos aprendido cómo extraer el texto de un docx y cómo convertirlo a HTML.

Al convertir a HTML, podemos diseñar la salida con las reglas CSS que creamos o las que vienen con marcos de interfaz de usuario comunes. También podemos omitir datos que no queremos que estén disponibles en el HTML. Por último, hemos visto cómo usar Mammoth CLI como una opción alternativa para la conversión de archivos.

Puede encontrar un archivo docx de muestra junto con el código completo del tutorial en este repositorio de GitHub.