I'estou tendo problemas para lidar com caracteres unicode de textos obtidos de diferentes páginas da web (em diferentes sites). Eu estou usando o BeautifulSoup.
O problema é que o erro nem sempre é reproduzível; às vezes, funciona com algumas páginas e, às vezes, barfs lançando um `UnicodeEncodeError'. Eu tentei quase tudo o que consegui pensar, e ainda assim não encontrei nada que funcione consistentemente sem atirar algum tipo de erro relacionado com o Unicode.
Uma das seções do código que está causando problemas é mostrada abaixo:
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()
Aqui está um traço de pilha produzido em ALGUMAS cordas, quando o trecho acima é executado:
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)
Suspeito que isto se deve ao facto de algumas páginas (ou mais especificamente, páginas de alguns dos sites) poderem estar codificadas, enquanto outras podem estar não codificadas. Todos os sites são baseados no Reino Unido e fornecem dados destinados ao consumo do Reino Unido - por isso não há questões relacionadas com a internalização ou lidar com textos escritos em qualquer outra língua que não seja o inglês.
Alguém tem alguma ideia de como resolver isto para que eu possa CONSISTENTEMENTE resolver este problema?
Você precisa ler o Python Unicode HOWTO. Este erro é o muito primeiro exemplo.
Basicamente, pare de utilizar str
para converter de unicode para texto / bytes codificados.
Ao invés disso, utilize corretamente .encode()
para codificar a string:
p.agent_info = u' '.join((agent_contact, agent_telno)).encode('utf-8').strip()
ou trabalhar inteiramente em unicode.
Este é um clássico ponto de dor python unicode! Considere o seguinte:
a = u'bats\u00E0'
print a
=> batsà
Tudo bem até agora, mas se chamarmos str(a), vamos's ver o que acontece:
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, isso'não vai fazer bem a ninguém! Para corrigir o erro, codifique os bytes explicitamente com .encode e diga à python qual o codec a usar:
a.encode('utf-8')
=> 'bats\xc3\xa0'
print a.encode('utf-8')
=> batsà
Voil\u00E0!
A questão é que quando você chama str(), python usa a codificação de caracteres padrão para tentar codificar os bytes que você lhe deu, que no seu caso são, às vezes, representações de caracteres unicode. Para corrigir o problema, você tem que dizer a python como lidar com a string que você lhe deu usando .encode('whatever_unicode'). Na maioria das vezes, você deve estar bem usando utf-8.
Para uma excelente exposição sobre este tópico, veja Ned Batchelder's PyCon falar aqui: http://nedbatchelder.com/text/unipain.html