Jeg har problemer med å håndtere unicode-tegn fra tekst hentet fra forskjellige nettsider (på forskjellige nettsteder). Jeg bruker BeautifulSoup.
Problemet er at feilen ikke alltid er reproduserbar; det fungerer noen ganger med noen sider, og noen ganger spyr det ved å kaste en UnicodeEncodeError
. Jeg har prøvd omtrent alt jeg kan tenke meg, og likevel har jeg ikke funnet noe som fungerer konsekvent uten å kaste en slags Unicode-relatert feil.
En av delene av koden som forårsaker problemer er vist nedenfor:
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()
Her er et stakkespor produsert på SOME-strenger når utdraget ovenfor kjøres:
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)
Jeg mistenker at dette skyldes at noen sider (eller mer spesifikt sider fra noen av nettstedene) kan være kodet, mens andre kan være ukodet. Alle nettstedene er basert i Storbritannia og tilbyr data som er ment for bruk i Storbritannia - så det er ingen problemer knyttet til internalisering eller håndtering av tekst skrevet på noe annet enn engelsk.
Er det noen som har noen ideer om hvordan jeg kan løse dette slik at jeg kan løse dette problemet KONSEKVENT?
Du må lese Python Unicode HOWTO. Denne feilen er det aller første eksempelet.
I utgangspunktet må du slutte å bruke str
for å konvertere fra unicode til kodet tekst / byte.
Bruk i stedet .encode()
på riktig måte for å kode strengen:
p.agent_info = u' '.join((agent_contact, agent_telno)).encode('utf-8').strip()
eller arbeid helt i unicode.
Dette er et klassisk python unicode smertepunkt! Tenk på følgende:
a = u'bats\u00E0'
print a
=> batsà
Alt bra så langt, men hvis vi kaller str(a), la oss se hva som skjer:
str(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)
Oh dip, det kommer ikke til å gjøre noen noe bra! For å fikse feilen, kod bytene eksplisitt med .encode og fortell python hvilken kodek som skal brukes:
a.encode('utf-8')
=> 'bats\xc3\xa0'
print a.encode('utf-8')
=> batsà
Voil\u00E0!
Problemet er at når du kaller str(), bruker python standard tegnkoding for å prøve å kode bytene du ga den, som i ditt tilfelle noen ganger er representasjoner av unicode-tegn. For å løse problemet må du fortelle python hvordan du skal håndtere strengen du gir den ved å bruke .encode('whatever_unicode'). Mesteparten av tiden bør det gå bra å bruke utf-8.
For en utmerket redegjørelse om dette emnet, se Ned Batchelders PyCon-foredrag her: http://nedbatchelder.com/text/unipain.html