URL路由:在创建友好的URL时处理空格和非法字符

8
我看到了很多有关URL路由的讨论,以及很多很好的建议......但在现实世界中,我没有看到讨论以下内容:
1. 创建带有空格和非法字符的友好URL 2. 查询数据库
假设你正在构建一个医疗网站,其中包含具有类别和可选子类别的文章(1对多)。 (可以使用任何示例,但医学领域有很多长单词)
例如类别/子/文章结构:
1. 你的一般健康(类别) - 自然健康(子类别) - 你身体的免疫系统及其需要帮助的原因。(文章) - 植物和草药真的是解决方案吗? - 我应该吃强化食品吗? - 银杏草药 - 什么是银杏草药? - 健康饮食 - 每天喝10杯咖啡好吗? - 有机蔬菜值得购买吗? - 汉堡王®邪恶吗? - “法式咖啡馆”或美式咖啡更健康吗?
2. 疾病与状况(类别) - 自身免疫性疾病(子类别) - 某种疾病是人类的头号杀手 - 如何获得帮助 - 遗传条件 - 在怀孕前预防脊柱裂。 - 你是否有长寿的倾向?
3. Dr. FooBar的个人建议(类别) - 我对草药医学和自然疗法的看法(文章-无子类别) - 为什么你应该关心自己的健康? - 吃得好,饮食均衡是可能的。 - 无血手术已经成熟了吗?
在这样的结构中,如果你使用 / {类别} / {子类别} / {文章标题},你将会有一些非常长的URL。此外,还有许多非法字符,例如#!?'é"等。
所以问题是:
  1. 您会如何处理非法字符和空格?(优缺点是什么?)
  2. 您会从数据库中获取这个内容吗?
    • 换句话说,您会信任数据库来查找该项,传递标题,还是在代码中提取所有标题并查找键以获取要传递给数据库的键(两次调用数据库)?

注意:我总是看到漂亮的例子,比如/products/beverages/Short-Product-Name/,那么如何处理一些丑陋的例子呢 ^_^

11个回答

4
我的最后一种方法是:
  1. 将所有“奇怪的字母”转换为“普通字母”——> à变成a,ñ变成n等。
  2. 将所有非单词字符转换为_(即不是a-zA-Z0-9)
  3. 用一个下划线替换下划线组
  4. 删除所有尾随和前导下划线
至于存储,我认为友好的URL应该进入数据库,并且是不可变的,毕竟酷的URI不会改变

4

基于易读性考虑,我个人更喜欢使用下划线 _ 而不是连字符 - (你在上面加一个下划线,_ 就看不见了),如果你要去掉空格。

你可能需要尝试将扩展字符(如 ü)转换为尽可能接近的 close-ascii 等价物,例如:

ü -> u

然而,根据我的经验,实际的 SEO 相关问题中最大的问题不是 URL 包含了所有可爱的文本,而是当人们更改链接中的文本时,所有的 SEO 工作都变成了垃圾,因为现在你有了索引中的死链接。

对于这个问题,我建议像 stackoverflow 一样,使用数值部分引用一个常量实体,并完全忽略其余文本(和/或在其错误时更新它)。

此外,过度层级化的结构只会导致人类使用效率低下。人类讨厌长 URL。复制粘贴它们很麻烦,它们也更容易出错。如果您可以将其细分为较低的层次结构,例如:

/article/1/Some_Article_Title_Here
/article/1/Section/5/Section_Title_Here
/section/19023/Section_Title_here  ( == above link ) 

这样,你只需要在编号文章真的被删除时才需要使用巫术魔法,此时你可以使用文本部分作为搜索字符串来尝试找到真正的文章或类似文章。


1
好主意,但在下划线链接中下划线看起来像空格,所以你可能会遇到问题。另一个建议看起来不错。 - Armstrongest
这是看起来最灵活的方法。我已经测试过了,似乎运行良好。标题被忽略,只使用ID。 - Armstrongest
好的,这似乎很有用,但如果有人更改了ID,例如:/section/123/Section_Title_here 变成 /section/222/Section_Title_here ... 如果有人在浏览器中更改了URL,那么页面将进行完整的后退,但是 Section_Title_here 不会更改...你应该如何手动更改它? - janilemy
@janilemy 更改部分的ID是一个设计错误。因为你不是在更改它,而是在实际上创建一个新的并删除旧的,至少从用户的角度来看。如果您希望使ID更改成为可能,则需要回退机制来跟踪old_id => new_id翻译。本质上,文本部分永远无法帮助您,您应该像在数据库中一样使用ID进行引用完整性。 - Kent Fredric

1
解决方案2是那些典型方法的一种...可以进行一些改进,例如将撇号转换为无符号而不是破折号,以提高可读性。通常,您会希望在数据库中存储标题的用于URL有效性的修改版本以及“真实”标题,这样您就可以使用索引的SELECT WHERE选择该项。
然而,在URL路径部分中实际上没有非法字符,只要适当地对其进行编码即可。例如,空格、井号或斜杠可以编码为%20、%23或%2F。这样,可以将任何字符串编码为URL部分,因此可以通过实际未更改的标题从数据库中选择它。
但是,这取决于您的Web框架,可能存在一些潜在问题。例如,基于CGI的任何内容都无法区分编码的%2F和实际/之间的区别,某些框架/部署可能难以处理Unicode字符。
另一种简单且安全的解决方案是在URL中包含主键,仅使用标题部分使地址更美观。例如:
http://www.example.com/x/category-name/subcat-name/article-name/348254863

这是eg.亚马逊的做法。它有一个优点,您可以在数据库中更改标题,并使具有旧标题的URL自动重定向到新标题。


好的观点,你必须在编码非法字符和为了用户友好而删除它们之间取得平衡。不仅亚马逊将PK添加到URL中 - Stack Overflow也这样做 :) - Nick
我非常喜欢使用主键的想法。无论如何,这就是我以前在查询字符串中传递的内容。 - Armstrongest

1
如果有人感兴趣的话,这是我采取的路线(哦...双关语):
Route r = new Route("{country}/{lang}/Article/{id}/{title}/", new NFRouteHandler("OneArticle"));
Route r2 = new Route("{country}/{lang}/Section/{id}-{subid}/{title}/", new NFRouteHandler("ArticlesInSubcategory"));
Route r3 = new Route("{country}/{lang}/Section/{id}/{title}/", new NFRouteHandler("ArticlesByCategory"));

这使我能够像这样处理URL:

  • site.com/ca/en/Article/123/my-life-and-health
  • site.com/ca/en/Section/12-3/Health-Issues
  • site.com/ca/en/Section/12/

1

在清理URL时,这是我使用的一种替换重音字符的方法:

private static string anglicized(this string urlpart) {
        string before = "àÀâÂäÄáÁéÉèÈêÊëËìÌîÎïÏòÒôÔöÖùÙûÛüÜçÇ’ñ";
        string  after = "aAaAaAaAeEeEeEeEiIiIiIoOoOoOuUuUuUcC'n";

        string cleaned = urlpart;

        for (int i = 0; i < avantConversion.Length; i++ ) {

            cleaned = Regex.Replace(urlpart, before[i].ToString(), after[i].ToString());
        }

        return cleaned;

        // Here's some for Spanish : ÁÉÍÑÓÚÜ¡¿áéíñóúü"

}

不知道这是否是最有效的正则表达式,但肯定是有效的。这是一个扩展方法,所以要调用它,只需将该方法放入静态类中,然后像这样执行:

string articleTitle = "My Article about café and the letters àâäá";
string cleaned = articleTitle.anglicized();

// replace spaces with dashes
cleaned = Regex.Replace( cleaned, "[^A-Za-z0-9- ]", "");

// strip all illegal characters like punctuation
cleaned = Regex.Replace( cleaned, " +", "-").ToLower();

// returns "my-article-about-cafe-and-the-letters-aaaa"

当然,你可以将它合并成一个名为“CleanUrl”之类的方法,但这取决于你。


为了获得更完整、完全支持Unicode的版本,请访问https://dev59.com/zXVC5IYBdhLWcg3wliGe。 - devstuff

0
作为一个客户端用户,而不是网页设计师,我发现 Firefox 有时会在尝试用可用字符替换“非法”字符时破坏 URL。例如,FF 用 %7E 替换 ~,这对我来说永远无法加载。我不明白为什么 HTML 编辑器和浏览器不能简单地约定只接受 A-Z 和 0-9 以外的字符。如果某些脚本需要使用 %、? 等字符,那么就改变脚本应用程序使它们能够与字母数字一起工作。

很遗憾,计算机程序需要尽可能地通用才能最有用...或者说要“可编程”,这意味着程序需要接受您提供的任何输入。 - Armstrongest

0
作为后续。我有一些想法。所以请随意评论这些想法或者给出你自己的答案:
解决方案#1:用破折号替换所有非法字符:
  • www.mysite.com/diseases---conditions/Auto-immune-disorders/the--1-killer-of-people-is-some-disease/

我觉得那看起来有点丑...

解决方案#2:去除非法字符并将空格替换为单破折号:

  • www.mysite.com/diseases-conditions/Auto-immune-disorders/the-1-killer-of-people-is-some-disease/

解决方案 #3:应用一些规则,将某些字符替换为单词:

  • www.mysite.com/diseases-and-conditions/Auto-immune-disorders/the-number1-killer-of-people-is-some-disease/

解决方案 #4:去除所有空格并使用大写字母

  • www.mysite.com/DiseasesAndConditions/AutoImmuneDisorders/TheNumber1KillerOfPeopleIsSomeDisease/

(在大小写敏感的服务器上可能无法正常工作,且难以阅读)


0
我的建议是方案2。虽然我不是世界上最专业的SEO专家,但我认为这基本上是获得良好排名的“标准”方法。

0
通常我所做的是只允许合法字符,并尽可能保持友好的URL简短。另外,重要的是友好的URL通常是由人插入的,我从不从标题或内容生成友好的URL,然后使用它来查询数据库。我会在表中使用一个列,例如friendly_url,以便网站管理员可以插入友好的URL。

0
我通过在数据库中添加一个额外的列(例如:UrlTitle列)并保存一个去除所有非法字符的标题,将'&'符号替换为'and',并用下划线替换空格来解决这个问题。然后,您可以通过UrlTitle进行查找,并在页面标题或其他位置使用真实的标题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接