String slugification en Python
je suis à la recherche de la meilleure façon 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? Ça marche bien, mais peut-être que je rate quelque chose ou que tu sais une meilleure façon?
9 réponses
il y a un paquet python nommé python-slugify
, qui fait un assez bon travail de limaces:
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 autres exemples
ce paquet fait un peu plus que ce que vous avez posté (regardez la source, c'est juste un fichier). Le projet est toujours en cours (mis à jour 2 jours avant que j'ai répondu à l'origine, plus quatre ans plus tard (dernière vérification 2017-04-26), il est toujours mis à jour).
attention : il y a un second paquet autour, nommé slugify
. Si vous avez les deux, vous pourriez avoir un problème, car ils ont 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é rapidement: "Ich heiße"
est devenu "ich-heie"
(devrait être "ich-heisse"
), donc assurez-vous de choisir le bon, en utilisant pip
ou easy_install
.
installez le formulaire Unidecode d'ici pour le support unicode
pip install 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)
>>> ma-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 est avec la ligne de normalisation ascii:
slug = unicodedata.normalize('NFKD', s)
Il est appelé normalisation unicode qui ne se décomposent pas beaucoup de caractères ascii. Par exemple, il supprimerait 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 essaie de transférer les chaînes vers ascii. Donc, si vous remplacez la ligne ci-dessus avec:
import unidecode
slug = unidecode.unidecode(s)
vous obtenez de meilleurs résultats pour les cordes ci-dessus et pour beaucoup de caractères grecs et russes aussi:
Mørdag -> mordag
Æther -> aether
Il fonctionne bien dans Django , donc je ne vois pas pourquoi ce ne serait pas un but d'intérêt général slugify fonction.
avez-vous des problèmes avec elle?
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 à django.utils.texte Cela devrait suffire à votre condition.
Unidecode est bonne; cependant, soyez prudent: unidecode est GPL. Si cette licence ne convient pas alors utiliser celui-ci
quelques options sur GitHub:
- https://github.com/dimka665/awesome-slugify
- https://github.com/un33k/python-slugify
- https://github.com/mozilla/unicode-slugify
chacun supporte des paramètres légèrement différents pour son API, donc vous aurez besoin de regarder à travers pour comprendre ce que vous préférer.
en particulier, faites attention aux différentes options qu'ils offrent pour traiter les caractères non ASCII. Pydanny a écrit un billet de blog très utile illustrant certaines des différences de gestion unicode dans ces bibliothèques slugify'ing: http://www.pydanny.com/awesome-slugify-human-readable-url-slugs-from-any-string.html ce billet de blog est légèrement dépassé car le unicode-slugify
de Mozilla n'est plus spécifique au Django.
aussi noter que actuellement awesome-slugify
est GPLv3, bien qu'il y ait un problème ouvert où l'auteur dit qu'ils préféreraient libérer comme MIT / BSD, juste 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 motif [-]+
n'est pas différent de -+
, et vous ne vous souciez pas vraiment de faire correspondre juste un trait d'Union, seulement deux ou plus.
Mais, bien sûr, c'est tout à fait mineur.