WebではUnicode(UTF-8など)で開発・表示するのが最も一般的になりました。
ですがそんな現在でも、Unicodeのサポートする文字のうちごく一部しか受け付けてくれないレガシーなシステム(サイト)も山のようにあります。
今回は、Pythonのプログラミングをしている中でそういった事態に遭遇したときに役立つ知識をひとつ解説しています。
Pythonのstr変数(文字列)から絵文字などの特殊な文字を削除するのはどうしたらいいでしょうか?
注意!
以下の方法はあくまで簡易的なものであり、手軽に十分実用的な用途に使用できますが、Unicodeの性質上不必要な変換やデータの欠落が生じる状況があります。シチュエーションに応じて、慎重に検討してから実装するようにしてください。
結論
文字列をいったんバイト列に変換(エンコード)して、すぐに文字列に戻す(デコード)という作業をします。
text = "消したい特殊文字を含む文字列"
bytes_emoji = text.encode('shift-jis', errors='ignore')
result = bytes_emoji.decode('shift-jis', errors='ignore')
実行環境
Python 3.9.2
(簡易的に)絵文字などの特殊文字を削除する方法
文字列をエンコードする
str.encode() は文字列から任意の文字エンコードを用いてPythonの世界のバイト列を生成する組み込み関数です。
ある文字というのは原則として何らかのバイト列表現(実態はただの数字)に一対一対応しています。str.encode() でその文字列→バイト列の変換ができます。
ちなみにこの文字 to/from バイト列の変換様式はエンコードというもので定められています。変換するための辞書みたいなものですね。
例えば、日本語の"あ"はバイト列だと以下のように表されます。
str_a = 'あ'
print(str_a)
# あ
bytes_a = str_a.encode()
print(bytes_a)
# b'\xe3\x81\x82'
Pythonでは文字列のエンコードはUTF-8で統一されています。
本題に戻ると、今回絵文字などの特殊文字を削除したい文字列を、一旦Shift-JISの文字列としてエンコードしてバイト列を取得します。
対象の文字列
emoji = "This is emoji [😀] string"
print(emoji)
# This is emoji [😀] string
ここで普通に、絵文字を含むUnicodeの文字列を str.encode() に入力してしまうと(絵文字の部分がShift-JISにないため)変換できずエラーとなります。
bin_emoji = emoji.encode('shift-jis')
# UnicodeEncodeError: 'shift_jis' codec can't encode character '\ufffd' in position 15: illegal multibyte sequence
そこで、エラーとなる箇所(文字)を無視してバイト列に変換してもらいます。
encode()の引数 errors
に'ignore'を指定すればOKです。
bin_emoji = emoji.encode('shift-jis', errors='ignore')
print(bin_emoji)
# b'This is emoji [] string'
引数errors
の仕様は以下の通り。
'strict' | デフォルト |
'ignore' | エラーが生じた文字をメッセージを一切出さず無視する |
'replace' | エラーが生じた文字に対し特定のコード(U+FFFD)で代替する |
'backslashreplace' | バックスラッシュつきのエスケープシーケンス(\xNN)を挿入する |
その他のオプションはドキュメント参照
今回は不要な文字列を削除するのが目的なので 'ignore' を指定します。
文字列をデコードする
絵文字などの特殊文字が削除されたバイト列が得られているので、今度は反対にデコードして文字列に戻します。
デコードするには str.decode() を用います。
result = bin_emoji.decode()
print(result)
# This is emoji [] string
特殊文字が削除された文字列が得られました。
注意事項
Unicode上ですべての文字が一対一対応するわけではありません。
そのため、encode→decode をするうちに情報が欠落することが、結構な確率で発生します。
英数字・ひらカタ・標準的な漢字なら問題なく運用できますが、それ以外ではstr.encode()、str.decode()は注意して使用する必要があります。
また上記の方法は(当然ですが)Shift-JISが対応していない文字(たとえば外国語)は完全に欠落しますので、使用できません。
あらかじめ削除したい文字・絵文字が決まっているときには str.replace() や str.translate() で削除します。
今回参考にしたページ・資料
Unicode HOWTO — Python 3.9.4 ドキュメント