Question Comment faire en sorte que l'interpréteur python gère correctement les caractères non-ASCII dans les opérations sur chaîne?


J'ai une chaîne qui ressemble à ça:

6 918 417 712

La manière claire de couper cette chaîne (si je comprends bien Python) est simplement de dire que la chaîne est dans une variable appelée s, on a:

s.replace('Â ', '')

Cela devrait faire l'affaire. Mais bien sûr, il se plaint que le caractère non-ASCII '\xc2' dans le fichier blabla.py n'est pas encodé.

Je n'ai jamais tout à fait compris comment basculer entre différents encodages.

Voici le code, il est vraiment le même que ci-dessus, mais maintenant, il est en contexte. Le fichier est enregistré au format UTF-8 dans le bloc-notes et comporte l'en-tête suivant:

#!/usr/bin/python2.4
# -*- coding: utf-8 -*-

Le code:

f = urllib.urlopen(url)

soup = BeautifulSoup(f)

s = soup.find('div', {'id':'main_count'})

#making a print 's' here goes well. it shows 6Â 918Â 417Â 712

s.replace('Â ','')

save_main_count(s)

Il ne va pas plus loin que s.replace...


90
2017-08-27 15:53


origine


Réponses:


Python 2 utilise ascii en tant que codage par défaut pour les fichiers source, ce qui signifie que vous devez spécifier un autre encodage en haut du fichier pour utiliser des caractères Unicode non ascii dans les littéraux. Python 3 utilise utf-8 en tant que codage par défaut pour les fichiers sources, cela pose donc moins de problèmes.

Voir: http://docs.python.org/tutorial/interpreter.html#source-code-encoding

Pour activer l'encodage de la source utf-8, cela irait dans l'une des deux premières lignes:

# -*- coding: utf-8 -*-

Ce qui précède est dans les docs, mais cela fonctionne aussi:

# coding: utf-8

Considérations supplémentaires:

  • Le fichier source doit également être enregistré en utilisant l’encodage correct dans votre éditeur de texte.

  • Dans Python 2, le littéral unicode doit avoir u avant lui, comme dans s.replace(u"Â ", u"") Mais dans Python 3, utilisez simplement des guillemets. En Python 2, vous pouvez from __future__ import unicode_literals pour obtenir le comportement de Python 3, sachez que cela affecte l'ensemble du module en cours.

  • s.replace(u"Â ", u"") va également échouer si s n'est pas une chaîne Unicode.

  • string.replace renvoie une nouvelle chaîne et ne la modifie pas, alors assurez-vous d'utiliser également la valeur de retour


66
2017-08-27 16:04



def removeNonAscii(s): return "".join(filter(lambda x: ord(x)<128, s))

edit: ma première impulsion est toujours d'utiliser un filtre, mais l'expression du générateur est plus efficace en mémoire (et plus courte) ...

def removeNonAscii(s): return "".join(i for i in s if ord(i)<128)

Gardez à l'esprit que cela fonctionne avec le codage UTF-8 (car tous les octets des caractères multi-octets ont le bit le plus élevé défini sur 1).


154
2017-08-27 16:57



>>> unicode_string = u"hello aåbäcö"
>>> unicode_string.encode("ascii", "ignore")
'hello abc'

28
2017-08-27 15:59



Le code suivant remplacera tous les caractères non ASCII par des points d'interrogation.

"".join([x if ord(x) < 128 else '?' for x in s])

16
2018-04-22 13:12



Utiliser Regex:

import re

strip_unicode = re.compile("([^-_a-zA-Z0-9!@#%&=,/'\";:~`\$\^\*\(\)\+\[\]\.\{\}\|\?\<\>\\]+|[^\s]+)")
print strip_unicode.sub('', u'6Â 918Â 417Â 712')

6
2017-08-27 18:54



Beaucoup trop tard pour une réponse, mais la chaîne d'origine était en UTF-8 et «\ xc2 \ xa0» correspond à UTF-8 pour NO-BREAK SPACE. Décodez simplement la chaîne originale comme s.decode('utf-8') (\ xa0 s’affiche comme un espace mal décodé comme Windows-1252 ou latin-1:

Exemple (Python 3)

s = b'6\xc2\xa0918\xc2\xa0417\xc2\xa0712'
print(s.decode('latin-1')) # incorrectly decoded
u = s.decode('utf8') # correctly decoded
print(u)
print(u.replace('\N{NO-BREAK SPACE}','_'))
print(u.replace('\xa0','-')) # \xa0 is Unicode for NO-BREAK SPACE

Sortie

6 918 417 712
6 918 417 712
6_918_417_712
6-918-417-712

4
2017-11-08 03:48



#!/usr/bin/env python
# -*- coding: utf-8 -*-

s = u"6Â 918Â 417Â 712"
s = s.replace(u"Â", "") 
print s

Cela va imprimer 6 918 417 712


3
2017-08-27 16:03