Meu código apenas raspa uma página da Web e depois a converte em Unicode.
html = urllib.urlopen(link).read()
html.encode("utf8","ignore")
self.response.out.write(html)
Mas eu recebo um UnicodeDecodeError
:
Traceback (most recent call last):
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/webapp/__init__.py", line 507, in __call__
handler.get(*groups)
File "/Users/greg/clounce/main.py", line 55, in get
html.encode("utf8","ignore")
UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 2818: ordinal not in range(128)
Suponho que isso signifique que o HTML contenha alguma tentativa incorreta de Unicode em algum lugar. Posso simplesmente eliminar os bytes de código que estão causando o problema em vez de receber um erro?
c2
byte ou você provavelmente obteria um erro de decodificação: hexutf8.com/?q=C2A0Respostas:
Atualização de 2018:
A partir de fevereiro de 2018, o uso de compressões como
gzip
se tornou bastante popular (cerca de 73% de todos os sites usam, incluindo sites grandes como Google, YouTube, Yahoo, Wikipedia, Reddit, Stack Overflow e Stack Exchange Network).Se você fizer uma decodificação simples, como na resposta original, com uma resposta compactada com gzip, receberá um erro semelhante ou semelhante a este:
Para decodificar uma resposta gzpipped, você precisa adicionar os seguintes módulos (no Python 3):
Nota: No Python 2 você usaria em
StringIO
vez deio
Em seguida, você pode analisar o conteúdo da seguinte maneira:
Este código lê a resposta e coloca os bytes em um buffer. O
gzip
módulo lê o buffer usando aGZipFile
função Depois disso, o arquivo compactado com gzip pode ser lido em bytes novamente e decodificado para texto normalmente legível no final.Resposta original de 2010:
Podemos obter o valor real usado
link
?Além disso, geralmente encontramos esse problema aqui quando estamos tentando
.encode()
uma sequência de bytes já codificada. Portanto, você pode tentar decodificá-lo primeiro, como emComo um exemplo:
Falha com
Enquanto:
Sucesso sem erro. Observe que "windows-1252" é algo que usei como exemplo . Eu peguei isso do chardet e tinha 0,5 confiança de que está certo! (bem, como fornecido com uma cadeia de caracteres de 1 caractere, o que você espera) Você deve alterar isso para a codificação da cadeia de bytes retornada
.urlopen().read()
para a que se aplica ao conteúdo recuperado.Outro problema que vejo é que o
.encode()
método string retorna a string modificada e não modifica a fonte no local. Portanto, é meio inútil ter,self.response.out.write(html)
pois html não é a sequência codificada de html.encode (se é isso que você estava originalmente buscando).Como Ignacio sugeriu, verifique na página de origem a codificação real da string retornada
read()
. Está em uma das metatags ou no cabeçalho ContentType na resposta. Use isso então como o parâmetro para.decode()
.Observe, no entanto, que não se deve presumir que outros desenvolvedores sejam responsáveis o suficiente para garantir que o cabeçalho e / ou as declarações do conjunto de meta caracteres correspondam ao conteúdo real. (Que é uma PITA, sim, eu deveria saber, eu era uma dessas antes).
fonte
encoded_str = decoded_str.encode("utf8")
raise IOError, 'Not a gzipped file'
. Qual foi a falha que fiz?Decodifique a sequência que você voltar, usando o conjunto de caracteres na
meta
tag apropriada na resposta ou noContent-Type
cabeçalho e, em seguida, codifique.O método
encode(encoding, errors)
aceita manipuladores personalizados para erros. Os valores padrão, além dissoignore
, são:Consulte https://docs.python.org/3/library/stdtypes.html#str.encode
fonte
Como extensão da resposta de Ignacio Vazquez-Abrams
Às vezes, é desejável remover acentos dos caracteres e imprimir o formulário base. Isso pode ser realizado com
Você também pode traduzir outros caracteres (como pontuação) para seus equivalentes mais próximos, por exemplo, o caractere unicode RIGHT SINGLE COOTATION MARK não é convertido em um APOSTROPHE ascii durante a codificação.
Embora existam maneiras mais eficientes de conseguir isso. Consulte esta pergunta para obter mais detalhes Onde está o banco de dados "melhor ASCII para este Unicode" do Python?
fonte
Use o unidecode - até converte caracteres estranhos em ascii instantaneamente e até converte chinês em ascii fonético.
então:
fonte
Eu uso essa função auxiliar em todos os meus projetos. Se ele não pode converter o unicode, ele o ignora. Isso está vinculado a uma biblioteca de django, mas com um pouco de pesquisa você pode ignorá-la.
Eu não recebo mais erros unicode depois de usá-lo.
fonte
Para consoles quebrados como
cmd.exe
e saída HTML, você sempre pode usar:Isso preservará todos os caracteres não-ascii e os imprimirá em ASCII puro e em HTML.
AVISO : Se você usar isso no código de produção para evitar erros, provavelmente haverá algo errado no seu código . O único caso de uso válido para isso é a impressão em um console não unicode ou a fácil conversão para entidades HTML em um contexto HTML.
E, finalmente, se você estiver no Windows e usar o cmd.exe, poderá digitar
chcp 65001
para ativar a saída utf-8 (funciona com a fonte do Lucida Console). Você pode precisar adicionarmyUnicodeString.encode('utf8')
.fonte
Você escreveu "" "Presumo que isso significa que o HTML contém alguma tentativa incorreta de unicode em algum lugar." ""
NÃO se espera que o HTML contenha qualquer tipo de "tentativa de unicode", bem formada ou não. Deve necessariamente conter caracteres Unicode codificados em alguma codificação, que geralmente é fornecida antecipadamente ... procure por "charset".
Você parece estar assumindo que o conjunto de caracteres é UTF-8 ... com que fundamento? O byte "\ xA0" mostrado na sua mensagem de erro indica que você pode ter um conjunto de caracteres de byte único, por exemplo, cp1252.
Se você não conseguir entender a declaração no início do HTML, tente usar chardet para descobrir qual é a provável codificação.
Por que você marcou sua pergunta com "regex"?
Atualize depois de substituir sua pergunta inteira por uma não-pergunta:
fonte
Se você tiver uma cadeia
line
, poderá usar o.encode([encoding], [errors='strict'])
método para converter cadeias de tipos.line = 'my big string'
line.encode('ascii', 'ignore')
Para obter mais informações sobre como lidar com ASCII e unicode em Python, este é um site realmente útil: https://docs.python.org/2/howto/unicode.html
fonte
Acho que a resposta está lá, mas apenas em partes, o que dificulta a solução rápida do problema, como
Vamos dar um exemplo: suponha que eu tenha um arquivo com alguns dados no seguinte formato (contendo caracteres ascii e não-ascii)
1/10/17, 21:36 - Terra: Bem-vindo
e queremos ignorar e preservar apenas caracteres ascii.
Este código fará:
e digite (rline) lhe dará
fonte
Funciona para mim
fonte
Parece que você está usando o python 2.x. O Python 2.x usa como padrão ascii e não sabe sobre Unicode. Daí a exceção.
Basta colar a linha abaixo após shebang, ele vai funcionar
fonte
coding
comentário não é um remédio mágico. Você precisa saber por que o erro está sendo gerado, isso só corrige as coisas quando há caracteres incorretos em sua fonte Python. Esse não parece ser o caso desta pergunta.