Python: \ xa0 aus String entfernen?

239

Ich verwende derzeit Beautiful Soup, um eine HTML-Datei zu analysieren und aufzurufen get_text(), aber es scheint, als würde mir eine Menge \ xa0 Unicode übrig bleiben, die Leerzeichen darstellen. Gibt es eine effiziente Möglichkeit, alle in Python 2.7 zu entfernen und in Leerzeichen umzuwandeln? Ich denke, die allgemeinere Frage wäre, gibt es eine Möglichkeit, die Unicode-Formatierung zu entfernen?

Ich habe versucht line = line.replace(u'\xa0',' '),: zu verwenden , wie von einem anderen Thread vorgeschlagen, aber das hat die \ xa0 in u geändert, sodass ich jetzt stattdessen überall "u" ​​habe. ):

EDIT: Das Problem scheint gelöst zu werden str.replace(u'\xa0', ' ').encode('utf-8'), aber nur tun , .encode('utf-8')ohne replace()es zu verursachen scheint noch seltsame Zeichen auszuzuspucken, \ xc2 zum Beispiel. Kann jemand das erklären?

zhuyxn
quelle
Ich habe bereits versucht, dass der Codec 'ascii' das Byte 0xa0 an Position 0 nicht dekodieren kann: Ordnungszahl nicht im Bereich (128)
zhuyxn
15
Unicode umarmen. Verwenden Sie u''s anstelle von ''s. :-)
jpaugh
1
habe versucht, str.replace (u '\ xa0', '') zu verwenden, habe aber überall "u" ​​anstelle von \ xa0s: /
zhuyxn
Wenn die Zeichenfolge die Unicode-Zeichenfolge ist, müssen Sie die u' 'Ersetzung verwenden, nicht die ' '. Ist die ursprüngliche Zeichenfolge die Unicode-Zeichenfolge?
Pepr

Antworten:

265

\ xa0 ist in Latin1 (ISO 8859-1), auch chr (160), ein nicht unterbrechender Raum. Sie sollten es durch ein Leerzeichen ersetzen.

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

Wenn .encode ('utf-8'), wird der Unicode in utf-8 codiert, was bedeutet, dass jeder Unicode durch 1 bis 4 Bytes dargestellt werden kann. In diesem Fall wird \ xa0 durch 2 Bytes \ xc2 \ xa0 dargestellt.

Lesen Sie unter http://docs.python.org/howto/unicode.html nach .

Bitte beachten Sie: Diese Antwort aus dem Jahr 2012, Python ist weitergegangen, sollten Sie unicodedata.normalizejetzt verwenden können

Samwize
quelle
11
Ich weiß nicht viel über Unicode- und Zeichencodierungen. Aber es scheint, als ob Unicodedata.normalize besser geeignet wäre als str.replace
dbr
Ihr Ratschlag für Zeichenfolgen ist praktikabel. Beachten Sie jedoch, dass alle Verweise auf diese Zeichenfolge ebenfalls ersetzt werden müssen. Wenn Sie beispielsweise ein Programm haben, das Dateien öffnet, und eine der Dateien einen nicht unterbrechenden Leerzeichen enthält, müssen Sie diese Datei zusätzlich zu dieser Ersetzung umbenennen .
g33kz0r
1
U + 00a0 ist ein nicht unterbrechbares Leerzeichen-Unicode-Zeichen , das b'\xa0'bei der Latin1-Codierung als Byte und b'\xc2\xa0'bei der Utf-8-Codierung als zwei Bytes codiert werden kann. Es kann wie  in HTML dargestellt werden.
JFS
3
Wenn ich das versuche, bekomme ich UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 397: ordinal not in range(128).
GWG
War für 1 Stunde festgefahren und endlich gelöst. Vielen Dank.
Sadman Hasan
215

Es gibt viele nützliche Dinge in Pythons unicodedataBibliothek. Eine davon ist die .normalize()Funktion.

Versuchen:

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

Ersetzen Sie NFKD durch eine der anderen im obigen Link aufgeführten Methoden, wenn Sie nicht die gewünschten Ergebnisse erzielen.

Jamie
quelle
9
das ist brilliant. Dies sollte die akzeptierte Antwort sein.
Houman
2
Stimme voll und ganz zu. Einfache, klare, kurze und präzise Lösung. Daumen hoch.
Billy Jhon
2
Nicht so sicher, vielleicht möchten Sie normalize('NFKD', '1º\xa0dia')'1º dia' zurückgeben, aber es gibt '1o dia'
Faccion zurück
1
Ah, wenn der Text 'KOREANISCH' ist, versuchen Sie dies nicht. 글자 가 전부 깨져 버리 네요.
Cho
17

Versuchen Sie es mit .strip () am Ende Ihrer Zeile line.strip() für mich gut funktioniert hat

user3590113
quelle
14

Nachdem ich verschiedene Methoden ausprobiert habe, um es zusammenzufassen, habe ich es so gemacht. Im Folgenden finden Sie zwei Möglichkeiten zum Vermeiden / Entfernen von \ xa0-Zeichen aus analysierten HTML-Zeichenfolgen.

Angenommen, wir haben unser rohes HTML wie folgt:

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>'

Versuchen wir also, diese HTML-Zeichenfolge zu bereinigen:

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'

Der obige Code erzeugt diese Zeichen \ xa0 in der Zeichenfolge. Um sie richtig zu entfernen, können wir zwei Möglichkeiten verwenden.

Methode 1 (empfohlen): Die erste ist die get_text- Methode von BeautifulSoup mit dem Strip-Argument True. Unser Code wird also zu:

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

Methode 2: Die andere Option besteht darin, die Unicodedata der Python-Bibliothek zu verwenden

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'

Ich habe diese Methoden auch in diesem Blog detailliert beschrieben, auf die Sie möglicherweise verweisen möchten.

Ali Raza Bhayani
quelle
Vielen Dank, Methode 1 ist das, wonach ich mich um alles gekümmert habe.
Vasim
12

Versuche dies:

string.replace('\\xa0', ' ')
user278064
quelle
5
@ RyanMartin: Dies ersetzt vier Bytes : len(b'\\xa0') == 4aber len(b'\xa0') == 1. Wenn möglich; Sie sollten den Upstream reparieren, der diese Escapes generiert.
JFS
12

Ich hatte das gleiche Problem beim Abrufen einiger Daten aus einer SQLite3-Datenbank mit Python. Die obigen Antworten haben bei mir nicht funktioniert (ich weiß nicht warum), aber das hat funktioniert:line = line.decode('ascii', 'ignore') weiß Mein Ziel war es jedoch, die \ xa0s zu löschen, anstatt sie durch Leerzeichen zu ersetzen.

Ich habe dies aus diesem super hilfreichen Unicode-Tutorial von Ned Batchelder erhalten.

Gemeinschaft
quelle
14
Sie entfernen jetzt alles, was kein ASCII-Zeichen ist. Sie maskieren wahrscheinlich Ihr eigentliches Problem. Das Verwenden 'ignore'ist wie das Durchschieben des Schalthebels, obwohl Sie nicht verstehen, wie die Kupplung funktioniert.
Martijn Pieters
@MartijnPieters Das verknüpfte Unicode-Tutorial ist gut, aber Sie sind völlig korrekt - entspricht str.encode(..., 'ignore')dem Unicode-Handling try: ... except: .... Die Fehlermeldung wird möglicherweise ausgeblendet, das Problem wird jedoch selten gelöst.
dbr
1
Für einige Zwecke wie den Umgang mit E-Mail oder URLs scheint es perfekt zu sein.decode('ascii', 'ignore')
andilabs
1
Die Antwort von samwize hat bei Ihnen nicht funktioniert, da sie bei Unicode- Zeichenfolgen funktioniert . line.decode()In Ihrer Antwort wird darauf hingewiesen , dass es sich bei Ihrer Eingabe um einen Bytestring handelt (Sie sollten keine .decode()Unicode-Zeichenfolge aufrufen (um dies zu erzwingen, wird die Methode in Python 3 entfernt). Ich verstehe nicht, wie das von Ihnen verwendete Lernprogramm angezeigt werden kann in Ihrer Antwort verknüpft und verpassen Sie den Unterschied zwischen Bytes und Unicode (mischen Sie sie nicht).
jfs
8

Ich lande hier, während ich nach dem Problem mit dem nicht druckbaren Zeichen google. Ich benutze MySQL UTF-8 general_ciund beschäftige mich mit polnischer Sprache. Für problematische Saiten muss ich wie folgt vorgehen:

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

Es ist nur eine schnelle Problemumgehung und Sie sollten wahrscheinlich etwas mit der richtigen Codierungskonfiguration ausprobieren.

Andilabs
quelle
1
Dies funktioniert, wenn textes sich um einen Bytestring handelt, der einen mit utf-8 codierten Text darstellt. Wenn Sie mit Text arbeiten; dekodiere es zuerst in Unicode ( .decode('utf-8')) und kodiere es erst ganz am Ende in einen Bytestring (wenn die API Unicode nicht direkt unterstützt, z socket. B. ). Alle Zwischenoperationen am Text sollten unter Unicode ausgeführt werden.
JFS
8

Versuchen Sie diesen Code

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

0xA0 (Unicode) ist in UTF-8 0xC2A0. .encode('utf8')Nehmen Sie einfach Ihren Unicode 0xA0 und ersetzen Sie ihn durch den 0xC2A0 von UTF-8. Daher die Erscheinung von 0xC2s ... Die Codierung ersetzt nicht, wie Sie wahrscheinlich jetzt erkannt haben.

dda
quelle
1
0xc2a0ist mehrdeutig (Bytereihenfolge). Verwenden Sie b'\xc2\xa0'stattdessen das Byte-Literal.
JFS
3

Es ist das Äquivalent eines Leerzeichens, also zieh es aus

print(string.strip()) # no more xa0
8bitjunkie
quelle
1

In Beautiful Soup können Sie get_text()den Strip-Parameter übergeben, der Leerzeichen vom Anfang und Ende des Textes entfernt. Dadurch werden \xa0andere Leerzeichen entfernt, wenn sie am Anfang oder Ende der Zeichenfolge auftreten. Beautiful Soup ersetzte eine leere Saite durch \xa0und dies löste das Problem für mich.

mytext = soup.get_text(strip=True)
Kennzeichen
quelle
5
strip=Truefunktioniert nur, wenn &nbsp;es am Anfang oder Ende jedes Textbits steht. Das Leerzeichen wird nicht entfernt, wenn es sich zwischen anderen Zeichen im Text befindet.
JFS
1

Generische Version mit dem regulären Ausdruck (alle Steuerzeichen werden entfernt):

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

Python erkennt es wie ein Leerzeichen, sodass Sie splites ohne Argumente verwenden und durch ein normales Leerzeichen verbinden können:

line = ' '.join(line.split())
Jonhy Beebop
quelle