UnicodeEncodeError: 'ascii' kodek ne more kodirati znaka u'\xa0' na položaju 20: ordinal ni v območju(128)

Imam težave z enokodnimi znaki iz besedila, ki se pridobi z različnih spletnih strani (na različnih spletnih mestih). Uporabljam BeautifulSoup.

Težava je v tem, da napake ni vedno mogoče ponoviti; včasih deluje z nekaterimi stranmi, včasih pa se zmoti in vrže UnicodeEncodeError. Preizkusil sem že vse, kar mi pride na misel, vendar še nisem našel ničesar, kar bi delovalo dosledno, ne da bi vrglo kakšno napako, povezano z Unicode.

Eden od delov kode, ki povzroča težave, je prikazan spodaj:

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()

Tukaj je sled za nekatere nize, ki se ustvarijo, ko se zažene zgornji delček:

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)

Domnevam, da je to posledica tega, da so nekatere strani (ali natančneje, strani z nekaterih spletnih mest) lahko kodirane, medtem ko so druge nekodirane. Vse strani imajo sedež v Združenem kraljestvu in zagotavljajo podatke, namenjene britanski potrošnji, zato ni težav v zvezi z internalizacijo ali obravnavo besedila, ki ni napisano v angleščini.

Ali ima kdo kakšno idejo, kako to rešiti, da bi lahko to težavo KONZISTENTNO odpravil?

Rešitev

Preberi si Python Unicode HOWTO. Ta napaka je prvi primer.

V bistvu prenehajte uporabljati str za pretvorbo iz Unicode v kodirano besedilo / bajte.

Namesto tega pravilno uporabite .encode() za kodiranje niza:

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

ali pa v celoti delajte v enokodi.

Komentarji (18)

To je klasična boleča točka unicode v Pythonu! Razmislite o naslednjem:

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

Do zdaj je vse v redu, toda če pokličemo str(a), poglejmo, kaj se bo zgodilo:

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, to ne bo nikomur koristilo! Napako odpravite tako, da bajte izrecno kodirate z .encode in pythonu poveste, kateri kodek naj uporabi:

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

Voil\u00E0!

Težava je v tem, da ko kličete funkcijo str(), python uporabi privzeto kodiranje znakov in poskuša kodirati bajte, ki ste mu jih posredovali, ki so v vašem primeru včasih predstavitve znakov unicode. Težavo odpravite tako, da pythonu poveste, kako naj ravna z nizom, ki ste mu ga dali, z uporabo .encode('whatever_unicode'). Večinoma vam bo zadostovala uporaba zapisa utf-8.

Za odlično predstavitev te teme si oglejte predavanje Neda Batchelderja na PyConu tukaj: http://nedbatchelder.com/text/unipain.html

Komentarji (4)

Ugotovil sem, da je v večini mojih primerov veliko enostavneje odstraniti te znake:

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