1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【 Insight Masking API 徹底活用 】Word ファイルの機密情報も安心!Insight Masking Web API と python-docx で手軽にマスキング

Last updated at Posted at 2025-05-27

ビジネス文書の作成に欠かせない Word ファイル。企画書、報告書、契約書など、重要な情報が記載されたファイルも多いのではないでしょうか。これらのファイルを安全に共有・管理するためには、適切なマスキング処理が求められます。

そこで今回は、高精度なマスキングが期待できる Insight Masking Web API と、Python で Word ファイル(.docx)を操作するための強力なライブラリ python-docx を組み合わせることで、Word ファイルに含まれる機密情報を手軽にマスキングする方法をご紹介します。「Word ファイルの中身もプログラムでマスキングできるの?」と思われた方も、ぜひこの記事を読み進めてください。

なぜ Word ファイルのマスキングに Insight Masking Web API を活用するのか?

Word ファイルのマスキングを手作業で行うのは、時間と手間がかかり、ミスも起こりやすいものです。Insight Masking Web API と連携することで、以下のようなメリットが期待できます。

  • 高精度なマスキング: テキストの内容を解析し、個人情報や機密情報を高精度に検出してマスキングできます。
  • 効率的な処理: 複数のファイルや長文のドキュメントも、プログラムで自動的に処理できるため、大幅な時間短縮につながります。
  • 多様なテキスト要素に対応: 本文だけでなく、表、ヘッダー、フッターなどに含まれるテキストデータもマスキングの対象にできます。

準備するもの

始める前に、以下の準備が必要です。

  1. Python が利用可能な環境
  2. Insight Masking Web API の URL と API キー: Insight Masking Web API を利用するためには、Insight Masking の Web コンソールからあらかじめプレーンテキストタイプの API を作成しておく必要があります。詳細は以下のサイトなどを参照ください。

image.png

ではさっそくやってみましょう。

必要なライブラリのインストール(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 ファイルと出力結果を以下に掲載します。なおマスキングの設定等により、実行結果は異なることがあります。※記載している社名、人名、サービス名等は架空のものです

入力:
image.png

image.png

出力:
image.png

image.png

簡単でしたね!

なお、今回作成した 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
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?