Python 中的字符串slugification

问题描述 投票:0回答:12

我正在寻找“slugify”字符串的最佳方法“slug”是什么,我当前的解决方案基于这个食谱

我将其稍微更改为:

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)

有人发现这段代码有任何问题吗?它工作正常,但也许我错过了一些东西或者你知道更好的方法?

python slug
12个回答
206
投票

有一个名为

python-slugify
的 python 包,它在 slugifying 方面做得非常好:

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 天更新,九年后(最后一次检查 2022-03-30),它仍然更新)。

小心:还有第二个包,名为

slugify
。如果您同时拥有它们,则可能会遇到问题,因为它们具有相同的导入名称。刚刚命名为
slugify
的那个并没有完成我快速检查的所有操作:
"Ich heiße"
变成了
"ich-heie"
(应该是
"ich-heisse"
),所以在使用
pip
easy_install
时一定要选择正确的一个.


41
投票

从这里安装unicode表单以获得unicode支持

pip 安装 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)

>>> 我的定制 khello-vorld


12
投票

有一个名为 awesome-slugify:

的 python 包
pip install awesome-slugify

工作原理如下:

from slugify import slugify

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

很棒的slugify github页面


9
投票
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)

这是 django.utils.text 中存在的 slugify 函数 这应该可以满足您的要求。


8
投票

它在 Django 中运行良好,所以我不明白为什么它不是一个好的通用 slugify 函数。

你有什么问题吗?


8
投票

问题出在 ascii 标准化行上:

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

它称为 unicode 规范化,它不会将大量字符分解为 ascii。例如,它会从以下字符串中去除非 ASCII 字符:

Mørdag -> mrdag
Æther -> ther

更好的方法是使用 unidecode 模块尝试将字符串音译为 ascii。因此,如果将上面的行替换为:

import unidecode
slug = unidecode.unidecode(s)

对于上述字符串以及许多希腊语和俄语字符,您也可以获得更好的结果:

Mørdag -> mordag
Æther -> aether

4
投票

Unicode 很好;但是,请注意:unicode 是 GPL。如果此许可证不适合,请使用这个


3
投票

GitHub 上的几个选项:

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

每个 API 所支持的参数都略有不同,因此您需要仔细查看以找出您喜欢的参数。

特别要注意它们为处理非 ASCII 字符提供的不同选项。 Pydanny 写了一篇非常有用的博客文章,说明了这些 slugify'ing 库中的一些 unicode 处理差异:http://www.pydanny.com/awesome-slugify- human-read-url-slugs-from-any-string。 html 这篇博文有点过时了,因为 Mozilla 的

unicode-slugify
不再是 Django 特定的。

另请注意,目前

awesome-slugify
是 GPLv3,尽管有一个未解决的问题,作者表示他们更愿意以 MIT/BSD 形式发布,只是不确定合法性:https://github.com/dimka665/awesome -slugify/问题/24


2
投票

创建它的另一个好答案可能是这种形式

import re
re.sub(r'\W+', '-', st).strip('-').lower()

1
投票

您可以考虑将最后一行更改为

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

因为模式

[-]+
-+
没有什么不同,并且您并不真正关心只匹配一个连字符,只关心两个或更多连字符。

但是,当然,这很小。


1
投票

另一个选项是

boltons.strutils.slugify
Boltons 还有很多其他有用的功能,并且是在
BSD
许可证下分发的。


0
投票

根据您的示例,快速执行此操作的方法可能是:

s = 'String to slugify'

slug = s.replace(" ", "-").lower()
© www.soinside.com 2019 - 2024. All rights reserved.