Python:如何使用string.translate()来替换引号? (用于“slug”创作)

时间:2012-03-08 18:47:28

标签: python string translate

我想从字符串中删除所有奇怪的字符,使其“url safe”。因此,我有一个这样的功能:

def urlize(url, safe=u''):
   intab =  u"àáâãäåòóôõöøèéêëçìíîïùúûüÿñ" + safe
   outtab = u"aaaaaaooooooeeeeciiiiuuuuyn" + safe
   trantab = dict((ord(a), b) for a, b in zip(intab, outtab))
   return url.lower().translate(trantab).strip()

这很好用,但现在我想重用那个功能来允许特殊字符。例如,引号。

urlize(u'This is sóme randóm "text" that í wánt to process',u'"')

...并抛出以下错误:

Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: expected a character buffer object

我试过了,但没有奏效:

urlize(u'text',u'\"')
intab =  u"àáâãäåòóôõöøèéêëçìíîïùúûüÿñ%s" , safe

- 编辑 - 完整功能看起来像这样

def urlize(url, safe=u''):

    intab =  u"àáâãäåòóôõöøèéêëçìíîïùúûüÿñ" + safe
    outtab = u"aaaaaaooooooeeeeciiiiuuuuyn" + safe
    trantab = dict((ord(a), b) for a, b in zip(intab, outtab))
    translated_url = url.lower().translate(trantab).strip()

    pos = 0
    stop = len(translated_url)
    new_url= ''
    last_division_char = False

    while pos < stop:
        if not translated_url[pos].isalnum() and translated_url[pos] not in safe:
            if (not last_division_char) and (pos != stop -1):
                new_url+='-'
                last_division_char = True
        else:
            new_url+=translated_url[pos]
            last_division_char = False
        pos+=1

    return new_url

- 编辑 - 目标

我想要的是规范化文本,以便我可以将其自己放在网址上,并像使用Id一样使用它。例如,如果我想展示一个类别的产品,我宁愿把“ninos-y-bebes”代替“niños-y-bebés”(西班牙语为孩子和婴儿)。我真的不想要我的网址中的所有áéíóúñ(这是西班牙语中的特殊字符),但我也不想摆脱它们。这就是为什么我想替换看起来相同的所有字符(不是100%所有字符,我都不在乎)然后删除所有非字母数字字符。

1 个答案:

答案 0 :(得分:6)

unidecode模块是一个更安全的选项(它将处理其他特殊的符号,如“度”):

>>> from unidecode import unidecode
>>> s = u'This is sóme randóm "text" that í wánt to process'
>>> unidecode(s)
'This is some random "text" that i want to process'
>>> import urllib
>>> urllib.urlencode(dict(x=unidecode(s)))[2:]
'This+is+some+random+%22text%22+that+i+want+to+process'

[更新]

  

我想我已经这样做了 - &gt;你是“aaaaaaooooooeeeeeeciiiiuuuuyn” - Marco Bruggmann

很公道,如果你愿意跟踪你的翻译表中的每个unicode字符(重音字符不是唯一的问题,你的游行中会有很多符号下雨)。

最糟糕的是,许多unicode符号在视觉上与它们的ASCII对应符号相同,导致难以诊断错误。

[更新]

如下:

>>> safe_chars = 'abcdefghijklmnopqrstuvwxyz01234567890-_'
>>> filter(lambda x: x in safe_chars, "i think i'm already doing that")
'ithinkimalreadydoingthat'

[更新]

  

@Daenyth我试过了,但我只收到错误:来自urllib import urlencode =&gt; urlencode('google.com/';)=&gt; TypeError:不是有效的非字符串序列或映射对象 - Marco Bruggmann

urlencode函数用于产生QUERYSTRING格式化输出(a = 1&amp; b = 2&amp; c = 3)。它期望键/值对:

>>> urllib.urlencode(dict(url='google.com/'))
'url=google.com%2F'

>>> help(urllib.urlencode)
Help on function urlencode in module urllib:

urlencode(query, doseq=0)
    Encode a sequence of two-element tuples or dictionary into a URL query string.

    If any values in the query arg are sequences and doseq is true, each
    sequence element is converted to a separate parameter.

    If the query arg is a sequence of two-element tuples, the order of the
    parameters in the output will match the order of parameters in the
    input.
(END)

[更新]

  

这将毫无疑问地运作,但我想要的是规范化文本,以便我可以将其自己放在网址上,并像使用Id一样使用它。例如,如果我想展示一个类别的产品,我宁愿把“ninos-y-bebes”代替“niños-y-bebés”(西班牙语为孩子和婴儿)。我真的不想要我的网址中的所有áéíóúñ(这是西班牙语中的特殊字符),但我也不想摆脱它们。这就是为什么我想替换看起来相同的所有字符(不是100%所有字符,我都不在乎)然后删除所有非字母数字字符。

好的,Marco,你想要的是创建所谓的slugs的常规,不是吗?

您可以在一行中完成:

>>> s = u'This is sóme randóm "text" that í wánt to process'
>>> allowed_chars = 'abcdefghijklmnopqrstuwvxyz01234567890'
>>> ''.join([ x if x in allowed_chars else '-' for x in unidecode(s.lower()) ])
u'this-is-some-random--text--that-i-want-to-process'
>>> s = u"Niños y Bebés"
>>> ''.join([ x if x in allowed_chars else '-' for x in unidecode(s.lower()) ])
u'ninos-y-bebes'
>>> s = u"1ª Categoria, ½ docena"
>>> ''.join([ x if x in allowed_chars else '-' for x in unidecode(s.lower()) ])
u'1a-categoria--1-2-docena'