파이썬에서 문자열 슬러지 화


97

"slug"가 무엇인지 " slugify"문자열을 "slugify"하는 가장 좋은 방법을 찾고 있으며 현재 솔루션은 이 레시피를 기반으로 합니다.

나는 그것을 약간 변경했습니다.

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)

누구든지이 코드에 문제가 있습니까? 잘 작동하지만 내가 뭔가를 놓치고 있거나 더 나은 방법을 알고 있습니까?


유니 코드를 많이 사용하고 있습니까? 그렇다면 마지막 re.sub가 unicode ()를 감싸면 더 좋을 것입니다. 이것이 django가하는 일입니다. 또한 [^ a-z0-9] +를 줄여서 \ w를 사용할 수 있습니다. django.template.defaultfilters를 참조하십시오. 당신의 것과 비슷하지만 좀 더 세련되었습니다.
Mike Ramirez

URL에 유니 코드 문자가 허용됩니까? 또한 \ w에는 _ 문자와 대문자가 포함되어 있으므로 \ w를 a-z0-9로 변경했습니다. 문자는 미리 소문자로 설정되어 있으므로 일치시킬 대문자가 없습니다.
Zygimantas 2011

'_'는 유효하지만 (귀하의 선택에 따라 요청 했음) 유니 코드는 퍼센트 인코딩 문자입니다.
Mike Ramirez 2011

마이크 감사합니다. 글쎄, 나는 잘못된 질문을했다. "az", "0-9"및 "-"를 제외한 모든 문자를 이미 바꾼 경우 다시 유니 코드 문자열로 인코딩 할 이유가 있습니까?
Zygimantas 2011

django의 경우 호환성을 위해 모든 문자열을 유니 코드 객체로 사용하는 것이 중요하다고 생각합니다. 당신이 이것을 원한다면 그것은 당신의 선택입니다.
Mike Ramirez 2011

답변:


146

라는 이름의 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 일 전에 업데이트되었으며 7 년이 지난 후 (최종 확인 2020-06-30), 여전히 업데이트 됨).

주의 :라는 이름의 두 번째 패키지가 있습니다 slugify. 둘 다 가지고있는 경우 가져 오기 이름이 같으므로 문제가 발생할 수 있습니다. 단지라는 이름의 한 slugify나는 빠른 검사 모든하지 않았다 "Ich heiße"되었다가 "ich-heie"(해야한다 "ich-heisse"), 그래서 사용할 때 오른쪽 하나를 선택해야합니다 pip또는 easy_install.


6
python-slugifyMIT에 따라 라이센스가 부여되었지만 UnidecodeGPL에 따라 라이센스가 부여 된 것을 사용 하므로 일부 프로젝트에는 적합하지 않을 수 있습니다.
Rotareti 2017-08-06

@Rotareti 왜 모든 프로젝트에 맞지 않는지 설명해 주시겠습니까? MIT 또는 GPL 라이선스에 따라 어떤 것도 사용하고 상용 소프트웨어에 포함시킬 수 없습니까? 유일한 제한은 우리가 개발하는 코드 외에 라이선스를 두는 것입니다. 내가 잘못?
Ghassem Tofighi

1
@GhassemTofighi 간단히 말해서 상용 소프트웨어에서 사용할 수 있지만 사용하는 경우 코드도 오픈 소스해야합니다. 어쨌든 IANAL과 이것은 법적 조언이 아닙니다.
Rotareti

@GhassemTofighi 어쩌면에서 살펴 softwareengineering.stackexchange.com/q/47032/71504 그 주제에
kratenko에게

1
@Rotareti는 python-slugify이제 text-unidecodeGPL 라이선스 대신 Artistic License'd로 기본 설정되어 Unidecode라이선스 문제를 해결합니다. github.com/un33k/python-slugify/commit/...
Emilien

31

유니 코드 지원을 위해 여기 에서 유니 코드 양식 설치 하십시오.

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)

>>> 내 사용자 정의 khello-vorld


1
안녕하세요, 자사의 이상한 비트 만은 "내-맞춤 ndud-D-d3-4-d2d3-4nd-D-"처럼 내 입술을 위해 제공
하기 Derevo

1
유니 코드 문자열을 보내지 않을 때 발생하는 @derevo. 교체 slugify("My custom хелло ворлд")와 함께 slugify(u"My custom хелло ворлд"), 그것은 작동합니다.
kratenko 2012

9
같은 변수 이름을 사용하지 않는 것이 좋습니다 str. 내장 str유형을 숨 깁니다 .
crodjer 2014

2
unidecode는 GPL이며 일부에게는 적합하지 않을 수 있습니다.
Jorge Leitao 2015

reslugifying 또는 deslugifying은 어떻습니까?
라이언 추

11

awesome-slugify 라는 파이썬 패키지가 있습니다 .

pip install awesome-slugify

다음과 같이 작동합니다.

from slugify import slugify

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

awesome-slugify github 페이지


2
멋진 패키지! 그러나 조심하십시오. GPL에 따라 라이센스가 부여되었습니다.
Rotareti 2017-08-06

1
주의 : 이것은 URL을 자동으로 .lower ()하지 않습니다. slugify(text).lower()원하는 경우 실행해야 합니다.
Kalob Taulien 19.04.06


6

문제는 ascii 정규화 라인에 있습니다.

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

많은 문자를 ASCII로 분해하지 않는 유니 코드 정규화 라고 합니다. 예를 들어 다음 문자열에서 ASCII가 아닌 문자를 제거합니다.

Mørdag -> mrdag
Æther -> ther

더 나은 방법은 문자열을 ascii로 음역 하는 unidecode 모듈 을 사용하는 것입니다 . 따라서 위의 줄을 다음으로 바꾸면 :

import unidecode
slug = unidecode.unidecode(s)

위의 문자열과 많은 그리스어 및 러시아어 문자에 대해 더 나은 결과를 얻을 수 있습니다.

Mørdag -> mordag
Æther -> aether

6
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 함수입니다. 이것은 귀하의 요구 사항을 충족시킬 것입니다.



2

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 라이브러리의 유니 코드 처리 차이점을 보여주는 매우 유용한 블로그 게시물을 작성했습니다 . 이 블로그 게시물은 Mozilla unicode-slugify가 더 이상 Django 전용이 아니기 때문에 약간 구식 입니다.

또한 현재 awesome-slugify는 GPLv3이지만 작성자가 MIT / BSD로 출시하는 것을 선호한다고 말하는 공개 된 문제가 있지만 합법성은 확실하지 않습니다 : https://github.com/dimka665/awesome-slugify/issues/ 24


1

마지막 줄을 다음으로 변경하는 것을 고려할 수 있습니다.

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

패턴 [-]+-+와 다르지 않기 때문에 하나의 하이픈, 두 개 이상 만 일치시키는 것은 신경 쓰지 않습니다.

그러나 물론 이것은 매우 사소합니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.