Слугирование строк в Python - PullRequest
76 голосов
/ 07 апреля 2011

Я нахожусь в поиске лучшего способа "загустить" строку что такое "слаг" , и мое текущее решение основано на этом рецепте

Iизменили его немного на:

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)

Кто-нибудь видел какие-либо проблемы с этим кодом?Работает нормально, но, может быть, я что-то упустил или вы знаете лучший способ?

Ответы [ 10 ]

121 голосов
/ 15 февраля 2013

Существует пакет python с именем python-slugify, который довольно хорошо справляется со слаганием:

pip install python-slugify

Работает так:

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")

См. Дополнительные примеры

Этот пакет делает немного больше того, что вы опубликовали (посмотрите на источник, это всего лишь один файл).Проект все еще активен (его обновили за 2 дня до моего первоначального ответа, спустя четыре года (последний раз проверял 2017-04-26), он все еще обновляется).

осторожный : естьэто второй пакет, названный slugify.Если у вас есть оба из них, вы можете столкнуться с проблемой, так как они имеют одинаковое имя для импорта.Тот, который только что назван slugify, не сделал всего, что я быстро проверил: "Ich heiße" стал "ich-heie" (должно быть "ich-heisse"), поэтому обязательно выберите правильный, когда используете pip или easy_install.

28 голосов
/ 03 декабря 2011

Установить форму unidecode отсюда для поддержки 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)

>>> my-custom-khello-vorld

10 голосов
/ 03 марта 2014

Существует пакет python с именем awesome-slugify :

pip install awesome-slugify

Работает так:

from slugify import slugify

slugify('one kožušček')  # one-kozuscek

awesome-slugify github page

6 голосов
/ 07 сентября 2011

Проблема с линией нормализации ascii:

slug = unicodedata.normalize('NFKD', s)

Это называется нормализацией Юникода , которая не разлагает множество символов на ascii. Например, он будет удалять символы не ascii из следующих строк:

Mørdag -> mrdag
Æther -> ther

Лучший способ сделать это - использовать модуль unidecode , который пытается транслировать строки в ascii. Так что если вы замените вышеуказанную строку на:

import unidecode
slug = unidecode.unidecode(s)

Вы получите лучшие результаты для вышеуказанных строк, а также для многих греческих и русских символов:

Mørdag -> mordag
Æther -> aether
6 голосов
/ 07 апреля 2011

Он хорошо работает в Django , поэтому я не понимаю, почему это не будет хорошей функцией слугификации общего назначения.

У вас есть какие-нибудь проблемы с этим?

5 голосов
/ 03 декабря 2014
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)

Это функция slugify, присутствующая в django.utils.text Это должно соответствовать вашему требованию.

3 голосов
/ 22 апреля 2013

Unidecode хорош; однако будьте осторожны: unidecode - это GPL. Если эта лицензия не подходит, используйте эту

2 голосов
/ 15 марта 2016

Несколько вариантов на GitHub:

  1. https://github.com/dimka665/awesome-slugify
  2. https://github.com/un33k/python-slugify
  3. https://github.com/mozilla/unicode-slugify

Каждый поддерживает немного разные параметры для своего API, так что вам нужно просмотреть, чтобы выяснить, что вы предпочитаете.

В частности, обратите внимание на различные опции, которые они предоставляют для работы с не-ASCII символами. Пиданни написал очень полезное сообщение в блоге, иллюстрирующее некоторые различия в обработке юникода в этих библиотеках slugify: http://www.pydanny.com/awesome-slugify-human-readable-url-slugs-from-any-string.html Этот пост в блоге несколько устарел, поскольку Mozilla unicode-slugify больше не относится к Django.

Также обратите внимание, что в настоящее время awesome-slugify - это GPLv3, хотя существует открытая проблема, в которой автор говорит, что они предпочли бы выпускать как MIT / BSD, но не уверен в законности: https://github.com/dimka665/awesome-slugify/issues/24

1 голос
/ 07 апреля 2011

Возможно, вы захотите изменить последнюю строку на

slug=re.sub(r'--+',r'-',slug)

, поскольку шаблон [-]+ ничем не отличается от -+, и вам не нужно совпадать только с одним дефисом, только двумя илиБольше.

Но, конечно, это довольно незначительно.

0 голосов
/ 17 ноября 2018

Другой вариант - boltons.strutils.slugify. Boltons также имеет немало других полезных функций и распространяется под лицензией BSD.

...