URL slug 生成器,免费
将任意文本转换为 URL 兼容的 slug。
什么是 URL slug?
A slug is the human-readable, URL-safe path segment that identifies a page within a site. It sits at the tail of the URL and replaces what would otherwise be an opaque database identifier with a descriptive token. In https://example.com/blog/2026/my-awesome-post, the slug is my-awesome-post. Mechanically, a slug is the output of a deterministic transformation: take an arbitrary input string, strip everything that isn't allowed in a URL path segment, fold case, replace whitespace with a separator, and emit ASCII. The transformation is one-way in practice, you can't reliably reconstruct "My Awesome Post: Take Two!" from my-awesome-post-take-two: which is why slugs are stored alongside the original title, not in place of it.
好的 slug 只使用小写字母、数字和连字符。它们会移除重音、特殊字符和多余空格。这既改善 SEO,也改善用户体验 · 搜索引擎和人类都能读懂 URL 并理解页面内容。
这个词的来历,19 世纪的报社编辑部
这个词比 Web 早了一个世纪。在 Linotype 时代的排字房里,每一行铅字都被铸成一条单独的金属条(一个「slug」)大约三十派卡宽,在铅里大约重十二盎司。这个词后来漂移到指代编辑写在一篇稿件顶部、以便在生产流程中标记它的简短标识符:一个一两词的 handle,比如 mayor-budget 或 school-fire,记者、副编辑和印刷工人无需打出完整大标题,就能用它互相提及这则稿件。AP 与各大日报的体例手册到现在还记录着这种用法。
当 Movable Type、WordPress 与早期 Django 文档在 2000 年代初采用「slug」作为字段名时,他们是把报社的术语原封不动地借了过来。Django 的文档至少从 2005 年的 0.91 版开始就把这个字段叫做 slug,定义现在已是规范级:一个简短标签,只包含字母、数字、下划线或连字符,通常用于 URL。这个比喻之所以恰到好处,是因为铅铸的 slug 与 URL 中的 slug 都是简短、独特、机器友好的 token,指向某个更长的东西。
RFC 3986 与未保留字符集
URL syntax is defined by RFC 3986 ("Uniform Resource Identifier (URI): Generic Syntax"), published January 2005 by Tim Berners-Lee, Roy Fielding and Larry Masinter, replacing RFCs 2396 and 2732. It is an STD 66 Internet Standard, the IETF's highest maturity tier, reserved for protocols of demonstrated stability and broad implementation. Section 2.3 of RFC 3986 defines the unreserved characters, the only characters that are guaranteed to be safe in any URI component without percent-encoding: A-Z, a-z, 0-9, hyphen, period, underscore, and tilde. That's sixty-six characters total. Everything else is either a reserved character (with structural meaning in some URI component) or "other", anything in the latter group must be percent-encoded if it appears in a URI.
因为未保留集是唯一一个能保证在历史上写过的每一个 URI 解析器中干净往返的字符集,各种 slug 生成器收敛到一条几乎相同的流水线:把字母字符变小写,保留数字,保留连字符,把空白替换为单个连字符,然后对其他所有内容,要么剥掉要么音译。下划线、句点和波浪号在技术上是允许的,但在 slug 中按惯例避开,句点会与文件扩展名冲突,波浪号在旧 URL 习惯里被读成主目录,而下划线由于下面要谈到的 SEO 原因败给了连字符。
「Cool URIs Don’t Change」,Berners-Lee,1998
Tim Berners-Lee 1998 年的风格说明《Cool URIs Don’t Change》,托管在 W3C 网站上,是 slug 哲学被引用得最多的一篇文章。开头一句很有名:酷的 URI 是不会变的。文章接下来读起来像是一篇反对那种把临时实现细节烤进路径里的 URL 设计的檄文。它推荐的「不要做」清单影响了 slug 实践近三十年:不要把作者工具的扩展名放进 URL(它们泄露实现,迁移时就坏掉;不要把状态放进 URL)页面会从「当前」中退出,但 URL 不应当;不要放作者名字,作者会换;不要放日期,除非日期对资源本身是基础的;不要把会话 ID、查询参数或登录状态放进规范URL。
Slug(那些描述性的、语义性的小写带连字符的词)正是「酷」URI 中允许的部分。其他一切都是不该渗到地址里去的结构性装饰。WordPress 的固定链接设计、Django 的 SlugField 与 Rails 的 to_param 都把这一指导内化:输出一条代表页面含义的 URL,而不是它如何被服务的那套机制。
连字符胜过下划线,而且有据可查
在 2005 年的 WebmasterWorld 访谈中,Google 工程师 Matt Cutts 说连字符被 Google 的 tokenizer 当作词分隔符,而下划线是词连接符。所以 green-apples 被读作两个 token green 与 apples,而 green_apples 被读作单个 token green_apples。对于查询 「green apples」,带连字符的 URL 会匹配标题关键词检查;带下划线的不会。Cutts 在 2007 年的博客上以及 2011 年 YouTube 上的 Google Webmaster Help 视频(《Underscores vs. dashes in URLs》)里又重申了这一点,并指出Google 一度评估过把下划线行为也改为分隔符,但没有这么做,因为那会破坏太多刻意把下划线当作连接符使用的现有 URL(__init__.py、编程函数名等)。
Google 现在的「URL structure best practices for Google Search」页面直接推荐连字符:/green-dress.html 这样的 URL 比 /greendress.html 更有用,而且应该用连字符而不是下划线。这条建议已被持续记录了二十多年。每一条 URL 上的影响很小,但跨数千页的网站会累积起来,而把连字符换成下划线没有任何上行收益,没有任何 SEO 场景下下划线胜出。每一份靠谱的 slug 指南都以同一句话结束:用连字符。
Unicode 归一化,NFD 如何剥掉重音
Unicode 标准为很多带重音的字符定义了两种编码方式:预组合(单个码位,é 是 U+00E9)与分解(基础字母后接组合标记,é 是 U+0065 加 U+0301,即组合锐音符)。视觉相同,字节不同。Unicode Technical Standard #15 定义了四种归一化形式(NFC、NFD、NFKC、NFKD)而对于 slug 生成,NFD 是抓手。如果你拿一段输入字符串,归一化到 NFD,然后把 Unicode 范围 U+0300 到 U+036F(组合附加符号块)中的每一个码位都剥掉,你就得回到了基础 ASCII 字母。Café 变成 cafe,naïve 变成 naive,François 变成 Francois,niño 变成 nino,crème brûlée 变成 creme brulee。
NFD 不会折叠那些不能分解为「基础+标记」的字符。德语 ß(锐音 s)在 NFD 下不会分解为 ss,它需要显式音译。波兰语 ł(带杠的 l)不会分解为 l。挪威语 ø 不会分解为 o。冰岛语 þ(thorn)与 ð(eth)需要查表。浏览器从大约 2015 年起原生支持 String.prototype.normalize()(Chrome 34、Firefox 31、Safari 10),所以即便是很小的 JavaScript slugify 工具,不靠库也能完成剥重音的工作。
slugify 库家族,每个生态各自给出什么
Django 的 django.utils.text.slugify() 自 2000 年代初就在这个 Python 框架中。它把字符变小写,剥掉不属于 [A-Za-z0-9_-] 的字符,把空白替换为连字符。从 Django 1.9(2015)开始,关键字 allow_unicode=True 会切换到一个 Unicode 感知模式,保留非 ASCII 字母。这是别人都在抄的参考实现。在 Node.js 里,Sindre Sorhus 的 @sindresorhus/slugify 是 npm 上下载量最大的 slugify 包,每周数百万次下载,特性包括人类可读分隔符、可定制替换(可以把 & 映射为 and,把 @ 映射为 at)、Unicode 处理与 locale 感知的小写化(土耳其语带点/不带点 I,德语 ß → ss)。对于不使用 Django 的 Python 用户,Val Neekman 在 PyPI 上的 python-slugify 包装了 unidecode 音译库,并加入 slug 专属行为:正则切词、替换字符、最大长度、停用词去除。
其他生态遵循同一模式。PHP 在 Packagist 上有 Cocur 的 cocur/slugify,被 Laravel 与 Symfony 插件使用,而 Symfony 自己自 5.0 版起就在 symfony/string 中提供了一个 AsciiSlugger。Ruby on Rails 用 String#parameterize,这至少从 Rails 1.0 起就内建于 ActiveSupport 中;friendly_id gem 在其上叠加历史跟踪与冲突处理。Go 有 gosimple/slug,带有八十多种语言的 locale 表。Rust 有 slug crate。Java 有 Apache Commons Text 与 slugify-jvm。值得注意的是,API 是何等地相似:输入字符串进,slug 字符串出,选项也都是那几样,分隔符、最大长度、小写、locale。Absolutool 的工具属于同一家族,但完全运行在你的浏览器里,不需要安装任何库。
WordPress:43% 的 Web 跑着这条流水线
WordPress 是 Web 上最大的单一 slug 输出系统,按照 W3Techs 2026 年的调查,它支撑大约 43% 的网站,所以对大多数读者来说,它的 slug 习惯实际上就是 Web 的 slug 习惯。一旦保存一篇 post,WordPress 通过 sanitize_title()(在默认 rewrite 情况下会调用 sanitize_title_with_dashes())从标题自动生成 slug:小写化,剥 HTML,解码实体,把空白与多数标点替换为连字符,对不安全字符做百分号编码,合并相邻连字符,修剪首尾连字符。如果结果与某篇已有 post 的 slug 冲突,WordPress 会追加 -2、-3,以此类推。Slug 在 post 编辑器里可以编辑,一篇 post 一旦发布,改 slug 就会让每一个现有链接断掉,除非编辑配置了一条重定向。WordPress 历史上默认不音译非 ASCII 字符;它对它们做百分号编码,产生了像 %D0%BF%D1%80%D0%B8... 这种有名的丑陋的西里尔 URL,Cyr-To-Lat 这类插件就是为修这个写出来的。
拉丁之外:为西里尔、CJK、阿拉伯做音译
NFD 只能处理那些能分解为 ASCII 基础 + 组合标记的字符。对于非拉丁脚本,slug 流水线需要音译,把每一个非拉丁字符映射到其拉丁文等价物。规范的 Python 库是 unidecode,最初是 Sean M. Burke 2001 年的 Perl Text::Unidecode 的移植,几乎把 Basic Multilingual Plane 中的每一个字符都映射成一个「最佳猜测」的 ASCII 字符串:Москва → Moskva、Αθήνα → Athena。CJK 的兜底是有争议的部分:unidecode 对所有 CJK 字符使用普通话拼音,因为中文有最大的 CJK 字符覆盖度,这对日文产生了荒谬的罗马化(東京 → 拼音里的 Dong Jing,而不是 Tokyo)。日语专用的工具如 pykakasi 才会把汉字 + 假名转换成正确的罗马字。International Components for Unicode(ICU)库,由 Unicode Consortium 与 IBM 维护,提供了一个 Transliterator API,带有像 Russian-Latin/BGN、Greek-Latin/UNGEGN 与 Han-Latin 这样的命名规则集,实现官方罗马化标准。Absolutool 的工具站在更轻的一端:它通过 NFD 折叠拉丁的变音符,把别的全部丢掉。想为俄文或中文标题生成 slug 的用户可以在把文本粘贴进来之前,先跑一次单独的音译步骤。
URL 长度限制,「2000 字符」规则的来历
RFC 3986 本身并没有规定长度限制,URI 语法是没有上限的。每一种限制都是工程上的。Internet Explorer 历史上把 URL 限定在 2,083 字符(这是烤进 Trident 引擎里的硬限),这就是被广泛引用的「2,000 字符」经验法则的来源。Chrome、Firefox、Safari 与现代 Edge 在地址栏里大约支持 64,000 到 100,000 以上字符的 URL。Apache 的 LimitRequestLine 默认对整个请求行设为 8,190 字节;nginx 的 large_client_header_buffers 默认 8 KB;IIS 默认 URL 是 16,384 字节、查询字符串是 4,096 字节。RFC 9110(HTTP/1.1,2022)在 §4.1 建议服务器「ought to be capable of handling URIs of length 8,000 octets or longer」,但没有强制规定上限。对 slug 来说,关键是它们按惯例都是短的(三到七个词,三十到六十字符)为了 SEO 和可分享性。Google 的 John Mueller 在多次 Webmaster Hangout 中说过,URL 长度本身不是排名信号,但过长的 URL 可能在搜索结果摘要中被截断,影响点击率,在社交分享中显得不专业。多数 slug 生成器因此会暴露一个最大长度选项;这一款默认无限制,允许你自己设定上限。
停用词去除:密集 vs 合乎语法
许多 slugify 库提供可选的停用词去除,在拼装 slug 之前丢弃常见短词(a、an、the、of、is、and、or、to、in、for、on)。理由是它们带不来任何 SEO 信号,反而把 URL 撑长。所以 「The Best Way to Make a Cup of Tea」 会变成 best-way-make-cup-tea(5 个 token,24 个字符),而不是 the-best-way-to-make-a-cup-of-tea(10 个 token,35 个字符)。代价:更短更密,但偶尔会出现语法塌陷(how-to-be-good 被剥成 how-good 失去了意思),也有把真正承担意图的词去掉的风险(art-of-war 被剥成 art-war)。WordPress 默认不去除停用词(这是一种插件 opt-in 行为)大多数现代 slug 生成器也都把它默认关掉、做成一个复选框。WordPress 的 Yoast SEO 把含停用词的 slug 标记为一个轻微的建议,而不是错误。本生成器不会自动去除停用词,理由是发布者比一份静态词表更清楚标题的意图。如果你想让它们消失,直接编辑输出就好。
Slug 冲突:当两篇 post 共享一个标题时,CMS 怎么办
当两篇 post 自动生成同一个 slug(「My Post」和 「My-Post!」都产生 my-post)系统就必须解决冲突。最常见的策略:数字后缀(my-post-2、my-post-3)(可预测,永不冲突,但后缀本身没有任何语义差异;日期前缀(2026-04-27/my-post))对博客内容效果好,是 Jekyll、Hugo 和大多数新闻站点的默认;作者后缀(my-post-jane)(被Medium 与多作者博客使用;随机哈希后缀(my-post-a3f9))被 Stack Overflow、Notion 与短链系统使用,用人类可读性换取了保证唯一;或者发布时手工编辑,编辑上很干净,但很少作为默认,因为它会打断流程。对大多数 CMS 来说,务实的选择是数字后缀+手工编辑这个逃生口。带日期前缀的固定链接对那种以时间为锚的内容(日期是有意义的信息)很受欢迎。
SEO 影响:Slug 作为微小但可见的信号
Google 的排名文档把 URL 结构列为一个次要排名信号(页面内容、反向链接、用户互动信号与时新性都比它权重更高。但 URL 中的词确实有贡献,而且贡献是看得见的。Slug 词出现在 SERP 摘要中标题下面那行 URL 里,这影响点击率,即便 slug 本身并没被排序进去。Slug 词在 SERP 中如果与用户查询匹配,可能会被加粗)额外的视觉权重。内部和外部链接的锚文本在没有提供链接文本时,常常默认就是 URL,所以一个语义化的 slug 就成了链接文本,把它的关键词通过入站链接的 link equity 带进来。各家发布者的 A/B 测试一致地表明,描述性 slug 相比不透明 ID 把 CTR 提升了个位数百分比。Backlinko 2020 年的排名因素研究(分析了 118 万次 SERP)发现,在 SERP 顶部,短 URL 略微胜过长 URL。
「关键词越多越好」这个直觉有一个例外:关键词堆砌。2012 年 9 月的 Exact-Match Domain(EMD)更新专门对低质量的 exact-match 域名和 slug 减分(cheap-life-insurance.com/buy-cheap-life-insurance),Google 之后也一直在 URL 中对关键词堆砌打折扣。2026 年的结论:slug 中出现关键词有适度帮助;堆砌关键词反而有害。从 slug 拿到的最大单一 SEO 收益是发布之后不去改它。入站链接是积累在某条 URL 上的。页面权威是按 URL 级别复利的。一条 301 重定向能保留大部分但不是全部 link equity,而且只有当发布者真的设置了重定向才有效,很多人不会。Berners-Lee 的「Cool URIs Don’t Change」忠告对 SEO 有直接后果:每一次 slug 的更改,即便配了重定向,也会损失一小部分权威,需要时间才能恢复回来。
slug 的 SEO 最佳实践
- slug 保持简短(3–5 个单词最佳)
- 包含目标关键词
- 使用连字符而非下划线(Google 将连字符视为单词分隔符)
- 在不增添意义时移除停用词(the、a、is、and 等)
- 只使用小写字母
- 避免在发布后更改 slug(或设置重定向)
- 剥掉或音译非 ASCII 字符,除非你的平台能在分析工具、社交分享与邮件客户端中干净地处理 IRI。
- 除非日期对资源本身是基础的,否则避免在 slug 中放日期;避免文件扩展名、会话 ID、作者名与状态词。
常见问题
支持带重音的字符吗?
支持。生成器使用 Unicode 规范化(NFD)来移除重音。例如「cafe」仍为「cafe」,而「café」也会变成「cafe」。这确保 slug 干净且为纯 ASCII。
应使用连字符还是下划线?
SEO 推荐使用连字符。Google 的官方文档确认,URL 中的连字符会被视为单词分隔符,而下划线不会。所以「my-article」被读作两个词,而「my_article」只是一个词。
emoji 与符号会怎样?
emoji 不在 URL 未保留字符集中,NFD 也不会分解它们,它们没有拉丁字母等价物。本生成器会把它们丢掉。其他工具会对 emoji 做百分号编码(把单个字符变成像 %F0%9F%94%A5 这样的长字符串),这在现代浏览器里技术上是可行的,但会在分析工具、社交分享与邮件预览里产生不可读的 URL。多数 slug 指南都建议把 emoji 直接剥掉;如果你想保留它们,在 slug 步骤之前先做百分号编码。
这个工具会处理俄文、中文或阿拉伯文标题吗?
靠它自己不会。NFD 只折叠拉丁字符的重音;它没法把西里尔、希腊、阿拉伯、希伯来或 CJK 文字音译成拉丁文。把一段俄文或中文标题粘到本工具里,会把那些字符全部丢掉,产出一个空的或几乎空的 slug。正确的工作流是先跑一次音译(Python 的 unidecode、JavaScript 的 transliteration npm 包,或者维基百科的罗马化习惯)再把罗马化结果贴到这里。具体到日文,请用一个 kana 感知的工具,比如 pykakasi:通用的 CJK 音译器会用普通话拼音,把 東京 输出成 Dong Jing,而不是 Tokyo。
如果发布之后我需要改一条 slug 怎么办?
在改 slug 之前,先把旧 URL 设一条 301 跳转到新 URL。一个 301(「Moved Permanently」)能保住老 URL 上积累的大部分 link equity,并告知爬虫与浏览器更新它们的书签。没有重定向的话,所有现有的入站链接都会断,你也会丢掉那些链接所代表的页面权威。即便配了重定向,也会损失一小部分 equity,需要数周或数月才能恢复回来。Berners-Lee 的格言(cool URIs don’t change)一半是审美,一半是 SEO 真相:每一次 slug 更改都要付代价,所以值得第一次就把 slug 写对。
有推荐的 slug 长度吗?
惯例是三到七个词,大约三十到六十个字符。足够长以做到描述性,足够短以让 Google 的 SERP 摘要不去截断它,人也能一眼把握话题。没有什么硬性的技术上限(RFC 3986 没有规定,现代浏览器能处理几万字符的 URL)但 Apache、nginx 与 IIS 在 KB 级别上有实际上限,而源自 Internet Explorer 的旧「2,000 字符」规则至今仍被作为安全的跨平台天花板引用。这里的「最大长度」选项可让你给输出设个上限;设为 0 表示不限。
我的文本会被保存或发送到任何地方吗?
不会。这个变换完全靠 JavaScript 内置的 String.prototype.normalize() 方法在你的浏览器中运行(Chrome 34、Firefox 31、Safari 10 起即支持(大约是 2015 年)。什么都不会上传,不会调用任何 API,不会写任何日志。你可以在生成 slug 时打开浏览器的 DevTools Network 面板自己验证)根本没有外发请求。这个页面对从未发布的标题、内部文档、草稿 post 等任何你不希望离开自己设备的内容派生出来的 slug,都是安全的。