파이썬 : 문자열에서 \ xa0 제거?


241

현재 Beautiful Soup을 사용하여 HTML 파일을 구문 분석 get_text()하고을 호출 하고 있지만 공백을 나타내는 \ xa0 유니 코드가 많이 남아있는 것 같습니다. 파이썬 2.7에서 그것들을 모두 제거하고 공백으로 바꾸는 효율적인 방법이 있습니까? 더 일반적인 질문은 유니 코드 형식을 제거하는 방법이 있습니까?

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
유니 코드를 받아들입니다. u''s 대신 s를 사용하십시오 ''. :-)
jpaugh

1
str.replace (u '\ xa0', '')를 사용해 보았지만 \ xa0s 대신 "u"를 얻었습니다 : /
zhuyxn

문자열이 유니 코드 문자열 인 경우 .가 u' '아닌 대체 를 사용해야 합니다 ' '. 원래 문자열이 유니 코드 문자열입니까?
pepr

답변:


267

\ 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
나는 유니 코드 및 문자 인코딩에 대한 엄청난 금액을 모른다 ..하지만 것처럼 보인다 unicodedata.normalize이 str.replace보다 더 적합 할 것
DBR

문자열에 대한 유용한 조언이지만이 문자열에 대한 모든 참조도 교체해야합니다. 예를 들어, 파일을 여는 프로그램이 있고 파일 중 하나에 이름에 공백 이없는 경우이 대체 작업 외에도 파일 이름바꿔야 합니다.
g33kz0r

1
U + 00a0은 중단 불가능한 공간 유니 코드 문자b'\xa0' 이며 latin1 인코딩에서 바이트로 b'\xc2\xa0', utf-8 인코딩에서 2 바이트로 인코딩 될 수 있습니다 .  html 로 표현할 수 있습니다 .
jfs

3
이것을 시도하면을 얻습니다 UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 397: ordinal not in range(128).
gwg

1 시간 동안 막혀 마침내 해결되었습니다. 고마워
Sadman Hasan

217

파이썬 unicodedata라이브러리 에는 많은 유용한 것들이 있습니다. 그중 하나가 .normalize()기능입니다.

시험:

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

원하는 결과를 얻지 못하면 위의 링크에 나열된 다른 방법으로 NFKD를 교체하십시오.


9
이것은 훌륭하다. 이것이 정답입니다.
Houman

2
전적으로 동의합니다. 쉽고 명확하며 짧고 포인트 솔루션입니다. 엄지 손가락.
Billy Jhon

2
확실하지 않은 경우 normalize('NFKD', '1º\xa0dia')'1º dia'를 반환 하고 싶지만 '1o dia'를 반환합니다.
Faccion


1
아, 텍스트가 'KOREAN'인 경우 시도하지 마십시오. 텍스트가 전부 깨져 버리 네요.
Cho


15

여러 가지 방법을 시도한 후 요약하면 다음과 같습니다. 다음은 구문 분석 된 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 (권장) : 첫 번째 메소드는 스트립 인수가 True 인 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 : 다른 옵션은 파이썬 라이브러리 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') == 4but len(b'\xa0') == 1. 가능하다면; 이스케이프를 생성하는 업스트림을 수정해야합니다.
jfs

12

파이썬으로 sqlite3 데이터베이스에서 일부 데이터를 가져 오는 것과 동일한 문제가 발생했습니다. 위의 답변은 저에게 효과가 없었지만 (이유는 확실하지 않습니다), 그러나 그렇게했습니다 : line = line.decode('ascii', 'ignore')그러나 내 목표는 \ xa0s를 공백으로 바꾸지 않고 삭제하는 것이 었습니다.

나는 Ned Batchelder 의이 도움이되는 유니 코드 자습서 에서 이것을 얻었습니다 .


14
이제 ASCII 문자가 아닌 것을 제거하고 실제 문제를 숨기고있을 것입니다. 'ignore'클러치의 작동 방식을 이해하지 못하더라도 변속 스틱을 사용 하는 것과 같습니다 ..
Martijn Pieters

@MartijnPieters 연결된 유니 코드 자습서는 훌륭하지만 완전히 맞습니다 str.encode(..., 'ignore'). 유니 코드 처리는 try: ... except: ...입니다. 오류 메시지를 숨길 수는 있지만 거의 문제를 해결하지 못합니다.
dbr

1
EMAIL 또는 URLS 처리와 같은 일부 목적으로 사용하는 것이 완벽 해 보입니다.decode('ascii', 'ignore')
andilabs

1
samwize의 답변유니 코드 문자열에서 작동하기 때문에 작동하지 않았습니다 . line.decode()귀하의 답변에 입력이 바이트.decode() 문자열 임을 제안합니다 ( 유니 코드 문자열을 호출해서는 안됩니다 (강제하기 위해 메소드는 Python 3에서 제거됩니다). 나는 당신이 자습서 를 볼 수있는 방법을 이해할 수 없습니다 귀하의 답변에 연결되어 바이트와 ​​유니 코드의 차이점을 놓치지 마십시오 (혼합하지 마십시오)
jfs

8

인쇄 할 수없는 문자로 문제를 찾기 위해 인터넷을 사용하는 동안 여기에 있습니다. 나는 MySQL을 사용 UTF-8 general_ci하고 세련된 언어를 다룬다. 문제가있는 문자열의 경우 다음과 같이 처리해야합니다.

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

그것은 빠른 해결 방법이며 올바른 인코딩 설정으로 무언가를 시도해야합니다.


1
이것은 textutf-8을 사용하여 인코딩 된 텍스트를 나타내는 바이트 문자열 인 경우 작동합니다 . 텍스트 작업을하는 경우 먼저 유니 코드로 디코딩 ( .decode('utf-8'))하고 맨 끝에서만 바이트 문자열로 인코딩합니다 (API가 유니 코드를 직접 지원하지 않는 경우 (예 :) socket). 텍스트에 대한 모든 중간 작업은 유니 코드로 수행해야합니다.
jfs

8

이 코드를 사용해보십시오

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

4

0xA0 (유니 코드)은 UTF-8에서 0xC2A0입니다. .encode('utf8')유니 코드 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

파이썬은 그것을 공백 문자처럼 인식하므로 split인수없이 일반 공백으로 결합 할 수 있습니다 .

line = ' '.join(line.split())
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.