Mon code gratte simplement une page Web, puis la convertit en Unicode.
html = urllib.urlopen(link).read()
html.encode("utf8","ignore")
self.response.out.write(html)
Mais j'obtiens un 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)
Je suppose que cela signifie que le HTML contient une tentative mal formée d'Unicode quelque part. Puis-je simplement supprimer les octets de code qui causent le problème au lieu d'obtenir une erreur?
c2
octet ou vous obtiendrez probablement une erreur de décodage: hexutf8.com/?q=C2A0Réponses:
Mise à jour 2018:
En février 2018, l'utilisation de compressions comme celles-ci
gzip
est devenue très populaire (environ 73% de tous les sites Web l'utilisent, y compris les grands sites comme Google, YouTube, Yahoo, Wikipedia, Reddit, Stack Overflow et Stack Exchange Network).Si vous effectuez un décodage simple comme dans la réponse d'origine avec une réponse gzippée, vous obtiendrez une erreur similaire ou similaire à celle-ci:
Afin de décoder une réponse gzpipped, vous devez ajouter les modules suivants (en Python 3):
import gzip import io
Remarque: dans Python 2, vous utiliseriez à la
StringIO
place deio
Ensuite, vous pouvez analyser le contenu comme ceci:
response = urlopen("https://example.com/gzipped-ressource") buffer = io.BytesIO(response.read()) # Use StringIO.StringIO(response.read()) in Python 2 gzipped_file = gzip.GzipFile(fileobj=buffer) decoded = gzipped_file.read() content = decoded.decode("utf-8") # Replace utf-8 with the source encoding of your requested resource
Ce code lit la réponse et place les octets dans un tampon. Le
gzip
module lit ensuite le tampon à l'aide de laGZipFile
fonction. Après cela, le fichier gzippé peut à nouveau être lu en octets et décodé en texte normalement lisible à la fin.Réponse originale de 2010:
Pouvons-nous obtenir la valeur réelle utilisée
link
?De plus, nous rencontrons généralement ce problème ici lorsque nous essayons
.encode()
une chaîne d'octets déjà codée. Vous pouvez donc essayer de le décoder d'abord comme danshtml = urllib.urlopen(link).read() unicode_str = html.decode(<source encoding>) encoded_str = unicode_str.encode("utf8")
Par 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)
Tandis 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 exemple . J'ai eu ceci de chardet et il avait 0,5 confiance que c'était juste! (enfin, comme indiqué avec une chaîne de 1 caractère, à quoi vous attendez-vous?) Vous devriez changer cela pour l'encodage de la chaîne d'octets renvoyée par
.urlopen().read()
ce qui s'applique au contenu que vous avez récupéré.Un autre problème que je vois là-bas est que la
.encode()
méthode de chaîne renvoie la chaîne modifiée et ne modifie pas la source en place. Il est donc inutile d'avoirself.response.out.write(html)
comme html n'est pas la chaîne encodée de html.encode (si c'est ce que vous visiez à l'origine).Comme Ignacio l'a suggéré, vérifiez la page Web source pour le codage réel de la chaîne renvoyée de
read()
. C'est soit dans l'une des balises Meta, soit dans l'en-tête ContentType de la réponse. Utilisez-le ensuite comme paramètre pour.decode()
.Notez cependant qu'il ne faut pas supposer que les autres développeurs sont suffisamment responsables pour s'assurer que les déclarations d'en-tête et / ou de jeu de méta caractères correspondent au contenu réel. ( Ce qui est un PITA, ouais, je sais, je suis un de ceux avant).
la source
encoded_str = decoded_str.encode("utf8")
raise IOError, 'Not a gzipped file'
. Quelle est la faute que j'ai faite?>>> u'aあä'.encode('ascii', 'ignore') 'a'
Décodez la chaîne que vous récupérez, en utilisant le jeu de caractères dans la
meta
balise appropriée dans la réponse ou dans l'en-Content-Type
tête, puis encodez.La méthode
encode(encoding, errors)
accepte des gestionnaires personnalisés pour les erreurs. Les valeurs par défaut, en outreignore
, sont:>>> u'aあä'.encode('ascii', 'replace') b'a??' >>> u'aあä'.encode('ascii', 'xmlcharrefreplace') b'aあä' >>> u'aあä'.encode('ascii', 'backslashreplace') b'a\\u3042\\xe4'
Voir https://docs.python.org/3/library/stdtypes.html#str.encode
la source
En prolongement de la réponse d'Ignacio Vazquez-Abrams
>>> u'aあä'.encode('ascii', 'ignore') 'a'
Il est parfois souhaitable de supprimer les accents des caractères et d'imprimer le formulaire de base. Cela peut être accompli avec
>>> import unicodedata >>> unicodedata.normalize('NFKD', u'aあä').encode('ascii', 'ignore') 'aa'
Vous pouvez également traduire d'autres caractères (tels que la ponctuation) en leurs équivalents les plus proches, par exemple, le caractère unicode DROIT UNIQUE QUOTATION MARQUE n'est pas converti en APOSTROPHE ascii 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 y parvenir. Voir cette question pour plus de détails. Où se trouve la "meilleure base de données ASCII de Python pour cette Unicode"?
la source
Utilisez unidecode - il convertit même instantanément les caractères étranges en ascii, et même le chinois en ascii phonétique.
puis:
>>> from unidecode import unidecode >>> unidecode(u'北京') 'Bei Jing' >>> unidecode(u'Škoda') 'Skoda'
la source
J'utilise cette fonction d'aide dans tous mes projets. S'il ne peut pas convertir l'Unicode, il l'ignore. Ceci est lié à une bibliothèque django, mais avec un peu de recherche, vous pouvez le contourner.
from django.utils import encoding def convert_unicode_to_string(x): """ >>> convert_unicode_to_string(u'ni\xf1era') 'niera' """ return encoding.smart_str(x, encoding='ascii', errors='ignore')
Je n'obtiens plus d'erreurs Unicode après avoir utilisé cela.
la source
Pour les consoles cassées comme la
cmd.exe
sortie HTML, vous pouvez toujours utiliser:my_unicode_string.encode('ascii','xmlcharrefreplace')
Cela conservera tous les caractères non-ascii tout en les rendant imprimables en ASCII pur et en HTML.
AVERTISSEMENT : si vous utilisez ceci dans le code de production pour éviter les erreurs, il y a probablement quelque chose qui ne va pas dans votre code . Le seul cas d'utilisation valable pour cela est l'impression sur une console non-Unicode ou la conversion facile en entités HTML dans un contexte HTML.
Et enfin, si vous êtes sous Windows et utilisez cmd.exe, vous pouvez taper
chcp 65001
pour activer la sortie utf-8 (fonctionne avec la police Lucida Console). Vous devrez peut-être ajoutermyUnicodeString.encode('utf8')
.la source
Vous avez écrit "" "Je suppose que cela signifie que le code HTML contient une tentative mal formée d'unicode quelque part." ""
Le HTML ne doit PAS contenir de "tentative d'Unicode", bien formée ou non. Il doit nécessairement contenir des caractères Unicode encodés dans un encodage, qui est généralement fourni à l'avance ... cherchez "charset".
Vous semblez supposer que le jeu de caractères est UTF-8 ... pour quelles raisons? L'octet "\ xA0" qui apparaît dans votre message d'erreur indique que vous pouvez avoir un jeu de caractères à un octet, par exemple cp1252.
Si vous ne parvenez pas à comprendre la déclaration au début du HTML, essayez d'utiliser chardet pour découvrir quel est le codage probable.
Pourquoi avez-vous tagué votre question avec "regex"?
Mettez à jour après avoir remplacé toute votre question par 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) ;-)
la source
Si vous avez une chaîne
line
, vous pouvez utiliser la.encode([encoding], [errors='strict'])
méthode des chaînes pour convertir les types de codage.line = 'my big string'
line.encode('ascii', 'ignore')
Pour plus d'informations sur la gestion de l'ASCII et de l'unicode en Python, c'est un site vraiment utile: https://docs.python.org/2/howto/unicode.html
la source
Je pense que la réponse est là, mais seulement par morceaux, ce qui rend difficile de résoudre rapidement le problème tel que
UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 2818: ordinal not in range(128)
Prenons un exemple, supposons que j'ai un fichier contenant des données sous la forme suivante (contenant des caractères ascii et non-ascii)
1/10/17, 21:36 - Terre: Bienvenue ��
et nous voulons ignorer et conserver uniquement les caractères ascii.
Ce code fera:
import unicodedata fp = open(<FILENAME>) for line in fp: rline = line.strip() rline = unicode(rline, "utf-8") rline = unicodedata.normalize('NFKD', rline).encode('ascii','ignore') if len(rline) != 0: print rline
et tapez (rline) vous donnera
>type(rline) <type 'str'>
la source
unicodestring = '\xa0' decoded_str = unicodestring.decode("windows-1252") encoded_str = decoded_str.encode('ascii', 'ignore')
Travaille pour moi
la source
On dirait que vous utilisez python 2.x. Python 2.x utilise par défaut ascii et il ne connaît pas Unicode. D'où l'exception.
Collez simplement la ligne ci-dessous après shebang, cela fonctionnera
# -*- coding: utf-8 -*-
la source
coding
commentaire n'est pas une panacée magique. Vous devez savoir pourquoi l'erreur est générée, cela ne corrige les choses que lorsqu'il y a de mauvais caractères dans votre source Python. Cela ne semble pas être le cas pour cette question.