1. はじめに
最近の絵文字、見た目は1文字なのに
Pythonで扱うと意外なバグにつながることがあります。
実はその原因、“2文字以上のUnicode絵文字” にあるかもしれません。
2. 問題の発端:正規表現が思った通りに動かない?
実はこの問題に気づいたきっかけは、
MarkdownからHTMLに変換する処理の中で、
絵文字を特定のタグ(たとえば <span class="emoji">
)に変換するために、
自作のPythonスクリプトを書いていました。
そのとき、正規表現で絵文字を抽出しようとしたのですが──
思ったようにマッチしてくれなかったのです。
例として、絵文字を含む文字列から記号だけを抜き出そうとしたコード:
import re
text = "これはテストです😊👍"
matched = re.findall(r'[^\w\s]', text)
print(matched)
結果は環境によって異なりますが、
「ちゃんと絵文字が取れていない」ケースが多発します。
調べてみると、絵文字の「1文字に見えるけど実は2文字以上」という落とし穴に気づいたんです。
3. 原因:見た目1文字なのに実は2文字以上?
例えば、国旗の「🇯🇵」をPythonで見てみると…
print(len("🇯🇵")) # => 2
これは「Regional Indicator Symbol」と呼ばれる
2つのUnicode文字の組み合わせでできています。
🇯=U+1F1EF
🇵=U+1F1F5
→ 🇯🇵 = 🇯 + 🇵
つまり、見た目では1文字でも、Pythonでは2文字として認識されているんです。
4. 対策その1:emoji
ライブラリで判定する
pip install emoji
import emoji
text = "これは🇯🇵のテスト😊"
for char in text:
if emoji.is_emoji(char):
print(f"{char} は絵文字です")
でもこの方法だと、1文字ずつしか見ていないので
🇯🇵
のような「組み合わせ絵文字」は分割されてしまうことも。
5. 対策その2:regex
ライブラリでGrapheme Cluster対応!
pip install regex
import regex
text = "これは🇯🇵のテスト😊"
graphemes = regex.findall(r'\X', text)
for g in graphemes:
print(g)
出力:
こ
れ
は
🇯🇵
の
テ
ス
ト
😊
→ 見た目通りに「1文字ずつ」取得できている!✨
6. まとめ:絵文字を扱うときの注意点
課題 | 対策 |
---|---|
見た目は1文字なのに、正規表現でマッチしない | 実は複数のUnicode文字(例:🇯🇵は2文字) |
re モジュールでは不十分なことがある |
regex モジュールを使って\X でGrapheme単位にマッチ |
絵文字を判定したい |
emoji ライブラリで存在をチェック(ただし単体文字ベース) |
🎀「絵文字は見た目どおりに扱えないことがあるけど、ちょっとした工夫で回避できるんだよ〜🐍✨」
7. 参考リンク
regex
(PyPI)emoji
(PyPI)- Unicode Technical Standard #18 - Regular Expressions
- Unicode Technical Standard #51 - Emoji
🔗 関連ブログ記事
この記事の元ネタは、ブログ「しゃちらぼ」の
技術寄り“寄り道回”から生まれました 🐬📡