Estoy buscando la mejor manera de "slugify" string lo que es "slug" , y mi solución actual se basa en esta receta
Lo he cambiado un poco a:
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)
¿Alguien ve algún problema con este código? Está funcionando bien, pero ¿tal vez me falta algo o conoces una mejor manera?
Respuestas:
Hay un paquete de Python llamado
python-slugify
, que hace un buen trabajo de slugificar:Funciona así:
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")
Ver más ejemplos
Este paquete hace un poco más de lo que publicó (eche un vistazo a la fuente, es solo un archivo). El proyecto todavía está activo (se actualizó 2 días antes de que respondiera originalmente, más de siete años después (última consulta 2020-06-30), todavía se actualiza).
cuidado : hay un segundo paquete, llamado
slugify
. Si tiene ambos, es posible que tenga un problema, ya que tienen el mismo nombre para la importación. El que acabo de nombrarslugify
no hizo todo lo que verifiqué rápidamente: se"Ich heiße"
convirtió"ich-heie"
(debería ser"ich-heisse"
), así que asegúrese de elegir el correcto cuando usepip
oeasy_install
.fuente
python-slugify
tiene licencia de MIT, pero utilizaUnidecode
la licencia de GPL, por lo que puede que no sea adecuada para algunos proyectos.python-slugify
ahora utiliza de forma predeterminada la licencia artística entext-unidecode
lugar de la licencia GPLUnidecode
, lo que aborda su problema de licencia. github.com/un33k/python-slugify/commit/…Instale el formulario unidecode desde aquí para compatibilidad con Unicode
# -*- 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)
fuente
slugify("My custom хелло ворлд")
conslugify(u"My custom хелло ворлд")
, y debería funcionar.str
. Esto oculta elstr
tipo incorporado .Hay un paquete de Python llamado awesome-slugify :
Funciona así:
from slugify import slugify slugify('one kožušček') # one-kozuscek
página de github impresionante-slugify
fuente
slugify(text).lower()
si quieres eso.Funciona bien en Django , así que no veo por qué no sería una buena función slugify de propósito general.
¿Tiene algún problema con él?
fuente
from django.utils.text import slugify
El problema es con la línea de normalización ascii:
slug = unicodedata.normalize('NFKD', s)
Se llama normalización unicode, que no descompone muchos caracteres en ascii. Por ejemplo, eliminaría los caracteres no ascii de las siguientes cadenas:
Una mejor manera de hacerlo es usar el módulo unidecode que intenta transliterar cadenas a ascii. Entonces, si reemplaza la línea anterior con:
import unidecode slug = unidecode.unidecode(s)
Obtiene mejores resultados para las cadenas anteriores y también para muchos caracteres griegos y rusos:
fuente
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)
Esta es la función slugify presente en django.utils.text Esto debería ser suficiente para su requisito.
fuente
Unidecode es bueno; sin embargo, tenga cuidado: unidecode es GPL. Si esta licencia no encaja, use esta
fuente
Un par de opciones en GitHub:
Cada uno admite parámetros ligeramente diferentes para su API, por lo que deberá revisar para averiguar qué prefiere.
En particular, preste atención a las diferentes opciones que ofrecen para tratar con caracteres no ASCII. Pydanny escribió una publicación de blog muy útil que ilustra algunas de las diferencias de manejo de Unicode en estas bibliotecas de slugify'ing: http://www.pydanny.com/awesome-slugify-human-readable-url-slugs-from-any-string.html Esta publicación de blog está un poco desactualizada porque Mozilla's
unicode-slugify
ya no es específica de Django.También tenga en cuenta que actualmente
awesome-slugify
es GPLv3, aunque hay un problema abierto en el que el autor dice que preferiría publicarlo como MIT / BSD, pero no estoy seguro de la legalidad: https://github.com/dimka665/awesome-slugify/issues/ 24fuente
Podría considerar cambiar la última línea a
slug=re.sub(r'--+',r'-',slug)
ya que el patrón
[-]+
no es diferente de-+
, y realmente no le importa hacer coincidir solo un guión, solo dos o más.Pero, por supuesto, esto es bastante menor.
fuente
Otra opción es
boltons.strutils.slugify
. Boltons también tiene algunas otras funciones útiles y se distribuye bajo unaBSD
licencia.fuente