Noob Front End Engineer Blog

PythonでWordファイルをHTMLに変換

Docker

Python

2021-01-09

目次

概要

静的なサイトで記事ページを作成する際、ライターの方から
頂いた Word ファイル(.docx)を元に実装する事はありませんか?

コピペを何度も何度も行う単純作業はきついですよね。

という事で、今回は Python を使用して Word ファイルを元に
いい感じの HTML を生成する方法を紹介していきます 🙂

完成品はこちらです。
使用方法は

README.md
に記載してありますので、お急ぎの方は上記を使用してみてください。
※ Docker 使用を想定して作成しています

Github強化中なので、☆, フォローいただけると喜びます

環境構築

Python3
がインストール済み、もしくは
Docker
等で
Python3
の実行環境ができているものとします。

まずは任意の場所にデモ用のディレクトリを作成してください。

bash
# ディレクトリ作成
mkdir demo

# ディレクトリ移動
cd demo

今回のデモは下記のようなディレクトリ構造で行っていきます。

demo
  └ dist
     └ index.html  # <-- 作成されたHTML
  └ src
     └ input.docx  # <-- 元となるWordファイル
  |
  └ converter.py   # <-- HTML生成処理

コマンドでもエクスプローラーでも構わないので、

dist/
ディレクトリと
src/
ディレクトリを作成しておいてください。

HTML 生成処理の作成

今回使用するモジュール達は下記の通り

| module | description | | ------- | ----------------------------------------------------------------- | | os | ファイル・ディレクトリ操作 | | re | 正規表現が使える | | glob | ファイル名取得 | | mammoth | docx ファイルから html ファイルに変換してくれる | | bs4 | HTML 操作全般をおこなってくれる(今回は html の整形用として使用) |

| test | test | | --- | --- | | test | test |

os
,
re
,
glob
はデフォルトでインストールされている為
mammoth
,
bs4(beautifulsoup4)
のみ明示的にインストールする必要があります。

今回は

converter.py
というファイルを作成して、そこに実装を行っていきます。

処理の内容は下記の通りです。

converter.py
import mammoth # docx → html
import os # create file
import glob # read file name

from bs4 import BeautifulSoup # html linter 
from bs4 import Tag

import re # 正規表現

files = glob.glob('./src/*.docx')

for file in files:
  with open(file, 'rb') as docx_file:
    result = mammoth.convert_to_html(docx_file)
    source = result.value

    # --------------------- class setting start ---------------------

    # 見出し 
    source = source.replace('<h1>', '<h1 class="">')
    source = source.replace('<h2>', '<h2 class="">')
    source = source.replace('<h3>', '<h3 class="">')
    source = source.replace('<h4>', '<h4 class="">')
    source = source.replace('<h5>', '<h5 class="">')

    # テーブル内のpタグ削除
    source = re.sub('<th(.*?)<p>(.*?)</p>', '<th\\1\\2', source)
    source = re.sub('<td(.*?)<p>(.*?)</p>', '<td\\1\\2', source)

    # パラグラフ
    source = source.replace('<p>', '<p class="">')

    # 画像 (画像は未対応の為、ダミー画像を表示)
    source = re.sub('<img src=\"(.*?)\"', '<img src="https://placehold.jp/150x150.png"', source)

    # リスト
    source =source.replace('<ul>', '<ul class="">')
    source =source.replace('<ol>', '<ol class="">')

    # テーブル
    source =source.replace('<table>', '<table class="">')
    source =source.replace('<tr>', '<tr class="">')
    source =source.replace('<td>', '<td class="">')

    # --------------------- class setting end ---------------------

    html = BeautifulSoup(source, 'lxml')
    html = html.prettify()
    messages = result.messages

    outputfile = file.replace('.docx', '.html')
    outputfile = outputfile.replace('/src/', '/dist/')

  with open(outputfile, mode='w') as f:
    f.write(html)

  print("finished convert (´-ω-`)")

それでは、実際にどのように処理を行っているか解説していきます!

元となるWordファイルの取得・ループ処理

まずは元となるWordファイルのファイルパスを全て取得し
ファイルの件数分だけループを回しています。

converter.py
# --- 略 ---
files = glob.glob('./src/*.docx')

for file in files:
# --- 略 ---

glob
モジュールを使用する事でファイルパスを取得することができます。
今回の場合は
./src/
ディレクトリ内にある
.docx
形式のファイル全てのファイルパスを
取得し
files
変数に格納しています。

Wordファイルを元にHTMLを作成

ここからは実際にWordファイルを元にHTMLを作成する機能を作成しています。

converter.py
# --- 略 ---
  with open(file, 'rb') as docx_file:
    result = mammoth.convert_to_html(docx_file)
    source = result.value
# --- 略 ---

file
には先ほど取得してきたWordファイルのパスが格納されているので
そちらのファイルを開き、
docx_file
変数にWordファイルの情報を格納します。

次に

docx_file
に取得したWordファイルを
mammoth
モジュールを使用してHTMLに変換します。
mammoth.convert_to_html()
docx_file
を渡すことでHTMLの情報を取得できます。
返ってきたHTML情報を
result
に格納し、
value
を確認すると、 実際にHTML入っていることが確認できると思います。

タグを独自に加工

ここから各HTMLタグを独自に加工していきます。

converter.py
# --- 略 ---
    # --------------------- class setting start ---------------------

    # 見出し 
    source = source.replace('<h1>', '<h1 class="">')
    source = source.replace('<h2>', '<h2 class="">')
    source = source.replace('<h3>', '<h3 class="">')
    source = source.replace('<h4>', '<h4 class="">')
    source = source.replace('<h5>', '<h5 class="">')

    # テーブル内のpタグ削除
    source = re.sub('<th(.*?)<p>(.*?)</p>', '<th\\1\\2', source)
    source = re.sub('<td(.*?)<p>(.*?)</p>', '<td\\1\\2', source)

    # パラグラフ
    source = source.replace('<p>', '<p class="">')

    # 画像 (画像は未対応の為、ダミー画像を表示)
    source = re.sub('<img src=\"(.*?)\"', '<img src="https://placehold.jp/150x150.png"', source)

    # リスト
    source =source.replace('<ul>', '<ul class="">')
    source =source.replace('<ol>', '<ol class="">')

    # テーブル
    source =source.replace('<table>', '<table class="">')
    source =source.replace('<tr>', '<tr class="">')
    source =source.replace('<td>', '<td class="">')

    # --------------------- class setting end ---------------------
# --- 略 ---

replace
を使用して開始タグを編集します。
ここは実際に入れたいclass名、id名等を自由に記入してください。

HTMLの整形・出力

最後にHTMLの整形を行い、ディレクトリ・ファイル名を指定して出力する処理を解説していきます。

converter.py
# --- 略 ---
    html = BeautifulSoup(source, 'lxml')
    html = html.prettify()
    messages = result.messages

    outputfile = file.replace('.docx', '.html')
    outputfile = outputfile.replace('/src/', '/dist/')

  with open(outputfile, mode='w') as f:
    f.write(html)

  print("finished convert (´-ω-`)")
# --- 略 ---

Wordから変換したHTMLデータが入っている

source

改行やインデント等が入っていないHTMLファイルになってしまっている為、
BeautifleSource
モジュールを使用して整形を行っています。

html = BeautifulSoup(source, 'lxml')
を行う事で、
source
に入っていたHTML情報の文字列を
HTMLデータ
として
html
変数に格納することができます。

このような、「どういったデータ構造になっているか明示的に示す」事を 「パースする」と言う事を初めて知りました

html
変数には
BeautifulSoup
で使用できる
HTMLデータ
になったので、
prettify
という整形用の関数を使用して整形を行えます。

最後にファイルパスを出力用のパスに書き換えて、
HTMLファイルを作成したら完成です🙆‍♂️

おわり

今回初めてまともにPythonを触ったのですが、記述方法がとても簡単で感動しました…
知識が薄いので、もっといい書き方、説明があれば是非ご指摘ください!