ビジネス文書の作成に欠かせない Word ファイル。企画書、報告書、契約書など、重要な情報が記載されたファイルも多いのではないでしょうか。これらのファイルを安全に共有・管理するためには、適切なマスキング処理が求められます。
そこで今回は、高精度なマスキングが期待できる Insight Masking Web API と、Python で Word ファイル(.docx)を操作するための強力なライブラリ python-docx を組み合わせることで、Word ファイルに含まれる機密情報を手軽にマスキングする方法をご紹介します。「Word ファイルの中身もプログラムでマスキングできるの?」と思われた方も、ぜひこの記事を読み進めてください。
なぜ Word ファイルのマスキングに Insight Masking Web API を活用するのか?
Word ファイルのマスキングを手作業で行うのは、時間と手間がかかり、ミスも起こりやすいものです。Insight Masking Web API と連携することで、以下のようなメリットが期待できます。
- 高精度なマスキング: テキストの内容を解析し、個人情報や機密情報を高精度に検出してマスキングできます。
- 効率的な処理: 複数のファイルや長文のドキュメントも、プログラムで自動的に処理できるため、大幅な時間短縮につながります。
- 多様なテキスト要素に対応: 本文だけでなく、表、ヘッダー、フッターなどに含まれるテキストデータもマスキングの対象にできます。
準備するもの
始める前に、以下の準備が必要です。
- Python が利用可能な環境
- Insight Masking Web API の URL と API キー: Insight Masking Web API を利用するためには、Insight Masking の Web コンソールからあらかじめプレーンテキストタイプの API を作成しておく必要があります。詳細は以下のサイトなどを参照ください。
ではさっそくやってみましょう。
必要なライブラリのインストール(requirements.txt)
このプロジェクトで必要なライブラリは python-docx, requests, python-dotenv です。以下の内容で requirements.txt ファイルをプロジェクトのルートディレクトリに作成してください。
python-docx
requests
python-dotenv
作成後、アクティベートされた venv 仮想環境内で以下のコマンドを実行し、必要なライブラリをインストールします。
python3 -m venv venv
venv/bin/activate
pip3 install -r requirements.txt
Insight Masking Web API の基本的な使い方
Insight Masking Web API (プレーンテキストタイプ) は、テキストデータを受け取り、その中に含まれる機密情報を検出してマスキングした結果を返してくれるサービスです。基本的なリクエストとレスポンスの形式は以下の通りです。API キーは、HTTP リクエストのヘッダーに X-Insight-Masking-API-KEY として含めて送信します。
-
リクエスト: マスキングしたいテキストデータを base64 エンコードしたものと、API キーを HTTP ヘッダーに
X-Insight-Masking-API-KEYを設定して HTTP リクエストを送信します。 - レスポンス: API は、base64 エンコードされたマスキング後のテキストデータを返します。
Python で docx ファイルをマスキングする具体的な手順
python-docx を使うと、Word ファイル内の段落、表、ヘッダー、フッターなどの要素にアクセスし、テキストを取得/更新することができます。これを利用して元のテキストを Insight Masking Web API での処理結果に更新していきます。
コマンドライン引数の処理
まず、argparse モジュールを使ってコマンドライン引数を処理します。
from docx import Document
import requests
import json
import os
import urllib.parse
import base64
from dotenv import load_dotenv
import argparse
load_dotenv()
# コマンドライン引数の設定
parser = argparse.ArgumentParser(description='Wordファイルのテキスト(本文、表、ヘッダー、フッター)をInsight Masking APIでマスキングします。')
parser.add_argument('docx_file', help='マスキング対象のWordファイルパス')
args = parser.parse_args()
docx_file_path = args.docx_file
ここでは、必須の引数として docx ファイルのパス (docx_file) を定義しています。
Insight Masking Web API との連携
次に、Word ファイルから抽出したテキストを Insight Masking Web API に送信してマスキング処理を行います。requests ライブラリを利用すると便利です。API のエンドポイントと API キーは環境変数から読み込みます。
# Insight Masking Web APIのエンドポイント (環境変数から取得)
api_url = os.getenv('INSIGHT_MASKING_API_ENDPOINT')
if not api_url:
print("エラー: 環境変数 INSIGHT_MASKING_API_ENDPOINT が設定されていません。")
exit()
# APIキー (環境変数 INSIGHT_MASKING_API_KEY から取得)
api_key = os.getenv('INSIGHT_MASKING_API_KEY')
if not api_key:
print("エラー: 環境変数 INSIGHT_MASKING_API_KEY が設定されていません。")
exit()
headers = {
'X-Insight-Masking-API-KEY': api_key
}
# マスキング処理を行う関数
def mask_text(text):
plain_text = base64.b64encode((urllib.parse.unquote(urllib.parse.quote(text)) + '\n').encode())
try:
response = requests.post(api_url, headers=headers, data=plain_text)
response.raise_for_status() # エラーレスポンスの場合に例外を発生させる
result = urllib.parse.unquote(urllib.parse.quote(base64.b64decode(response.text)))
return result.rstrip('\n')
except requests.exceptions.RequestException as e:
print(f"APIリクエストエラー: {e}")
return text
except json.JSONDecodeError as e:
print(f"JSONデコードエラー: {e}")
return text
API の URL と、API キーは以下のように .env ファイルに記載しておくと便利です。
cat .env
INSIGHT_MASKING_API_ENDPOINT="https://xxxx.xx.xx/webapi/xxxxxxxxx/xxxxxxxxx/plain"
INSIGHT_MASKING_API_KEY="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx"
docx ファイルの読み込みとテキスト要素の処理
Word ファイルを読み込み、本文、表、ヘッダー、フッターに含まれるテキストデータを取得し、マスキング処理を行います。
try:
# Wordファイルを読み込む
document = Document(docx_file_path)
# 本文の段落を処理
for paragraph in document.paragraphs:
if paragraph.text:
original_text = paragraph.text
masked_text = mask_text(original_text)
paragraph.text = masked_text
print(f"本文 - 元のテキスト: {original_text}, マスク後のテキスト: {masked_text}")
# 表を処理
for table in document.tables:
for row in table.rows:
for cell in row.cells:
if cell.text:
original_text = cell.text
masked_text = mask_text(original_text)
cell.text = masked_text
print(f"表 - 元のテキスト: {original_text}, マスク後のテキスト: {masked_text}")
# ヘッダーとフッターを処理
for section in document.sections:
header = section.header
for paragraph in header.paragraphs:
if paragraph.text:
original_text = paragraph.text
masked_text = mask_text(original_text)
paragraph.text = masked_text
print(f"ヘッダー - 元のテキスト: {original_text}, マスク後のテキスト: {masked_text}")
footer = section.footer
for paragraph in footer.paragraphs:
if paragraph.text:
original_text = paragraph.text
masked_text = mask_text(original_text)
paragraph.text = masked_text
print(f"フッター - 元のテキスト: {original_text}, マスク後のテキスト: {masked_text}")
# マスク処理後の Word ファイルを保存 (元のファイル名に 'masked_' を付加)
output_file_path = f'masked_{os.path.basename(docx_file_path)}'
document.save(output_file_path)
print(f"Wordファイルのマスキング処理が完了しました。結果は {output_file_path} に保存されました。")
except FileNotFoundError:
print(f"エラー: ファイル '{docx_file_path}' が見つかりません。")
except Exception as e:
print(f"予期せぬエラーが発生しました: {e}")
実行方法
このスクリプトは、コマンドラインから以下のように実行します。
python your_script_name.py your_document.docx
では実際に実行してみます。以下のように、masked_入力ファイル名 のファイルがマスキング結果として生成されました。
python3 test.py test.docx
...
マスキング処理完了。結果は masked_test.docx に保存されました。
入力に使用した Word ファイルと出力結果を以下に掲載します。なおマスキングの設定等により、実行結果は異なることがあります。※記載している社名、人名、サービス名等は架空のものです
簡単でしたね!
なお、今回作成した Python スクリプトでは書式が維持されません。簡単な書式であれば、頑張れば書式の設定も可能かもしれませんが、複雑な書式を完全に再現するのは困難を伴います。Masking 後の文章を何に使用したいかで、どこまで実装を頑張るかを検討する必要があると思います。
まとめ
この記事では、python-docx ライブラリと Insight Masking Web API を連携させて Word ファイルに含まれる機密情報を効率的にマスキングする方法をご紹介しました。API を活用することで、Word ファイルの様々なテキスト要素のマスキングを自動化できることが確認できたのではないでしょうか?
まだ Insight Masking をご利用いただいたことがない方で、ご興味をお持ちの方は以下から是非お問合せください。
参考情報
ソースコードの生成、テスト用 Word (docx) ファイルの用意、文章の校正などに Gemini for Google Workspace を活用しています
ソースコード全体
以下に、この記事で解説した Python スクリプトの全体像を記載します。
from docx import Document
import requests
import json
import os
import urllib.parse
import base64
from dotenv import load_dotenv
import argparse
load_dotenv()
# コマンドライン引数の設定
parser = argparse.ArgumentParser(description='Wordファイルのテキスト(本文、表、ヘッダー、フッター)をInsight Masking APIでマスキングします。')
parser.add_argument('docx_file', help='マスキング対象のWordファイルパス')
args = parser.parse_args()
docx_file_path = args.docx_file
# Insight Masking Web APIのエンドポイント (環境変数から取得)
api_url = os.getenv('INSIGHT_MASKING_API_ENDPOINT')
if not api_url:
print("エラー: 環境変数 INSIGHT_MASKING_API_ENDPOINT が設定されていません。")
exit()
# APIキー (環境変数 INSIGHT_MASKING_API_KEY から取得)
api_key = os.getenv('INSIGHT_MASKING_API_KEY')
if not api_key:
print("エラー: 環境変数 INSIGHT_MASKING_API_KEY が設定されていません。")
exit()
headers = {
'X-Insight-Masking-API-KEY': api_key
}
# マスキング処理を行う関数
def mask_text(text):
plain_text = base64.b64encode((urllib.parse.unquote(urllib.parse.quote(text)) + '\n').encode())
try:
response = requests.post(api_url, headers=headers, data=plain_text)
response.raise_for_status() # エラーレスポンスの場合に例外を発生させる
result = urllib.parse.unquote(urllib.parse.quote(base64.b64decode(response.text)))
return result.rstrip('\n')
except requests.exceptions.RequestException as e:
print(f"APIリクエストエラー: {e}")
return text
except json.JSONDecodeError as e:
print(f"JSONデコードエラー: {e}")
return text
try:
# Wordファイルを読み込む
document = Document(docx_file_path)
# 本文の段落を処理
for paragraph in document.paragraphs:
if paragraph.text:
original_text = paragraph.text
masked_text = mask_text(original_text)
paragraph.text = masked_text
print(f"本文 - 元のテキスト: {original_text}, マスク後のテキスト: {masked_text}")
# 表を処理
for table in document.tables:
for row in table.rows:
for cell in row.cells:
if cell.text:
original_text = cell.text
masked_text = mask_text(original_text)
cell.text = masked_text
print(f"表 - 元のテキスト: {original_text}, マスク後のテキスト: {masked_text}")
# ヘッダーとフッターを処理
for section in document.sections:
header = section.header
for paragraph in header.paragraphs:
if paragraph.text:
original_text = paragraph.text
masked_text = mask_text(original_text)
paragraph.text = masked_text
print(f"ヘッダー - 元のテキスト: {original_text}, マスク後のテキスト: {masked_text}")
footer = section.footer
for paragraph in footer.paragraphs:
if paragraph.text:
original_text = paragraph.text
masked_text = mask_text(original_text)
paragraph.text = masked_text
print(f"フッター - 元のテキスト: {original_text}, マスク後のテキスト: {masked_text}")
# マスク処理後の Word ファイルを保存 (元のファイル名に 'masked_' を付加)
output_file_path = f'masked_{os.path.basename(docx_file_path)}'
document.save(output_file_path)
print(f"Wordファイルのマスキング処理が完了しました。結果は {output_file_path} に保存されました。")
except FileNotFoundError:
print(f"エラー: ファイル '{docx_file_path}' が見つかりません。")
except Exception as e:
print(f"予期せぬエラーが発生しました: {e}")
requirements.txt
python-docx
requests
python-dotenv




