Je suis à la recherche du meilleur moyen de "slugify" chaîne ce que "slug" est , et ma solution actuelle est basée sur cette recette
Je l'ai changé un peu en:
s = 'String to slugify'
slug = unicodedata.normalize('NFKD', s)
slug = slug.encode('ascii', 'ignore').lower()
slug = re.sub(r'[^a-z0-9]+', '-', slug).strip('-')
slug = re.sub(r'[-]+', '-', slug)
Quelqu'un a vu des problèmes avec ce code? Cela fonctionne bien, mais peut-être me manque quelque chose ou vous connaissez une meilleure façon?
Il y a un paquet python nommé python-slugify
, qui fait un très bon travail de slugification:
pip install python-slugify
Fonctionne comme ceci:
from slugify import slugify
txt = "This is a test ---"
r = slugify(txt)
self.assertEquals(r, "this-is-a-test")
txt = "This -- is a ## test ---"
r = slugify(txt)
self.assertEquals(r, "this-is-a-test")
txt = 'C\'est déjà l\'été.'
r = slugify(txt)
self.assertEquals(r, "cest-deja-lete")
txt = 'Nín hǎo. Wǒ shì zhōng guó rén'
r = slugify(txt)
self.assertEquals(r, "nin-hao-wo-shi-zhong-guo-ren")
txt = 'Компьютер'
r = slugify(txt)
self.assertEquals(r, "kompiuter")
txt = 'jaja---lol-méméméoo--a'
r = slugify(txt)
self.assertEquals(r, "jaja-lol-mememeoo-a")
Voir Plus d'exemples
Ce paquet fait un peu plus que ce que vous avez posté (regardez le source, ce n'est qu'un fichier). Le projet est toujours actif (mis à jour deux jours avant la réponse initiale, plus de quatre ans plus tard (dernière vérification: 2017-04-26), il est toujours mis à jour).
attention: Il existe un second paquet nommé slugify
. Si vous en possédez tous les deux, vous risquez de rencontrer un problème, car ils portent le même nom pour l'importation. Celui qui vient de s'appeler slugify
n'a pas fait tout ce que j'ai vérifié: "Ich heiße"
est devenu "ich-heie"
(devrait être "ich-heisse"
), assurez-vous donc de choisir celui qui vous convient lorsque vous utilisez pip
ou easy_install
.
Installer le formulaire unidecode à partir d'ici pour la prise en charge de l'unicode
pip installer unidecode
# -*- coding: utf-8 -*-
import re
import unidecode
def slugify(text):
text = unidecode.unidecode(text).lower()
return re.sub(r'[\W_]+', '-', text)
text = u"My custom хелло ворлд"
print slugify(text)
>>> mon-custom-khello-vorld
Il y a un paquet python nommé awesome-slugify :
pip install awesome-slugify
Fonctionne comme ceci:
from slugify import slugify
slugify('one kožušček') # one-kozuscek
Le problème vient de la ligne de normalisation ascii:
slug = unicodedata.normalize('NFKD', s)
C'est ce qu'on appelle normalisation unicode qui ne décompose pas beaucoup de caractères en ascii. Par exemple, cela éliminerait les caractères non-ascii des chaînes suivantes:
Mørdag -> mrdag
Æther -> ther
Une meilleure façon de le faire est d'utiliser le module unidecode qui tente de translittérer des chaînes en ascii. Donc, si vous remplacez la ligne ci-dessus par:
import unidecode
slug = unidecode.unidecode(s)
Vous obtenez de meilleurs résultats pour les chaînes ci-dessus et pour de nombreux caractères grecs et russes:
Mørdag -> mordag
Æther -> aether
def slugify(value):
"""
Converts to lowercase, removes non-Word characters (alphanumerics and
underscores) and converts spaces to hyphens. Also strips leading and
trailing whitespace.
"""
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore').decode('ascii')
value = re.sub('[^\w\s-]', '', value).strip().lower()
return mark_safe(re.sub('[-\s]+', '-', value))
slugify = allow_lazy(slugify, six.text_type)
C'est la fonction slugify présente dans Django.utils.text Cela devrait suffire à votre besoin.
Cela fonctionne bien dans Django , donc je ne vois pas pourquoi ce ne serait pas une bonne fonction slugify à usage général.
Avez-vous des problèmes avec cela?
Unidecode est bon; cependant, soyez prudent: unidecode est GPL. Si cette licence ne vous convient pas, utilisez celui-ci
Quelques options sur GitHub:
Chacune prend en charge des paramètres légèrement différents pour son API. Vous devrez donc vous renseigner pour déterminer ce que vous préférez.
Faites particulièrement attention aux différentes options qu’ils offrent pour traiter les caractères non-ASCII. Pydanny a écrit un article de blog très utile illustrant certaines des différences de traitement unicode dans ces bibliothèques de slugify ': http://www.pydanny.com/awesome-slugify-human-readable-url-slugs-from-any-string .html Cet article de blog est légèrement obsolète, car le unicode-slugify
de Mozilla n'est plus spécifique à Django.
Notez également que awesome-slugify
correspond actuellement à la GPLv3, bien qu’il existe un problème en suspens dans lequel l’auteur dit qu’il préférerait publier sous le nom de MIT/BSD, mais qui n'est pas sûr de la légalité: https://github.com/dimka665/awesome-slugify/issues/24
Vous pourriez envisager de changer la dernière ligne en
slug=re.sub(r'--+',r'-',slug)
puisque le modèle [-]+
n'est pas différent de -+
et que vous ne vous souciez pas vraiment de faire correspondre un seul trait d'union, seulement deux ou plus.
Mais, bien sûr, c'est assez mineur.
Une autre option est boltons.strutils.slugify
. Boltons a quelques autres fonctions utiles et est distribué sous une licence BSD
.