Python: Menghapus \ xa0 dari string?


241

Saat ini saya menggunakan Beautiful Soup untuk mem-parsing file HTML dan menelepon get_text(), tetapi sepertinya saya dibiarkan dengan banyak \ xa0 Unicode yang mewakili spasi. Apakah ada cara yang efisien untuk menghapus semuanya di Python 2.7, dan mengubahnya menjadi spasi? Saya kira pertanyaan yang lebih umum, apakah ada cara untuk menghapus pemformatan Unicode?

Saya mencoba menggunakan line = line.replace(u'\xa0',' '):, seperti yang disarankan oleh utas lain, tetapi itu mengubah \ xa0 menjadi milik Anda, jadi sekarang saya memiliki "kamu" di mana-mana. ):

EDIT: Masalahnya tampaknya diselesaikan dengan str.replace(u'\xa0', ' ').encode('utf-8'), tetapi hanya melakukan .encode('utf-8')tanpa replace()tampaknya menyebabkannya meludah bahkan lebih aneh karakter, \ xc2 misalnya. Adakah yang bisa menjelaskan ini?


sudah mencobanya, 'ascii' codec tidak dapat mendekode byte 0xa0 di posisi 0: ordinal tidak dalam jangkauan (128)
zhuyxn

15
merangkul Unicode. Gunakan u''s bukan ''s. :-)
jpaugh

1
mencoba menggunakan str.replace (u '\ xa0', '') tetapi mendapat "u" di mana-mana alih-alih \ xa0s: /
zhuyxn

Jika string adalah yang unicode, Anda harus menggunakan u' 'penggantinya, bukan ' '. Apakah string asli satu unicode?
pepr

Jawaban:


267

\ xa0 sebenarnya adalah ruang non-breaking dalam Latin1 (ISO 8859-1), juga chr (160). Anda harus menggantinya dengan spasi.

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

Ketika .encode ('utf-8'), itu akan menyandikan unicode ke utf-8, itu berarti setiap unicode dapat diwakili oleh 1 hingga 4 byte. Untuk kasus ini, \ xa0 diwakili oleh 2 byte \ xc2 \ xa0.

Baca di http://docs.python.org/howto/unicode.html .

Harap perhatikan: jawaban ini mulai dari tahun 2012, Python telah pindah, Anda seharusnya dapat menggunakannya unicodedata.normalizesekarang


11
Saya tidak tahu banyak tentang pengkodean Unicode dan karakter .. tetapi sepertinya unicodedata.normalisasi akan lebih tepat daripada str.replace
dbr

Milik Anda adalah saran yang bisa diterapkan untuk string, tetapi perhatikan bahwa semua referensi untuk string ini juga perlu diganti. Misalnya, jika Anda memiliki program yang membuka file, dan salah satu file memiliki ruang yang tidak melanggar namanya, Anda perlu mengganti nama file itu selain melakukan penggantian ini.
g33kz0r

1
U + 00a0 adalah karakter Unicode ruang yang tidak dapat dipecah yang dapat dikodekan sebagai b'\xa0'byte dalam pengkodean latin1, sebagai dua byte b'\xc2\xa0'dalam pengkodean utf-8. Itu bisa direpresentasikan  dalam html.
jfs

3
Ketika saya mencoba ini, saya mengerti UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 397: ordinal not in range(128).
gwg

Terjebak selama 1 jam dan akhirnya dipecahkan. Terima kasih banyak.
Sadman Hasan

217

Ada banyak hal berguna di unicodedataperpustakaan Python . Salah satunya adalah .normalize()fungsinya.

Mencoba:

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

Mengganti NFKD dengan salah satu metode lain yang tercantum dalam tautan di atas jika Anda tidak mendapatkan hasil yang Anda cari.


9
ini brilian. Ini harus menjadi jawaban yang diterima.
Houman

2
Setuju. Solusi mudah, jelas, singkat dan to the point. Jempolan.
Billy Jhon

2
Tidak begitu yakin, Anda mungkin ingin normalize('NFKD', '1º\xa0dia')mengembalikan '1º dia' tetapi mengembalikan '1o dia'
Faccion


1
ah, jika teksnya 'KOREAN', jangan coba ini. 글자 가 전부 깨져 버리 네요.
Cho

18

Coba gunakan .strip () di akhir baris Anda line.strip()bekerja dengan baik untuk saya


15

Setelah mencoba beberapa metode, untuk meringkasnya, ini adalah bagaimana saya melakukannya. Berikut ini adalah dua cara untuk menghindari / menghapus \ xa0 karakter dari string HTML yang diuraikan.

Asumsikan kami memiliki html mentah kami sebagai berikut:

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

Jadi mari kita coba bersihkan string HTML ini:

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'

Kode di atas menghasilkan karakter-karakter ini \ xa0 dalam string. Untuk menghapusnya dengan benar, kita dapat menggunakan dua cara.

Metode # 1 (Disarankan): Yang pertama adalah metode get_text BeautifulSoup dengan argumen strip sebagai True Jadi kode kita menjadi:

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

Metode # 2: Opsi lainnya adalah menggunakan pustaka unicodedata 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'

Saya juga telah merinci metode ini di blog ini yang mungkin ingin Anda rujuk.


Terima kasih, Metode 1 adalah yang saya cari setelah ini.
Vasim

12

coba ini:

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

5
@RyanMartin: ini menggantikan empat byte : len(b'\\xa0') == 4tetapi len(b'\xa0') == 1. Jika memungkinkan; Anda harus memperbaiki hulu yang menghasilkan pelarian ini.
jfs

12

Saya mengalami masalah yang sama menarik beberapa data dari database sqlite3 dengan python. Jawaban di atas tidak bekerja untuk saya (tidak yakin mengapa), tetapi ini berhasil:line = line.decode('ascii', 'ignore') Namun, tujuan saya menghapus \ xa0s, alih-alih menggantinya dengan spasi.

Saya mendapatkan ini dari tutorial unicode yang sangat membantu oleh Ned Batchelder.


14
Anda sekarang menghapus apa pun yang bukan karakter ASCII, Anda mungkin menutupi masalah Anda yang sebenarnya. Menggunakan 'ignore'seperti mendorong melalui tongkat persneling meskipun Anda tidak mengerti bagaimana kopling bekerja ..
Martijn Pieters

@ MartijnPieters Tutorial unicode yang tertaut baik, tetapi Anda sepenuhnya benar - str.encode(..., 'ignore')adalah setara dengan penanganan Unicode try: ... except: .... Meskipun mungkin menyembunyikan pesan kesalahan, itu jarang menyelesaikan masalah.
dbr

1
untuk beberapa tujuan seperti berurusan dengan EMAIL atau URL, tampaknya sempurna untuk digunakan.decode('ascii', 'ignore')
andilabs

1
jawaban samwize tidak bekerja untuk Anda karena itu bekerja pada string Unicode . line.decode()dalam jawaban Anda menunjukkan bahwa input Anda adalah bytestring (Anda tidak boleh memanggil .decode()string Unicode (untuk menegakkannya, metode ini dihapus dengan Python 3). Saya tidak mengerti bagaimana mungkin melihat tutorial yang telah Anda buat ditautkan dalam jawaban Anda dan lewatkan perbedaan antara byte dan Unicode (jangan campur mereka)
jfs

8

Saya berakhir di sini sambil mencari masalah dengan karakter yang tidak dapat dicetak. Saya menggunakan MySQL UTF-8 general_cidan berurusan dengan bahasa Polandia. Untuk string yang bermasalah saya harus melakukan sebagai berikut:

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

Ini hanya solusi cepat dan Anda mungkin harus mencoba sesuatu dengan pengaturan penyandian yang tepat.


1
ini berfungsi jika textbytestring yang mewakili teks yang dikodekan menggunakan utf-8. Jika Anda bekerja dengan teks; decode ke Unicode terlebih dahulu ( .decode('utf-8')) dan encode ke bytestring hanya di akhir (jika API tidak mendukung Unicode secara langsung misalnya, socket). Semua operasi perantara pada teks harus dilakukan pada Unicode.
jfs

8

Coba kode ini

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

4

0xA0 (Unicode) adalah 0xC2A0 di UTF-8. .encode('utf8')hanya akan mengambil Unicode 0xA0 Anda dan ganti dengan 0xC2A0 UTF-8. Oleh karena itu kemunculan 0xC2s ... Pengkodean tidak menggantikan, seperti yang mungkin Anda sadari sekarang.


1
0xc2a0ambigu (urutan byte). Gunakan b'\xc2\xa0'byte literal sebagai gantinya.
jfs

3

Ini setara dengan karakter ruang, jadi lepaskan

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

1

Dalam Beautiful Soup, Anda dapat melewatkan get_text()parameter strip, yang menghapus spasi ruang putih dari awal dan akhir teks. Ini akan menghapus \xa0atau spasi putih lainnya jika itu terjadi pada awal atau akhir string. Sup yang indah menggantikan string kosong dengan \xa0dan ini memecahkan masalah bagi saya.

mytext = soup.get_text(strip=True)

5
strip=Truehanya berfungsi jika &nbsp;berada di awal atau akhir setiap bit teks. Ini tidak akan menghapus spasi jika tidak ada di antara karakter lain dalam teks.
jfs

1

Versi generik dengan ekspresi reguler (Ini akan menghapus semua karakter kontrol):

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

-1

Python mengenalinya seperti karakter spasi, jadi Anda bisa splitmelakukannya tanpa args dan bergabung dengan spasi putih normal:

line = ' '.join(line.split())
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.