Echapper les caractères utf-8 spéciaux

Le problème exposé dans ce sujet a été résolu.

Bonjour,

Je fais du scrapping avec BeautifulSoup mais des fois les données que je récupère ont des caractères spéciaux. Par exemple, en inspectant le html de certaines pages ont peut voir des zones de textes entourés de " " ce qui correspond à mettre des espaces spéciaux avant et après le texte, ou encore on peut voir des &nsbp; etc…

J’aimerai beaucoup remplacer ces caractères spéciaux par les caractères usuels du clavier. Par exemple si je vois des espaces de type &nsbp; je le remplace par l’espace classique (celui qui se produit lorsqu’on appuie sur la touche espace du clavier), ou si je vois le caractères UTF-8 : U+22EF alors je le remplace par les trois petits points : ... etc…

Le problème c’est que je ne sais pas comment faire, puisque c’est impossible de lister tous les caractères spéciaux UTF-8… J’imagine qu’il faut utiliser la librairie re de python mais je ne vois pas quelle regex utiliser pour résoudre ce problème. J’avais pensé à des choses du type re.sub("^\s+|\s+$", " ", mon_string) mais évidemment ça ne marche pas.

Déjà je pense que trouver la solution pour tous les caractères espaces bizarres serait déjà un bon début mais je ne vois pas comment faire…

Merci beaucoup !

Bonjour,

Quelle raison te pousse à faire ce genre de traitement ? C’est le genre d’idée qui va te créer énormément de problèmes, comme tu commences à t’en rendre compte. Et donc, à moins d’avoir une excellente raison se le faire, il vaut mieux ne pas essayer de remplacer automatiquement des caractères – le remplacement des entités HTML par les caractères correspondants peut rester intéressant, notamment pour éviter les problèmes de double encodage.

Aujourd’hui toute pile logicielle pas trop antique est tout à fait capable de gérer l’intégralité d’Unicode sans souci, et donc d’éviter les transformations sort tu parles.

Pour l’HTML, tu as un module html pour faire ça.

>>> import html
>>> html.unescape('Hello   > " " !')
'Hello \xa0 > " " !'

Par-contre, &nsbp; n’existe pas il me semble. Aussi pour l’unicode, je te déconseil très fortement de le faire. Si tu insistes alors utilise simplement str.replace pas besoin de regex ici.

>>> "Hello ...".replace('...', '…')
'Hello …'
+0 -0

Quelle raison te pousse à faire ce genre de traitement ?

Merci pour ta réponse.

Je veux effectuer ce type de traitement, car j’ai besoin d’afficher les données que je récupère. Sauf que si les donnés ont des caractères spéciaux, les affichages sont désordonnés et plus difficilement lisible ce qui m’embête beaucoup.

Pour l’HTML, tu as un module html pour faire ça.

>>> import html
>>> html.unescape('Hello   > " " !')
'Hello \xa0 > " " !'

Ok sympa ça, je ne connaissais pas. Mais du coup le problème c’est que je me retrouve avec les caractères utf-8 à la place qui au final ne résout pas mon problème malheureusement.

>>> "Hello ...".replace('...', '…')
'Hello …'

ache

Ok mais du coup faut que que je traite un par un tous les caractères à la main non ?

Sauf que si les donnés ont des caractères spéciaux, les affichages sont désordonnés et plus difficilement lisible ce qui m’embête beaucoup.

C’est plutôt l’affichage en question que tu devrais essayer de débugger.

Si les données sont en UTF-8 tout au long de la chaîne (DB/stockage, connexions aux API, encodage déclarés dans les métadonnées/en-têtes, etc.) normalement ça ne devrait plus poser de probème aujourd’hui. Je t’invite à vérifier l’encodage à chacune des étape par lesquelles passent les données, car il suffit d’une seule mauvaise déclaration ou configuration quelque part pour tout casser, et c’est vite arrivé.

+0 -0

Est-ce que tu peux préciser ceci ?

En gros j’affiche les donnés, sauf que si les donnés ont des espaces insécables ça les affiches bizarrement. Par exemple une donnée va s’afficher au milieu de ma page parce-qu’elle de la forme : " ma donnée " et que "" représente un espace insécable.

Le problème c’est vraiment l’affichage.

Ben s’il y a un espace insécable c’est que ça à certainement un sens d’avoir un espace insécable ici. Tu peux tenter de remplacer tous les espaces par un espace simple. re.sub('\s', ' ', ta_chaîne). Tu peux également faire en sorte que plusieurs espaces soient remplacer par un seul. Si le problème n’est que la gestion des espaces alors ça devrait correspondre à ce que tu veux.

Mais le problème de remplacer l’Unicode par de l’ASCII de manière générale est certainement pire que la gestion de la date et l’heure. C’est casse-gueule comme pas possible. Tu devras effectivement faire du cas par cas. Ne serait-ce que mettre en majuscule un texte en Unicode ou encore calculer la taille (le nombre de caractère) d’une chaîne sont des problèmes complexes alors imagine remplacer des caractères par quelque chose de cohérent.

+2 -0

Mais ce n’est pas normal qu’à l’afficahe ça fasse n’importe quoi, si tes scripts gèrent l’utf-8, ça ne devrait pas. Tu es sous Linux ou Windows ? Je sais que Windows utilise pas forcément l’utf-8 par défaut.

Edit : en fait il faudrait surtout que tu nous décrives ta chaîne de traitement pour qu’on essaye de trouver où ça pose problème.

+0 -0

Mais ce n’est pas normal qu’à l’afficahe ça fasse n’importe quoi, si tes scripts gèrent l’utf-8, ça ne devrait pas.

Moté

Pour le NBSP, c’est normal. C’est le comportement voulu.

On peut le vérifier avec un petit test HTML :

<!doctype>
<html>
  <head>
    <meta charset="UTF-8">
  </head>
  <body>
    <h1>Test Non Breaking Space</h1>
    <div>
      <h2>Only NBSP</h2>
J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir !
    </div>
    <br/>
    <div>
      <h2>Only spaces</h2>
J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir !
    </div>
    <br/>
    <div style="word-break: break-all;">
      <h2>Only NBSP but with CSS property "word-break" seted to "break-all"</h2>
J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir ! J'aime Zeste de Savoir !
    </div>
  </body>
</html>

@InaDeepThink: As-tu d’autres problèmes que les espaces insécables ? Des caractères qui s’affichent bizarrement ou quoi ?

Normalement le premier div devrait s’afficher sur une seule ligne et dépasser de l’écran. Le deuxième devrait juste se couper là où il faut. Le troisième également à cause de la propriété CSS qui force le cassage mais peu casser en plein milieu d’un mot.

PS: Je me répète mais les espaces insécables ont normalement un sens et ce n’est pas une bonne solution de les remplacer systématiquement pas des espaces.

+0 -0

Salut,

pour ce qui est des points de suspension ou autres ligatures du genre, plutôt que de faire des remplacements à la sauvage tu peux aussi changer de normalisation unicode pour opter pour une forme « compatibilité » comme NFKC.

En Python on peut faire ça à l’aide du module unicodedata.

>>> import unicodedata
>>> unicodedata.normalize('NFKC', '…')
'...'

Note quand même que la normalisation Unicode ne fait probablement pas ce que tu veux, le but premier étant de normaliser des chaines de caractères équivalentes mais différentes dans leur représentation pour pouvoir les comparer, et la normalisation « de compatibilité » ne servant qu’à éliminer des différences non pertinentes au niveau du sens : caractères précomposés dont ligatures (dont ), kanas en demi-chasse pour le japonais, codage des diacritiques (mais ça ne les élimine pas), symboles en lettres correspondantes, jeu sur la casse (chiffres en exposants)… Cf ce document pour plus de détails.

@InaDeepThink: As-tu d’autres problèmes que les espaces insécables ? Des caractères qui s’affichent bizarrement ou quoi ?

J’ai enlevé tous les espaces insécables et j’ai traité les trois petits points et honnêtement je suis assez satisfait. La suppression des espaces me permet d’avoir des affichages plus corrects. Le sujet est donc résolu, merci à tout le monde pour votre aide !

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte