質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Unicode

Unicodeはエンコーディングの標準規格です。1つの文字コード体系で多国語の表現を可能にすることを目指して作られています。

Q&A

解決済

4回答

3630閲覧

pythonで絵文字だけ取り除く方法

memu2

総合スコア16

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Unicode

Unicodeはエンコーディングの標準規格です。1つの文字コード体系で多国語の表現を可能にすることを目指して作られています。

0グッド

0クリップ

投稿2018/02/16 07:45

python3のtkinterで、テキストウィジェットに文章を挿入しようとしたところ、
「ユニコードの基本多言語面(U+0000からU+FFFF)の範囲を超えています。tkinterでは扱いきれません。」といったエラーが出ました。

調べてみると、楓の葉の絵文字が混じっていたため、文章をinsertできなかったようです。
そこで、ある文章に先ほどの範囲を超える特殊文字が含まれていれば取り除き、含まれていなければ何もしない処理を行いたいのですが、どうすれば実現できるでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

過去に似た質問がありました。
python3, 表現できないユニコードを一部無視して処理したい

基本多言語面(BMP)外の文字は空文字に置き換える手法です。

Python

1# BMP外を''に置換するマップ 2import sys 3non_bmp_map = dict.fromkeys(range(0x10000, sys.maxunicode + 1), '') 4 5s = 'これ「????」は絵文字です' 6print(s) 7 8# 置換 9s = s.translate(non_bmp_map) 10print(s)

投稿2018/02/16 08:07

編集2018/02/16 08:24
can110

総合スコア38262

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

memu2

2018/02/16 08:17

ありがとうございます、家に帰ったら早速試してみたいと思います。 ひとつ質問なのですが、これを使うと漢字や中国語まで空白になってしまう、ということはないでしょうか? 文章の中にはそれらが含まれると思うので。
can110

2018/02/16 08:26

いわゆる普通の漢字やひらがななど(CJK統合文字)はBMP内なので問題ないと思います。
memu2

2018/02/17 02:07

上手く実現できました。ベストアンサーのつけ方がよく分からず、知らないうちに別の方になっていました。申し訳ありません。 解決方法にこのやり方を書いておきます。 ありがとうございました。
guest

0

ベストアンサー

can110さんの回答を拝見して以下を妄想しました。

Python

1# unicode対応のPython3限定なのかも 2def leaveOnlyBMP(s): 3 return "".join(filter(lambda c: c < '\uD800' or '\uDFFF' < c, s))

「dictにしたときメモリーをそこそこ使うかもしれない...」という単なる貧乏根性です。

Python3(?)ではUTF16がstrの表現に用いられいると思いますが、BMP範囲外の文字はサロゲートペア(長さが2の文字列)で表現されていて、それぞれのUTF16文字コードがU+D800~U+DFFFの範囲になるということを利用したものです。

不備ありましたらご容赦を・・・


追記:申し訳ありません。不備がありました。
Python3.6.3 LANG=ja_JP.UTF8でUTF-8のソースコード上にBMP範囲外の文字列リテラルを直接記述して、列挙してみたところ以下のようにサロゲートペアでなく単一の文字として扱われていました。

len('????') == 1
ord('????') == 0x1f40d

このため最初の回答の関数ではNGで次のようにしなくてはなりませんでした。
リスト2

Python

1# BMP範囲外のUNICODE文字が1文字として扱われている場合 2def leaveOnlyBMP(s): 3 return "".join(filter(lambda c: ord(c) < 0x10000, s))

ソースコード上に直接書いたり外部からエンコーディングを指定して文字列を読み込んだ場合など、Python3の環境でサロゲートペアになることがあるのかないのかが自分にはわかってませんが、BMP以外を含めたユニコード全範囲の文字を単一のコードポイントとして扱う能力が今のPythonにはあるようなのでその条件下ではリスト2でないといけないと思いました。

投稿2018/02/16 09:12

編集2018/02/17 02:06
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

memu2

2018/02/16 17:42

楓の葉の絵文字ですが、この方法では上手く取り除くことが出来なかったようです。
KSwordOfHaste

2018/02/17 01:44

すみません!本当ですね!追記しておきます
memu2

2018/02/17 02:09

ありがとうございます。丁寧な回答で助かりました。
KSwordOfHaste

2018/02/17 02:14

自分の環境では sys.maxunicode==0x10FFFF だったのでBMP範囲外も全て一文字として扱えるよということなのだろうと思います。 https://www.python.org/dev/peps/pep-0393/ をみるとサロゲートペアとして扱われる場面もありそうなので、どちらの環境でも動作するよう配慮するにはもう少し緻密なコードにせねばならないと思います。
guest

0

いちおうこういうのは前に見たので紹介しておきます。
Qiita - pythonで絵文字を駆逐する

投稿2018/02/16 07:48

LouiS0616

総合スコア35660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

python

1# BMP外を''に置換するマップ 2import sys 3non_bmp_map = dict.fromkeys(range(0x10000, sys.maxunicode + 1), '') 4 5s = 'これ「????」は絵文字です' 6print(s) 7 8# 置換 9s = s.translate(non_bmp_map) 10print(s) 11 12#結果 13#これ「」は絵文字です

投稿2018/02/17 02:14

memu2

総合スコア16

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KSwordOfHaste

2018/02/17 02:32

Python3.3以前でsys.maxunicodeが0xFFFFとなるような環境(サロゲートペア2文字でBMP範囲外の文字を表す環境)では、dict.fromkeys(range(0x10000, sys.maxunicode + 1), '')の結果は「空の辞書」になり望む結果は得られないのかも知れませんね。 しかしhttps://docs.python.jp/3/library/sys.htmlをみれば現在の最新バージョンではsys.maxunicodeは0x10FFFFであると明記されており、最新のPython3であればBMP範囲外を含め全てのUNICODE文字は1文字として表現できるということなのだと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問