Python:文字列から\ xa0を削除しますか?


240

現在、Beautiful Soupを使用してHTMLファイルを解析し、を呼び出していますが、get_text()スペースを表す多くの\ xa0 Unicodeが残っているようです。Python 2.7でそれらすべてを削除し、スペースに変更する効率的な方法はありますか?より一般的な質問になると思いますが、Unicode形式を削除する方法はありますか?

line = line.replace(u'\xa0',' ')別のスレッドで提案されているように、を使用してみましたが、\ xa0がuに変更されたため、代わりに "u"がどこにでもあります。):

編集:問題はによって解決されたようですがstr.replace(u'\xa0', ' ').encode('utf-8').encode('utf-8')何もせずに実行するreplace()と、たとえば\ xc2などの奇妙な文字が吐き出されます。誰かがこれを説明できますか?


すでに試してみましたが、「ascii」コーデックは位置0のバイト0xa0をデコードできません:序数が範囲(128)にありません
zhuyxn

15
Unicodeを採用します。u''sの代わりに''sを使用します。:-)
jpaugh

1
str.replace(u '\ xa0'、 '')を使用しようとしましたが、\ xa0sではなく "u"がどこにでもあります:/
zhuyxn

文字列がユニコード文字列の場合は、u' 'ではなく置換を使用する必要があり' 'ます。元の文字列はUnicodeのものですか?
pepr

回答:


265

\ xa0は実際にはLatin1(ISO 8859-1)の非改行スペースであり、chr(160)でもあります。スペースで置き換える必要があります。

string = string.replace(u'\xa0', u' ')

.encode( 'utf-8')の場合、ユニコードはutf-8にエンコードされます。つまり、すべてのユニコードは1〜4バイトで表すことができます。この場合、\ xa0は2バイトの\ xc2 \ xa0で表されます。

http://docs.python.org/howto/unicode.htmlを読んでください。

注意:2012年からこの回答、Pythonは移行しました。unicodedata.normalize今すぐ使用できます。


11
Unicodeと文字エンコーディングについてはあまり知りませんが、unicodedata.normalizeはstr.replaceよりも適切だと思います
dbr

あなたは文字列に対して実行可能なアドバイスですが、この文字列へのすべての参照も置き換える必要があることに注意してください。たとえば、ファイルを開くプログラムがあり、ファイルの1つに改行なしのスペースが含まれている場合、この置換を行うことに加えて、そのファイルの名前変更する必要があります。
g33kz0r 2014

1
U + 00a0は、分割不可能なスペースUnicode文字で、utf-8エンコーディングでb'\xa0'は2バイトとして、latin1エンコーディングではバイトとしてエンコードできますb'\xc2\xa0' htmlのように表現できます。
jfs

3
私はこれをしようとすると、私が得ますUnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 397: ordinal not in range(128)
gwg

1時間立ち往生し、ようやく解決しました。どうもありがとう。
Sadman Hasan、2015

216

Pythonのunicodedataライブラリには便利なものがたくさんあります。それらの1つは.normalize()関数です。

試してください:

new_str = unicodedata.normalize("NFKD", unicode_str)

目的の結果が得られない場合は、上記のリンクに記載されている他の方法でNFKDを置き換えます。


9
これは素晴らしいです。これは受け入れられる答えになるはずです。
Houman 2016

2
完全に同意する。簡単、明快、短く、的を絞ったソリューション。いいぞ。
Billy Jhon 2017

2
よくnormalize('NFKD', '1º\xa0dia')
わかりません。


1
ああ、テキストが「韓国語」の場合、これを試さないでください。글자가전부깨져버리네요。
Cho


14

いくつかの方法を試した後、要約すると、これが私のやり方です。以下は、解析されたHTML文字列から\ xa0文字を回避/削除する2つの方法です。

次のような生のhtmlがあるとします。

raw_html = '<p>Dear Parent, </p><p><span style="font-size: 1rem;">This is a test message, </span><span style="font-size: 1rem;">kindly ignore it. </span></p><p><span style="font-size: 1rem;">Thanks</span></p>'

このHTML文字列を整理してみましょう。

from bs4 import BeautifulSoup
raw_html = '<p>Dear Parent, </p><p><span style="font-size: 1rem;">This is a test message, </span><span style="font-size: 1rem;">kindly ignore it. </span></p><p><span style="font-size: 1rem;">Thanks</span></p>'
text_string = BeautifulSoup(raw_html, "lxml").text
print text_string
#u'Dear Parent,\xa0This is a test message,\xa0kindly ignore it.\xa0Thanks'

上記のコードは、これらの文字\ xa0を文字列に生成します。それらを適切に削除するには、2つの方法を使用できます。

メソッド#1(推奨): 最初のメソッドは、BeautifulSoupのget_textメソッドで、ストリップ引数がTrueに設定されているため 、コードは次のようになります。

clean_text = BeautifulSoup(raw_html, "lxml").get_text(strip=True)
print clean_text
# Dear Parent,This is a test message,kindly ignore it.Thanks

方法2: もう1つのオプションは、Pythonのライブラリunicodedataを使用することです

import unicodedata
text_string = BeautifulSoup(raw_html, "lxml").text
clean_text = unicodedata.normalize("NFKD",text_string)
print clean_text
# u'Dear Parent,This is a test message,kindly ignore it.Thanks'

これらの方法について、このブログで詳しく説明していますので、参考にしてください。


ありがとう、方法1は私がずっと探していたものです。
Vasim、

12

これを試して:

string.replace('\\xa0', ' ')

5
@RyanMartin:この置き換え4バイトlen(b'\\xa0') == 4しかしlen(b'\xa0') == 1。可能なら; これらのエスケープを生成する上流を修正する必要があります。
jfs、2015年

12

Pythonでsqlite3データベースからデータを取得する同じ問題に遭遇しました。上記の答えはうまくline = line.decode('ascii', 'ignore')いきませんでした(理由はわかりません)が、うまくいきました:しかし、私の目標は、\ xa0をスペースで置き換えるのではなく、削除することでした。

これは、Ned Batchelderによるこの非常に役立つUnicodeチュートリアルから入手しました


14
これで、ASCII文字以外のものが削除されました。おそらく、実際の問題を覆い隠しています。使用すると、'ignore'あなたはクラッチが...どのように機能するかを理解していないにもかかわらず、シフトレバーによって追いやらようなものです
マルタインピータース

@MartijnPietersリンクされたUnicodeチュートリアルは優れていますが、完全に正しいstr.encode(..., 'ignore')です。Unicodeを処理するのと同じですtry: ... except: ...。エラーメッセージは非表示になる場合がありますが、問題が解決することはほとんどありません。
dbr

1
EMAILやURLの処理など、いくつかの目的で使用するのに最適と思われます.decode('ascii', 'ignore')
andilabs

1
samwizeの答えUnicode文字列で機能するため、うまくいきませんでした。line.decode()あなたの答えにあなたの入力がされることを示唆しているバイト文字列(あなたが呼び出すべきではありません.decode()方法はPython 3で削除され、それを強制する(Unicode文字列で)。私は見ることが可能であるかを理解していないあなたがしたことのチュートリアルをあなたの答えにリンクされ、バイトとUnicodeの違いを見逃します(それらを混在させないでください)
jfs

8

印刷できない文字の問題を探している間、私はここに行きます。私はMySQLを使用UTF-8 general_ciし、ポーランド語を扱います。問題のある文字列については、次のように処理する必要があります。

text=text.replace('\xc2\xa0', ' ')

これは高速の回避策であり、おそらく正しいエンコーディング設定で何かを試す必要があります。


1
これtextは、utf-8を使用してエンコードされたテキストを表すバイト文字列の場合に機能します。テキストで作業している場合; 最初にUnicodeにデコードし(.decode('utf-8'))、最後にのみバイト文字列にエンコードします(APIがUnicodeを直接サポートしていない場合などsocket)。テキストのすべての中間操作はUnicodeで実行する必要があります。
jfs、

8

このコードを試してください

import re
re.sub(r'[^\x00-\x7F]+','','paste your string here').decode('utf-8','ignore').strip()

4

0xA0(Unicode)は、UTF-8では0xC2A0です。.encode('utf8')Unicode 0xA0を取得し、UTF-8の0xC2A0に置き換えます。したがって、0xC2sの出現...おそらく今気付いているように、エンコーディングは置き換えられていません。


1
0xc2a0あいまいです(バイト順)。b'\xc2\xa0'代わりにバイトリテラルを使用してください。
jfs、

3

スペース文字に相当するので、それを取り除きます

print(string.strip()) # no more xa0

1

Beautiful Soupではget_text()、テキストの最初と最後から空白を取り除くstripパラメーターを渡すことができます。\xa0文字列の先頭または末尾にある場合、これにより、またはその他の空白が削除されます。Beautiful Soupが空の文字列を置き換え、\xa0これで問題が解決しました。

mytext = soup.get_text(strip=True)

5
strip=True&nbsp;がテキストの各ビットの最初または最後にある場合にのみ機能します。テキスト内の他の文字の間にあるスペースは削除されません。
jfs

1

正規表現を使用したジェネリックバージョン(すべての制御文字が削除されます):

import re
def remove_control_chart(s):
    return re.sub(r'\\x..', '', s)

-1

Pythonはそれをスペース文字のように認識するため、split引数なしで通常の空白で結合できます。

line = ' '.join(line.split())
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.