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?

68
demandé sur Community 2011-04-07 03:08:55

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 .

108
répondu kratenko 2018-05-21 16:13:59

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

26
répondu user1078810 2014-11-14 09:21:51

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

awesome-slugify GitHub page

8
répondu voronin 2014-03-02 21:01:10

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
6
répondu Björn Lindqvist 2011-09-07 13:16:09

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?

5
répondu Nick Presta 2011-04-06 23:22:30
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.

5
répondu Animesh Sharma 2014-12-03 05:35:16

Unidecode est bonne; cependant, soyez prudent: unidecode est GPL. Si cette licence ne convient pas alors utiliser celui-ci

3
répondu Mikhail Korobov 2014-11-14 09:21:59

quelques options sur GitHub:

  1. https://github.com/dimka665/awesome-slugify
  2. https://github.com/un33k/python-slugify
  3. 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

2
répondu Jeff Widman 2016-03-16 13:35:01

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.

1
répondu unutbu 2011-04-06 23:36:57