183 votes

Python : Convertir Unicode en ASCII, sans erreurs

Mon code juste éraflures une page web, puis le convertit au format Unicode.

Mais j’ai une `` :


Alors je suppose que cela signifie que le code HTML contient certains mal formé tentative à Unicode quelque part. Juste que je peux apporter quelque octets de code sont la cause du problème au lieu d’obtenir une erreur ?

232voto

<pre><code></code><p><strong>EDIT :</strong></p><p><code></code><code></code>en-tête, puis Encoder.</p></pre>

123voto

Peter Gibson Points 5376

Comme une extension de Ignacio Vazquez-Abrams répondre

>>> u'aあä'.encode('ascii', 'ignore')
'a'

Il est parfois souhaitable de supprimer les accents des personnages et de l'imprimer le formulaire de base. Ceci peut être accompli avec

>>> import unicodedata
>>> unicodedata.normalize('NFKD', u'aあä').encode('ascii', 'ignore')
'aa'

Vous pouvez également traduire d'autres caractères (ponctuation) à leur équivalent le plus proche, par exemple le DROIT de guillemet SIMPLE de caractères unicode ne pas obtenir converti en ascii APOSTROPHE lors de l'encodage.

>>> print u'\u2019'
'
>>> unicodedata.name(u'\u2019')
'RIGHT SINGLE QUOTATION MARK'
>>> u'\u2019'.encode('ascii', 'ignore')
''
# Note we get an empty string back
>>> u'\u2019'.replace(u'\u2019', u'\'').encode('ascii', 'ignore')
"'"

Bien qu'il existe des moyens plus efficaces pour ce faire. Voir cette question pour plus de détails, Où est Python "meilleur ASCII pour cette Unicode" de la base de données?

106voto

Vin-G Points 2441

Pouvons-nous obtenir la valeur réelle utilisée pour link?

En outre, nous avons l'habitude de rencontrer ce problème lorsque nous essayons d' .encode() déjà codé chaîne d'octets. Donc, vous pourriez essayer de décrypter, d'abord en

html = urllib.urlopen(link).read()
unicode_str = html.decode(<source encoding>)
encoded_str = unicode_str.encode("utf8")

À titre d'exemple:

html = '\xa0'
encoded_str = html.encode("utf8")

Échoue avec

UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 0: ordinal not in range(128)

Alors que:

html = '\xa0'
decoded_str = html.decode("windows-1252")
encoded_str = decoded_str.encode("utf8")

Réussit sans erreur. Notez que "windows-1252" est quelque chose que j'ai utilisé comme un exemple. J'ai obtenu ce à partir de chardet et il avait de 0,5 confiance qu'il est bon! (eh bien, comme avec un 1 caractères chaîne de longueur, qu'attendez-vous de), Vous devez modifier que l'encodage de la chaîne d'octets renvoyés à partir de .urlopen().read() pour ce qui concerne le contenu que vous avez récupéré.

Un autre problème que je vois, il n'y a que l' .encode() chaîne de méthode renvoie la chaîne modifiée et ne pas modifier la source. Il est donc inutile d'avoir self.response.out.write(html) que le html n'est pas la chaîne codée en html.coder (si c'est ce que vous avez été à l'origine de viser).

Comme Ignacio proposé, vérifier la source de la page web pour l'encodage réel de la chaîne renvoyée par read(). C'est dans l'un des balises Meta-tags ou dans le ContentType tête dans la réponse. Utiliser ensuite comme paramètre .decode().

Notez cependant qu'il ne faut pas croire que les autres développeurs sont assez responsable pour s'assurer de l'en-tête et/ou méta-jeu de caractères déclarations correspondre au contenu réel. (Qui est un pain PITA, ouais, je sais, j'ai été l'un de ceux d'avant).

24voto

Gattster Points 1113

J’utilise cette fonction d’assistance dans l’ensemble de mes projets. Si elle ne peut pas convertir l’unicode, il l’ignore. Cela rejoint dans une bibliothèque de django, mais avec un peu de recherche vous pourriez contourner.

Je n’obtiens plus d’erreurs unicode après l’utilisation de ce.

7voto

John Machin Points 39706

Vous avez écrit """je suppose que cela signifie que le code HTML contient certains, à tort, formé tentative unicode quelque part."""

Le HTML n'est PAS prévu pour contenir toute sorte de "tentative unicode", bien formé ou non. Il doit nécessairement contenir des caractères Unicode codés dans certains encodage, ce qui est généralement fourni à l'avant ... rechercher pour "jeu de caractères".

Vous semblez être en supposant que le jeu de caractères UTF-8 ... pour quelles raisons? Le "\xA0" octet qui est indiqué dans votre message d'erreur indique que vous pouvez avoir un seul octet jeu de caractères par exemple cp1252.

Si vous ne pouvez pas obtenir le sens de la déclaration au début de l'HTML, essayez d'utiliser chardet pour savoir quels risquent d'encodage.

Pourquoi avez-vous tagged votre question avec "regex"?

Mise à jour après que vous avez remplacé votre question avec une non-question:

html = urllib.urlopen(link).read()
# html refers to a str object. To get unicode, you need to find out
# how it is encoded, and decode it.

html.encode("utf8","ignore")
# problem 1: will fail because html is a str object;
# encode works on unicode objects so Python tries to decode it using 
# 'ascii' and fails
# problem 2: even if it worked, the result will be ignored; it doesn't 
# update html in situ, it returns a function result.
# problem 3: "ignore" with UTF-n: any valid unicode object 
# should be encodable in UTF-n; error implies end of the world,
# don't try to ignore it. Don't just whack in "ignore" willy-nilly,
# put it in only with a comment explaining your very cogent reasons for doing so.
# "ignore" with most other encodings: error implies that you are mistaken
# in your choice of encoding -- same advice as for UTF-n :-)
# "ignore" with decode latin1 aka iso-8859-1: error implies end of the world.
# Irrespective of error or not, you are probably mistaken
# (needing e.g. cp1252 or even cp850 instead) ;-)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X