Jeg har problemer med at håndtere unicode-tegn fra tekst hentet fra forskellige websider (på forskellige websteder). Jeg bruger BeautifulSoup.
Problemet er, at fejlen ikke altid kan reproduceres; nogle gange virker det med nogle sider, og andre gange er det en UnicodeEncodeError
. Jeg har prøvet stort set alt, hvad jeg kan komme i tanke om, og alligevel har jeg ikke fundet noget, der virker konsekvent uden at kaste en eller anden form for Unicode-relateret fejl.
En af de sektioner af kode, der forårsager 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 en stacktrace, der produceres på nogle strenge, når ovenstående udsnit kø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 formoder, at dette skyldes, at nogle sider (eller mere specifikt sider fra nogle af webstederne) kan være kodet, mens andre kan være ukodet. Alle siderne er baseret i Storbritannien og leverer data beregnet til britisk forbrug - så der er ingen problemer i forbindelse med internalisering eller håndtering af tekst skrevet på andet end engelsk.
Er der nogen der har nogen ideer til hvordan jeg kan løse dette, så jeg KONSTANT kan løse dette problem?
Du skal læse Python [Unicode HOWTO] (https://docs.python.org/2.7/howto/unicode.html). Denne fejl er det allerførste eksempel.
Grundlæggende skal du holde op med at bruge str
til at konvertere fra unicode til kodet tekst/bytes.
Brug i stedet korrekt .encode()
til at kode strengen:
p.agent_info = u' '.join((agent_contact, agent_telno)).encode('utf-8').strip()
eller arbejde helt i unicode.
Dette er et klassisk python unicode-smertepunkt! Overvej følgende:
a = u'bats\u00E0'
print a
=> batsà
Alt er godt indtil videre, men hvis vi kalder str(a), så lad os se, hvad der sker:
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)
Åh dip, det vil ikke gøre nogen godt! For at rette fejlen skal du kode bytesne eksplicit med .encode og fortælle python, hvilken codec der skal bruges:
a.encode('utf-8')
=> 'bats\xc3\xa0'
print a.encode('utf-8')
=> batsà
Voil\u00E0!
Problemet er, at når du kalder str(), bruger python standardtegnkodningen til at forsøge at kode de bytes, du gav den, som i dit tilfælde nogle gange er repræsentationer af unicode-tegn. For at løse problemet skal du fortælle python, hvordan den skal håndtere den streng, du giver den, ved at bruge .encode('whatever_unicode'). Det meste af tiden burde du være fint nok til at bruge utf-8.
For en fremragende redegørelse om dette emne, se Ned Batchelder's PyCon talk her: http://nedbatchelder.com/text/unipain.html