Python: \ xa0 dizeden kaldırılsın mı?


241

Şu anda bir HTML dosyasını ayrıştırmak ve çağırmak için Güzel Çorba kullanıyorum get_text(), ancak boşlukları temsil eden \ xa0 Unicode bir sürü bırakılıyor gibi görünüyor. Hepsini Python 2.7'de kaldırmanın ve boşluklara dönüştürmenin etkili bir yolu var mı? Daha genel bir soru olurdu, Unicode biçimlendirmesini kaldırmak için bir yolu var mı?

line = line.replace(u'\xa0',' ')Başka bir iş parçacığı tarafından önerildiği gibi : kullanarak denedim , ama bu \ xa0's u's değişti, bu yüzden şimdi bunun yerine her yerde "u" s var. ):

DÜZENLEME: Sorun çözülmüş gibi görünüyor str.replace(u'\xa0', ' ').encode('utf-8'), ama sadece .encode('utf-8')olmadan replace()yapmak örneğin garip karakterler, örneğin \ xc2 tükürmek neden gibi görünüyor. Bunu açıklayan var mı?


denedim, 'ascii' codec bileşeni 0 pozisyonunda bayt 0xa0 kodunu çözemez: sıra
sayı

15
Unicode'u kucaklayın. Kullanım u''yerine s ''s. :-)
jpaugh

1
str.replace (u '\ xa0', '') kullanmayı denedim ancak \ xa0s yerine her yerde "u" var: /
zhuyxn

Dize unicode ise, u' 'yerine değil, yerine kullanmanız gerekir ' '. Orijinal dize unicode bir dize mi?
pepr

Yanıtlar:


267

\ xa0 aslında Latin1'de (ISO 8859-1), ayrıca chr (160) da kırılmaz bir alandır. Bir boşlukla değiştirmelisiniz.

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

.Encode ('utf-8') olduğunda, unicode'u utf-8 olarak kodlar, yani her unicode 1 ila 4 bayt ile temsil edilebilir. Bu durumda \ xa0, 2 bayt \ xc2 \ xa0 ile temsil edilir.

Http://docs.python.org/howto/unicode.html adresinde okuyun .

Lütfen dikkat: 2012'den itibaren bu cevap, Python devam etti, unicodedata.normalizeşimdi kullanabilmelisiniz


11
Unicode ve karakter kodlamaları hakkında çok fazla şey bilmiyorum .. ama unicodedata.normalize str.replace
dbr

Sizinki dizeler için uygulanabilir bir tavsiye, ancak bu dizeye yapılan tüm referansların da değiştirilmesi gerektiğini unutmayın. Örneğin, dosyaları açan bir programınız varsa ve dosyalardan birinde adında kesintisiz bir alan varsa, bu değişikliği yapmanın yanı sıra bu dosyayı yeniden adlandırmanız gerekir .
g33kz0r

1
U +, 00a0 olmayan bir kırılabilir alan Unicode karakter olarak kodlanabilir b'\xa0'iki bayt, latin1 kodlama byte b'\xc2\xa0'UTF-8 kodlama.  Html biçiminde gösterilebilir .
jfs

3
Bunu denediğimde anladım UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 397: ordinal not in range(128).
gwg

1 saat sıkışmış ve sonunda çözüldü. Çok teşekkürler.
Sadman Hasan

217

Python'un unicodedatakütüphanesinde birçok yararlı şey var . Bunlardan biri .normalize()fonksiyon.

Deneyin:

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

NFKD'yi, takip ettiğiniz sonuçları almazsanız yukarıdaki bağlantıda listelenen diğer yöntemlerden herhangi biriyle değiştirmek.


9
bu harika. Bu kabul edilen cevap olmalı.
Houman

2
Tamamen katılıyorum. Kolay, anlaşılır, kısa ve doğru çözüm. Başparmak havaya.
Billy Jhon

2
O kadar emin değilim, normalize('NFKD', '1º\xa0dia')'1º dia' döndürmek isteyebilirsiniz , ancak '1o dia' döndürür
Faccion


1
ah, metin 'KOREAN' ise, bunu denemeyin. 글자 가 전부 깨져 버리 네요.
Cho

18

Senin satırın sonundaki .strip () kullanmayı deneyin line.strip()benim için iyi çalıştı


15

Birkaç yöntemi denedikten sonra, özetlemek gerekirse, ben böyle yaptım. Aşağıda, ayrıştırılmış HTML dizesinden \ xa0 karakterleri kullanmanın / kaldırmanın iki yolu vardır.

Ham html'mizin aşağıdaki gibi olduğunu varsayalım:

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

Bu HTML dizesini temizlemeye çalışalım:

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'

Yukarıdaki kod bu karakterleri dizede \ xa0 üretir . Onları düzgün bir şekilde çıkarmak için iki yol kullanabiliriz.

Yöntem # 1 (Önerilen): İlki BeautifulSoup'un şerit argümanı True olarak get_text yöntemidir. Yani kodumuz şöyle olur:

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

Yöntem # 2: Diğer seçenek python kitaplığı unicodedata kullanmaktır

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'

Ayrıca , bu blogda başvurmak isteyebileceğiniz bu yöntemleri ayrıntılı olarak açıkladım.


Teşekkür ederim, Yöntem 1 sonuçta aradığım şeydi.
Vasim

12

bunu dene:

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

5
@RyanMartin: bu dört baytın yerine geçer : len(b'\\xa0') == 4ama len(b'\xa0') == 1. Eğer mümkünse; bu kaçışları oluşturan yukarı akışı düzeltmelisiniz.
jfs

12

Python ile bir sqlite3 veritabanından bazı veriler çekerek bu aynı sorunla karşılaştım. Yukarıdaki cevaplar benim için işe yaramadı (neden olduğundan emin değilim), ama bu işe yaradı: line = line.decode('ascii', 'ignore')Ancak, amacım boşluklarla değiştirmek yerine \ xa0'ları silmekti.

Ned Batchelder'in bu süper yararlı unicode öğreticisinden aldım .


14
Artık ASCII karakteri olmayan bir şeyi kaldırıyorsunuz, muhtemelen gerçek probleminizi maskeliyorsunuz. 'ignore'Debriyajın nasıl çalıştığını anlamasanız da kullanmak vites çubuğunu itmek gibidir ..
Martijn Pieters

@MartijnPieters Bağlantılı unicode öğretici iyidir, ancak tamamen haklısınız - str.encode(..., 'ignore')Unicode işleme eşdeğeri try: ... except: .... Hata mesajını gizleyebilse de, sorunu nadiren çözer.
dbr

1
EMAIL veya URLS ile uğraşmak gibi bazı amaçlar için kullanmak mükemmel görünüyor.decode('ascii', 'ignore')
andilabs

1
samwize'in cevabı sizin için işe yaramadı çünkü Unicode dizelerinde çalışıyor . line.decode()Cevabınız da girdi bir olduğunu göstermektedir bytestring aramak gerekir ( .decode()(bunu uygulamak için, yöntemi) Python 3'te kaldırılır. Ben görmek nasıl mümkün olduğunu anlamıyorum Unicode dizesi bu iş parçacığı öğretici Cevabınıza bağlı ve bayt ve Unicode arasındaki farkı kaçırmayın (karıştırmayın)
jfs

8

Burada yazdırılamayan karakterle ilgili sorun için googling yaparken sonunda. MySQL kullanıyorum UTF-8 general_cive lehçe ile ilgileniyorum. Sorunlu dizeler için aşağıdaki gibi işlem yapmam gerekiyor:

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

Bu sadece hızlı bir çözümdür ve muhtemelen doğru kodlama kurulumu ile bir şey denemelisiniz.


1
textutf-8 kullanılarak kodlanmış bir metni temsil eden bir bytestring ise bu işe yarar . Metinle çalışıyorsanız; önce Unicode'a ( .decode('utf-8')) kodunu çözün ve yalnızca en sonunda bir test koduna kodlayın (API doğrudan Unicode'u desteklemiyorsa, ör socket.). Metin üzerindeki tüm ara işlemler Unicode üzerinde yapılmalıdır.
jfs

8

Bu kodu deneyin

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

4

UTF-8'de 0xA0 (Unicode), 0xC2A0'dır. .encode('utf8')Unicode 0xA0'ınızı alır ve UTF-8'in 0xC2A0'ı ile değiştirir. Bu nedenle 0xC2'lerin görünüşü ... Muhtemelen şimdi fark ettiğiniz gibi kodlama yerini almıyor.


1
0xc2a0belirsiz (bayt sırası). Kullanım b'\xc2\xa0'yerine literal bayt.
jfs

3

Boşluk karakterine eşdeğerdir, bu yüzden soy

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

1

Güzel Çorba'da get_text()metnin başından ve sonundan itibaren beyaz boşluk bırakan strip parametresini iletebilirsiniz . Bu \xa0, dizenin başlangıcında veya sonunda oluşursa veya başka herhangi bir beyaz alanı kaldıracaktır . Güzel Çorba boş bir dize ile değiştirdi \xa0ve bu benim için sorunu çözdü.

mytext = soup.get_text(strip=True)

5
strip=Trueyalnızca &nbsp;metnin her bitinin başında veya sonundaysa çalışır . Metindeki diğer karakterler arasında boşluk varsa kaldırılmaz.
jfs

1

Normal ifadeye sahip genel sürüm (Tüm kontrol karakterlerini silecektir):

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

-1

Python bunu bir boşluk karakteri gibi tanır, böylece splitargüman olmadan ve normal bir boşlukla katılabilirsiniz:

line = ' '.join(line.split())
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.