Python: rimozione di \ xa0 dalla stringa?


241

Attualmente sto usando Beautiful Soup per analizzare un file HTML e chiamare get_text(), ma sembra che mi venga lasciato un sacco di \ xa0 Unicode che rappresentano gli spazi. Esiste un modo efficace per rimuoverli tutti in Python 2.7 e trasformarli in spazi? Immagino che la domanda più generalizzata sarebbe: esiste un modo per rimuovere la formattazione Unicode?

Ho provato a usare line = line.replace(u'\xa0',' '):, come suggerito da un altro thread, ma questo ha cambiato gli \ xa0 in u, quindi ora ho "u" ovunque. ):

EDIT: Il problema sembra essere risolto str.replace(u'\xa0', ' ').encode('utf-8'), ma solo facendo .encode('utf-8')senza replace()sembra causare a sputare personaggi anche più strane, \ xc2 per esempio. Qualcuno può spiegare questo?


già provato, il codec "ascii" non può decodificare il byte 0xa0 in posizione 0: ordinale non compreso nell'intervallo (128)
zhuyxn,

15
abbraccia Unicode. Usa u''s invece di ''s. :-)
jpaugh,

1
ho provato a usare str.replace (u '\ xa0', '') ma ho ottenuto "u" dappertutto invece di \ xa0s: /
zhuyxn il

Se la stringa è quella Unicode, devi usare la u' 'sostituzione, non la ' '. La stringa originale è quella Unicode?
pepr

Risposte:


267

\ xa0 è in realtà spazio non-break in Latin1 (ISO 8859-1), anche chr (160). Dovresti sostituirlo con uno spazio.

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

Quando .encode ('utf-8'), codificherà l'unicode in utf-8, ciò significa che ogni unicode potrebbe essere rappresentato da 1 a 4 byte. In questo caso, \ xa0 è rappresentato da 2 byte \ xc2 \ xa0.

Leggi su http://docs.python.org/howto/unicode.html .

Nota: questa risposta a partire dal 2012, Python è andata avanti, dovresti essere in grado di utilizzare unicodedata.normalizeora


11
Non conosco una grande quantità di Unicode e codifiche di caratteri ... ma sembra che unicodedata.normalize sarebbe più appropriato di str.replace
dbr

Il tuo è un consiglio praticabile per le stringhe, ma nota che anche tutti i riferimenti a questa stringa dovranno essere sostituiti. Ad esempio, se si dispone di un programma che apre i file e uno dei file ha uno spazio non interrotto nel suo nome, sarà necessario rinominare quel file oltre a fare questa sostituzione.
g33kz0r,

1
U + 00a0 è un carattere Unicode di spazio non interrompibile che può essere codificato come b'\xa0'byte nella codifica latin1, come due byte b'\xc2\xa0'nella codifica utf-8. Può essere rappresentato come  in HTML.
jfs,

3
Quando provo questo, ottengo UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 397: ordinal not in range(128).
gwg,

Rimase bloccato per 1 ora e finalmente risolto. Molte grazie.
Sadman Hasan,

217

Ci sono molte cose utili nella unicodedatalibreria di Python . Uno di questi è la .normalize()funzione.

Provare:

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

Sostituendo NFKD con uno qualsiasi degli altri metodi elencati nel link sopra se non si ottengono i risultati desiderati.


9
è brillante. Questa dovrebbe essere la risposta accettata.
Houman,

2
Completamente d'accordo. Soluzione facile, chiara, breve e precisa. Pollice su.
Billy Jhon,

2
Non così sicuro, potresti voler normalize('NFKD', '1º\xa0dia')restituire '1º dia' ma restituisce '1o dia'
Faccion


1
ah, se il testo è 'COREANO', non provare questo. 글자 가 전부 깨져 버리 네요.
Scegli il

18

Prova a usare .strip () alla fine della tua riga ha line.strip()funzionato bene per me


15

Dopo aver provato diversi metodi, per riassumere, ecco come l'ho fatto. Di seguito sono riportati due modi per evitare / rimuovere i caratteri \ xa0 dalla stringa HTML analizzata.

Supponiamo di avere il nostro codice HTML come segue:

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

Quindi proviamo a pulire questa stringa 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'

Il codice sopra produce questi caratteri \ xa0 nella stringa. Per rimuoverli correttamente, possiamo usare due modi.

Metodo n. 1 (consigliato): il primo è il metodo get_text di BeautifulSoup con argomento strip come True Quindi il nostro codice diventa:

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

Metodo n. 2: l'altra opzione è usare la libreria unicodedata di python

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'

Ho anche dettagliato questi metodi su questo blog che potresti voler fare riferimento.


Grazie, il Metodo 1 è ciò che cercavo da sempre.
Vasim,

12

prova questo:

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

5
@RyanMartin: questo sostituisce quattro byte : len(b'\\xa0') == 4ma len(b'\xa0') == 1. Se possibile; è necessario correggere l'upstream che genera queste escape.
jfs,

12

Ho riscontrato questo stesso problema estraendo alcuni dati da un database sqlite3 con Python. Le risposte sopra non hanno funzionato per me (non so perché), ma questo ha fatto:line = line.decode('ascii', 'ignore') Tuttavia, il mio obiettivo era eliminare gli \ xa0s, anziché sostituirli con spazi.

L'ho preso da questo tutorial unicode super utile di Ned Batchelder.


14
Stai rimuovendo tutto ciò che non è un carattere ASCII, probabilmente stai mascherando il tuo vero problema. Usare 'ignore'è come spingere la leva del cambio anche se non capisci come funziona la frizione ..
Martijn Pieters

@MartijnPieters Il tutorial unicode collegato è buono, ma tu hai completamente ragione - str.encode(..., 'ignore')è l'equivalente di gestione Unicode di try: ... except: .... Mentre potrebbe nascondere il messaggio di errore, raramente risolve il problema.
dbr

1
per alcuni scopi come trattare con EMAIL o URL sembra perfetto da usare.decode('ascii', 'ignore')
andilabs

1
La risposta di samwize non ha funzionato per te perché funziona su stringhe Unicode . line.decode()nella tua risposta suggerisce che il tuo input è un bytestring (non dovresti chiamare .decode()una stringa Unicode (per applicarlo, il metodo è rimosso in Python 3). Non capisco come sia possibile vedere il tutorial che hai collegato nella tua risposta e perdere la differenza tra byte e Unicode (non mescolarli).
jfs

8

Finisco qui mentre cerco il problema con un carattere non stampabile. Uso MySQL UTF-8 general_cie mi occupo del linguaggio polacco. Per le stringhe problematiche devo procedere come segue:

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

È solo una soluzione rapida e probabilmente dovresti provare qualcosa con la corretta configurazione della codifica.


1
funziona se textè un bytestring che rappresenta un testo codificato usando utf-8. Se stai lavorando con il testo; decodificalo prima in Unicode ( .decode('utf-8')) e codificalo in un bytestring solo alla fine (se l'API non supporta direttamente Unicode, ad es socket.). Tutte le operazioni intermedie sul testo devono essere eseguite su Unicode.
jfs,

8

Prova questo codice

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

4

0xA0 (Unicode) è 0xC2A0 in UTF-8. .encode('utf8')prenderà semplicemente il tuo Unicode 0xA0 e lo sostituirà con 0xC2A0 di UTF-8. Da qui l'apparizione di 0xC2s ... La codifica non sta sostituendo, come probabilmente hai capito ora.


1
0xc2a0è ambiguo (ordine dei byte). Utilizzare b'\xc2\xa0'invece i byte letterali.
jfs,

3

È l'equivalente di un personaggio spaziale, quindi eliminalo

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

1

In Beautiful Soup, puoi passare get_text()il parametro strip, che rimuove gli spazi bianchi dall'inizio e dalla fine del testo. Questo rimuoverà \xa0o qualsiasi altro spazio bianco se si verifica all'inizio o alla fine della stringa. Beautiful Soup ha sostituito una stringa vuota con \xa0e questo ha risolto il problema per me.

mytext = soup.get_text(strip=True)

5
strip=Truefunziona solo se si &nbsp;trova all'inizio o alla fine di ogni bit di testo. Non rimuoverà lo spazio se si trova tra altri caratteri nel testo.
jfs,

1

Versione generica con l'espressione regolare (rimuoverà tutti i caratteri di controllo):

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

-1

Python lo riconosce come un personaggio spaziale, quindi puoi splitfarlo senza argomenti e unirti a un normale spazio bianco:

line = ' '.join(line.split())
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.