UnicodeEncodeError: 'ascii' codec 20 konumundaki u'\xa0' karakterini kodlayamıyor: ordinal not in range(128)

Farklı web sayfalarından (farklı sitelerde) alınan metinlerdeki unicode karakterlerle ilgili sorunlar yaşıyorum. BeautifulSoup kullanıyorum.

Sorun, hatanın her zaman tekrarlanabilir olmamasıdır; bazen bazı sayfalarla çalışır ve bazen bir UnicodeEncodeError atarak barfs yapar. Aklıma gelen hemen hemen her şeyi denedim, ancak Unicode ile ilgili bir hata vermeden tutarlı bir şekilde çalışan hiçbir şey bulamadım.

Sorunlara neden olan kod bölümlerinden biri aşağıda gösterilmiştir:

agent_telno = agent.find('div', 'agent_contact_number')
agent_telno = '' if agent_telno is None else agent_telno.contents[0]
p.agent_info = str(agent_contact + ' ' + agent_telno).strip()

İşte yukarıdaki kod parçacığı çalıştırıldığında BAZI dizeler üzerinde üretilen bir yığın izi:

Traceback (most recent call last):
  File "foobar.py", line 792, in <module>
    p.agent_info = str(agent_contact + ' ' + agent_telno).strip()
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 20: ordinal not in range(128)

Bunun nedeninin bazı sayfaların (ya da daha spesifik olarak, bazı sitelerdeki sayfaların) kodlanmış, diğerlerinin ise kodlanmamış olabileceğinden şüpheleniyorum. Tüm siteler Birleşik Krallık'ta yerleşiktir ve Birleşik Krallık tüketimine yönelik veriler sağlar - bu nedenle içselleştirme veya İngilizce dışında bir dilde yazılmış metinlerle ilgili herhangi bir sorun yoktur.

Bu sorunu SÜREKLİ olarak çözebilmem için bunu nasıl çözebileceğime dair herhangi bir fikri olan var mı?

Çözüm

Python Unicode HOWTO belgesini okumanız gerekmektedir. Bu hata ilk örnek.

Temel olarak, unicode'dan kodlanmış metne / baytlara dönüştürmek için str kullanmayı bırakın.

Bunun yerine, dizeyi kodlamak için .encode() öğesini uygun şekilde kullanın:

p.agent_info = u' '.join((agent_contact, agent_telno)).encode('utf-8').strip()

veya tamamen unicode olarak çalışın.

Yorumlar (18)

Bu klasik bir python unicode sorun noktasıdır! Aşağıdakileri düşünün:

a = u'bats\u00E0'
print a
 => batsà

Buraya kadar her şey iyi, ancak str(a)'yı çağırırsak ne olacağını görelim:

str(a)
Traceback (most recent call last):
  File "", line 1, in 
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)

Oh dip, bunun kimseye bir yararı olmaz! Hatayı düzeltmek için baytları .encode ile açıkça kodlayın ve python'a hangi codec'i kullanacağını söyleyin:

a.encode('utf-8')
 => 'bats\xc3\xa0'
print a.encode('utf-8')
 => batsà

Voil\u00E0!

Sorun şu ki, str() işlevini çağırdığınızda python, verdiğiniz baytları kodlamak için varsayılan karakter kodlamasını kullanır; sizin durumunuzda bunlar bazen unicode karakterlerin temsilleridir. Sorunu çözmek için, python'a .encode('whatever_unicode') kullanarak verdiğiniz dizeyle nasıl başa çıkacağını söylemelisiniz. Çoğu zaman utf-8 kullanarak sorun yaşamazsınız.

Bu konuyla ilgili mükemmel bir açıklama için Ned Batchelder'ın PyCon konuşmasına bakın: http://nedbatchelder.com/text/unipain.html

Yorumlar (4)

Aslında çoğu durumda bu karakterleri çıkarmanın çok daha basit olduğunu gördüm:

s = mystring.decode('ascii', 'ignore')
Yorumlar (7)