如何用 python,Djano 生成 SEO 友好的 URL, 包含中文处理
By:Roy.LiuLast updated:2014-05-27
做技术的人,在搜索技术问题时,估计经常会搜索到一个网站:stackoverflow, 你会发现这个网站的的 url 的设计对搜索引擎来说是非常友好的, 在 url 的后面直接跟上了这篇文章的核心关键字, 很多英文习惯的用户很自然的就能搜索到这些文章. 当然 stackoverflow 是英文版的,在这方面有天然的优势。因为因为英文字母都是 acsii 码的,比较容易做到,我在用 Django 做项目的时候,也尝试了这种 url 的方式,django 严格说来是天生支持这种方式的,只是没有考虑中国用户的习惯,下面总结几种处理方式:
利用 Django 的 slugify 来处理
一个简单的例子如下:
运行结果如下:
这说明,仅仅将英文标题生成了slug 方式,而中文完全被忽略了,原因很简单,django 的源代码里面这里就是按照 ascii 来处理的:
所以,如果是中文字符是被忽略掉了。对于英文写作的人来说,这就已经足够了,但对于要写中文的来说,估计还得采用下面的方式.
采用 Firefox 里面用到的方法
这种解决方法的来源是在github上的一个开源项目: https://github.com/mozilla/unicode-slugify , 它的一个优点是,中文还是中文,仍然保留不变,英文内容做处理,看测试源码如下:
结果如下:
完美的输出,中文完好,英文也符合国外用户习惯,同时完全满足SEO的 URL 规则, 但这只是一种喜欢用汉子直接显示在 url 的用户,但是就我看来,我不喜欢这样,因为不同的浏览器对汉子在url 上的解析方式不同,会有所变化.
回归 url , 用原生的ascii 码来表示url 是绝对正确的选择,但ascii 码表示 汉子兼职就像乱码,对中国用户来说估计最不友好了,而 URL 设计的标准既然是友好的,那么乱码是不可接受的。 但是,我们可以用拼音,将汉子转换成拼音显示在 URL 中,不就可以了吗, 开源世界早有人这么做了,所以不需要重造轮子,安装现有的开源库: https://github.com/iki/unidecode, 这是国人写的一个库,将常用汉子的拼音以及ascii 码之间的关系全部映射了,我们直接拿来用就好了,作者干了不少体力活,佩服中, 安装好这个库之后,测试代码如下:
结果如下;
完美的汉语拼音与英文都能满足的结合。如果我今后做项目,估计会采用这个了。另外还有一种方式,比较适合走极端的人,我们可以用python 发请求到 google translate, 然后将翻译之后的结果得到再做处理,做法不难,有时间弄一个试试,但现在就可以想到结果,翻译出来的东西估计错误很多。所以不是很可取.
利用 Django 的 slugify 来处理
一个简单的例子如下:
from django.template.defaultfilters import slugify if __name__ == "__main__": # 测试英语与拼音能否处理 myurl = slugify("what is this, could you tell me? ni neng gao su wo ma") print myurl # 测试汉子是否能处理,结果是不能处理 chinese_url = slugify("这是什么东西,你能告诉我吗?"); print chinese_url
运行结果如下:
what-is-this-could-you-tell-me-ni-neng-gao-su-wo-ma
这说明,仅仅将英文标题生成了slug 方式,而中文完全被忽略了,原因很简单,django 的源代码里面这里就是按照 ascii 来处理的:
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore') value = unicode(re.sub('[^\w\s-]', '', value).strip().lower()) return mark_safe(re.sub('[-\s]+', '-', value))
所以,如果是中文字符是被忽略掉了。对于英文写作的人来说,这就已经足够了,但对于要写中文的来说,估计还得采用下面的方式.
采用 Firefox 里面用到的方法
这种解决方法的来源是在github上的一个开源项目: https://github.com/mozilla/unicode-slugify , 它的一个优点是,中文还是中文,仍然保留不变,英文内容做处理,看测试源码如下:
#coding:utf-8 ''' Created on 2014-5-27 @author: Administrator ''' import re import unicodedata try: from django.utils.encoding import smart_unicode as smart_text except ImportError: from django.utils.encoding import smart_text # Extra characters outside of alphanumerics that we'll allow. SLUG_OK = '-_~' def slugify(s, ok=SLUG_OK, lower=True, spaces=False): # L and N signify letter/number. # http://www.unicode.org/reports/tr44/tr44-4.html#GC_Values_Table rv = [] for c in unicodedata.normalize('NFKC', smart_text(s)): cat = unicodedata.category(c)[0] if cat in 'LN' or c in ok: rv.append(c) if cat == 'Z': # space rv.append(' ') new = ''.join(rv).strip() if not spaces: new = re.sub('[-\s]+', '-', new) return new.lower() if lower else new if __name__ == "__main__": #测试汉字是否能处理 print slugify("这是什么东西,你能告诉我吗?") #测试英文拼音 print slugify("what is this, ni neng gao su wo ma?") #测试中英文混合 print slugify("这是什么东西,could you tell me?")
结果如下:
这是什么东西你能告诉我吗 what-is-this-ni-neng-gao-su-wo-ma 这是什么东西could-you-tell-me
完美的输出,中文完好,英文也符合国外用户习惯,同时完全满足SEO的 URL 规则, 但这只是一种喜欢用汉子直接显示在 url 的用户,但是就我看来,我不喜欢这样,因为不同的浏览器对汉子在url 上的解析方式不同,会有所变化.
回归 url , 用原生的ascii 码来表示url 是绝对正确的选择,但ascii 码表示 汉子兼职就像乱码,对中国用户来说估计最不友好了,而 URL 设计的标准既然是友好的,那么乱码是不可接受的。 但是,我们可以用拼音,将汉子转换成拼音显示在 URL 中,不就可以了吗, 开源世界早有人这么做了,所以不需要重造轮子,安装现有的开源库: https://github.com/iki/unidecode, 这是国人写的一个库,将常用汉子的拼音以及ascii 码之间的关系全部映射了,我们直接拿来用就好了,作者干了不少体力活,佩服中, 安装好这个库之后,测试代码如下:
#coding:utf-8 from django.utils.safestring import mark_safe from unidecode import unidecode import re import unicodedata value = unidecode("中文 URL 能生成拼音的吗?" + u"") value = re.sub('[^\w\s-]', '', value).strip().lower() value = mark_safe(re.sub('[-\s]+', '-', value)) print value.lower() value = unidecode("english url, does this tool can generate it?") value = re.sub('[^\w\s-]', '', value).strip().lower() value = mark_safe(re.sub('[-\s]+', '-', value)) print value.lower()
结果如下;
zhong-wen-url-neng-sheng-cheng-pin-yin-de-ma english-url-does-this-tool-can-generate-it
完美的汉语拼音与英文都能满足的结合。如果我今后做项目,估计会采用这个了。另外还有一种方式,比较适合走极端的人,我们可以用python 发请求到 google translate, 然后将翻译之后的结果得到再做处理,做法不难,有时间弄一个试试,但现在就可以想到结果,翻译出来的东西估计错误很多。所以不是很可取.
From:一号门
Previous:自定义django class based view 的一个例子
COMMENTS