web-dev-qa-db-fra.com

Slugification de chaînes en Python

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?

68
Zygimantas

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.

113
kratenko

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

27
user1078810

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

Page génial-slugify-github

8
voronin

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
6
Björn Lindqvist
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.

5
Animesh Sharma

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?

5
Nick Presta

Unidecode est bon; cependant, soyez prudent: unidecode est GPL. Si cette licence ne vous convient pas, utilisez celui-ci

3
Mikhail Korobov

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

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

2
Jeff Widman

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.

1
unutbu

Une autre option est boltons.strutils.slugify . Boltons a quelques autres fonctions utiles et est distribué sous une licence BSD.

0
ostrokach