近年、企業や組織における情報漏洩のリスクは増大の一途を辿っています。特に、日常業務で頻繁に利用されるExcelファイルには、顧客情報や売上データなど、多くの機密情報が含まれている可能性があります。これらの情報を適切に保護・利用するためにマスキング処理が必要となるケースも多々あると思います。
そこで今回は、Insight Masking Web API と Python の openpyxl を組み合わせることで、Excel ファイルに含まれる機密情報を手軽にマスキングする方法をご紹介します。「なんだか難しそう…」と感じた方もご安心ください。この記事では、具体的なコード例を交えながら説明していきます。
なぜ Insight Masking Web API を使うのか?
「Excel のマスキングなら、手作業で頑張って機微な情報を削除していけばいいのでは?」と思われる方もいるかもしれません。しかし、Insight Masking Web API を利用することには、以下のようなメリットがあります。
- 高精度なマスキング: テキストの内容を解析し、個人情報や機密情報を高精度に検出してマスキングできます。
- 多様なデータ形式に対応: Excel ファイルだけでなく、様々なデータ形式に対応しています。
- 効率的な処理: 大量のファイルや複雑なデータに対しても、プログラムで自動的に処理できるため、効率的です。
準備するもの
始める前に、以下の準備が必要です。
- Python が利用可能な環境
- Insight Masking Web API の URL と API キー: Insight Masking Web API を利用するためには、Insight Masking の Web コンソールからあらかじめプレーンテキストタイプの API を作成しておく必要があります。詳細は以下のサイトなどを参照ください。
ではさっそくやってみましょう。
実行環境の構築(venv)
Pythonのプロジェクトでは、仮想環境を利用することが推奨されます。venvを使ってこのプロジェクト専用の仮想環境を作成しましょう。
-
仮想環境の作成: ターミナルまたはコマンドプロンプトを開き、プロジェクトのディレクトリに移動した後、以下のコマンドを実行します。
python3 -m venv venv
-
仮想環境のアクティベート: 作成した仮想環境を有効にします。
アクティベートされると、ターミナルのプロンプトの先頭に
venv/bin/activate
(venv)
と表示されます。
必要なライブラリのインストール(requirements.txt)
このプロジェクトで必要なライブラリは openpyxl
, requests
, python-dotenv
です。以下の内容で requirements.txt
ファイルをプロジェクトのルートディレクトリに作成してください。
openpyxl
requests
python-dotenv
作成後、アクティベートされた仮想環境内で以下のコマンドを実行し、必要なライブラリをインストールします。
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 で Excel ファイルのシートを指定してマスキングする具体的な手順
それでは、実際に Python と openpyxl を使って Excel ファイルを読み込み、Insight Masking Web API でマスキング処理を行い、結果を Excel ファイルに書き込む手順を見ていきましょう。今回は、コマンドラインオプションでシート名を指定するか、指定がない場合は最初のシートを対象とすることとします。
コマンドライン引数の処理
まず、argparse
モジュールを使ってコマンドライン引数を処理します。
import openpyxl
import requests
import json
import os
from dotenv import load_dotenv
import argparse
import urllib.parse
import base64
load_dotenv()
# コマンドライン引数の設定
parser = argparse.ArgumentParser(description='Excelファイルの指定シートをInsight Masking APIでマスキングします。')
parser.add_argument('excel_file', help='マスキング対象のExcelファイルパス')
parser.add_argument('-s', '--sheet_name', help='処理対象のシート名(省略時は最初のシート)')
args = parser.parse_args()
excel_file_path = args.excel_file
sheet_name = args.sheet_name
ここでは、必須の引数としてExcelファイルのパス (excel_file
) を、オプション引数としてシート名 (-s
または --sheet_name
) を定義しています。
Insight Masking Web API との連携
次に、各セルの値を Insight Masking Web API に送信してマスキング処理を行います。requests
ライブラリを利用すると便利です。API のエンドポイントと API キーは環境変数から読み込みます。
# Insight Masking Web APIのエンドポイント (環境変数 INSIGHT_MASKING_API_ENDPOINT から取得)
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"
Excel ファイルの読み込みとシートの選択
Excel ファイルを読み込み、コマンドライン引数で指定されたシート、または最初のシートを取得します。その後、全カラムの文字列型のセルに対してマスキング処理を行い、結果を保存します。
# Excelブックを読み込む
try:
workbook = openpyxl.load_workbook(excel_file_path)
if sheet_name:
try:
sheet = workbook[sheet_name]
except KeyError:
print(f"エラー: シート '{sheet_name}' は存在しません。")
exit()
else:
sheet = workbook.active # 最初のシートを取得
print(f"シート名が指定されなかったため、最初のシート '{sheet.title}' を処理します。")
# 各行のすべてのセルを処理
for row in sheet.iter_rows(min_row=1):
for cell in row:
original_value = cell.value
if original_value is not None and isinstance(original_value, str):
masked_value = mask_text(original_value)
cell.value = masked_value
# マスキング後のExcelファイルを保存
output_file_path = f'masked_{os.path.basename(excel_file_path)}'
workbook.save(output_file_path)
print(f"マスキング処理完了。結果は {output_file_path} に保存されました。")
except FileNotFoundError:
print(f"エラー: ファイル '{excel_file_path}' が見つかりません。")
except Exception as e:
print(f"予期せぬエラーが発生しました: {e}")
実行方法
このスクリプトは、コマンドラインから以下のように実行します。
python your_script_name.py your_excel_file.xlsx -s Sheet1
または、最初のシートを処理する場合は -s
オプションを省略します。
python your_script_name.py your_excel_file.xlsx
では実際に実行してみます。以下のように、masked_入力ファイル名
のファイルがマスキング結果として生成されました。
python3 test.py test.xlsx
シート名が指定されなかったため、最初のシート 'Sheet1' を処理します。
マスキング処理完了。結果は masked_test.xlsx に保存されました。
入力に使用した Excel ファイルと出力結果を以下に掲載します。なおマスキングの設定等により、実行結果は異なることがあります。
簡単でしたね!
まとめ
この記事では、openpyxl
ライブラリと Insight Masking Web API を連携させて Excel ファイルに含まれる機密情報を効率的にマスキングする方法をご紹介しました。API を活用することで、面倒なマスキング処理を自動化できることが確認できたのではないでしょうか?
まだ Insight Masking をご利用いただいたことがない方で、ご興味をお持ちの方は https://www.insight-tec.com/products/masking/#f から是非お問合せください。
参考情報
ソースコードの生成、テスト用 Excel ファイルの用意、文章の校正などに Gemini for Google Workspace を活用しています
ソースコード全体
以下に、この記事で解説したPythonスクリプトの全体像を記載します。
import openpyxl
import requests
import json
import os
from dotenv import load_dotenv
import argparse
import urllib.parse
import base64
load_dotenv()
# コマンドライン引数の設定
parser = argparse.ArgumentParser(description='Excelファイルの指定シートをInsight Masking APIでマスキングします。')
parser.add_argument('excel_file', help='マスキング対象のExcelファイルパス')
parser.add_argument('-s', '--sheet_name', help='処理対象のシート名(省略時は最初のシート)')
args = parser.parse_args()
excel_file_path = args.excel_file
sheet_name = args.sheet_name
# Insight Masking Web APIのエンドポイント (環境変数 INSIGHT_MASKING_API_ENDPOINT から取得)
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
# Excelブックを読み込む
try:
workbook = openpyxl.load_workbook(excel_file_path)
if sheet_name:
try:
sheet = workbook[sheet_name]
except KeyError:
print(f"エラー: シート '{sheet_name}' は存在しません。")
exit()
else:
sheet = workbook.active # 最初のシートを取得
print(f"シート名が指定されなかったため、最初のシート '{sheet.title}' を処理します。")
# 各行のすべてのセルを処理
for row in sheet.iter_rows(min_row=1):
for cell in row:
original_value = cell.value
if original_value is not None and isinstance(original_value, str):
masked_value = mask_text(original_value)
cell.value = masked_value
# マスキング後のExcelファイルを保存
output_file_path = f'masked_{os.path.basename(excel_file_path)}'
workbook.save(output_file_path)
print(f"マスキング処理完了。結果は {output_file_path} に保存されました。")
except FileNotFoundError:
print(f"エラー: ファイル '{excel_file_path}' が見つかりません。")
except Exception as e:
print(f"予期せぬエラーが発生しました: {e}")
requirements.txt
openpyxl
requests
python-dotenv