2012-06-12 432 views
127

我目前使用美丽的汤来解析一个HTML文件,并呼吁get_text(),但它似乎是我留下了很多\ xa0代表空格的Unicode。有没有一种有效的方法在Python 2.7中删除它们,并将它们更改为空格?我想更普遍的问题是,有没有办法去除Unicode格式?Python:从字符串中删除 xa0?

我试过使用:line = line.replace(u'\xa0',' '),正如另一个线程所建议的那样,但是把\ xa0改成了u,所以现在我到处都是“u”。 ):

编辑:问题似乎通过str.replace(u'\xa0', ' ').encode('utf-8')解决,但只是做.encode('utf-8')没有replace()似乎导致它吐出甚至超出字符,\ xc2例如。任何人都可以解释吗?

+2

'str.replace('\ xa0','')'? –

+0

已经尝试过,'ascii'编解码器无法解码位置0中的字节0xa0:序号不在范围内(128) – zhuyxn

+11

包含Unicode。使用'''''而不是'''s。 :-) – jpaugh

回答

6

尝试:

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

@RyanMartin:替换**四个字节**:len(b'\\ xa0')== 4'但是len(b'\ xa0')== 1'。如果可能的话;你应该修复产生这些转义的上游。 – jfs

3

0XA0(Unicode)的是在0xC2A0 UTF-8。 .encode('utf8')只会将您的Unicode 0xA0替换为UTF-8的0xC2A0。因此,0xC2s的幻影......编码并没有取代,因为你现在可能已经意识到了。

+1

'0xc2a0'不明确(字节顺序)。改为使用'b'\ xc2 \ xa0''字节。 – jfs

129

\ xa0实际上是拉丁文1(ISO 8859-1)中的非破坏性空间,也是chr(160)。你应该用空格替换它。

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

当.encode( 'UTF-8'),其将编码的Unicode的为UTF-8,这意味着每个unicode可通过1至4个字节来表示。对于这种情况,\ xa0由2个字节\ xc2 \ xa0表示。

请阅读http://docs.python.org/howto/unicode.html

+2

我不知道有关Unicode和字符编码的大量数据,但它看起来像[unicodedata.normalize](http://docs.python.org/2/library/unicodedata.html#unicodedata.normalize)将是比str.replace更合适 – dbr

+0

你的字符串是可行的建议,但是请注意,对这个字符串的所有引用也需要被替换。例如,如果您有一个打开文件的程序,并且其中一个文件的名称中有一个非中断空间,则除了执行此替换操作之外,还需要*重命名该文件。 – g33kz0r

+1

[U + 00a0是一个不可破坏的空格Unicode字符](http://codepoints.net/U+00a0),可以用latin1编码将其编码为'b'\ xa0''字节,如两个字节'b' \ xc2 \ xa0''以utf-8编码。它可以用html表示为' '。 – jfs

11

我遇到了这个问题,用python从sqlite3数据库中提取一些数据。上面的答案对我来说不起作用(不知道为什么),但是确实如此:line = line.decode('ascii', 'ignore')但是,我的目标是删除\ xa0s,而不是用空格替换它们。

我从this super-helpful unicode tutorial by Ned Batchelder.

+11

您现在正在移除任何不是ASCII字符的东西,您可能会掩盖您的实际问题。使用''忽略''就像是通过换挡杆推动,即使你不明白离合器是如何工作的。 –

+0

@MartijnPieters链接的unicode教程很好,但你完全正确 - 'str.encode(... ,'ignore')'是'try:的Unicode处理等价物:... except:...'。虽然它可能隐藏错误信息,但它很少能解决问题。 – dbr

+1

为处理EMAIL或URLS的某些目的,它似乎完美使用'.decode('ascii','ignore')' – andi

6

我这里就结束了,而谷歌搜索与不可打印字符的问题得到了这一点。我使用MySQL UTF-8general_ci并处理波兰语。对于有问题的字符串我必须procced如下:

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

这只是快速的解决方法,你probablly应该尝试用正确的编码设置的东西。

+1

如果'text'是一个表示使用utf-8编码的文本的字符串,这将起作用如果您正在处理文本;先将它解码为Unicode('.decode('utf-8')')并进行编码它只在最后一个字节串(如果API不直接支持Unicode,例如'socket')。文本上的所有中间操作应该以Unicode编码。 – jfs

0

在Beautiful Soup中,您可以传递get_text() strip参数,该参数从文本的开头和结尾剥离空白区域。这将删除\xa0或任何其他空白,如果它出现在字符串的开头或结尾。美丽的汤用\xa0替换了一个空字符串,这解决了我的问题。

mytext = soup.get_text(strip=True) 
+3

'strip = True'只有在' '处于文本的每一位的开始或结尾,如果它位于文本中的其他字符之间,则不会删除该空格。 – jfs

7

尝试使用.strip()在您的线路 line.strip()结束工作很适合我

87

有一个在Python的unicodedata库很多有用的东西。其中之一是.normalize()功能。

尝试:

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

与任何上面,如果你没有得到你之后的结果链接列出的其他方法更换NFKD。

+2

这太棒了。这应该是被接受的答案。 – Houman

+1

完全同意。简单,清晰,简短并且重点突出。竖起大拇指。 –

+0

这个伎俩。有一些HTML生成...微软Word有很多奇怪的Unicode字符,并以某种方式清除它们。 –

3

试试这个代码

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

尝试几种方法后,总结它,这是我做到了。以下是避免/从解析的HTML字符串中移除\ xa0个字符的两种方法。

假设我们有原始的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。要正确删除它们,我们可以使用两种方法。

方法#1(推荐): 第一个是BeautifulSoup的get_text方法与条参数作为真 因此,我们的代码变为:

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: 另一种选择是使用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' 

我也详细介绍了这些方法on this blog你可能想参考。